This commit is contained in:
lifestorm
2024-08-05 18:40:29 +03:00
parent c4d91bf369
commit 324f19217d
8040 changed files with 1853423 additions and 21 deletions

View File

@@ -0,0 +1,375 @@
--[[
| 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/
--]]
if ( SERVER ) then return end
local meta = FindMetaTable( "Panel" )
--[[---------------------------------------------------------
Name: SetTerm
Desc: Kill the panel at this time
-----------------------------------------------------------]]
function meta:SetTerm( term )
self.Term = SysTime() + term
self:SetAnimationEnabled( true )
end
--[[---------------------------------------------------------
Name: AnimationThinkInternal
-----------------------------------------------------------]]
function meta:AnimationThinkInternal()
local systime = SysTime()
if ( self.Term && self.Term <= systime ) then self:Remove() return end
if ( !self.m_AnimList ) then return end -- This can happen if we only have term
for k, anim in pairs( self.m_AnimList ) do
if ( systime >= anim.StartTime ) then
local Fraction = math.TimeFraction( anim.StartTime, anim.EndTime, systime )
Fraction = math.Clamp( Fraction, 0, 1 )
if ( anim.Think ) then
local Frac = Fraction ^ anim.Ease
-- Ease of -1 == ease in out
if ( anim.Ease < 0 ) then
Frac = Fraction ^ ( 1.0 - ( ( Fraction - 0.5 ) ) )
elseif ( anim.Ease > 0 && anim.Ease < 1 ) then
Frac = 1 - ( ( 1 - Fraction ) ^ ( 1 / anim.Ease ) )
end
anim:Think( self, Frac )
end
if ( Fraction == 1 ) then
if ( anim.OnEnd ) then anim:OnEnd( self ) end
self.m_AnimList[k] = nil
end
end
end
end
--[[---------------------------------------------------------
Name: SetAnimationEnabled
Desc: Enables animations on a panel
-----------------------------------------------------------]]
function meta:SetAnimationEnabled( b )
if ( !b ) then
self.AnimationThink = nil
return
end
if ( self.AnimationThink ) then return end
self.AnimationThink = self.AnimationThinkInternal
end
function meta:Stop()
self.m_AnimList = {}
end
function meta:Queue()
self.m_AnimQueue = true
end
function meta:AnimTail()
local last = SysTime()
for k, anim in pairs( self.m_AnimList ) do
last = math.max( last, anim.EndTime )
end
return last
end
--[[---------------------------------------------------------
Name: NewAnimation
Desc: Creates a new animation
-----------------------------------------------------------]]
function meta:NewAnimation( length, delay, ease, callback )
if ( delay == nil ) then delay = 0 end
if ( ease == nil ) then ease = -1 end
if ( self.m_AnimQueue ) then
delay = delay + self:AnimTail()
self.m_AnimQueue = false
else
delay = delay + SysTime()
end
local anim = {
EndTime = delay + length,
StartTime = delay,
Ease = ease,
OnEnd = callback
}
self:SetAnimationEnabled( true )
if ( self.m_AnimList == nil ) then self.m_AnimList = {} end
table.insert( self.m_AnimList, anim )
return anim
end
local function MoveThink( anim, panel, fraction )
if ( !anim.StartPos ) then anim.StartPos = Vector( panel.x, panel.y, 0 ) end
local pos = LerpVector( fraction, anim.StartPos, anim.Pos )
panel:SetPos( pos.x, pos.y )
end
--[[---------------------------------------------------------
Name: MoveTo
-----------------------------------------------------------]]
function meta:MoveTo( x, y, length, delay, ease, callback )
if ( self.x == x && self.y == y ) then return end
local anim = self:NewAnimation( length, delay, ease, callback )
anim.Pos = Vector( x, y, 0 )
anim.Think = MoveThink
end
local function SizeThink( anim, panel, fraction )
if ( !anim.StartSize ) then local w, h = panel:GetSize() anim.StartSize = Vector( w, h, 0 ) end
local size = LerpVector( fraction, anim.StartSize, anim.Size )
if ( anim.SizeX && anim.SizeY ) then
panel:SetSize( size.x, size.y )
elseif ( anim.SizeX ) then
panel:SetWide( size.x )
else
panel:SetTall( size.y )
end
if ( panel:GetDock() > 0 ) then
panel:InvalidateParent()
end
end
--[[---------------------------------------------------------
Name: SizeTo
-----------------------------------------------------------]]
function meta:SizeTo( w, h, length, delay, ease, callback )
local anim = self:NewAnimation( length, delay, ease, callback )
anim.SizeX = w != -1
anim.SizeY = h != -1
if ( !anim.SizeX ) then w = self:GetWide() end
if ( !anim.SizeY ) then h = self:GetTall() end
anim.Size = Vector( w, h, 0 )
anim.Think = SizeThink
return anim
end
--[[---------------------------------------------------------
Name: SlideUp
-----------------------------------------------------------]]
function meta:SlideUp( length )
local height = self:GetTall()
local anim = self:SizeTo( -1, 0, length )
anim.OnEnd = function()
self:SetVisible( false )
self:SetTall( height )
end
end
--[[---------------------------------------------------------
Name: SlideDown
-----------------------------------------------------------]]
function meta:SlideDown( length )
local height = self:GetTall()
self:SetVisible( true )
self:SetTall( 0 )
local anim = self:SizeTo( -1, height, length )
end
local function ColorThink( anim, panel, fraction )
if ( !anim.StartColor ) then anim.StartColor = panel:GetColor() end
panel:SetColor( Color( Lerp( fraction, anim.StartColor.r, anim.Color.r ),
Lerp( fraction, anim.StartColor.g, anim.Color.g ),
Lerp( fraction, anim.StartColor.b, anim.Color.b ),
Lerp( fraction, anim.StartColor.a, anim.Color.a ) ) )
end
--[[---------------------------------------------------------
Name: ColorTo
-----------------------------------------------------------]]
function meta:ColorTo( col, length, delay, callback )
-- We can only use this on specific panel types!
if ( !self.SetColor ) then return end
if ( !self.GetColor ) then return end
local anim = self:NewAnimation( length, delay, nil, callback )
anim.Color = col
anim.Think = ColorThink
end
local function AlphaThink( anim, panel, fraction )
if ( !anim.StartAlpha ) then anim.StartAlpha = panel:GetAlpha() end
panel:SetAlpha( Lerp( fraction, anim.StartAlpha, anim.Alpha ) )
end
--[[---------------------------------------------------------
Name: AlphaTo
-----------------------------------------------------------]]
function meta:AlphaTo( alpha, length, delay, callback )
local anim = self:NewAnimation( length, delay, nil, callback )
anim.Alpha = alpha
anim.Think = AlphaThink
end
local function MoveByThink( anim, panel, fraction )
if ( !anim.StartPos ) then
anim.StartPos = Vector( panel.x, panel.y, 0 )
anim.Pos = anim.StartPos + anim.Pos
end
local pos = LerpVector( fraction, anim.StartPos, anim.Pos )
panel:SetPos( pos.x, pos.y )
end
--[[---------------------------------------------------------
Name: MoveBy
-----------------------------------------------------------]]
function meta:MoveBy( x, y, length, delay, ease, callback )
local anim = self:NewAnimation( length, delay, ease, callback )
anim.Pos = Vector( x, y, 0 )
anim.Think = MoveByThink
end
-- This code is bad and will run forever, never reaching the targetpos.
local function LerpPositions( anim, panel )
if ( !panel.TargetPos ) then return end
local Speed = FrameTime() * 100 * anim.Speed
local Pos = Vector( panel.x, panel.y, 0 )
local Distance = panel.TargetPos - Pos
local Length = Distance:Length()
if ( anim.UseGravity && Length > 1 ) then
Speed = Speed * ( Length * 0.1 )
else
Speed = Speed * 10
end
if ( Length < Speed ) then
panel:SetPosReal( panel.TargetPos.x, panel.TargetPos.y )
panel.TargetPos = nil
return
end
Distance:Normalize()
Distance = Pos + ( Distance * Speed )
panel:SetPosReal( Distance.x, Distance.y )
end
local function NewSetPos( self, x, y )
self.TargetPos = Vector( x, y )
end
local function NewGetPos( self )
return self.TargetPos.x, self.TargetPos.y
end
--[[---------------------------------------------------------
Name: LerpPositions
-----------------------------------------------------------]]
function meta:LerpPositions( speed, usegravity )
if ( self.SetPosReal ) then return end
NewSetPos( self, self:GetPos() )
self.SetPosReal = self.SetPos
self.SetPos = NewSetPos
self.GetPosReal = self.GetPos
self.GetPos = NewGetPos
self.LerpAnim = self:NewAnimation( 86400 )
self.LerpAnim.Speed = speed
self.LerpAnim.UseGravity = usegravity
self.LerpAnim.Think = LerpPositions
end
--
-- DisableLerp
--
function meta:DisableLerp()
self.LerpAnim = nil
self.SetPos = self.SetPosReal
self.GetPos = self.GetPosReal
end

View File

@@ -0,0 +1,591 @@
--[[
| 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/
--]]
if ( SERVER ) then return end
dragndrop = {}
function dragndrop.Clear()
dragndrop.m_Receiver = nil
dragndrop.m_ReceiverSlot = nil
dragndrop.m_HoverStart = nil
dragndrop.m_MouseCode = 0
dragndrop.m_DragWatch = nil
dragndrop.m_MouseX = 0
dragndrop.m_MouseY = 0
dragndrop.m_DraggingMain = nil
dragndrop.m_Dragging = nil
dragndrop.m_DropMenu = nil
end
function dragndrop.IsDragging()
if ( dragndrop.m_Dragging != nil ) then return true end
return false
end
function dragndrop.HandleDroppedInGame()
local panel = vgui.GetHoveredPanel()
if ( !IsValid( panel ) ) then return end
if ( panel:GetClassName() != "CGModBase" ) then return end
end
function dragndrop.Drop()
if ( dragndrop.HandleDroppedInGame() ) then
dragndrop.StopDragging()
return
end
-- Show the menu
if ( dragndrop.m_MouseCode == MOUSE_RIGHT && dragndrop.m_ReceiverSlot && dragndrop.m_ReceiverSlot.Menu ) then
local x, y = dragndrop.m_Receiver:LocalCursorPos()
local menu = DermaMenu()
menu.OnRemove = function( m ) -- If user clicks outside of the menu - drop the dragging
dragndrop.StopDragging()
end
for k, v in pairs( dragndrop.m_ReceiverSlot.Menu ) do
menu:AddOption( v, function()
dragndrop.CallReceiverFunction( true, k, x, y )
dragndrop.StopDragging()
end )
end
menu:Open()
dragndrop.m_DropMenu = menu
return
end
dragndrop.CallReceiverFunction( true, nil, nil, nil )
dragndrop.StopDragging()
end
function dragndrop.StartDragging()
if ( !dragndrop.m_DragWatch:IsSelected() ) then
dragndrop.m_Dragging = { dragndrop.m_DragWatch }
else
local canvas = dragndrop.m_DragWatch:GetSelectionCanvas()
dragndrop.m_Dragging = {}
for k, v in pairs( canvas:GetSelectedChildren() ) do
if ( !v.m_DragSlot ) then continue end
table.insert( dragndrop.m_Dragging, v )
end
end
for k, v in pairs( dragndrop.m_Dragging ) do
if ( !IsValid( v ) ) then continue end
v:OnStartDragging()
end
dragndrop.m_DraggingMain = dragndrop.m_DragWatch
dragndrop.m_DraggingMain:MouseCapture( true )
dragndrop.m_DragWatch = nil
end
function dragndrop.StopDragging()
if ( IsValid( dragndrop.m_Receiver ) ) then
dragndrop.m_Receiver:DragHoverEnd()
dragndrop.m_Receiver = nil
end
for k, v in pairs( dragndrop.m_Dragging or {} ) do
if ( !IsValid( v ) ) then continue end
v:OnStopDragging()
end
dragndrop.Clear()
end
function dragndrop.UpdateReceiver()
local hovered = vgui.GetHoveredPanel()
local receiver = nil
local receiverslot = nil
if ( IsValid( hovered ) ) then
receiver, receiverslot = hovered:GetValidReceiverSlot()
end
if ( IsValid( dragndrop.m_Receiver ) ) then
if ( receiver == dragndrop.m_Receiver ) then return end
dragndrop.m_Receiver:DragHoverEnd()
end
if ( !IsValid( receiver ) ) then
dragndrop.m_Receiver = nil
dragndrop.m_ReceiverSlot = nil
end
dragndrop.m_Receiver = receiver
dragndrop.m_ReceiverSlot = receiverslot
end
--
-- Return all the dragged panels that match this name
--
function dragndrop.GetDroppable( name )
if ( !name ) then return dragndrop.m_Dragging end
if ( !dragndrop.m_Dragging ) then return end
local t = {}
for id, pnl in pairs( dragndrop.m_Dragging ) do
if ( pnl.m_DragSlot && pnl.m_DragSlot[ name ] ) then table.insert( t, pnl ) end
end
return t
end
function dragndrop.CallReceiverFunction( bDoDrop, command, mx, my )
if ( !dragndrop.m_ReceiverSlot ) then return end
if ( !IsValid( dragndrop.m_Receiver ) ) then return end
local x, y = dragndrop.m_Receiver:LocalCursorPos()
if ( mx ) then x = mx end
if ( my ) then y = my end
if ( dragndrop.m_ReceiverSlot.Func ) then
local droppable = dragndrop.GetDroppable( dragndrop.m_ReceiverSlot.Name )
dragndrop.m_ReceiverSlot.Func( dragndrop.m_Receiver, droppable, bDoDrop, command, x, y )
end
end
function dragndrop.Think()
if ( IsValid( dragndrop.m_DropMenu ) ) then return end
--
-- We're dragging but no mouse buttons are down..
-- So force the drop whereever it is!
--
--[[if ( dragndrop.m_Dragging != nil && !input.IsMouseDown( MOUSE_LEFT ) && !input.IsMouseDown( MOUSE_RIGHT ) ) then
dragndrop.m_Dragging:DragMouseRelease( dragndrop.m_MouseCode )
return
end]]
--
-- We're holding down a panel, watch for start of dragging
--
if ( IsValid( dragndrop.m_DragWatch ) ) then
local dist = math.abs( dragndrop.m_MouseX - gui.MouseX() ) + math.abs( dragndrop.m_MouseY - gui.MouseY() )
if ( dist > 20 ) then
dragndrop.StartDragging()
return
end
end
if ( dragndrop.m_Dragging != nil ) then
dragndrop.HoverThink()
dragndrop.UpdateReceiver()
if ( IsValid( dragndrop.m_Receiver ) ) then
dragndrop.CallReceiverFunction( false )
end
end
end
hook.Add( "DrawOverlay", "DragNDropPaint", function()
if ( dragndrop.m_Dragging == nil ) then return end
if ( dragndrop.m_DraggingMain == nil ) then return end
if ( IsValid( dragndrop.m_DropMenu ) ) then return end
local hold_offset_x = 65535
local hold_offset_y = 65535
-- Find the top, left most panel
for k, v in pairs( dragndrop.m_Dragging ) do
if ( !IsValid( v ) ) then continue end
hold_offset_x = math.min( hold_offset_x, v.x )
hold_offset_y = math.min( hold_offset_y, v.y )
end
local wasEnabled = DisableClipping( true )
local Alpha = 0.7
if ( IsValid( dragndrop.m_Hovered ) ) then Alpha = 0.8 end
surface.SetAlphaMultiplier( Alpha )
local ox = gui.MouseX() - hold_offset_x + 8
local oy = gui.MouseY() - hold_offset_y + 8
for k, v in pairs( dragndrop.m_Dragging ) do
if ( !IsValid( v ) ) then continue end
local dist = 512 - v:Distance( dragndrop.m_DraggingMain )
if ( dist < 0 ) then continue end
dist = dist / 512
surface.SetAlphaMultiplier( Alpha * dist )
v.PaintingDragging = true
v:PaintAt( ox + v.x - v:GetWide() / 2, oy + v.y - v:GetTall() / 2 ) -- fill the gap between the top left corner and the mouse position
v.PaintingDragging = nil
end
surface.SetAlphaMultiplier( 1.0 )
DisableClipping( wasEnabled )
end )
hook.Add( "Think", "DragNDropThink", dragndrop.Think )
--
--
--
-- Panel Drag n Drop Extensions
--
--
--
local meta = FindMetaTable( "Panel" )
--
-- Make this panel droppable
--
function meta:Droppable( name )
self.m_DragSlot = self.m_DragSlot or {}
self.m_DragSlot[ name ] = {}
return self.m_DragSlot[ name ]
end
--
-- Make this pannel a drop target
--
function meta:Receiver( name, func, menu )
self.m_ReceiverSlot = self.m_ReceiverSlot or {}
self.m_ReceiverSlot[ name ] = {}
self.m_ReceiverSlot[ name ].Name = name
self.m_ReceiverSlot[ name ].Func = func
self.m_ReceiverSlot[ name ].Menu = menu
end
--
-- Drag parent means that when we start to
-- drag this panel, we'll really start
-- dragging the defined parent
--
function meta:SetDragParent( parent )
self.m_pDragParent = parent
end
function meta:GetValidReceiverSlot()
if ( self.m_ReceiverSlot ) then
-- Find matching slot..
for k, v in pairs( self.m_ReceiverSlot ) do
if ( !dragndrop.m_DraggingMain.m_DragSlot ) then continue end
local slot = dragndrop.m_DraggingMain.m_DragSlot[ k ]
if ( !slot ) then continue end
return self, v
end
end
if ( !IsValid( self:GetParent() ) ) then
return false
end
return self:GetParent():GetValidReceiverSlot()
end
function meta:IsDraggable()
return self.m_DragSlot != nil
end
function meta:IsDragging()
if ( !self.m_DragSlot ) then return false end
return self.Dragging
end
function meta:DroppedOn( pnl )
-- For override.
end
function meta:OnDrop()
-- We're being dropped on something
-- we can create a new panel here and return it, so that instead of
-- dropping us - it drops the new panel instead! We remain where we are!
-- By default we return ourself
return self
end
function meta:OnStartDragging()
self.Dragging = true
self:InvalidateLayout()
if ( self:IsSelectable() ) then
local canvas = self:GetSelectionCanvas()
if ( IsValid( canvas ) && !self:IsSelected() ) then
canvas:UnselectAll()
end
end
end
function meta:OnStopDragging()
self.Dragging = false
end
function meta:DragMousePress( mcode )
if ( IsValid( dragndrop.m_DropMenu ) ) then return end
if ( dragndrop.IsDragging() ) then dragndrop.StopDragging() return end
if ( IsValid( self.m_pDragParent ) and self.m_pDragParent ~= self ) then
return self.m_pDragParent:DragMousePress( mcode )
end
if ( !self.m_DragSlot ) then return end
dragndrop.Clear()
dragndrop.m_MouseCode = mcode
dragndrop.m_DragWatch = self
dragndrop.m_MouseX = gui.MouseX()
dragndrop.m_MouseY = gui.MouseY()
end
function meta:DragClick( mcode )
self:MouseCapture( true )
-- Clicking one mouse button while dragging with another!
-- Return true to stop us clicking and selecting stuff below..
return true
end
function meta:DragMouseRelease( mcode )
if ( IsValid( dragndrop.m_DropMenu ) ) then return end
-- This wasn't the button we clicked with - so don't release drag
if ( dragndrop.IsDragging() && dragndrop.m_MouseCode != mcode ) then
return self:DragClick( mcode )
end
if ( !dragndrop.IsDragging() ) then
dragndrop.Clear()
return false
end
dragndrop.Drop()
-- Todo.. we should only do this if we enabled it!
if ( gui.EnableScreenClicker ) then
gui.EnableScreenClicker( false )
end
self:MouseCapture( false )
return true
end
function meta:SetDropTarget( x, y, w, h )
if ( !self.m_bDrawingPaintOver ) then
self.m_OldPaintOver = self.PaintOver
self.m_bDrawingPaintOver = true
end
self.PaintOver = function()
if ( self.m_OldPaintOver ) then
self:m_OldPaintOver()
end
self:DrawDragHover( x, y, w, h )
end
end
--
-- Drag Hover
--
-- These functions are used for things like trees
-- So that when you hover over the tree while dragging something
-- it will open up the tree. This works regardless of whether the
-- is droppable or not.
--
-- Implement DragHoverClick in your panel class to get this functionality
--
function meta:DragHover( HoverTime )
--
-- Call DragHoverClick if we've been hovering for 0.1 seconds..
--
if ( HoverTime < 0.1 ) then dragndrop.m_bHoverClick = false end
if ( HoverTime > 0.1 && !dragndrop.m_bHoverClick ) then
self:DragHoverClick( HoverTime )
dragndrop.m_bHoverClick = true
end
end
function meta:DrawDragHover( x, y, w, h )
DisableClipping( true )
surface.SetDrawColor( 255, 0, 255, 100 )
surface.DrawRect( x, y, w, h )
surface.SetDrawColor( 255, 220, 255, 230 )
surface.DrawOutlinedRect( x, y, w, h )
surface.SetDrawColor( 255, 100, 255, 50 )
surface.DrawOutlinedRect( x - 1, y - 1, w + 2, h + 2 )
DisableClipping( false )
end
function meta:DragHoverEnd()
if ( !self.m_bDrawingPaintOver ) then return end
self.PaintOver = self.m_OldPaintOver
self.m_bDrawingPaintOver = false
end
function meta:DragHoverClick( HoverTime )
end
--
--
-- This is called to open stuff when you're hovering over it.
--
--
local LastHoverThink = nil
local LastHoverChangeTime = 0
local LastX = 0
local LastY = 0
function dragndrop.HoverThink()
local hovered = vgui.GetHoveredPanel()
local x = gui.MouseX()
local y = gui.MouseY()
-- Hovering a different panel
if ( LastHoverThink != hovered or x != LastX or y != LastY ) then
LastHoverChangeTime = SysTime()
LastHoverThink = hovered
end
-- Hovered panel might do stuff when we're hovering it
-- so give it a chance to do that now.
if ( IsValid( LastHoverThink ) ) then
LastX = x
LastY = y
LastHoverThink:DragHover( SysTime() - LastHoverChangeTime )
end
end

View File

@@ -0,0 +1,139 @@
--[[
| 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/
--]]
if ( SERVER ) then return end
local PanelFactory = {}
local panel_metatable = FindMetaTable( "Panel" )
baseclass.Set( "Panel", panel_metatable )
baseclass.Set( "Label", panel_metatable )
baseclass.Set( "EditablePanel", panel_metatable )
-- Keep the old function
vgui.CreateX = vgui.Create
function vgui.GetControlTable( classname )
return PanelFactory[ classname ]
end
function vgui.Exists( classname )
return PanelFactory[ classname ] != nil
end
function vgui.Create( classname, parent, name )
-- Is this a user-created panel?
if ( PanelFactory[ classname ] ) then
local metatable = PanelFactory[ classname ]
local panel = vgui.Create( metatable.Base, parent, name or classname )
if ( !panel ) then
Error( "Tried to create panel with invalid base '" .. metatable.Base .. "'\n" );
end
table.Merge( panel:GetTable(), metatable )
panel.BaseClass = PanelFactory[ metatable.Base ]
panel.ClassName = classname
-- Call the Init function if we have it
if ( panel.Init ) then
panel:Init()
end
panel:Prepare()
return panel
end
return vgui.CreateX( classname, parent, name or classname )
end
function vgui.CreateFromTable( metatable, parent, name )
if ( !istable( metatable ) ) then return nil end
local panel = vgui.Create( metatable.Base, parent, name )
table.Merge( panel:GetTable(), metatable )
panel.BaseClass = PanelFactory[ metatable.Base ]
-- Call the Init function if we have it
if ( panel.Init ) then
panel:Init()
end
panel:Prepare()
return panel
end
function vgui.Register( classname, mtable, base )
-- Remove the global
PANEL = nil
-- Default base is Panel
mtable.Base = base or "Panel"
mtable.Init = mtable.Init or function() end
PanelFactory[ classname ] = mtable
baseclass.Set( classname, mtable )
local mt = {}
mt.__index = function( t, k )
if ( PanelFactory[ mtable.Base ] && PanelFactory[ mtable.Base ][k] ) then return PanelFactory[ mtable.Base ][k] end
return panel_metatable[k]
end
setmetatable( mtable, mt )
return mtable
end
function vgui.RegisterTable( mtable, base )
-- Remove the global
PANEL = nil
mtable.Base = base or "Panel"
mtable.Init = mtable.Init or function() end
return mtable
end
function vgui.RegisterFile( filename )
local OldPanel = PANEL
PANEL = {}
-- The included file should fill the PANEL global.
include( filename )
local mtable = PANEL
PANEL = OldPanel
mtable.Base = mtable.Base or "Panel"
mtable.Init = mtable.Init or function() end
return mtable
end

View File

@@ -0,0 +1,259 @@
--[[
| 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/
--]]
if ( SERVER ) then return end
local StartX = 0
local StartY = 0
local SelectionCanvas = nil
local meta = FindMetaTable( "Panel" )
function meta:SetSelectionCanvas( bSet )
self.m_bSelectionCanvas = bSet
self:SetMouseInputEnabled( true )
end
function meta:IsSelectionCanvas()
return self.m_bSelectionCanvas
end
function meta:SetSelectable( bSet )
self.m_bSelectable = bSet
end
function meta:ToggleSelection()
self:SetSelected( !self.m_bSelected )
end
function meta:UnselectAll()
self:SetSelected( false )
for k, v in ipairs( self:GetChildren() ) do
v:UnselectAll()
end
end
function meta:SetSelected( bSet )
if ( self.m_bSelected == bSet ) then return end
self.m_bSelected = bSet
if ( self.ApplySchemeSettings ) then
self:ApplySchemeSettings()
end
end
function meta:IsSelected( bSet )
if ( !self:IsSelectable() ) then return false end
return self.m_bSelected == true
end
function meta:IsSelectable()
return self.m_bSelectable == true
end
local function GetSelectionRect()
if ( !SelectionCanvas ) then
debug.Trace()
return
end
local CurX, CurY = SelectionCanvas:ScreenToLocal( gui.MouseX(), gui.MouseY() )
local x = math.min( CurX, StartX )
local y = math.min( CurY, StartY )
local w = math.abs( CurX - StartX )
local h = math.abs( CurY - StartY )
return x, y, w, h
end
function meta:DrawSelections()
if ( !self.m_bSelectable ) then return end
if ( !self.m_bSelected ) then return end
local w, h = self:GetSize()
surface.SetDrawColor( 255, 0, 255, 100 )
surface.DrawRect( 0, 0, w, h )
end
local function PaintSelectionBox( self )
if ( !IsValid( SelectionCanvas ) ) then return end
local x, y, w, h = GetSelectionRect()
surface.SetDrawColor( 255, 0, 255, 50 )
surface.DrawRect( x, y, w, h )
surface.SetDrawColor( 255, 200, 255, 200 )
surface.DrawOutlinedRect( x, y, w, h )
end
function meta:GetSelectionCanvas()
if ( !self.m_bSelectionCanvas ) then
local parent = self:GetParent()
if ( IsValid( parent ) ) then
return parent:GetSelectionCanvas()
end
return nil
end
return self
end
function meta:StartBoxSelection()
if ( !self.m_bSelectionCanvas ) then
local parent = self:GetParent()
if ( IsValid( parent ) ) then
return parent:StartBoxSelection()
end
return
end
self:MouseCapture( true )
if ( !input.IsShiftDown() && !input.IsControlDown() ) then
self:UnselectAll()
end
SelectionCanvas = self
StartX, StartY = self:ScreenToLocal( gui.MouseX(), gui.MouseY() )
self.PaintOver_Old = self.PaintOver
self.PaintOver = PaintSelectionBox
end
function meta:GetChildrenInRect( x, y, w, h )
local tab = {}
for k, v in ipairs( self:GetChildren() ) do
local vw, vh = v:GetSize()
if ( !self:IsVisible() ) then continue end
if ( x > v.x + vw ) then continue end
if ( y > v.y + vh ) then continue end
if ( v.x > x + w ) then continue end
if ( v.y > y + h ) then continue end
if ( v.m_bSelectable ) then
table.insert( tab, v )
end
table.Add( tab, v:GetChildrenInRect( x - v.x, y - v.y, w, h ) )
end
return tab
end
function meta:GetSelectedChildren()
local tab = {}
for k, v in ipairs( self:GetChildren() ) do
if ( v:IsSelected() ) then
table.insert( tab, v )
end
table.Add( tab, v:GetSelectedChildren() )
end
return tab
end
function meta:NumSelectedChildren()
local i = 0
for k, v in ipairs( self:GetChildren() ) do
if ( v:IsSelected() ) then
i = i + 1
end
end
return i
end
function meta:EndBoxSelection()
if ( SelectionCanvas != self ) then return false end
self:MouseCapture( false )
self.PaintOver = self.PaintOver_Old
self.PaintOver_Old = nil
for k, v in ipairs( self:GetChildrenInRect( GetSelectionRect() ) ) do
-- If player is holding shift, add new planels to existing selections, do not toggle
-- This mimics already familiar behavior of Windows Explorer, etc
if ( input.IsShiftDown() ) then
v:SetSelected( true )
else
v:ToggleSelection()
end
end
SelectionCanvas = nil
StartX, StartY = 0, 0
return true
end