--[[ | This file was obtained through the combined efforts | of Madbluntz & Plymouth Antiquarian Society. | | Credits: lifestorm, Gregory Wayne Rossel JR., | Maloy, DrPepper10 @ RIP, Atle! | | Visit for more: https://plymouth.thetwilightzone.ru/ --]] -- -- Widgets are like gui controls in the 3D world(!!!) -- widgets = {} -- -- Holds the currently hovered widget -- widgets.Hovered = nil widgets.HoveredPos = vector_origin -- -- Holds the current pressed widget -- widgets.Pressed = nil local function UpdateHovered( pl, mv ) if ( !IsValid( pl ) ) then return end if ( !pl:Alive() ) then pl:SetHoveredWidget( NULL ) return end local OldHovered = pl:GetHoveredWidget() pl:SetHoveredWidget( NULL ) local eyePos = pl:EyePos() local aimVector = pl:GetAimVector() aimVector:Mul( 256 ) aimVector:Add( eyePos ) local trace = { start = eyePos, endpos = aimVector, filter = function( ent ) return IsValid( ent ) && ent:IsWidget() end } -- debugoverlay.Line( trace.start, trace.endpos, 0.5 ) widgets.Tracing = true local tr = util.TraceLine( trace ) widgets.Tracing = false if ( !IsValid( tr.Entity ) ) then return end if ( tr.Entity:IsWorld() ) then return end if ( !tr.Entity:IsWidget() ) then return end -- debugoverlay.Cross( tr.HitPos, 1, 60 ) if ( OldHovered != tr.Entity ) then -- On hover changed? why bother? end pl:SetHoveredWidget( tr.Entity ) pl.WidgetHitPos = tr.HitPos end local function UpdateButton( pl, mv, btn, mousebutton ) local now = mv:KeyDown( btn ) local was = mv:KeyWasDown( btn ) local hvr = pl:GetHoveredWidget() local prs = pl:GetPressedWidget() if ( now && !was && IsValid( hvr ) ) then hvr:OnPress( pl, mousebutton, mv ) end if ( !now && was && IsValid( prs ) ) then prs:OnRelease( pl, mousebutton, mv ) end end -- -- The idea here is to have exactly the same -- behaviour on the client as the server. -- function widgets.PlayerTick( pl, mv ) UpdateHovered( pl, mv ) UpdateButton( pl, mv, IN_ATTACK, 1 ) UpdateButton( pl, mv, IN_ATTACK2, 2 ) local prs = pl:GetPressedWidget() if ( IsValid( prs ) ) then prs:PressedThinkInternal( pl, mv ) end end --- --- Render the widgets! --- local RenderList = {} function widgets.RenderMe( ent ) -- -- The pressed widget gets to decide what should draw -- if ( LocalPlayer() && IsValid(LocalPlayer():GetPressedWidget()) ) then if ( !LocalPlayer():GetPressedWidget():PressedShouldDraw( ent ) ) then return end end table.insert( RenderList, ent ) end hook.Add( "PostDrawEffects", "RenderWidgets", function() -- -- Don't do anything if we don't have widgets to render! -- if ( #RenderList == 0 ) then return end cam.Start3D( EyePos(), EyeAngles() ) for k, v in ipairs( RenderList ) do v:OverlayRender() end cam.End3D() RenderList = {} end ) hook.Add( "PlayerTick", "TickWidgets", function( pl, mv ) widgets.PlayerTick( pl, mv ) end ) local ENTITY = FindMetaTable( "Entity" ) function ENTITY:IsWidget() return self.Widget end