From 08e309763d206d63378318e9fbc30f79bc657618 Mon Sep 17 00:00:00 2001 From: wav3 Date: Wed, 27 Aug 2025 22:23:08 +0200 Subject: [PATCH 01/43] intprop --- .../gmod_wire_characterlcd/cl_init.lua | 40 ++ lua/entities/gmod_wire_characterlcd/init.lua | 70 ++- .../gmod_wire_consolescreen/cl_init.lua | 41 ++ lua/entities/gmod_wire_consolescreen/init.lua | 424 ++++++++++-------- lua/entities/gmod_wire_interactiveprop.lua | 84 ++-- lua/wire/stools/interactiveprop.lua | 4 +- 6 files changed, 440 insertions(+), 223 deletions(-) diff --git a/lua/entities/gmod_wire_characterlcd/cl_init.lua b/lua/entities/gmod_wire_characterlcd/cl_init.lua index 90061c3720..e28f2ca533 100644 --- a/lua/entities/gmod_wire_characterlcd/cl_init.lua +++ b/lua/entities/gmod_wire_characterlcd/cl_init.lua @@ -1,5 +1,6 @@ include("shared.lua") + function ENT:Initialize() local mem = {} self.Memory = mem @@ -7,6 +8,18 @@ function ENT:Initialize() mem[i] = 0 end + self.InteractiveData = {} + self.LastButtons = {} + self.Buttons = {} + local interactive_model = WireLib.GetInteractiveModel(self:GetModel()) + self.IsInteractive = false + if interactive_model then + self.IsInteractive = true + for i=1, #WireLib.GetInteractiveModel(self:GetModel()).widgets do + self.InteractiveData[i] = 0 + end + end + -- Screen control: -- [1003] - Background red -- [1004] - Background green @@ -74,10 +87,37 @@ function ENT:Initialize() GPULib.ClientCacheCallback(self,function(Address,Value) self:WriteCell(Address,Value) end) + + WireLib.netRegister(self) end +local panel + +function ENT:SendData() + net.Start("wire_interactiveprop_action") + + local data = WireLib.GetInteractiveModel(self:GetModel()).widgets + net.WriteEntity(self) + for i=1, #data do + net.WriteFloat(self.InteractiveData[i]) + end + net.SendToServer() +end + +function ENT:GetPanel() + if not self.IsInteractive then return end + local data = WireLib.GetInteractiveModel(self:GetModel()) + return WireLib.GetInteractiveWidgetBody(self, data) +end + + +function ENT:AddButton(id,button) + if not self.IsInteractive then return end + self.Buttons[id] = button +end + function ENT:OnRemove() self.GPU:Finalize() end diff --git a/lua/entities/gmod_wire_characterlcd/init.lua b/lua/entities/gmod_wire_characterlcd/init.lua index 6f5261409f..e1f929a335 100644 --- a/lua/entities/gmod_wire_characterlcd/init.lua +++ b/lua/entities/gmod_wire_characterlcd/init.lua @@ -1,16 +1,36 @@ -AddCSLuaFile("cl_init.lua") +AddCSLuaFile("cl_init.lua") AddCSLuaFile("shared.lua") include("shared.lua") ENT.WireDebugName = "CharacterLcdScreen" +function ENT:InitInteractive() + local model = self:GetModel() + local outputs = {"Memory"} + local interactivemodel = WireLib.GetInteractiveModel(self:GetModel()) + for i=1, #interactivemodel.widgets do + outputs[i+1] = interactivemodel.widgets[i].name + end + self.BlockInput = false + self.NextPrompt = 0 + self.Outputs=WireLib.CreateOutputs(self,outputs) + self.IsInteractive = true +end + function ENT:Initialize() self:PhysicsInit(SOLID_VPHYSICS) self:SetMoveType(MOVETYPE_VPHYSICS) self:SetSolid(SOLID_VPHYSICS) self.Inputs = WireLib.CreateInputs(self, { "CharAddress", "Char (ASCII/Unicode)", "Contrast", "Clk", "Reset" }) - self.Outputs = WireLib.CreateOutputs(self, { "Memory" }) + + self.InteractiveData = {} + self.IsInteractive = false + if WireLib.IsValidInteractiveModel(self:GetModel()) then + self:InitInteractive() + else + self.Outputs = WireLib.CreateOutputs(self, { "Memory" }) + end self.Memory = {} @@ -179,4 +199,50 @@ function ENT:ClientWriteCell(Address, value) end end + + +function ENT:ReceiveData() + if not self.IsInteractive then return end + local data = WireLib.GetInteractiveModel(self:GetModel()).widgets + for i = 1, #data do + WireLib.TriggerOutput(self, data[i].name, net.ReadFloat()) + end +end + +function ENT:UpdateOverlay() -- required by interactiveprop functions + +end + + +function ENT:Prompt( ply ) + if not self.IsInteractive then return end + if ply then + if CurTime() < self.NextPrompt then return end -- anti spam + self.NextPrompt = CurTime() + 0.1 + + if IsValid( self.User ) then + WireLib.AddNotify(ply,"That interactive prop is in use by another player!",NOTIFY_ERROR,5,6) + return + end + + self.User = ply + + net.Start( "wire_interactiveprop_show" ) + net.WriteEntity( self ) + net.Send( ply ) + else + self:Prompt( self:GetPlayer() ) -- prompt for owner + end +end + +function ENT:Use(ply) + if not IsValid( ply ) then return end + self:Prompt( ply ) +end + +function ENT:Unprompt() + if not self.IsInteractive then return end + self.User = nil +end + duplicator.RegisterEntityClass("gmod_wire_characterlcd", WireLib.MakeWireEnt, "Data", "ScreenWidth", "ScreenHeight") diff --git a/lua/entities/gmod_wire_consolescreen/cl_init.lua b/lua/entities/gmod_wire_consolescreen/cl_init.lua index 5b1222f146..7de763341b 100644 --- a/lua/entities/gmod_wire_consolescreen/cl_init.lua +++ b/lua/entities/gmod_wire_consolescreen/cl_init.lua @@ -1,11 +1,25 @@ include("shared.lua") + + function ENT:Initialize() self.Memory1 = {} self.Memory2 = {} for i = 0, 2047 do self.Memory1[i] = 0 end + + self.InteractiveData = {} + self.LastButtons = {} + self.Buttons = {} + local interactive_model = WireLib.GetInteractiveModel(self:GetModel()) + self.IsInteractive = false + if interactive_model then + self.IsInteractive = true + for i=1, #WireLib.GetInteractiveModel(self:GetModel()).widgets do + self.InteractiveData[i] = 0 + end + end -- Caching control: -- [2020] - Force cache refresh @@ -694,3 +708,30 @@ end function ENT:IsTranslucent() return true end + + + +local panel + +function ENT:SendData() + net.Start("wire_interactiveprop_action") + + local data = WireLib.GetInteractiveModel(self:GetModel()).widgets + net.WriteEntity(self) + for i=1, #data do + net.WriteFloat(self.InteractiveData[i]) + end + net.SendToServer() +end + +function ENT:GetPanel() + if not self.IsInteractive then return end + local data = WireLib.GetInteractiveModel(self:GetModel()) + return WireLib.GetInteractiveWidgetBody(self, data) +end + + +function ENT:AddButton(id,button) + if not self.IsInteractive then return end + self.Buttons[id] = button +end \ No newline at end of file diff --git a/lua/entities/gmod_wire_consolescreen/init.lua b/lua/entities/gmod_wire_consolescreen/init.lua index f9eb661953..ce0f0d1502 100644 --- a/lua/entities/gmod_wire_consolescreen/init.lua +++ b/lua/entities/gmod_wire_consolescreen/init.lua @@ -4,95 +4,159 @@ include('shared.lua') ENT.WireDebugName = "ConsoleScreen" +function ENT:InitInteractive() + local model = self:GetModel() + local outputs = {"Memory"} + local interactivemodel = WireLib.GetInteractiveModel(self:GetModel()) + for i=1, #interactivemodel.widgets do + outputs[i+1] = interactivemodel.widgets[i].name + end + self.BlockInput = false + self.NextPrompt = 0 + self.Outputs=WireLib.CreateOutputs(self,outputs) + self.IsInteractive = true +end + + +function ENT:ReceiveData() + if not self.IsInteractive then return end + local data = WireLib.GetInteractiveModel(self:GetModel()).widgets + for i = 1, #data do + WireLib.TriggerOutput(self, data[i].name, net.ReadFloat()) + end +end + +function ENT:UpdateOverlay() -- required by interactiveprop functions + +end + + +function ENT:Prompt( ply ) + if not self.IsInteractive then return end + if ply then + if CurTime() < self.NextPrompt then return end -- anti spam + self.NextPrompt = CurTime() + 0.1 + + if IsValid( self.User ) then + WireLib.AddNotify(ply,"That interactive prop is in use by another player!",NOTIFY_ERROR,5,6) + return + end + + self.User = ply + + net.Start( "wire_interactiveprop_show" ) + net.WriteEntity( self ) + net.Send( ply ) + else + self:Prompt( self:GetPlayer() ) -- prompt for owner + end +end + +function ENT:Use(ply) + if not IsValid( ply ) then return end + self:Prompt( ply ) +end + +function ENT:Unprompt() + if not self.IsInteractive then return end + self.User = nil +end + + function ENT:Initialize() - self:PhysicsInit(SOLID_VPHYSICS) - self:SetMoveType(MOVETYPE_VPHYSICS) - self:SetSolid(SOLID_VPHYSICS) - - self.Inputs = WireLib.CreateInputs(self, { "CharX", "CharY", "Char (ASCII/Unicode)", "CharParam (RGBrgb; White=999)", "Clk", "Reset" }) - self.Outputs = WireLib.CreateOutputs(self, { "Memory" }) - - self.Memory = {} - - for i = 0, 2047 do - self.Memory[i] = 0 - end - - self.CharX = 0 - self.CharY = 0 - self.Char = 0 - self.CharParam = 0 - - self.Memory[2020] = 0 - self.Memory[2021] = 0 - - self.Memory[2022] = 3/4 - self.Memory[2023] = 0 - self.Memory[2024] = 0 - self.Memory[2025] = 1 - self.Memory[2026] = 1 - self.Memory[2027] = 1 - self.Memory[2028] = 1 - self.Memory[2029] = 1 - self.Memory[2030] = 1 - self.Memory[2031] = 0 - self.Memory[2032] = 29 - self.Memory[2033] = 0 - self.Memory[2034] = 17 - self.Memory[2035] = 0 - self.Memory[2036] = 0 - - self.Memory[2042] = 000 - self.Memory[2043] = 0.5 - self.Memory[2044] = 0.25 - self.Memory[2045] = 0 - self.Memory[2046] = 0 - self.Memory[2047] = 1 -- CLK - - self.Cache = GPUCacheManager(self,true) + self:PhysicsInit(SOLID_VPHYSICS) + self:SetMoveType(MOVETYPE_VPHYSICS) + self:SetSolid(SOLID_VPHYSICS) + + self.Inputs = WireLib.CreateInputs(self, { "CharX", "CharY", "Char (ASCII/Unicode)", "CharParam (RGBrgb; White=999)", "Clk", "Reset" }) + if WireLib.IsValidInteractiveModel(self:GetModel()) then + self:InitInteractive() + else + self.Outputs = WireLib.CreateOutputs(self, { "Memory" }) + end + + + self.Memory = {} + + for i = 0, 2047 do + self.Memory[i] = 0 + end + + self.CharX = 0 + self.CharY = 0 + self.Char = 0 + self.CharParam = 0 + + self.Memory[2020] = 0 + self.Memory[2021] = 0 + + self.Memory[2022] = 3/4 + self.Memory[2023] = 0 + self.Memory[2024] = 0 + self.Memory[2025] = 1 + self.Memory[2026] = 1 + self.Memory[2027] = 1 + self.Memory[2028] = 1 + self.Memory[2029] = 1 + self.Memory[2030] = 1 + self.Memory[2031] = 0 + self.Memory[2032] = 29 + self.Memory[2033] = 0 + self.Memory[2034] = 17 + self.Memory[2035] = 0 + self.Memory[2036] = 0 + + self.Memory[2042] = 000 + self.Memory[2043] = 0.5 + self.Memory[2044] = 0.25 + self.Memory[2045] = 0 + self.Memory[2046] = 0 + self.Memory[2047] = 1 -- CLK + + self.Cache = GPUCacheManager(self,true) end function ENT:SendPixel() - if (self.Memory[2047] ~= 0) and (self.CharX >= 0) and (self.CharX < 30) and - (self.CharY >= 0) and (self.CharY < 18) then - local pixelno = math.floor(self.CharY)*30+math.floor(self.CharX) + if (self.Memory[2047] ~= 0) and (self.CharX >= 0) and (self.CharX < 30) and + (self.CharY >= 0) and (self.CharY < 18) then + local pixelno = math.floor(self.CharY)*30+math.floor(self.CharX) - self:WriteCell(pixelno*2, self.Char) - self:WriteCell(pixelno*2+1, self.CharParam) - end + self:WriteCell(pixelno*2, self.Char) + self:WriteCell(pixelno*2+1, self.CharParam) + end end function ENT:ReadCell(Address) - Address = math.floor(Address) - if Address < 0 then return nil end - if Address >= 2048 then return nil end - if Address == 2022 then return WireGPU_Monitors[self:GetModel()].RatioX end + Address = math.floor(Address) + if Address < 0 then return nil end + if Address >= 2048 then return nil end + if Address == 2022 then return WireGPU_Monitors[self:GetModel()].RatioX end - return self.Memory[Address] + return self.Memory[Address] end function ENT:WriteCell(Address, value) - Address = math.floor(Address) - if Address < 0 then return false end - if Address >= 2048 then return false end - if Address < 2000 then -- text/attribute data - if self.Memory[Address] == value then return true end - else --- self.Memory[Address] = value - self:ClientWriteCell(Address, value) --- self.Cache:WriteNow(Address, value) --- return true - end - - self.Memory[Address] = value - self.Cache:Write(Address,value) - return true + Address = math.floor(Address) + if Address < 0 then return false end + if Address >= 2048 then return false end + if Address < 2000 then -- text/attribute data + if self.Memory[Address] == value then return true end + else +-- self.Memory[Address] = value + self:ClientWriteCell(Address, value) +-- self.Cache:WriteNow(Address, value) +-- return true + end + + self.Memory[Address] = value + self.Cache:Write(Address,value) + return true end function ENT:Think() - self.Cache:Flush() - self:NextThink(CurTime()+0.1) - return true + self.Cache:Flush() + self:NextThink(CurTime()+0.1) + return true end function ENT:Retransmit(ply) @@ -104,115 +168,115 @@ function ENT:Retransmit(ply) end function ENT:TriggerInput(iname, value) - if iname == "CharX" then - self.CharX = value - self:SendPixel() - elseif iname == "CharY" then - self.CharY = value - self:SendPixel() - elseif iname == "Char" then - self.Char = value - self:SendPixel() - elseif iname == "CharParam" then - self.CharParam = value - self:SendPixel() - elseif iname == "Clk" then - self:WriteCell(2047, value) - self:SendPixel() - elseif iname == "Reset" then - self:WriteCell(2041,0) - self:WriteCell(2046,0) - self:WriteCell(2042,0) - end + if iname == "CharX" then + self.CharX = value + self:SendPixel() + elseif iname == "CharY" then + self.CharY = value + self:SendPixel() + elseif iname == "Char" then + self.Char = value + self:SendPixel() + elseif iname == "CharParam" then + self.CharParam = value + self:SendPixel() + elseif iname == "Clk" then + self:WriteCell(2047, value) + self:SendPixel() + elseif iname == "Reset" then + self:WriteCell(2041,0) + self:WriteCell(2046,0) + self:WriteCell(2042,0) + end end function ENT:ClientWriteCell(Address, value) - if Address == 2019 then -- Hardware Clear Viewport - local low = math.floor(math.Clamp(self.Memory[2033],0,17)) - local high = math.floor(math.Clamp(self.Memory[2034],0,17)) - local lowc = math.floor(math.Clamp(self.Memory[2031],0,29)) - local highc = math.floor(math.Clamp(self.Memory[2032],0,29)) - for j = low, high do - for i = 2*lowc, 2*highc+1 do - self.Memory[i*60+value] = 0 - end - end - elseif Address == 2037 then -- Shift cells (number of cells, >0 right, <0 left) - local delta = math.floor(math.Clamp(math.abs(value),-30,30)) - local low = math.floor(math.Clamp(self.Memory[2033],0,17)) - local high = math.floor(math.Clamp(self.Memory[2034],0,17)) - local lowc = math.floor(math.Clamp(self.Memory[2031],0,29)) - local highc = math.floor(math.Clamp(self.Memory[2032],0,29)) - if value > 0 then - for j = low,high do - for i = highc,lowc+delta,-1 do - self.Memory[j*60+i*2] = self.Memory[j*60+i*2-delta*2] - self.Memory[j*60+i*2+1] = self.Memory[j*60+i*2+1-delta*2] - end - end - for j = low,high do - for i = lowc, lowc+delta-1 do - self.Memory[j*60+i*2] = 0 - self.Memory[j*60+i*2+1] = 0 - end - end - else - for j = low,high do - for i = lowc,highc-delta do - self.Memory[j*60+i*2] = self.Memory[j*60+i*2+delta*2] - self.Memory[j*60+i*2+1] = self.Memory[j*60+i*2+1+delta*2] - end - end - for j = low,high do - for i = highc-delta+1,highc do - self.Memory[j*60+i*2] = 0 - self.Memory[j*60+i*2+1] = 0 - end - end - end - elseif Address == 2038 then -- Shift rows (number of rows, >0 shift down, <0 shift up) - local delta = math.floor(math.Clamp(math.abs(value),-30,30)) - local low = math.floor(math.Clamp(self.Memory[2033],0,17)) - local high = math.floor(math.Clamp(self.Memory[2034],0,17)) - local lowc = math.floor(math.Clamp(self.Memory[2031],0,29)) - local highc = math.floor(math.Clamp(self.Memory[2032],0,29)) - if value > 0 then - for j = low, high-delta do - for i = 2*lowc, 2*highc+1 do - self.Memory[j*60+i] = self.Memory[(j+delta)*60+i] - end - end - for j = high-delta+1,high do - for i = 2*lowc, 2*highc+1 do - self.Memory[j*60+i] = 0 - end - end - else - for j = high,low+delta,-1 do - for i = 2*lowc, 2*highc+1 do - self.Memory[j*60+i] = self.Memory[(j-delta)*60+i] - end - end - for j = low,low+delta-1 do - for i = 2*lowc, 2*highc+1 do - self.Memory[j*60+i] = 0 - end - end - end - elseif Address == 2039 then -- Hardware Clear Row (Writing clears row) - for i = 0, 59 do - self.Memory[value*60+i] = 0 - end - elseif Address == 2040 then -- Hardware Clear Column (Writing clears column) - for i = 0, 17 do - self.Memory[i*60+value] = 0 - end - elseif Address == 2041 then -- Hardware Clear Screen - for i = 0, 18*30*2-1 do - self.Memory[i] = 0 - end - self.Cache:Reset() - end + if Address == 2019 then -- Hardware Clear Viewport + local low = math.floor(math.Clamp(self.Memory[2033],0,17)) + local high = math.floor(math.Clamp(self.Memory[2034],0,17)) + local lowc = math.floor(math.Clamp(self.Memory[2031],0,29)) + local highc = math.floor(math.Clamp(self.Memory[2032],0,29)) + for j = low, high do + for i = 2*lowc, 2*highc+1 do + self.Memory[i*60+value] = 0 + end + end + elseif Address == 2037 then -- Shift cells (number of cells, >0 right, <0 left) + local delta = math.floor(math.Clamp(math.abs(value),-30,30)) + local low = math.floor(math.Clamp(self.Memory[2033],0,17)) + local high = math.floor(math.Clamp(self.Memory[2034],0,17)) + local lowc = math.floor(math.Clamp(self.Memory[2031],0,29)) + local highc = math.floor(math.Clamp(self.Memory[2032],0,29)) + if value > 0 then + for j = low,high do + for i = highc,lowc+delta,-1 do + self.Memory[j*60+i*2] = self.Memory[j*60+i*2-delta*2] + self.Memory[j*60+i*2+1] = self.Memory[j*60+i*2+1-delta*2] + end + end + for j = low,high do + for i = lowc, lowc+delta-1 do + self.Memory[j*60+i*2] = 0 + self.Memory[j*60+i*2+1] = 0 + end + end + else + for j = low,high do + for i = lowc,highc-delta do + self.Memory[j*60+i*2] = self.Memory[j*60+i*2+delta*2] + self.Memory[j*60+i*2+1] = self.Memory[j*60+i*2+1+delta*2] + end + end + for j = low,high do + for i = highc-delta+1,highc do + self.Memory[j*60+i*2] = 0 + self.Memory[j*60+i*2+1] = 0 + end + end + end + elseif Address == 2038 then -- Shift rows (number of rows, >0 shift down, <0 shift up) + local delta = math.floor(math.Clamp(math.abs(value),-30,30)) + local low = math.floor(math.Clamp(self.Memory[2033],0,17)) + local high = math.floor(math.Clamp(self.Memory[2034],0,17)) + local lowc = math.floor(math.Clamp(self.Memory[2031],0,29)) + local highc = math.floor(math.Clamp(self.Memory[2032],0,29)) + if value > 0 then + for j = low, high-delta do + for i = 2*lowc, 2*highc+1 do + self.Memory[j*60+i] = self.Memory[(j+delta)*60+i] + end + end + for j = high-delta+1,high do + for i = 2*lowc, 2*highc+1 do + self.Memory[j*60+i] = 0 + end + end + else + for j = high,low+delta,-1 do + for i = 2*lowc, 2*highc+1 do + self.Memory[j*60+i] = self.Memory[(j-delta)*60+i] + end + end + for j = low,low+delta-1 do + for i = 2*lowc, 2*highc+1 do + self.Memory[j*60+i] = 0 + end + end + end + elseif Address == 2039 then -- Hardware Clear Row (Writing clears row) + for i = 0, 59 do + self.Memory[value*60+i] = 0 + end + elseif Address == 2040 then -- Hardware Clear Column (Writing clears column) + for i = 0, 17 do + self.Memory[i*60+value] = 0 + end + elseif Address == 2041 then -- Hardware Clear Screen + for i = 0, 18*30*2-1 do + self.Memory[i] = 0 + end + self.Cache:Reset() + end end duplicator.RegisterEntityClass("gmod_wire_consolescreen", WireLib.MakeWireEnt, "Data") diff --git a/lua/entities/gmod_wire_interactiveprop.lua b/lua/entities/gmod_wire_interactiveprop.lua index 749c56bc94..2210df6f47 100644 --- a/lua/entities/gmod_wire_interactiveprop.lua +++ b/lua/entities/gmod_wire_interactiveprop.lua @@ -203,11 +203,38 @@ function WireLib.IsValidInteractiveModel( model ) return InteractiveModels[model] ~= nil end +function WireLib.GetInteractiveModel( model ) + return InteractiveModels[model] +end + +function WireLib.GetInteractiveWidgetBody( ent, data ) + local body = vgui.Create("DFrame") + body:SetTitle(data.title) + body:SetSize(data.width, data.height) + body:SetVisible(true) + body.Paint = function( self, w, h ) -- 'function Frame:Paint( w, h )' works too + -- surface.SetDrawColor(255,255,255) + -- surface.DrawOutlinedRect(0, 0, w, h) + -- surface.SetDrawColor(0,0,0) + -- surface.DrawOutlinedRect(1, 1, w-2, h-2) + draw.RoundedBox( 4, 0, 0, w, h, Color( 255, 255, 255 ) ) + draw.RoundedBox( 4, 1, 1, w-2, h-2, Color( 64, 64, 64 ) ) + end + body:SetDraggable(false) + body:Center() + body:ShowCloseButton(true) + body:MakePopup() + for id, widget in ipairs( data.widgets ) do + WidgetBuilders[widget.type](ent, widget, body, id) + end + return body +end + InteractiveModels["models/props_c17/furnituresink001a.mdl"] = copyPropUI( "models/props_interiors/bathtub01a.mdl", "Furniture Sink" ) InteractiveModels["models/props_interiors/sinkkitchen01a.mdl"] = copyPropUI( "models/props_interiors/bathtub01a.mdl", "Kitchen Sink" ) InteractiveModels["models/props_wasteland/prison_sink001a.mdl"] = copyPropUI( "models/props_interiors/bathtub01a.mdl", "Prison Sink" ) -local WidgetBuilders = { +WidgetBuilders = { DCheckBox = function(self, data, body, index) local checkbox = vgui.Create("DCheckBox", body) @@ -252,6 +279,14 @@ local WidgetBuilders = { button:SetPos(data.x, data.y) button:SetText(data.text or "") button:SetSize(data.width or 20, data.height or 20) + button.OnDepressed = function(scratch) + self.InteractiveData[index] = 1 + self:SendData() + end + button.OnReleased = function(scratch) + self.InteractiveData[index] = 0 + self:SendData() + end self:AddButton(index,button) end @@ -259,26 +294,7 @@ local WidgetBuilders = { function ENT:GetPanel() local data = InteractiveModels[ self:GetModel() ] - local body = vgui.Create("DFrame") - body:SetTitle(data.title) - body:SetSize(data.width, data.height) - body:SetVisible(true) - body.Paint = function( self, w, h ) -- 'function Frame:Paint( w, h )' works too - -- surface.SetDrawColor(255,255,255) - -- surface.DrawOutlinedRect(0, 0, w, h) - -- surface.SetDrawColor(0,0,0) - -- surface.DrawOutlinedRect(1, 1, w-2, h-2) - draw.RoundedBox( 4, 0, 0, w, h, Color( 255, 255, 255 ) ) - draw.RoundedBox( 4, 1, 1, w-2, h-2, Color( 64, 64, 64 ) ) - end - body:SetDraggable(false) - body:Center() - body:ShowCloseButton(true) - body:MakePopup() - for id, widget in ipairs( data.widgets ) do - WidgetBuilders[widget.type](self, widget, body, id) - end - return body + return WireLib.GetInteractiveWidgetBody(self, data) end @@ -312,22 +328,6 @@ if CLIENT then end end - function ENT:Think() - if IsValid( panel ) and #self.Buttons ~= 0 then - local needToUpdate = false - for k,v in pairs(self.Buttons) do - self.LastButtons[k] = self.InteractiveData[k] - self.InteractiveData[k] = v:IsDown() and 1 or 0 - if self.InteractiveData[k] ~= self.LastButtons[k] then - needToUpdate = true - end - end - if needToUpdate then - self:SendData() - end - end - end - net.Receive("wire_interactiveprop_show",function() local self = net.ReadEntity() if not IsValid(self) then return end @@ -419,7 +419,10 @@ end util.AddNetworkString("wire_interactiveprop_action") net.Receive("wire_interactiveprop_action",function(len,ply) local ent = net.ReadEntity() - if not ent:IsValid() or ent:GetClass() ~= "gmod_wire_interactiveprop" or ply ~= ent.User then return end + if not ent:IsValid() or (ent:GetClass() ~= "gmod_wire_interactiveprop" and + ent:GetClass() ~= "gmod_wire_characterlcd" and + ent:GetClass() ~= "gmod_wire_consolescreen" + ) or ply ~= ent.User then return end ent:ReceiveData() ent:UpdateOverlay() @@ -455,7 +458,10 @@ end util.AddNetworkString("wire_interactiveprop_close") net.Receive("wire_interactiveprop_close",function(len,ply) local ent = net.ReadEntity() - if not ent:IsValid() or ent:GetClass() ~= "gmod_wire_interactiveprop" or ply ~= ent.User then return end + if not ent:IsValid() or (ent:GetClass() ~= "gmod_wire_interactiveprop" and + ent:GetClass() ~= "gmod_wire_characterlcd" and + ent:GetClass() ~= "gmod_wire_consolescreen" + ) or ply ~= ent.User then return end ent:Unprompt() end) diff --git a/lua/wire/stools/interactiveprop.lua b/lua/wire/stools/interactiveprop.lua index 6d5815bd6c..44ea69b21f 100644 --- a/lua/wire/stools/interactiveprop.lua +++ b/lua/wire/stools/interactiveprop.lua @@ -16,8 +16,8 @@ TOOL.ClientConVar = { if SERVER then function TOOL:GetDataTables() - return {} - end + return {} + end end WireToolSetup.BaseLang() From 579e40761d0496f37e85b7615b59b0785f90748f Mon Sep 17 00:00:00 2001 From: wav3 Date: Wed, 27 Aug 2025 22:30:14 +0200 Subject: [PATCH 02/43] digi --- .../gmod_wire_consolescreen/cl_init.lua | 47 +++++++------- .../gmod_wire_digitalscreen/cl_init.lua | 37 +++++++++++ lua/entities/gmod_wire_digitalscreen/init.lua | 65 ++++++++++++++++++- lua/entities/gmod_wire_interactiveprop.lua | 16 ++++- 4 files changed, 138 insertions(+), 27 deletions(-) diff --git a/lua/entities/gmod_wire_consolescreen/cl_init.lua b/lua/entities/gmod_wire_consolescreen/cl_init.lua index 7de763341b..5ccb5a1477 100644 --- a/lua/entities/gmod_wire_consolescreen/cl_init.lua +++ b/lua/entities/gmod_wire_consolescreen/cl_init.lua @@ -1,6 +1,29 @@ include("shared.lua") +local panel + +function ENT:SendData() + net.Start("wire_interactiveprop_action") + + local data = WireLib.GetInteractiveModel(self:GetModel()).widgets + net.WriteEntity(self) + for i=1, #data do + net.WriteFloat(self.InteractiveData[i]) + end + net.SendToServer() +end +function ENT:GetPanel() + if not self.IsInteractive then return end + local data = WireLib.GetInteractiveModel(self:GetModel()) + return WireLib.GetInteractiveWidgetBody(self, data) +end + + +function ENT:AddButton(id,button) + if not self.IsInteractive then return end + self.Buttons[id] = button +end function ENT:Initialize() self.Memory1 = {} @@ -711,27 +734,3 @@ end -local panel - -function ENT:SendData() - net.Start("wire_interactiveprop_action") - - local data = WireLib.GetInteractiveModel(self:GetModel()).widgets - net.WriteEntity(self) - for i=1, #data do - net.WriteFloat(self.InteractiveData[i]) - end - net.SendToServer() -end - -function ENT:GetPanel() - if not self.IsInteractive then return end - local data = WireLib.GetInteractiveModel(self:GetModel()) - return WireLib.GetInteractiveWidgetBody(self, data) -end - - -function ENT:AddButton(id,button) - if not self.IsInteractive then return end - self.Buttons[id] = button -end \ No newline at end of file diff --git a/lua/entities/gmod_wire_digitalscreen/cl_init.lua b/lua/entities/gmod_wire_digitalscreen/cl_init.lua index 2295fdf215..b14c1bd788 100644 --- a/lua/entities/gmod_wire_digitalscreen/cl_init.lua +++ b/lua/entities/gmod_wire_digitalscreen/cl_init.lua @@ -1,9 +1,46 @@ include('shared.lua') +local panel + +function ENT:SendData() + net.Start("wire_interactiveprop_action") + + local data = WireLib.GetInteractiveModel(self:GetModel()).widgets + net.WriteEntity(self) + for i=1, #data do + net.WriteFloat(self.InteractiveData[i]) + end + net.SendToServer() +end + +function ENT:GetPanel() + if not self.IsInteractive then return end + local data = WireLib.GetInteractiveModel(self:GetModel()) + return WireLib.GetInteractiveWidgetBody(self, data) +end + + +function ENT:AddButton(id,button) + if not self.IsInteractive then return end + self.Buttons[id] = button +end + function ENT:Initialize() self.Memory1 = {} self.Memory2 = {} + self.InteractiveData = {} + self.LastButtons = {} + self.Buttons = {} + local interactive_model = WireLib.GetInteractiveModel(self:GetModel()) + self.IsInteractive = false + if interactive_model then + self.IsInteractive = true + for i=1, #WireLib.GetInteractiveModel(self:GetModel()).widgets do + self.InteractiveData[i] = 0 + end + end + self.LastClk = true self.NewClk = true self.Memory1[1048575] = 1 diff --git a/lua/entities/gmod_wire_digitalscreen/init.lua b/lua/entities/gmod_wire_digitalscreen/init.lua index 3fc448cbd4..f882e00956 100644 --- a/lua/entities/gmod_wire_digitalscreen/init.lua +++ b/lua/entities/gmod_wire_digitalscreen/init.lua @@ -5,6 +5,65 @@ DEFINE_BASECLASS( "base_wire_entity" ) ENT.WireDebugName = "DigitalScreen" + +function ENT:InitInteractive() + local model = self:GetModel() + local outputs = {"Memory"} + local interactivemodel = WireLib.GetInteractiveModel(self:GetModel()) + for i=1, #interactivemodel.widgets do + outputs[i+1] = interactivemodel.widgets[i].name + end + self.BlockInput = false + self.NextPrompt = 0 + self.Outputs=WireLib.CreateOutputs(self,outputs) + self.IsInteractive = true +end + + +function ENT:ReceiveData() + if not self.IsInteractive then return end + local data = WireLib.GetInteractiveModel(self:GetModel()).widgets + for i = 1, #data do + WireLib.TriggerOutput(self, data[i].name, net.ReadFloat()) + end +end + +function ENT:UpdateOverlay() -- required by interactiveprop functions + +end + + +function ENT:Prompt( ply ) + if not self.IsInteractive then return end + if ply then + if CurTime() < self.NextPrompt then return end -- anti spam + self.NextPrompt = CurTime() + 0.1 + + if IsValid( self.User ) then + WireLib.AddNotify(ply,"That interactive prop is in use by another player!",NOTIFY_ERROR,5,6) + return + end + + self.User = ply + + net.Start( "wire_interactiveprop_show" ) + net.WriteEntity( self ) + net.Send( ply ) + else + self:Prompt( self:GetPlayer() ) -- prompt for owner + end +end + +function ENT:Use(ply) + if not IsValid( ply ) then return end + self:Prompt( ply ) +end + +function ENT:Unprompt() + if not self.IsInteractive then return end + self.User = nil +end + function ENT:Initialize() self:PhysicsInit(SOLID_VPHYSICS) @@ -12,7 +71,11 @@ function ENT:Initialize() self:SetSolid(SOLID_VPHYSICS) self.Inputs = Wire_CreateInputs(self, { "PixelX", "PixelY", "PixelG", "Clk", "FillColor", "ClearRow", "ClearCol" }) - self.Outputs = Wire_CreateOutputs(self, { "Memory" }) + if WireLib.IsValidInteractiveModel(self:GetModel()) then + self:InitInteractive() + else + self.Outputs = WireLib.CreateOutputs(self, { "Memory" }) + end self.Memory = {} diff --git a/lua/entities/gmod_wire_interactiveprop.lua b/lua/entities/gmod_wire_interactiveprop.lua index 2210df6f47..4c8b4a3653 100644 --- a/lua/entities/gmod_wire_interactiveprop.lua +++ b/lua/entities/gmod_wire_interactiveprop.lua @@ -194,6 +194,16 @@ InteractiveModels = { {type="DButton", x=135, y=60, name="Button11"}, {type="DButton", x=160, y=60, name="Button12"}, } + }, + ["models/props_lab/monitor01b.mdl"] = { + width = 40, + height = 128, + title = "plotter", + widgets={ + {type="DNumberScratch", x = 10, y = 32, name="Knob1"}, + {type="DNumberScratch", x = 10, y = 64, name="Knob2"}, + {type="DNumberScratch", x = 10, y = 96, name="Knob3"}, + } } } @@ -421,7 +431,8 @@ net.Receive("wire_interactiveprop_action",function(len,ply) local ent = net.ReadEntity() if not ent:IsValid() or (ent:GetClass() ~= "gmod_wire_interactiveprop" and ent:GetClass() ~= "gmod_wire_characterlcd" and - ent:GetClass() ~= "gmod_wire_consolescreen" + ent:GetClass() ~= "gmod_wire_consolescreen" and + ent:GetClass() ~= "gmod_wire_digitalscreen" ) or ply ~= ent.User then return end ent:ReceiveData() @@ -460,7 +471,8 @@ net.Receive("wire_interactiveprop_close",function(len,ply) local ent = net.ReadEntity() if not ent:IsValid() or (ent:GetClass() ~= "gmod_wire_interactiveprop" and ent:GetClass() ~= "gmod_wire_characterlcd" and - ent:GetClass() ~= "gmod_wire_consolescreen" + ent:GetClass() ~= "gmod_wire_consolescreen" and + ent:GetClass() ~= "gmod_wire_digitalscreen" ) or ply ~= ent.User then return end ent:Unprompt() end) From 44049cd932d4a7890cfea7d710587005b04889e9 Mon Sep 17 00:00:00 2001 From: wav3 Date: Wed, 27 Aug 2025 22:44:25 +0200 Subject: [PATCH 03/43] add oscilloscope --- lua/entities/gmod_wire_interactiveprop.lua | 12 +-- lua/entities/gmod_wire_oscilloscope.lua | 103 +++++++++++++++++++++ lua/wire/stools/characterlcd.lua | 34 +++---- 3 files changed, 122 insertions(+), 27 deletions(-) diff --git a/lua/entities/gmod_wire_interactiveprop.lua b/lua/entities/gmod_wire_interactiveprop.lua index 4c8b4a3653..395e5ae217 100644 --- a/lua/entities/gmod_wire_interactiveprop.lua +++ b/lua/entities/gmod_wire_interactiveprop.lua @@ -429,11 +429,7 @@ end util.AddNetworkString("wire_interactiveprop_action") net.Receive("wire_interactiveprop_action",function(len,ply) local ent = net.ReadEntity() - if not ent:IsValid() or (ent:GetClass() ~= "gmod_wire_interactiveprop" and - ent:GetClass() ~= "gmod_wire_characterlcd" and - ent:GetClass() ~= "gmod_wire_consolescreen" and - ent:GetClass() ~= "gmod_wire_digitalscreen" - ) or ply ~= ent.User then return end + if not ent:IsValid() or ply ~= ent.User then return end ent:ReceiveData() ent:UpdateOverlay() @@ -469,11 +465,7 @@ end util.AddNetworkString("wire_interactiveprop_close") net.Receive("wire_interactiveprop_close",function(len,ply) local ent = net.ReadEntity() - if not ent:IsValid() or (ent:GetClass() ~= "gmod_wire_interactiveprop" and - ent:GetClass() ~= "gmod_wire_characterlcd" and - ent:GetClass() ~= "gmod_wire_consolescreen" and - ent:GetClass() ~= "gmod_wire_digitalscreen" - ) or ply ~= ent.User then return end + if not ent:IsValid() or ply ~= ent.User then return end ent:Unprompt() end) diff --git a/lua/entities/gmod_wire_oscilloscope.lua b/lua/entities/gmod_wire_oscilloscope.lua index ee44bf7d82..ae41a7ac86 100644 --- a/lua/entities/gmod_wire_oscilloscope.lua +++ b/lua/entities/gmod_wire_oscilloscope.lua @@ -4,8 +4,47 @@ ENT.PrintName = "Wire Oscilloscope" ENT.WireDebugName = "Oscilloscope" if CLIENT then + + local panel + + function ENT:SendData() + net.Start("wire_interactiveprop_action") + + local data = WireLib.GetInteractiveModel(self:GetModel()).widgets + net.WriteEntity(self) + for i=1, #data do + net.WriteFloat(self.InteractiveData[i]) + end + net.SendToServer() + end + + function ENT:GetPanel() + if not self.IsInteractive then return end + local data = WireLib.GetInteractiveModel(self:GetModel()) + return WireLib.GetInteractiveWidgetBody(self, data) + end + + + function ENT:AddButton(id,button) + if not self.IsInteractive then return end + self.Buttons[id] = button + end + function ENT:Initialize() self.GPU = WireGPU(self) + + + self.InteractiveData = {} + self.LastButtons = {} + self.Buttons = {} + local interactive_model = WireLib.GetInteractiveModel(self:GetModel()) + self.IsInteractive = false + if interactive_model then + self.IsInteractive = true + for i=1, #WireLib.GetInteractiveModel(self:GetModel()).widgets do + self.InteractiveData[i] = 0 + end + end self.Nodes = {} end @@ -109,12 +148,76 @@ function ENT:SetNextNode(x, y) net.SendPVS( self:GetPos() ) end + +function ENT:InitInteractive() + local model = self:GetModel() + local outputs = {} + local interactivemodel = WireLib.GetInteractiveModel(self:GetModel()) + for i=1, #interactivemodel.widgets do + outputs[i+1] = interactivemodel.widgets[i].name + end + self.BlockInput = false + self.NextPrompt = 0 + self.Outputs=WireLib.CreateOutputs(self,outputs) + self.IsInteractive = true +end + + +function ENT:ReceiveData() + if not self.IsInteractive then return end + local data = WireLib.GetInteractiveModel(self:GetModel()).widgets + for i = 1, #data do + WireLib.TriggerOutput(self, data[i].name, net.ReadFloat()) + end +end + +function ENT:UpdateOverlay() -- required by interactiveprop functions + +end + + +function ENT:Prompt( ply ) + if not self.IsInteractive then return end + if ply then + if CurTime() < self.NextPrompt then return end -- anti spam + self.NextPrompt = CurTime() + 0.1 + + if IsValid( self.User ) then + WireLib.AddNotify(ply,"That interactive prop is in use by another player!",NOTIFY_ERROR,5,6) + return + end + + self.User = ply + + net.Start( "wire_interactiveprop_show" ) + net.WriteEntity( self ) + net.Send( ply ) + else + self:Prompt( self:GetPlayer() ) -- prompt for owner + end +end + +function ENT:Use(ply) + if not IsValid( ply ) then return end + self:Prompt( ply ) +end + +function ENT:Unprompt() + if not self.IsInteractive then return end + self.User = nil +end + + function ENT:Initialize() self:PhysicsInit( SOLID_VPHYSICS ) self:SetMoveType( MOVETYPE_VPHYSICS ) self:SetSolid( SOLID_VPHYSICS ) self.Inputs = WireLib.CreateInputs(self, { "X", "Y", "R", "G", "B", "Pause", "Length", "Update Frequency" }) + + if WireLib.IsValidInteractiveModel(self:GetModel()) then + self:InitInteractive() + end end function ENT:Think() diff --git a/lua/wire/stools/characterlcd.lua b/lua/wire/stools/characterlcd.lua index f5d4c2b08f..cbb9565e61 100644 --- a/lua/wire/stools/characterlcd.lua +++ b/lua/wire/stools/characterlcd.lua @@ -4,8 +4,8 @@ WireToolSetup.open( "characterlcd", "Character LCD", "gmod_wire_characterlcd", n if CLIENT then language.Add( "tool.wire_characterlcd.name", "Character LCD Tool (Wire)" ) language.Add( "tool.wire_characterlcd.desc", "Spawns a Character LCD, which can be used to display text" ) - language.Add( "tool.wire_characterlcd.bgcolor", "Background color:" ) - language.Add( "tool.wire_characterlcd.fgcolor", "Text color:" ) + language.Add( "tool.wire_characterlcd.bgcolor", "Background color:" ) + language.Add( "tool.wire_characterlcd.fgcolor", "Text color:" ) TOOL.Information = { { name = "left", text = "Create/Update " .. TOOL.Name } } WireToolSetup.setToolMenuIcon("icon16/application_xp_terminal.png") @@ -16,33 +16,33 @@ WireToolSetup.SetupMax( 20 ) if SERVER then function TOOL:GetConVars() return self:GetClientInfo("width"), self:GetClientInfo("height"), - math.Clamp(self:GetClientNumber("bgred"), 0, 255), + math.Clamp(self:GetClientNumber("bgred"), 0, 255), math.Clamp(self:GetClientNumber("bggreen"), 0, 255), math.Clamp(self:GetClientNumber("bgblue"), 0, 255), - math.Clamp(self:GetClientNumber("fgred"), 0, 255), + math.Clamp(self:GetClientNumber("fgred"), 0, 255), math.Clamp(self:GetClientNumber("fggreen"), 0, 255), math.Clamp(self:GetClientNumber("fgblue"), 0, 255) end end TOOL.ClientConVar = { - model = "models/props_lab/monitor01b.mdl", - width = 16, - height = 2, - createflat = 0, - bgred = 148, - bggreen = 178, - bgblue = 15, - fgred = 45, - fggreen = 91, - fgblue = 45, + model = "models/props_lab/monitor01b.mdl", + width = 16, + height = 2, + createflat = 0, + bgred = 148, + bggreen = 178, + bgblue = 15, + fgred = 45, + fggreen = 91, + fgblue = 45, } function TOOL.BuildCPanel(panel) - WireToolHelpers.MakePresetControl(panel, "wire_characterlcd") + WireToolHelpers.MakePresetControl(panel, "wire_characterlcd") WireDermaExts.ModelSelect(panel, "wire_characterlcd_model", list.Get( "WireScreenModels" ), 5) - panel:AddControl("Color", { + panel:AddControl("Color", { Label = "#tool.wire_characterlcd.bgcolor", Red = "wire_characterlcd_bgred", Green = "wire_characterlcd_bggreen", @@ -52,7 +52,7 @@ function TOOL.BuildCPanel(panel) ShowRGB = "1", Multiplier = "255" }) - panel:AddControl("Color", { + panel:AddControl("Color", { Label = "#tool.wire_characterlcd.fgcolor", Red = "wire_characterlcd_fgred", Green = "wire_characterlcd_fggreen", From ca83be4bdc04f1749f812b20b0172af7aea88f78 Mon Sep 17 00:00:00 2001 From: wav3 Date: Wed, 27 Aug 2025 23:40:10 +0200 Subject: [PATCH 04/43] Fix linting --- lua/entities/gmod_wire_characterlcd/cl_init.lua | 9 ++++----- lua/entities/gmod_wire_characterlcd/init.lua | 6 +++--- lua/entities/gmod_wire_consolescreen/cl_init.lua | 6 ++---- lua/entities/gmod_wire_consolescreen/init.lua | 2 +- lua/entities/gmod_wire_digitalscreen/cl_init.lua | 2 +- lua/entities/gmod_wire_digitalscreen/init.lua | 2 +- lua/entities/gmod_wire_oscilloscope.lua | 12 +++++------- 7 files changed, 17 insertions(+), 22 deletions(-) diff --git a/lua/entities/gmod_wire_characterlcd/cl_init.lua b/lua/entities/gmod_wire_characterlcd/cl_init.lua index e28f2ca533..16275b2216 100644 --- a/lua/entities/gmod_wire_characterlcd/cl_init.lua +++ b/lua/entities/gmod_wire_characterlcd/cl_init.lua @@ -19,7 +19,7 @@ function ENT:Initialize() self.InteractiveData[i] = 0 end end - + -- Screen control: -- [1003] - Background red -- [1004] - Background green @@ -87,17 +87,16 @@ function ENT:Initialize() GPULib.ClientCacheCallback(self,function(Address,Value) self:WriteCell(Address,Value) end) - - + + WireLib.netRegister(self) end -local panel function ENT:SendData() net.Start("wire_interactiveprop_action") - + local data = WireLib.GetInteractiveModel(self:GetModel()).widgets net.WriteEntity(self) for i=1, #data do diff --git a/lua/entities/gmod_wire_characterlcd/init.lua b/lua/entities/gmod_wire_characterlcd/init.lua index e1f929a335..95d119c004 100644 --- a/lua/entities/gmod_wire_characterlcd/init.lua +++ b/lua/entities/gmod_wire_characterlcd/init.lua @@ -1,4 +1,4 @@ -AddCSLuaFile("cl_init.lua") +AddCSLuaFile("cl_init.lua") AddCSLuaFile("shared.lua") include("shared.lua") @@ -7,7 +7,7 @@ ENT.WireDebugName = "CharacterLcdScreen" function ENT:InitInteractive() local model = self:GetModel() local outputs = {"Memory"} - local interactivemodel = WireLib.GetInteractiveModel(self:GetModel()) + local interactivemodel = WireLib.GetInteractiveModel(model) for i=1, #interactivemodel.widgets do outputs[i+1] = interactivemodel.widgets[i].name end @@ -23,7 +23,7 @@ function ENT:Initialize() self:SetSolid(SOLID_VPHYSICS) self.Inputs = WireLib.CreateInputs(self, { "CharAddress", "Char (ASCII/Unicode)", "Contrast", "Clk", "Reset" }) - + self.InteractiveData = {} self.IsInteractive = false if WireLib.IsValidInteractiveModel(self:GetModel()) then diff --git a/lua/entities/gmod_wire_consolescreen/cl_init.lua b/lua/entities/gmod_wire_consolescreen/cl_init.lua index 5ccb5a1477..780605c986 100644 --- a/lua/entities/gmod_wire_consolescreen/cl_init.lua +++ b/lua/entities/gmod_wire_consolescreen/cl_init.lua @@ -1,10 +1,8 @@ include("shared.lua") -local panel - function ENT:SendData() net.Start("wire_interactiveprop_action") - + local data = WireLib.GetInteractiveModel(self:GetModel()).widgets net.WriteEntity(self) for i=1, #data do @@ -31,7 +29,7 @@ function ENT:Initialize() for i = 0, 2047 do self.Memory1[i] = 0 end - + self.InteractiveData = {} self.LastButtons = {} self.Buttons = {} diff --git a/lua/entities/gmod_wire_consolescreen/init.lua b/lua/entities/gmod_wire_consolescreen/init.lua index ce0f0d1502..d0086b8748 100644 --- a/lua/entities/gmod_wire_consolescreen/init.lua +++ b/lua/entities/gmod_wire_consolescreen/init.lua @@ -7,7 +7,7 @@ ENT.WireDebugName = "ConsoleScreen" function ENT:InitInteractive() local model = self:GetModel() local outputs = {"Memory"} - local interactivemodel = WireLib.GetInteractiveModel(self:GetModel()) + local interactivemodel = WireLib.GetInteractiveModel(model) for i=1, #interactivemodel.widgets do outputs[i+1] = interactivemodel.widgets[i].name end diff --git a/lua/entities/gmod_wire_digitalscreen/cl_init.lua b/lua/entities/gmod_wire_digitalscreen/cl_init.lua index b14c1bd788..cb76842e13 100644 --- a/lua/entities/gmod_wire_digitalscreen/cl_init.lua +++ b/lua/entities/gmod_wire_digitalscreen/cl_init.lua @@ -4,7 +4,7 @@ local panel function ENT:SendData() net.Start("wire_interactiveprop_action") - + local data = WireLib.GetInteractiveModel(self:GetModel()).widgets net.WriteEntity(self) for i=1, #data do diff --git a/lua/entities/gmod_wire_digitalscreen/init.lua b/lua/entities/gmod_wire_digitalscreen/init.lua index f882e00956..5858f21d3e 100644 --- a/lua/entities/gmod_wire_digitalscreen/init.lua +++ b/lua/entities/gmod_wire_digitalscreen/init.lua @@ -1,6 +1,6 @@ AddCSLuaFile( "cl_init.lua" ) AddCSLuaFile( "shared.lua" ) -include('shared.lua') +include("shared.lua") DEFINE_BASECLASS( "base_wire_entity" ) ENT.WireDebugName = "DigitalScreen" diff --git a/lua/entities/gmod_wire_oscilloscope.lua b/lua/entities/gmod_wire_oscilloscope.lua index ae41a7ac86..21ffcbeca8 100644 --- a/lua/entities/gmod_wire_oscilloscope.lua +++ b/lua/entities/gmod_wire_oscilloscope.lua @@ -4,12 +4,10 @@ ENT.PrintName = "Wire Oscilloscope" ENT.WireDebugName = "Oscilloscope" if CLIENT then - - local panel function ENT:SendData() net.Start("wire_interactiveprop_action") - + local data = WireLib.GetInteractiveModel(self:GetModel()).widgets net.WriteEntity(self) for i=1, #data do @@ -32,8 +30,8 @@ if CLIENT then function ENT:Initialize() self.GPU = WireGPU(self) - - + + self.InteractiveData = {} self.LastButtons = {} self.Buttons = {} @@ -152,7 +150,7 @@ end function ENT:InitInteractive() local model = self:GetModel() local outputs = {} - local interactivemodel = WireLib.GetInteractiveModel(self:GetModel()) + local interactivemodel = WireLib.GetInteractiveModel(model) for i=1, #interactivemodel.widgets do outputs[i+1] = interactivemodel.widgets[i].name end @@ -214,7 +212,7 @@ function ENT:Initialize() self:SetSolid( SOLID_VPHYSICS ) self.Inputs = WireLib.CreateInputs(self, { "X", "Y", "R", "G", "B", "Pause", "Length", "Update Frequency" }) - + if WireLib.IsValidInteractiveModel(self:GetModel()) then self:InitInteractive() end From a0471593e6c0a190981a789763ad1a1e189b8e9f Mon Sep 17 00:00:00 2001 From: wav3 Date: Thu, 28 Aug 2025 02:54:21 +0200 Subject: [PATCH 05/43] linter should be happy now --- lua/entities/gmod_wire_consolescreen/init.lua | 2 +- .../gmod_wire_digitalscreen/cl_init.lua | 22 +++++++++---------- lua/entities/gmod_wire_digitalscreen/init.lua | 4 ++-- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/lua/entities/gmod_wire_consolescreen/init.lua b/lua/entities/gmod_wire_consolescreen/init.lua index d0086b8748..463cf74c21 100644 --- a/lua/entities/gmod_wire_consolescreen/init.lua +++ b/lua/entities/gmod_wire_consolescreen/init.lua @@ -1,6 +1,6 @@ AddCSLuaFile("cl_init.lua") AddCSLuaFile("shared.lua") -include('shared.lua') +include("shared.lua") ENT.WireDebugName = "ConsoleScreen" diff --git a/lua/entities/gmod_wire_digitalscreen/cl_init.lua b/lua/entities/gmod_wire_digitalscreen/cl_init.lua index cb76842e13..788a343127 100644 --- a/lua/entities/gmod_wire_digitalscreen/cl_init.lua +++ b/lua/entities/gmod_wire_digitalscreen/cl_init.lua @@ -1,6 +1,6 @@ -include('shared.lua') +include("shared.lua") + -local panel function ENT:SendData() net.Start("wire_interactiveprop_action") @@ -58,15 +58,15 @@ function ENT:Initialize() self.RefreshRows[i] = i-1 end - //0..786431 - RGB data + --0..786431 - RGB data - //1048569 - Color mode (0: RGBXXX; 1: R G B) - //1048570 - Clear row - //1048571 - Clear column - //1048572 - Screen Height - //1048573 - Screen Width - //1048574 - Hardware Clear Screen - //1048575 - CLK + --1048569 - Color mode (0: RGBXXX; 1: R G B) + --1048570 - Clear row + --1048571 - Clear column + --1048572 - Screen Height + --1048573 - Screen Width + --1048574 - Hardware Clear Screen + --1048575 - CLK self.GPU = WireGPU(self) @@ -264,8 +264,6 @@ transformcolor[4] = function(c) -- XXX return c, c, c end -local floor = math.floor - function ENT:RedrawPixel(a) if a >= self.ScreenWidth*self.ScreenHeight then return end diff --git a/lua/entities/gmod_wire_digitalscreen/init.lua b/lua/entities/gmod_wire_digitalscreen/init.lua index 5858f21d3e..f76e0a1cfa 100644 --- a/lua/entities/gmod_wire_digitalscreen/init.lua +++ b/lua/entities/gmod_wire_digitalscreen/init.lua @@ -9,7 +9,7 @@ ENT.WireDebugName = "DigitalScreen" function ENT:InitInteractive() local model = self:GetModel() local outputs = {"Memory"} - local interactivemodel = WireLib.GetInteractiveModel(self:GetModel()) + local interactivemodel = WireLib.GetInteractiveModel(model) for i=1, #interactivemodel.widgets do outputs[i+1] = interactivemodel.widgets[i].name end @@ -378,7 +378,7 @@ function ENT:WriteCell(Address, value) -- reset memory self.Memory = mem - elseif Address == 1048575 then -- CLK + -- elseif Address == 1048575 then -- CLK -- not needed atm end end From 2b4f898cb6ff200fb72941ee57e4f40391b4c280 Mon Sep 17 00:00:00 2001 From: wav3 Date: Fri, 29 Aug 2025 18:19:28 +0200 Subject: [PATCH 06/43] This should be better --- lua/entities/gmod_wire_interactiveprop.lua | 47 +++++++++++----------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/lua/entities/gmod_wire_interactiveprop.lua b/lua/entities/gmod_wire_interactiveprop.lua index 395e5ae217..8990df01de 100644 --- a/lua/entities/gmod_wire_interactiveprop.lua +++ b/lua/entities/gmod_wire_interactiveprop.lua @@ -219,24 +219,23 @@ end function WireLib.GetInteractiveWidgetBody( ent, data ) local body = vgui.Create("DFrame") - body:SetTitle(data.title) - body:SetSize(data.width, data.height) - body:SetVisible(true) - body.Paint = function( self, w, h ) -- 'function Frame:Paint( w, h )' works too - -- surface.SetDrawColor(255,255,255) - -- surface.DrawOutlinedRect(0, 0, w, h) - -- surface.SetDrawColor(0,0,0) - -- surface.DrawOutlinedRect(1, 1, w-2, h-2) - draw.RoundedBox( 4, 0, 0, w, h, Color( 255, 255, 255 ) ) - draw.RoundedBox( 4, 1, 1, w-2, h-2, Color( 64, 64, 64 ) ) - end - body:SetDraggable(false) - body:Center() - body:ShowCloseButton(true) - body:MakePopup() - for id, widget in ipairs( data.widgets ) do - WidgetBuilders[widget.type](ent, widget, body, id) - end + + body:SetTitle(data.title) + body:SetSize(data.width, data.height) + body:SetVisible(true) + body:SetDraggable(false) + body:ShowCloseButton(true) + body:MakePopup() + body:Center() + + function body:Paint(w, h) + draw.RoundedBox(4, 0, 0, w, h, color_white) + draw.RoundedBox(4, 1, 1, w - 2, h - 2, Color(64, 64, 64)) + end + + for id, widget in ipairs( data.widgets ) do + WidgetBuilders[widget.type](ent, widget, body, id) + end return body end @@ -250,7 +249,7 @@ WidgetBuilders = { local checkbox = vgui.Create("DCheckBox", body) checkbox:SetPos(data.x, data.y) checkbox:SetValue(self.InteractiveData[index]) - checkbox.OnChange = function(box,value) + function checkbox.OnChange(box, value) surface.PlaySound("buttons/lightswitch2.wav") self.InteractiveData[index] = value and 1 or 0 self:SendData() @@ -265,13 +264,13 @@ WidgetBuilders = { numberscratch:SetDecimals(4) numberscratch:SetPos(data.x, data.y) numberscratch:SetValue(self.InteractiveData[index]) - numberscratch.OnValueChanged = function(scratch,value) + function numberscratch.OnValueChanged(scratch, value) self.InteractiveData[index] = value self:SendData() end numberscratch:SetImageVisible( false ) numberscratch:SetSize( 17, 17 ) - numberscratch.Paint = function( self, w, h ) + function numberscratch:Paint( w, h ) draw.RoundedBox( 8.5, 0, 0, w, h, numberscratch.color ) local value = self:GetFloatValue() surface.SetDrawColor(255, 255, 255) @@ -289,11 +288,11 @@ WidgetBuilders = { button:SetPos(data.x, data.y) button:SetText(data.text or "") button:SetSize(data.width or 20, data.height or 20) - button.OnDepressed = function(scratch) + function button.OnDepressed(btn) self.InteractiveData[index] = 1 self:SendData() end - button.OnReleased = function(scratch) + function button.OnReleased(btn) self.InteractiveData[index] = 0 self:SendData() end @@ -342,7 +341,7 @@ if CLIENT then local self = net.ReadEntity() if not IsValid(self) then return end panel = self:GetPanel() - panel.OnClose = function(panel) + function panel.OnClose(panel) net.Start("wire_interactiveprop_close") self.Buttons = {} self.LastButtons = {} From fa18df478620410d59cb34cbbf570c70e35099e1 Mon Sep 17 00:00:00 2001 From: wav3 Date: Fri, 29 Aug 2025 19:19:10 +0200 Subject: [PATCH 07/43] get rid of trailing ws --- lua/entities/gmod_wire_interactiveprop.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/entities/gmod_wire_interactiveprop.lua b/lua/entities/gmod_wire_interactiveprop.lua index 8990df01de..f41b4000e5 100644 --- a/lua/entities/gmod_wire_interactiveprop.lua +++ b/lua/entities/gmod_wire_interactiveprop.lua @@ -219,7 +219,7 @@ end function WireLib.GetInteractiveWidgetBody( ent, data ) local body = vgui.Create("DFrame") - + body:SetTitle(data.title) body:SetSize(data.width, data.height) body:SetVisible(true) @@ -227,7 +227,7 @@ function WireLib.GetInteractiveWidgetBody( ent, data ) body:ShowCloseButton(true) body:MakePopup() body:Center() - + function body:Paint(w, h) draw.RoundedBox(4, 0, 0, w, h, color_white) draw.RoundedBox(4, 1, 1, w - 2, h - 2, Color(64, 64, 64)) From fdd6adf7daee80ec00820993421c45c6ec9c9374 Mon Sep 17 00:00:00 2001 From: wav3 Date: Fri, 29 Aug 2025 19:19:43 +0200 Subject: [PATCH 08/43] They are visible by default --- lua/entities/gmod_wire_interactiveprop.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/lua/entities/gmod_wire_interactiveprop.lua b/lua/entities/gmod_wire_interactiveprop.lua index f41b4000e5..e3acce6dd4 100644 --- a/lua/entities/gmod_wire_interactiveprop.lua +++ b/lua/entities/gmod_wire_interactiveprop.lua @@ -222,9 +222,7 @@ function WireLib.GetInteractiveWidgetBody( ent, data ) body:SetTitle(data.title) body:SetSize(data.width, data.height) - body:SetVisible(true) body:SetDraggable(false) - body:ShowCloseButton(true) body:MakePopup() body:Center() From eb55f3d005030a71a8b166d923a34c2674aaa8fa Mon Sep 17 00:00:00 2001 From: wav3 Date: Mon, 1 Sep 2025 01:03:10 +0200 Subject: [PATCH 09/43] Optional interactiveness --- lua/entities/gmod_wire_characterlcd/init.lua | 21 ++++++++++++++++--- lua/entities/gmod_wire_consolescreen/init.lua | 18 ++++++++++++++-- lua/entities/gmod_wire_digitalscreen/init.lua | 17 ++++++++++++--- lua/entities/gmod_wire_oscilloscope.lua | 18 +++++++++++++++- lua/wire/stools/characterlcd.lua | 6 +++++- lua/wire/stools/consolescreen.lua | 10 ++++++++- lua/wire/stools/digitalscreen.lua | 5 ++++- lua/wire/stools/oscilloscope.lua | 10 ++++++++- 8 files changed, 92 insertions(+), 13 deletions(-) diff --git a/lua/entities/gmod_wire_characterlcd/init.lua b/lua/entities/gmod_wire_characterlcd/init.lua index 95d119c004..7622d96bb9 100644 --- a/lua/entities/gmod_wire_characterlcd/init.lua +++ b/lua/entities/gmod_wire_characterlcd/init.lua @@ -15,8 +15,11 @@ function ENT:InitInteractive() self.NextPrompt = 0 self.Outputs=WireLib.CreateOutputs(self,outputs) self.IsInteractive = true + self:UpdateOverlay() end + + function ENT:Initialize() self:PhysicsInit(SOLID_VPHYSICS) self:SetMoveType(MOVETYPE_VPHYSICS) @@ -61,7 +64,7 @@ function ENT:Initialize() self.Cache = GPUCacheManager(self,true) end -function ENT:Setup(ScreenWidth, ScreenHeight, bgred,bggreen,bgblue,fgred,fggreen,fgblue) +function ENT:Setup(ScreenWidth, ScreenHeight, bgred,bggreen,bgblue,fgred,fggreen,fgblue,IsInteractive) self:WriteCell(1010, tonumber(ScreenHeight) or 2) self:WriteCell(1009, tonumber(ScreenWidth) or 16) self:WriteCell(1008, tonumber(fgblue) or 45) @@ -71,6 +74,7 @@ function ENT:Setup(ScreenWidth, ScreenHeight, bgred,bggreen,bgblue,fgred,fggreen self:WriteCell(1004, tonumber(bggreen) or 178) self:WriteCell(1003, tonumber(bgred) or 148) self:WriteCell(1023,1) + self.IsInteractive = WireLib.IsValidInteractiveModel(self:GetModel()) and (IsInteractive == 1) end function ENT:SendPixel() if (self.Memory[1023] ~= 0) and (self.CharAddress >= 0) and (self.CharAddress < self.ScreenWidth*self.ScreenHeight) then @@ -209,11 +213,22 @@ function ENT:ReceiveData() end end -function ENT:UpdateOverlay() -- required by interactiveprop functions +function ENT:UpdateOverlay() + if not self.IsInteractive then + return + end + + txt = "" + if IsValid(self.User) then + txt = "In use by: " .. self.User:Nick() + end + + self:SetOverlayText(txt) end + function ENT:Prompt( ply ) if not self.IsInteractive then return end if ply then @@ -245,4 +260,4 @@ function ENT:Unprompt() self.User = nil end -duplicator.RegisterEntityClass("gmod_wire_characterlcd", WireLib.MakeWireEnt, "Data", "ScreenWidth", "ScreenHeight") +duplicator.RegisterEntityClass("gmod_wire_characterlcd", WireLib.MakeWireEnt, "Data", "ScreenWidth", "ScreenHeight", "IsInteractive") diff --git a/lua/entities/gmod_wire_consolescreen/init.lua b/lua/entities/gmod_wire_consolescreen/init.lua index 463cf74c21..ae0672e645 100644 --- a/lua/entities/gmod_wire_consolescreen/init.lua +++ b/lua/entities/gmod_wire_consolescreen/init.lua @@ -15,6 +15,7 @@ function ENT:InitInteractive() self.NextPrompt = 0 self.Outputs=WireLib.CreateOutputs(self,outputs) self.IsInteractive = true + self:UpdateOverlay() end @@ -26,8 +27,17 @@ function ENT:ReceiveData() end end -function ENT:UpdateOverlay() -- required by interactiveprop functions +function ENT:UpdateOverlay() + if not self.IsInteractive then + return + end + + txt = "" + if IsValid(self.User) then + txt = "In use by: " .. self.User:Nick() + end + self:SetOverlayText(txt) end @@ -52,6 +62,10 @@ function ENT:Prompt( ply ) end end +function ENT:Setup(IsInteractive) + self.IsInteractive = WireLib.IsValidInteractiveModel(self:GetModel()) and (IsInteractive == 1) +end + function ENT:Use(ply) if not IsValid( ply ) then return end self:Prompt( ply ) @@ -279,4 +293,4 @@ function ENT:ClientWriteCell(Address, value) end end -duplicator.RegisterEntityClass("gmod_wire_consolescreen", WireLib.MakeWireEnt, "Data") +duplicator.RegisterEntityClass("gmod_wire_consolescreen", WireLib.MakeWireEnt, "Data", "IsInteractive") diff --git a/lua/entities/gmod_wire_digitalscreen/init.lua b/lua/entities/gmod_wire_digitalscreen/init.lua index f76e0a1cfa..23d49f53d2 100644 --- a/lua/entities/gmod_wire_digitalscreen/init.lua +++ b/lua/entities/gmod_wire_digitalscreen/init.lua @@ -17,6 +17,7 @@ function ENT:InitInteractive() self.NextPrompt = 0 self.Outputs=WireLib.CreateOutputs(self,outputs) self.IsInteractive = true + self:UpdateOverlay() end @@ -28,8 +29,17 @@ function ENT:ReceiveData() end end -function ENT:UpdateOverlay() -- required by interactiveprop functions +function ENT:UpdateOverlay() + if not self.IsInteractive then + return + end + + txt = "" + if IsValid(self.User) then + txt = "In use by: " .. self.User:Nick() + end + self:SetOverlayText(txt) end @@ -97,9 +107,10 @@ function ENT:Initialize() self.ChangedStep = 1 end -function ENT:Setup(ScreenWidth, ScreenHeight) +function ENT:Setup(ScreenWidth, ScreenHeight, IsInteractive) self:WriteCell(1048572, ScreenHeight or 32) self:WriteCell(1048573, ScreenWidth or 32) + self.IsInteractive = WireLib.IsValidInteractiveModel(self:GetModel()) and (IsInteractive == 1) end function ENT:SendPixel() @@ -418,4 +429,4 @@ function ENT:TriggerInput(iname, value) end end -duplicator.RegisterEntityClass("gmod_wire_digitalscreen", WireLib.MakeWireEnt, "Data", "ScreenWidth", "ScreenHeight") +duplicator.RegisterEntityClass("gmod_wire_digitalscreen", WireLib.MakeWireEnt, "Data", "ScreenWidth", "ScreenHeight", "IsInteractive") diff --git a/lua/entities/gmod_wire_oscilloscope.lua b/lua/entities/gmod_wire_oscilloscope.lua index 21ffcbeca8..77731ff233 100644 --- a/lua/entities/gmod_wire_oscilloscope.lua +++ b/lua/entities/gmod_wire_oscilloscope.lua @@ -146,6 +146,9 @@ function ENT:SetNextNode(x, y) net.SendPVS( self:GetPos() ) end +function ENT:Setup(IsInteractive) + self.IsInteractive = WireLib.IsValidInteractiveModel(self:GetModel()) and (IsInteractive == 1) +end function ENT:InitInteractive() local model = self:GetModel() @@ -158,6 +161,7 @@ function ENT:InitInteractive() self.NextPrompt = 0 self.Outputs=WireLib.CreateOutputs(self,outputs) self.IsInteractive = true + self:UpdateOverlay() end @@ -169,11 +173,22 @@ function ENT:ReceiveData() end end -function ENT:UpdateOverlay() -- required by interactiveprop functions +function ENT:UpdateOverlay() + if not self.IsInteractive then + return + end + + txt = "" + if IsValid(self.User) then + txt = "In use by: " .. self.User:Nick() + end + + self:SetOverlayText(txt) end + function ENT:Prompt( ply ) if not self.IsInteractive then return end if ply then @@ -197,6 +212,7 @@ end function ENT:Use(ply) if not IsValid( ply ) then return end + if not self.IsInteractive then return end self:Prompt( ply ) end diff --git a/lua/wire/stools/characterlcd.lua b/lua/wire/stools/characterlcd.lua index cbb9565e61..05b6ca756c 100644 --- a/lua/wire/stools/characterlcd.lua +++ b/lua/wire/stools/characterlcd.lua @@ -6,6 +6,7 @@ if CLIENT then language.Add( "tool.wire_characterlcd.desc", "Spawns a Character LCD, which can be used to display text" ) language.Add( "tool.wire_characterlcd.bgcolor", "Background color:" ) language.Add( "tool.wire_characterlcd.fgcolor", "Text color:" ) + language.Add( "tool.wire_characterlcd.interactive", "Interactive (if available):" ) TOOL.Information = { { name = "left", text = "Create/Update " .. TOOL.Name } } WireToolSetup.setToolMenuIcon("icon16/application_xp_terminal.png") @@ -21,7 +22,8 @@ if SERVER then math.Clamp(self:GetClientNumber("bgblue"), 0, 255), math.Clamp(self:GetClientNumber("fgred"), 0, 255), math.Clamp(self:GetClientNumber("fggreen"), 0, 255), - math.Clamp(self:GetClientNumber("fgblue"), 0, 255) + math.Clamp(self:GetClientNumber("fgblue"), 0, 255), + self:GetClientNumber("interactive") end end @@ -36,6 +38,7 @@ TOOL.ClientConVar = { fgred = 45, fggreen = 91, fgblue = 45, + interactive = 1, } @@ -64,6 +67,7 @@ function TOOL.BuildCPanel(panel) }) panel:NumSlider("Width", "wire_characterlcd_width", 1, 56, 0) panel:NumSlider("Height", "wire_characterlcd_height", 1, 16, 0) + panel:CheckBox("#tool.wire_characterlcd.interactive", "wire_characterlcd_interactive") panel:CheckBox("#Create Flat to Surface", "wire_characterlcd_createflat") end diff --git a/lua/wire/stools/consolescreen.lua b/lua/wire/stools/consolescreen.lua index 836b51e427..aa1d4bbb95 100644 --- a/lua/wire/stools/consolescreen.lua +++ b/lua/wire/stools/consolescreen.lua @@ -4,6 +4,7 @@ WireToolSetup.open( "consolescreen", "Console Screen", "gmod_wire_consolescreen" if CLIENT then language.Add( "tool.wire_consolescreen.name", "Console Screen Tool (Wire)" ) language.Add( "tool.wire_consolescreen.desc", "Spawns a console screen" ) + language.Add( "tool.wire_consolescreen.interactive", "Interactive (if available):" ) TOOL.Information = { { name = "left", text = "Create " .. TOOL.Name } } WireToolSetup.setToolMenuIcon( "icon16/application_xp_terminal.png" ) @@ -11,14 +12,21 @@ end WireToolSetup.BaseLang() WireToolSetup.SetupMax( 20 ) -TOOL.NoLeftOnClass = true -- no update ent function needed +if SERVER then + function TOOL:GetConVars() + return self:GetClientNumber("interactive") + end +end + TOOL.ClientConVar = { model = "models/props_lab/monitor01b.mdl", createflat = 0, + interactive = 1, } function TOOL.BuildCPanel(panel) WireDermaExts.ModelSelect(panel, "wire_consolescreen_model", list.Get( "WireScreenModels" ), 5) + panel:CheckBox("#tool.wire_consolescreen.interactive", "wire_consolescreen_interactive") panel:CheckBox("#Create Flat to Surface", "wire_consolescreen_createflat") panel:Help("CharParam is LBBBFFF format: background and foreground colour of the character (one digit each for RGB), if L is nonzero the char flashes") end diff --git a/lua/wire/stools/digitalscreen.lua b/lua/wire/stools/digitalscreen.lua index 0a3b03ed27..5f984d5ecf 100644 --- a/lua/wire/stools/digitalscreen.lua +++ b/lua/wire/stools/digitalscreen.lua @@ -4,6 +4,7 @@ WireToolSetup.open( "digitalscreen", "Digital Screen", "gmod_wire_digitalscreen" if CLIENT then language.Add( "tool.wire_digitalscreen.name", "Digital Screen Tool (Wire)" ) language.Add( "tool.wire_digitalscreen.desc", "Spawns a digital screen, which can be used to draw pixel by pixel." ) + language.Add( "tool.wire_digitalscreen.interactive", "Interactive (if available):" ) TOOL.Information = { { name = "left", text = "Create/Update " .. TOOL.Name } } WireToolSetup.setToolMenuIcon("icon16/application_xp_terminal.png") @@ -13,7 +14,7 @@ WireToolSetup.SetupMax( 20 ) if SERVER then function TOOL:GetConVars() - return self:GetClientInfo("width"), self:GetClientInfo("height") + return self:GetClientInfo("width"), self:GetClientInfo("height"), self:GetClientNumber("interactive") end end @@ -22,11 +23,13 @@ TOOL.ClientConVar = { width = 32, height = 32, createflat = 0, + interactive = 1, } function TOOL.BuildCPanel(panel) WireDermaExts.ModelSelect(panel, "wire_digitalscreen_model", list.Get( "WireScreenModels" ), 5) panel:NumSlider("Width", "wire_digitalscreen_width", 1, 512, 0) panel:NumSlider("Height", "wire_digitalscreen_height", 1, 512, 0) + panel:CheckBox("#tool.wire_digitalscreen.interactive", "wire_digitalscreen_interactive") panel:CheckBox("#Create Flat to Surface", "wire_digitalscreen_createflat") end diff --git a/lua/wire/stools/oscilloscope.lua b/lua/wire/stools/oscilloscope.lua index 531af22dbe..ff97632400 100644 --- a/lua/wire/stools/oscilloscope.lua +++ b/lua/wire/stools/oscilloscope.lua @@ -4,6 +4,7 @@ WireToolSetup.open( "oscilloscope", "Oscilloscope", "gmod_wire_oscilloscope", ni if CLIENT then language.Add( "tool.wire_oscilloscope.name", "Oscilloscope Tool (Wire)" ) language.Add( "tool.wire_oscilloscope.desc", "Spawns an oscilloscope that displays line graphs." ) + language.Add( "tool.wire_oscilloscope.interactive", "Interactive (if available):" ) TOOL.Information = { { name = "left", text = "Create/Update " .. TOOL.Name } } WireToolSetup.setToolMenuIcon("icon16/chart_line.png") @@ -11,13 +12,20 @@ end WireToolSetup.BaseLang() WireToolSetup.SetupMax( 20 ) -TOOL.NoLeftOnClass = true -- no update ent function needed +if SERVER then + function TOOL:GetConVars() + return self:GetClientNumber("interactive") + end +end + TOOL.ClientConVar = { model = "models/props_lab/monitor01b.mdl", createflat = 0, + interactive = 1, } function TOOL.BuildCPanel(panel) WireDermaExts.ModelSelect(panel, "wire_oscilloscope_model", list.Get( "WireScreenModels" ), 5) + panel:CheckBox("#tool.wire_oscilloscope.interactive", "wire_oscilloscope_interactive") panel:CheckBox("#Create Flat to Surface", "wire_oscilloscope_createflat") end From 599365b636ccd48f2efab71557eef5d28bfcefac Mon Sep 17 00:00:00 2001 From: wav3 Date: Wed, 3 Sep 2025 08:52:02 +0200 Subject: [PATCH 10/43] Fix lint --- lua/entities/gmod_wire_characterlcd/init.lua | 2 +- lua/entities/gmod_wire_consolescreen/init.lua | 2 +- lua/entities/gmod_wire_digitalscreen/init.lua | 2 +- lua/entities/gmod_wire_oscilloscope.lua | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lua/entities/gmod_wire_characterlcd/init.lua b/lua/entities/gmod_wire_characterlcd/init.lua index 7622d96bb9..1acba99350 100644 --- a/lua/entities/gmod_wire_characterlcd/init.lua +++ b/lua/entities/gmod_wire_characterlcd/init.lua @@ -218,7 +218,7 @@ function ENT:UpdateOverlay() if not self.IsInteractive then return end - + txt = "" if IsValid(self.User) then txt = "In use by: " .. self.User:Nick() diff --git a/lua/entities/gmod_wire_consolescreen/init.lua b/lua/entities/gmod_wire_consolescreen/init.lua index ae0672e645..252002559a 100644 --- a/lua/entities/gmod_wire_consolescreen/init.lua +++ b/lua/entities/gmod_wire_consolescreen/init.lua @@ -31,7 +31,7 @@ function ENT:UpdateOverlay() if not self.IsInteractive then return end - + txt = "" if IsValid(self.User) then txt = "In use by: " .. self.User:Nick() diff --git a/lua/entities/gmod_wire_digitalscreen/init.lua b/lua/entities/gmod_wire_digitalscreen/init.lua index 23d49f53d2..3be26fc1ee 100644 --- a/lua/entities/gmod_wire_digitalscreen/init.lua +++ b/lua/entities/gmod_wire_digitalscreen/init.lua @@ -33,7 +33,7 @@ function ENT:UpdateOverlay() if not self.IsInteractive then return end - + txt = "" if IsValid(self.User) then txt = "In use by: " .. self.User:Nick() diff --git a/lua/entities/gmod_wire_oscilloscope.lua b/lua/entities/gmod_wire_oscilloscope.lua index 77731ff233..c7320560b3 100644 --- a/lua/entities/gmod_wire_oscilloscope.lua +++ b/lua/entities/gmod_wire_oscilloscope.lua @@ -178,7 +178,7 @@ function ENT:UpdateOverlay() if not self.IsInteractive then return end - + txt = "" if IsValid(self.User) then txt = "In use by: " .. self.User:Nick() From 72c52c7aa6b194aac0b203b78e9e1eda013ea928 Mon Sep 17 00:00:00 2001 From: wav3 Date: Sat, 6 Sep 2025 16:14:31 +0200 Subject: [PATCH 11/43] Multisegment lcd --- lua/entities/gmod_wire_addressbus.lua | 2 +- .../gmod_wire_multisegmentlcd/cl_init.lua | 133 ++++++ .../gmod_wire_multisegmentlcd/init.lua | 146 +++++++ .../gmod_wire_multisegmentlcd/shared.lua | 16 + lua/wire/stools/multisegmentlcd.lua | 381 ++++++++++++++++++ 5 files changed, 677 insertions(+), 1 deletion(-) create mode 100644 lua/entities/gmod_wire_multisegmentlcd/cl_init.lua create mode 100644 lua/entities/gmod_wire_multisegmentlcd/init.lua create mode 100644 lua/entities/gmod_wire_multisegmentlcd/shared.lua create mode 100644 lua/wire/stools/multisegmentlcd.lua diff --git a/lua/entities/gmod_wire_addressbus.lua b/lua/entities/gmod_wire_addressbus.lua index efadda46f5..9afb40b31d 100644 --- a/lua/entities/gmod_wire_addressbus.lua +++ b/lua/entities/gmod_wire_addressbus.lua @@ -95,7 +95,7 @@ end function ENT:TriggerInput(iname, value) for i = 1,4 do if iname == "Memory"..i then - self.Memory[i] = self.Inputs["Memory"..i].Src + self.Memory[i] = self.Inputs["Memory"..i].Src and self.Inputs["Memory"..i].Src:GetTable() or nil end end end diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua new file mode 100644 index 0000000000..f8f94bb958 --- /dev/null +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -0,0 +1,133 @@ +include("shared.lua") + + +function ENT:Initialize() + self.Memory = {} + + self.InteractiveData = {} + self.LastButtons = {} + self.Buttons = {} + local interactive_model = WireLib.GetInteractiveModel(self:GetModel()) + self.IsInteractive = false + if interactive_model then + self.IsInteractive = true + for i=1, #WireLib.GetInteractiveModel(self:GetModel()).widgets do + self.InteractiveData[i] = 0 + end + end + + self.GPU = WireGPU(self) + + GPULib.ClientCacheCallback(self,function(Address,Value) + self:WriteCell(Address,Value) + end) + + WireLib.netRegister(self) +end + + +function ENT:SendData() + net.Start("wire_interactiveprop_action") + + local data = WireLib.GetInteractiveModel(self:GetModel()).widgets + net.WriteEntity(self) + for i=1, #data do + net.WriteFloat(self.InteractiveData[i]) + end + net.SendToServer() +end + +function ENT:GetPanel() + if not self.IsInteractive then return end + local data = WireLib.GetInteractiveModel(self:GetModel()) + return WireLib.GetInteractiveWidgetBody(self, data) +end + + +function ENT:AddButton(id,button) + if not self.IsInteractive then return end + self.Buttons[id] = button +end + +function ENT:OnRemove() + self.GPU:Finalize() +end + +function ENT:ReadCell(Address) + return self.Memory[math.floor(Address)] +end + +function ENT:WriteCell(Address,value) + self.Memory[math.floor(Address)] = value +end + +function ENT:DrawSegment(segment) + if bit.band(self.Memory[bit.rshift(self.BitIndex,3)] or 0,bit.lshift(1,bit.band(self.BitIndex,7))) ~= 0 then + surface.DrawRect(segment.X+self.LocalX,segment.Y+self.LocalY,segment.W,segment.H) + end + self.BitIndex = self.BitIndex+1 +end + +function ENT:DrawUnion(group) + self.LocalX = self.LocalX + (group.X or 0) + self.LocalY = self.LocalY + (group.Y or 0) + local savedindex = self.BitIndex + local biggestindex = savedindex + for k,v in ipairs(group.Children) do + if v.Type == GROUP then + self:DrawGroup(v) + elseif v.Type == UNION then + self:DrawUnion(v) + elseif v.Type == SEGMENT then + self:DrawSegment(v) + end + biggestindex = math.max(biggestindex,self.BitIndex) + self.BitIndex = savedindex + end + self.BitIndex = biggestindex + self.LocalX = self.LocalX - (group.X or 0) + self.LocalY = self.LocalY - (group.Y or 0) +end + +function ENT:DrawGroup(group) + self.LocalX = self.LocalX + (group.X or 0) + self.LocalY = self.LocalY + (group.Y or 0) + for k,v in ipairs(group.Children) do + if v.Type == GROUP then + self:DrawGroup(v) + elseif v.Type == UNION then + self:DrawUnion(v) + elseif v.Type == SEGMENT then + self:DrawSegment(v) + end + end + self.LocalX = self.LocalX - (group.X or 0) + self.LocalY = self.LocalY - (group.Y or 0) +end + +function ENT:Draw() + self:DrawModel() + self.GPU:RenderToGPU(function() + surface.SetDrawColor(0,0,0,255) + surface.DrawRect(0,0,1024,1024) + + if self.Tree then + surface.SetDrawColor(255,255,255,255) + self.BitIndex = 0 + self.LocalX = 0 + self.LocalY = 0 + self:DrawGroup(self.Tree) + end + end) + self.GPU:Render(0,0,1024,1024,nil,0,0) + Wire_Render(self) +end + +function ENT:IsTranslucent() + return true +end + +function ENT:Receive() + local ent = net.ReadEntity() + self.Tree = net.ReadTable() +end diff --git a/lua/entities/gmod_wire_multisegmentlcd/init.lua b/lua/entities/gmod_wire_multisegmentlcd/init.lua new file mode 100644 index 0000000000..2238b5a1fa --- /dev/null +++ b/lua/entities/gmod_wire_multisegmentlcd/init.lua @@ -0,0 +1,146 @@ +AddCSLuaFile("cl_init.lua") +AddCSLuaFile("shared.lua") +include("shared.lua") + +ENT.WireDebugName = "MultiSegmentLcdScreen" + + + +function ENT:InitInteractive() + local model = self:GetModel() + local outputs = {"Memory"} + local interactivemodel = WireLib.GetInteractiveModel(model) + for i=1, #interactivemodel.widgets do + outputs[i+1] = interactivemodel.widgets[i].name + end + self.BlockInput = false + self.NextPrompt = 0 + self.Outputs=WireLib.CreateOutputs(self,outputs) + self.IsInteractive = true + self:UpdateOverlay() +end + +util.AddNetworkString("wire_multisegmentlcd_init") + +function ENT:Initialize() + self:PhysicsInit(SOLID_VPHYSICS) + self:SetMoveType(MOVETYPE_VPHYSICS) + self:SetSolid(SOLID_VPHYSICS) + + self.InteractiveData = {} + self.IsInteractive = false + if WireLib.IsValidInteractiveModel(self:GetModel()) then + self:InitInteractive() + else + self.Outputs = WireLib.CreateOutputs(self, { "Memory" }) + end + + self.Memory = {} + self.Cache = GPUCacheManager(self,true) +end + +function ENT:SendSerializedTree(ply) + if self.Tree == nil then return end + WireLib.netStart(self) + net.WriteEntity(self) + net.WriteTable(self.Tree) + WireLib.netEnd(ply) +end + +function ENT:Retransmit(ply) + self:SendSerializedTree(ply) + + self.Cache:Flush() + for address,value in pairs(self.Memory) do + self.Cache:Write(address,value) + end + self.Cache:Flush(ply) +end + +function ENT:Setup(IsInteractive) + self.IsInteractive = WireLib.IsValidInteractiveModel(self:GetModel()) and (IsInteractive == 1) +end + +function ENT:ReadCell(Address) + Address = math.floor(Address) + if Address < 0 then return nil end + + return self.Memory[Address] +end + +function ENT:WriteCell(Address, value) + Address = math.floor(Address) + if Address < 0 then return false end + + self.Memory[Address] = value + self.Cache:Write(Address, value) + return true +end + +function ENT:TriggerInput(iname, value) + +end + +function ENT:Think() + self.Cache:Flush() + self:NextThink(CurTime()+0.01) + return true +end + + +function ENT:ReceiveData() + if not self.IsInteractive then return end + local data = WireLib.GetInteractiveModel(self:GetModel()).widgets + for i = 1, #data do + WireLib.TriggerOutput(self, data[i].name, net.ReadFloat()) + end +end + + +function ENT:UpdateOverlay() + if not self.IsInteractive then + return + end + + txt = "" + if IsValid(self.User) then + txt = "In use by: " .. self.User:Nick() + end + + self:SetOverlayText(txt) +end + + + +function ENT:Prompt( ply ) + if not self.IsInteractive then return end + if ply then + if CurTime() < self.NextPrompt then return end -- anti spam + self.NextPrompt = CurTime() + 0.1 + + if IsValid( self.User ) then + WireLib.AddNotify(ply,"That interactive prop is in use by another player!",NOTIFY_ERROR,5,6) + return + end + + self.User = ply + + net.Start( "wire_interactiveprop_show" ) + net.WriteEntity( self ) + net.Send( ply ) + else + self:Prompt( self:GetPlayer() ) -- prompt for owner + end +end + +function ENT:Use(ply) + if not IsValid( ply ) then return end + self:Prompt( ply ) +end + +function ENT:Unprompt() + if not self.IsInteractive then return end + self.User = nil +end + +duplicator.RegisterEntityClass("gmod_wire_multisegmentlcd", WireLib.MakeWireEnt, "Data", "IsInteractive") diff --git a/lua/entities/gmod_wire_multisegmentlcd/shared.lua b/lua/entities/gmod_wire_multisegmentlcd/shared.lua new file mode 100644 index 0000000000..c2a1f25af3 --- /dev/null +++ b/lua/entities/gmod_wire_multisegmentlcd/shared.lua @@ -0,0 +1,16 @@ +ENT.Type = "anim" +ENT.Base = "base_wire_entity" + +ENT.PrintName = "Wire Multi-segment LCD" +ENT.Author = "" +ENT.Contact = "" +ENT.Purpose = "" +ENT.Instructions = "" + +ENT.Spawnable = false + +ENT.RenderGroup = RENDERGROUP_BOTH + +GROUP = -1 +UNION = 0 +SEGMENT = 1 \ No newline at end of file diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua new file mode 100644 index 0000000000..cdf2cbe305 --- /dev/null +++ b/lua/wire/stools/multisegmentlcd.lua @@ -0,0 +1,381 @@ +WireToolSetup.setCategory( "Visuals/Screens" ) +WireToolSetup.open( "multisegmentlcd", "Multi-segment LCD", "gmod_wire_multisegmentlcd", nil, "Multi-segment LCDs" ) + +GROUP = -1 +UNION = 0 +SEGMENT = 1 + +WireLib.SegmentLCD_Tree = { + Type=GROUP, + X=0, + Y=0, + Children= + { + + } + } + + +if CLIENT then + language.Add( "tool.wire_multisegmentlcd.name", "Multi-segment LCD Tool (Wire)" ) + language.Add( "tool.wire_multisegmentlcd.desc", "Spawns a Multi-segment LCD, which can be used to display numbers and miscellaneous graphics" ) + language.Add( "tool.wire_multisegmentlcd.interactive", "Interactive (if available):" ) + TOOL.Information = { { name = "left", text = "Create/Update " .. TOOL.Name } } + + WireToolSetup.setToolMenuIcon("icon16/application_xp_terminal.png") + + + + net.Receive("wire_multisegmentlcd_tool_upload_request", function(len, ply) + local ent = net.ReadUInt(16) + net.Start("wire_multisegmentlcd_tool_upload") + net.WriteUInt(ent,16) + net.WriteTable(WireLib.SegmentLCD_Tree) + net.SendToServer() + --ent.Tree = table.Copy(WireLib.SegmentLCD_Tree) + end) +end +WireToolSetup.BaseLang() +WireToolSetup.SetupMax( 20 ) + +if SERVER then + + function TOOL:GetConVars() + return self:GetClientNumber("interactive") + end + + util.AddNetworkString("wire_multisegmentlcd_tool_upload_request") + util.AddNetworkString("wire_multisegmentlcd_tool_upload") + + + function TOOL:LeftClick_Update( trace ) + net.Start("wire_multisegmentlcd_tool_upload_request") + net.WriteUInt(trace.Entity:EntIndex(),16) + net.Send(self:GetOwner()) + end + + net.Receive("wire_multisegmentlcd_tool_upload", function(len, ply) + local ent = ents.GetByIndex(net.ReadUInt(16)) + ent.Tree = net.ReadTable() + ent:Retransmit() + end) + + function TOOL:MakeEnt( ply, model, Ang, trace ) + local ent = WireLib.MakeWireEnt( ply, {Class = self.WireClass, Pos=trace.HitPos, Angle=Ang, Model=model}, self:GetConVars() ) + if ent and ent.RestoreNetworkVars then ent:RestoreNetworkVars(self:GetDataTables()) end + net.Start("wire_multisegmentlcd_tool_upload_request") + net.WriteUInt(ent:EntIndex(),16) + net.Send(ply) + return ent + end +end + +TOOL.ClientConVar = { + model = "models/props_lab/monitor01b.mdl", + createflat = 0, + interactive = 1, + +} + + +function BuildNode(v,node,group) + local new = nil + if v.Type == GROUP then + new = node:AddNode( "Group", "icon16/text_list_numbers.png" ) + BuildNodes(new,v) + elseif v.Type == UNION then + new = node:AddNode( "Union", "icon16/text_list_bullets.png" ) + BuildNodes(new,v) + else + new = node:AddNode( "Segment", "icon16/bullet_green.png" ) + end + new.group = v + new.parentgroup = group +end + +function BuildNodes(node,group) + for i,v in ipairs(group.Children) do + BuildNode(v,node,group) + end +end + +local invalid_filename_chars = { + ["*"] = "", + ["?"] = "", + [">"] = "", + ["<"] = "", + ["|"] = "", + ["\\"] = "", + ['"'] = "", + [" "] = "_", +} + +function TOOL.BuildCPanel(panel) + WireDermaExts.ModelSelect(panel, "wire_multisegmentlcd_model", list.Get( "WireScreenModels" ), 5) + panel:CheckBox("#tool.wire_multisegmentlcd.interactive", "wire_multisegmentlcd_interactive") + panel:CheckBox("#Create Flat to Surface", "wire_multisegmentlcd_createflat") + TreeDataHolder = vgui.Create("DPanel", panel) + panel:AddPanel(TreeDataHolder) + TreeDataHolder:DockMargin(0, 0, 0, 0) + TreeDataHolder:Dock(TOP) + TreeDataHolder:SetHeight(480) + DisplayData = vgui.Create("DTree", TreeDataHolder) + DisplayData:Dock(FILL) + DisplayData:DockMargin(0, 0, 0, 0) + --DisplayData.RootNode:AddNode( "Root", "icon16/monitor.png" ) + DisplayData.RootNode.group = WireLib.SegmentLCD_Tree + BuildNodes(DisplayData.RootNode,WireLib.SegmentLCD_Tree) + ButtonsHolder = TreeDataHolder:Add( "DPanel" ) + ButtonsHolder:Dock(TOP) + ButtonsHolder:DockMargin(0, 0, 0, 0) + ButtonsHolder.buttons = {} + ButtonsHolder:SetHeight(48) + + AddSegment = ButtonsHolder:Add( "DButton" ) + AddSegment:SetText( "Add Segment" ) + ButtonsHolder.buttons[1] = AddSegment + function AddSegment:DoClick() + local node = DisplayData:GetSelectedItem() + if node == nil then + node = DisplayData.RootNode + end + local group = node.group + local children = nil + if group ~= nil then + children = group.Children + end + + if children == nil then + node = DisplayData.RootNode + children = WireLib.SegmentLCD_Tree.Children + group = WireLib.SegmentLCD_Tree + end + local newgroup = {Type=SEGMENT, X=30,Y=0,W=10,H=20} + children[#children+1] = newgroup + local new = node:AddNode( "Segment", "icon16/bullet_green.png" ) + new.group = newgroup + new.parentgroup = group + end + + AddGroup = ButtonsHolder:Add( "DButton" ) + AddGroup:SetText( "Add Group" ) + ButtonsHolder.buttons[2] = AddGroup + function AddGroup:DoClick() + local node = DisplayData:GetSelectedItem() + if node == nil then + node = DisplayData.RootNode + end + local group = node.group + local children = nil + if group ~= nil then + children = group.Children + end + if children == nil then + node = DisplayData.RootNode + children = WireLib.SegmentLCD_Tree.Children + group = WireLib.SegmentLCD_Tree + end + local newgroup = {Type=GROUP,Children={},X=0,Y=0} + children[#children+1] = newgroup + local new = node:AddNode( "Group", "icon16/text_list_numbers.png" ) + new.group = newgroup + new.parentgroup = group + end + + AddUnion = ButtonsHolder:Add( "DButton" ) + AddUnion:SetText( "Add Union" ) + ButtonsHolder.buttons[3] = AddUnion + function AddUnion:DoClick() + local node = DisplayData:GetSelectedItem() + if node == nil then + node = DisplayData.RootNode + end + local group = node.group + local children = nil + if group ~= nil then + children = group.Children + end + if children == nil then + node = DisplayData.RootNode + children = WireLib.SegmentLCD_Tree.Children + group = WireLib.SegmentLCD_Tree + end + local newgroup = {Type=UNION,Children={},X=0,Y=0} + children[#children+1] = newgroup + local new = node:AddNode( "Union", "icon16/text_list_bullets.png" ) + new.group = newgroup + new.parentgroup = group + end + + Remove = ButtonsHolder:Add( "DButton" ) + Remove:SetText( "Remove" ) + ButtonsHolder.buttons[4] = Remove + function Remove:DoClick() + local node = DisplayData:GetSelectedItem() + if node == nil then + return + end + local parentgroup = node.parentgroup + if parentgroup == nil then + return + end + for i,v in pairs(parentgroup.Children) do + if v == node.group then + table.remove(parentgroup.Children,i) + node:Remove() + return + end + end + end + ButtonsHolder.textboxes = {} + WangX = ButtonsHolder:Add( "DNumberWang" ) + function WangX:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil then + return + end + node.group.X = value + end + ButtonsHolder.textboxes[1] = WangX + WangY = ButtonsHolder:Add( "DNumberWang" ) + function WangY:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil then + return + end + node.group.Y = value + end + ButtonsHolder.textboxes[2] = WangY + WangW = ButtonsHolder:Add( "DNumberWang" ) + function WangW:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group.Type ~= SEGMENT then + return + end + node.group.W = value + end + ButtonsHolder.textboxes[3] = WangW + WangH = ButtonsHolder:Add( "DNumberWang" ) + function WangH:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group.Type ~= SEGMENT then + return + end + node.group.H = value + end + ButtonsHolder.textboxes[4] = WangH + function ButtonsHolder:PerformLayout(w, h) + for i,v in ipairs(self.buttons) do + v:SetPos((i-1)*w/#self.buttons,0) + v:SetSize(w/#self.buttons,h/2) + end + for i,v in ipairs(self.textboxes) do + v:SetPos((i-1)*w/#self.textboxes,h/2) + v:SetSize(w/#self.textboxes,h/2) + end + end + + + + function DisplayData:DoClick(node) + group = node.group + if group.Type == SEGMENT then + WangX:SetValue(group.X) + WangY:SetValue(group.Y) + WangW:SetValue(group.W) + WangH:SetValue(group.H) + else + WangX:SetValue(group.X) + WangY:SetValue(group.Y) + WangW:SetValue(0) + WangH:SetValue(0) + end + return true + end + + function DisplayData:DoRightClick(node) + local Menu = DermaMenu() + Menu:AddOption( "Copy" ) + Menu:AddOption( "Paste" ) + Menu:Open() + function Menu:OptionSelected(option, optionText) + if optionText == "Copy" then + SegmentLCD_Clipboard = table.Copy(node.group) + elseif optionText == "Paste" then + if node.group.Children then + local newgroup = table.Copy(SegmentLCD_Clipboard) + node.group.Children[#node.group.Children+1] = newgroup + BuildNode(newgroup,node,node.group) + else + local newgroup = table.Copy(SegmentLCD_Clipboard) + WireLib.SegmentLCD_Tree.Children[#WireLib.SegmentLCD_Tree.Children+1] = newgroup + BuildNode(newgroup,DisplayData.RootNode,WireLib.SegmentLCD_Tree) + end + end + end + return true + end + + local FileBrowser = vgui.Create("wire_expression2_browser", panel) + panel:AddPanel(FileBrowser) + FileBrowser:Setup("multisegmentlcd") + FileBrowser:SetSize(w, 320) + FileBrowser:DockMargin(0, 0, 0, 0) + FileBrowser:DockPadding(0, 0, 0, 0) + FileBrowser:Dock(TOP) + FileBrowser:RemoveRightClick("New File") + + for k, v in pairs(FileBrowser.foldermenu) do + if (v[1] == "New File..") then + FileBrowser.foldermenu[k] = nil + break + end + end + + function SaveFile(curloc,path) + file.CreateDir(curloc) + file.Write(path, util.TableToJSON(WireLib.SegmentLCD_Tree)) + FileBrowser:UpdateFolders() + end + + function FileBrowser:OnFileOpen(filepath, newtab) + local newgroup = util.JSONToTable(file.Read(filepath)) + local node = DisplayData:GetSelectedItem() + if node == nil then + node = DisplayData.RootNode + end + local group = node.group + local children = nil + if group ~= nil then + children = group.Children + end + if children == nil then + node = DisplayData.RootNode + children = WireLib.SegmentLCD_Tree.Children + group = WireLib.SegmentLCD_Tree + end + node.group.Children[#node.group.Children+1] = newgroup + BuildNode(newgroup,node,node.group) + end + + local Save = panel:Button("Save") + function Save:DoClick() + Derma_StringRequestNoBlur("Save to file", "", "", + function(strTextOut) + strTextOut = string.gsub(strTextOut, ".", invalid_filename_chars) + local curlocation = "multisegmentlcd" + if FileBrowser.File then + local newcurloc = FileBrowser.File:GetFolder() + curlocation = newcurloc or curlocation + end + local save_location = curlocation .. "/" .. strTextOut .. ".txt" + if file.Exists(save_location, "DATA") then + Derma_QueryNoBlur("The file '" .. strTextOut .. "' already exists. Do you want to overwrite it?", "File already exists", + "Yes", function() SaveFile(curlocation,save_location) end, + "No", function() end) + else + SaveFile(curlocation,save_location) + end + end) + end +end From c002c2fb96833d1534fdd6160ab08a707da26b5a Mon Sep 17 00:00:00 2001 From: wav3 Date: Sat, 6 Sep 2025 16:45:14 +0200 Subject: [PATCH 12/43] try using RenderToWorld --- lua/entities/gmod_wire_multisegmentlcd/cl_init.lua | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index f8f94bb958..a028243221 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -16,7 +16,7 @@ function ENT:Initialize() end end - self.GPU = WireGPU(self) + self.GPU = WireGPU(self, true) GPULib.ClientCacheCallback(self,function(Address,Value) self:WriteCell(Address,Value) @@ -107,19 +107,17 @@ end function ENT:Draw() self:DrawModel() - self.GPU:RenderToGPU(function() + self.GPU:RenderToWorld(nil, 188, function(x, y, w, h) surface.SetDrawColor(0,0,0,255) - surface.DrawRect(0,0,1024,1024) - + surface.DrawRect(x,y,w,h) if self.Tree then surface.SetDrawColor(255,255,255,255) self.BitIndex = 0 - self.LocalX = 0 - self.LocalY = 0 + self.LocalX = x + self.LocalY = y self:DrawGroup(self.Tree) end end) - self.GPU:Render(0,0,1024,1024,nil,0,0) Wire_Render(self) end From 94e019ca2115cbef926c34e7f192baefc9470b52 Mon Sep 17 00:00:00 2001 From: wav3 Date: Sat, 6 Sep 2025 17:17:13 +0200 Subject: [PATCH 13/43] Have a ratio changer --- .../gmod_wire_multisegmentlcd/cl_init.lua | 15 ++++++++++----- lua/entities/gmod_wire_multisegmentlcd/init.lua | 10 +++++++++- lua/wire/stools/multisegmentlcd.lua | 10 ++++++++-- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index a028243221..a6b3523a6e 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -16,7 +16,9 @@ function ENT:Initialize() end end - self.GPU = WireGPU(self, true) + self.GPU = WireGPU(self) + self.ResolutionW = 1024 + self.ResolutionH = 1024 GPULib.ClientCacheCallback(self,function(Address,Value) self:WriteCell(Address,Value) @@ -107,17 +109,18 @@ end function ENT:Draw() self:DrawModel() - self.GPU:RenderToWorld(nil, 188, function(x, y, w, h) + self.GPU:RenderToGPU(function() surface.SetDrawColor(0,0,0,255) - surface.DrawRect(x,y,w,h) + surface.DrawRect(0,0,1024,1024) if self.Tree then surface.SetDrawColor(255,255,255,255) self.BitIndex = 0 - self.LocalX = x - self.LocalY = y + self.LocalX = 0 + self.LocalY = 0 self:DrawGroup(self.Tree) end end) + self.GPU:Render(0,0,1024,1024,nil,-(1024-self.ResolutionW)/1024,-(1024-self.ResolutionH)/1024) Wire_Render(self) end @@ -128,4 +131,6 @@ end function ENT:Receive() local ent = net.ReadEntity() self.Tree = net.ReadTable() + self.ResolutionW = net.ReadUInt(16) + self.ResolutionH = net.ReadUInt(16) end diff --git a/lua/entities/gmod_wire_multisegmentlcd/init.lua b/lua/entities/gmod_wire_multisegmentlcd/init.lua index 2238b5a1fa..34ac19d3cf 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/init.lua @@ -35,6 +35,9 @@ function ENT:Initialize() self.Outputs = WireLib.CreateOutputs(self, { "Memory" }) end + self.ResolutionW = 1024 + self.ResolutionH = 1024 + self.Memory = {} self.Cache = GPUCacheManager(self,true) end @@ -44,6 +47,8 @@ function ENT:SendSerializedTree(ply) WireLib.netStart(self) net.WriteEntity(self) net.WriteTable(self.Tree) + net.WriteUInt(self.ResolutionW,16) + net.WriteUInt(self.ResolutionH,16) WireLib.netEnd(ply) end @@ -57,8 +62,11 @@ function ENT:Retransmit(ply) self.Cache:Flush(ply) end -function ENT:Setup(IsInteractive) +function ENT:Setup(IsInteractive, ResolutionW, ResolutionH) self.IsInteractive = WireLib.IsValidInteractiveModel(self:GetModel()) and (IsInteractive == 1) + self.ResolutionW = ResolutionW + self.ResolutionH = ResolutionH + self:Retransmit() end function ENT:ReadCell(Address) diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index cdf2cbe305..b9fff3e6d3 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -20,6 +20,8 @@ if CLIENT then language.Add( "tool.wire_multisegmentlcd.name", "Multi-segment LCD Tool (Wire)" ) language.Add( "tool.wire_multisegmentlcd.desc", "Spawns a Multi-segment LCD, which can be used to display numbers and miscellaneous graphics" ) language.Add( "tool.wire_multisegmentlcd.interactive", "Interactive (if available):" ) + language.Add( "tool.wire_multisegmentlcd.resw", "Canvas Width:" ) + language.Add( "tool.wire_multisegmentlcd.resh", "Canvas Height:" ) TOOL.Information = { { name = "left", text = "Create/Update " .. TOOL.Name } } WireToolSetup.setToolMenuIcon("icon16/application_xp_terminal.png") @@ -41,7 +43,7 @@ WireToolSetup.SetupMax( 20 ) if SERVER then function TOOL:GetConVars() - return self:GetClientNumber("interactive") + return self:GetClientNumber("interactive"), math.max(0,math.min(1024,self:GetClientNumber("resw"))), math.max(0,math.min(1024,self:GetClientNumber("resh"))) end util.AddNetworkString("wire_multisegmentlcd_tool_upload_request") @@ -52,6 +54,7 @@ if SERVER then net.Start("wire_multisegmentlcd_tool_upload_request") net.WriteUInt(trace.Entity:EntIndex(),16) net.Send(self:GetOwner()) + trace.Entity:Setup(self:GetConVars()) end net.Receive("wire_multisegmentlcd_tool_upload", function(len, ply) @@ -74,7 +77,8 @@ TOOL.ClientConVar = { model = "models/props_lab/monitor01b.mdl", createflat = 0, interactive = 1, - + resw = 1024, + resh = 1024, } @@ -114,6 +118,8 @@ function TOOL.BuildCPanel(panel) WireDermaExts.ModelSelect(panel, "wire_multisegmentlcd_model", list.Get( "WireScreenModels" ), 5) panel:CheckBox("#tool.wire_multisegmentlcd.interactive", "wire_multisegmentlcd_interactive") panel:CheckBox("#Create Flat to Surface", "wire_multisegmentlcd_createflat") + panel:TextEntry("#tool.wire_multisegmentlcd.resw", "wire_multisegmentlcd_resw") + panel:TextEntry("#tool.wire_multisegmentlcd.resh", "wire_multisegmentlcd_resh") TreeDataHolder = vgui.Create("DPanel", panel) panel:AddPanel(TreeDataHolder) TreeDataHolder:DockMargin(0, 0, 0, 0) From 7860fd598187852c54249aec58f3ce3b07c11cbe Mon Sep 17 00:00:00 2001 From: wav3 Date: Sat, 6 Sep 2025 18:16:03 +0200 Subject: [PATCH 14/43] Do fixes --- .../gmod_wire_multisegmentlcd/cl_init.lua | 17 ++++- .../gmod_wire_multisegmentlcd/init.lua | 7 +- .../gmod_wire_multisegmentlcd/shared.lua | 4 +- lua/wire/stools/multisegmentlcd.lua | 69 +++++++++++++++++-- 4 files changed, 88 insertions(+), 9 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index a6b3523a6e..26341c1fd0 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -70,6 +70,16 @@ function ENT:DrawSegment(segment) self.BitIndex = self.BitIndex+1 end +function ENT:DrawText(text) + if bit.band(self.Memory[bit.rshift(self.BitIndex,3)] or 0,bit.lshift(1,bit.band(self.BitIndex,7))) ~= 0 then + surface.SetTextPos(text.X+self.LocalX,text.Y+self.LocalY) + surface.SetFont("Default") + surface.SetTextColor(255,255,255,255) + surface.DrawText(text.Text) + end + self.BitIndex = self.BitIndex+1 +end + function ENT:DrawUnion(group) self.LocalX = self.LocalX + (group.X or 0) self.LocalY = self.LocalY + (group.Y or 0) @@ -82,6 +92,8 @@ function ENT:DrawUnion(group) self:DrawUnion(v) elseif v.Type == SEGMENT then self:DrawSegment(v) + elseif v.Type == TEXT then + self:DrawText(v) end biggestindex = math.max(biggestindex,self.BitIndex) self.BitIndex = savedindex @@ -101,6 +113,8 @@ function ENT:DrawGroup(group) self:DrawUnion(v) elseif v.Type == SEGMENT then self:DrawSegment(v) + elseif v.Type == TEXT then + self:DrawText(v) end end self.LocalX = self.LocalX - (group.X or 0) @@ -130,7 +144,8 @@ end function ENT:Receive() local ent = net.ReadEntity() - self.Tree = net.ReadTable() + local sz = net.ReadUInt(16) + self.Tree = WireLib.von.deserialize(net.ReadData(sz)) self.ResolutionW = net.ReadUInt(16) self.ResolutionH = net.ReadUInt(16) end diff --git a/lua/entities/gmod_wire_multisegmentlcd/init.lua b/lua/entities/gmod_wire_multisegmentlcd/init.lua index 34ac19d3cf..737f4669ed 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/init.lua @@ -44,9 +44,14 @@ end function ENT:SendSerializedTree(ply) if self.Tree == nil then return end + local serialized = WireLib.von.serialize(self.Tree) + if #serialized > 65535 then + return + end WireLib.netStart(self) net.WriteEntity(self) - net.WriteTable(self.Tree) + net.WriteUInt(#serialized,16) + net.WriteData(serialized) net.WriteUInt(self.ResolutionW,16) net.WriteUInt(self.ResolutionH,16) WireLib.netEnd(ply) diff --git a/lua/entities/gmod_wire_multisegmentlcd/shared.lua b/lua/entities/gmod_wire_multisegmentlcd/shared.lua index c2a1f25af3..e20f1983b7 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/shared.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/shared.lua @@ -13,4 +13,6 @@ ENT.RenderGroup = RENDERGROUP_BOTH GROUP = -1 UNION = 0 -SEGMENT = 1 \ No newline at end of file +SEGMENT = 1 +TEXT = 2 +MATRIX = 3 \ No newline at end of file diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index b9fff3e6d3..c541f292bb 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -4,6 +4,8 @@ WireToolSetup.open( "multisegmentlcd", "Multi-segment LCD", "gmod_wire_multisegm GROUP = -1 UNION = 0 SEGMENT = 1 +TEXT = 2 +MATRIX = 3 WireLib.SegmentLCD_Tree = { Type=GROUP, @@ -30,9 +32,14 @@ if CLIENT then net.Receive("wire_multisegmentlcd_tool_upload_request", function(len, ply) local ent = net.ReadUInt(16) + local serialized = WireLib.von.serialize(WireLib.SegmentLCD_Tree) + if #serialized > 65535 then + return + end net.Start("wire_multisegmentlcd_tool_upload") net.WriteUInt(ent,16) - net.WriteTable(WireLib.SegmentLCD_Tree) + net.WriteUInt(#serialized,16) + net.WriteData(serialized) net.SendToServer() --ent.Tree = table.Copy(WireLib.SegmentLCD_Tree) end) @@ -43,7 +50,7 @@ WireToolSetup.SetupMax( 20 ) if SERVER then function TOOL:GetConVars() - return self:GetClientNumber("interactive"), math.max(0,math.min(1024,self:GetClientNumber("resw"))), math.max(0,math.min(1024,self:GetClientNumber("resh"))) + return self:GetClientNumber("interactive"), math.Clamp(self:GetClientNumber("resw"),0,1024), math.Clamp(self:GetClientNumber("resh"),0,1024) end util.AddNetworkString("wire_multisegmentlcd_tool_upload_request") @@ -59,7 +66,8 @@ if SERVER then net.Receive("wire_multisegmentlcd_tool_upload", function(len, ply) local ent = ents.GetByIndex(net.ReadUInt(16)) - ent.Tree = net.ReadTable() + local sz = net.ReadUInt(16) + ent.Tree = WireLib.von.deserialize(net.ReadData(sz)) ent:Retransmit() end) @@ -90,6 +98,10 @@ function BuildNode(v,node,group) elseif v.Type == UNION then new = node:AddNode( "Union", "icon16/text_list_bullets.png" ) BuildNodes(new,v) + elseif v.Type == TEXT then + new = node:AddNode( "Text", "icon16/bullet_yellow.png" ) + elseif v.Type == MATRIX then + new = node:AddNode( "Matrix", "icon16/bullet_red.png" ) else new = node:AddNode( "Segment", "icon16/bullet_green.png" ) end @@ -163,9 +175,35 @@ function TOOL.BuildCPanel(panel) new.parentgroup = group end + AddText = ButtonsHolder:Add( "DButton" ) + AddText:SetText( "Add Text" ) + ButtonsHolder.buttons[2] = AddText + function AddText:DoClick() + local node = DisplayData:GetSelectedItem() + if node == nil then + node = DisplayData.RootNode + end + local group = node.group + local children = nil + if group ~= nil then + children = group.Children + end + + if children == nil then + node = DisplayData.RootNode + children = WireLib.SegmentLCD_Tree.Children + group = WireLib.SegmentLCD_Tree + end + local newgroup = {Type=TEXT, X=30, Y=0, Text="Hello"} + children[#children+1] = newgroup + local new = node:AddNode( "Text", "icon16/bullet_yellow.png" ) + new.group = newgroup + new.parentgroup = group + end + AddGroup = ButtonsHolder:Add( "DButton" ) AddGroup:SetText( "Add Group" ) - ButtonsHolder.buttons[2] = AddGroup + ButtonsHolder.buttons[3] = AddGroup function AddGroup:DoClick() local node = DisplayData:GetSelectedItem() if node == nil then @@ -190,7 +228,7 @@ function TOOL.BuildCPanel(panel) AddUnion = ButtonsHolder:Add( "DButton" ) AddUnion:SetText( "Add Union" ) - ButtonsHolder.buttons[3] = AddUnion + ButtonsHolder.buttons[4] = AddUnion function AddUnion:DoClick() local node = DisplayData:GetSelectedItem() if node == nil then @@ -215,7 +253,7 @@ function TOOL.BuildCPanel(panel) Remove = ButtonsHolder:Add( "DButton" ) Remove:SetText( "Remove" ) - ButtonsHolder.buttons[4] = Remove + ButtonsHolder.buttons[5] = Remove function Remove:DoClick() local node = DisplayData:GetSelectedItem() if node == nil then @@ -270,6 +308,17 @@ function TOOL.BuildCPanel(panel) node.group.H = value end ButtonsHolder.textboxes[4] = WangH + + TextSetter = ButtonsHolder:Add( "DTextEntry" ) + function TextSetter:OnValueChange(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group.Type ~= TEXT then + return + end + node.group.Text = value + end + ButtonsHolder.textboxes[5] = TextSetter + function ButtonsHolder:PerformLayout(w, h) for i,v in ipairs(self.buttons) do v:SetPos((i-1)*w/#self.buttons,0) @@ -290,11 +339,19 @@ function TOOL.BuildCPanel(panel) WangY:SetValue(group.Y) WangW:SetValue(group.W) WangH:SetValue(group.H) + TextSetter:SetValue("") + elseif group.Type == TEXT then + WangX:SetValue(group.X) + WangY:SetValue(group.Y) + WangW:SetValue(0) + WangH:SetValue(0) + TextSetter:SetValue(group.Text) else WangX:SetValue(group.X) WangY:SetValue(group.Y) WangW:SetValue(0) WangH:SetValue(0) + TextSetter:SetValue("") end return true end From c62513012f7761f8fa8a5697418b6863b969e7cb Mon Sep 17 00:00:00 2001 From: wav3 Date: Sat, 6 Sep 2025 18:53:24 +0200 Subject: [PATCH 15/43] Matrix segment --- .../gmod_wire_multisegmentlcd/cl_init.lua | 18 +++ lua/wire/stools/multisegmentlcd.lua | 148 +++++++++++++++--- 2 files changed, 146 insertions(+), 20 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index 26341c1fd0..aeffeb5b8a 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -80,6 +80,20 @@ function ENT:DrawText(text) self.BitIndex = self.BitIndex+1 end +function ENT:DrawMatrix(matrix) + for y = 0,matrix.H do + for x = 0,matrix.W do + if bit.band(self.Memory[bit.rshift(self.BitIndex,3)] or 0,bit.lshift(1,bit.band(self.BitIndex,7))) ~= 0 then + surface.DrawRect(matrix.X+self.LocalX+x*matrix.OffsetX,matrix.Y+self.LocalY+y*matrix.OffsetY,matrix.ScaleW,matrix.ScaleH) + end + self.BitIndex = self.BitIndex+1 + end + end + + +end + + function ENT:DrawUnion(group) self.LocalX = self.LocalX + (group.X or 0) self.LocalY = self.LocalY + (group.Y or 0) @@ -94,6 +108,8 @@ function ENT:DrawUnion(group) self:DrawSegment(v) elseif v.Type == TEXT then self:DrawText(v) + elseif v.Type == MATRIX then + self:DrawMatrix(v) end biggestindex = math.max(biggestindex,self.BitIndex) self.BitIndex = savedindex @@ -115,6 +131,8 @@ function ENT:DrawGroup(group) self:DrawSegment(v) elseif v.Type == TEXT then self:DrawText(v) + elseif v.Type == MATRIX then + self:DrawMatrix(v) end end self.LocalX = self.LocalX - (group.X or 0) diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index c541f292bb..7a75d5ae00 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -147,7 +147,7 @@ function TOOL.BuildCPanel(panel) ButtonsHolder:Dock(TOP) ButtonsHolder:DockMargin(0, 0, 0, 0) ButtonsHolder.buttons = {} - ButtonsHolder:SetHeight(48) + ButtonsHolder:SetHeight(60) AddSegment = ButtonsHolder:Add( "DButton" ) AddSegment:SetText( "Add Segment" ) @@ -201,9 +201,35 @@ function TOOL.BuildCPanel(panel) new.parentgroup = group end + AddMatrix = ButtonsHolder:Add( "DButton" ) + AddMatrix:SetText( "Add Matrix" ) + ButtonsHolder.buttons[3] = AddMatrix + function AddMatrix:DoClick() + local node = DisplayData:GetSelectedItem() + if node == nil then + node = DisplayData.RootNode + end + local group = node.group + local children = nil + if group ~= nil then + children = group.Children + end + + if children == nil then + node = DisplayData.RootNode + children = WireLib.SegmentLCD_Tree.Children + group = WireLib.SegmentLCD_Tree + end + local newgroup = {Type=MATRIX, X=0, Y=0, W=6, H=8, ScaleW=5, ScaleH=5, OffsetX=6, OffsetY=6} + children[#children+1] = newgroup + local new = node:AddNode( "Matrix", "icon16/bullet_red.png" ) + new.group = newgroup + new.parentgroup = group + end + AddGroup = ButtonsHolder:Add( "DButton" ) AddGroup:SetText( "Add Group" ) - ButtonsHolder.buttons[3] = AddGroup + ButtonsHolder.buttons[4] = AddGroup function AddGroup:DoClick() local node = DisplayData:GetSelectedItem() if node == nil then @@ -228,7 +254,7 @@ function TOOL.BuildCPanel(panel) AddUnion = ButtonsHolder:Add( "DButton" ) AddUnion:SetText( "Add Union" ) - ButtonsHolder.buttons[4] = AddUnion + ButtonsHolder.buttons[5] = AddUnion function AddUnion:DoClick() local node = DisplayData:GetSelectedItem() if node == nil then @@ -253,7 +279,7 @@ function TOOL.BuildCPanel(panel) Remove = ButtonsHolder:Add( "DButton" ) Remove:SetText( "Remove" ) - ButtonsHolder.buttons[5] = Remove + ButtonsHolder.buttons[6] = Remove function Remove:DoClick() local node = DisplayData:GetSelectedItem() if node == nil then @@ -275,7 +301,7 @@ function TOOL.BuildCPanel(panel) WangX = ButtonsHolder:Add( "DNumberWang" ) function WangX:OnValueChanged(value) local node = DisplayData:GetSelectedItem() - if node == nil then + if node == nil or node.group == nil then return end node.group.X = value @@ -284,7 +310,7 @@ function TOOL.BuildCPanel(panel) WangY = ButtonsHolder:Add( "DNumberWang" ) function WangY:OnValueChanged(value) local node = DisplayData:GetSelectedItem() - if node == nil then + if node == nil or node.group == nil then return end node.group.Y = value @@ -293,7 +319,7 @@ function TOOL.BuildCPanel(panel) WangW = ButtonsHolder:Add( "DNumberWang" ) function WangW:OnValueChanged(value) local node = DisplayData:GetSelectedItem() - if node == nil or node.group.Type ~= SEGMENT then + if node == nil or node.group == nil or node.group.Type ~= SEGMENT then return end node.group.W = value @@ -302,7 +328,7 @@ function TOOL.BuildCPanel(panel) WangH = ButtonsHolder:Add( "DNumberWang" ) function WangH:OnValueChanged(value) local node = DisplayData:GetSelectedItem() - if node == nil or node.group.Type ~= SEGMENT then + if node == nil or node.group == nil or node.group.Type ~= SEGMENT then return end node.group.H = value @@ -312,24 +338,75 @@ function TOOL.BuildCPanel(panel) TextSetter = ButtonsHolder:Add( "DTextEntry" ) function TextSetter:OnValueChange(value) local node = DisplayData:GetSelectedItem() - if node == nil or node.group.Type ~= TEXT then + if node == nil or node.group == nil or node.group.Type ~= TEXT then return end node.group.Text = value end - ButtonsHolder.textboxes[5] = TextSetter + + WangScaleW = ButtonsHolder:Add( "DNumberWang" ) + function WangScaleW:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil or node.group.Type ~= MATRIX then + return + end + node.group.ScaleW = value + end + + WangScaleH = ButtonsHolder:Add( "DNumberWang" ) + function WangScaleH:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil or node.group.Type ~= MATRIX then + return + end + node.group.ScaleH = value + end + + WangOffsetX = ButtonsHolder:Add( "DNumberWang" ) + function WangOffsetX:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil or node.group.Type ~= MATRIX then + return + end + node.group.OffsetX = value + end + + WangOffsetY = ButtonsHolder:Add( "DNumberWang" ) + function WangOffsetY:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil or node.group.Type ~= MATRIX then + return + end + node.group.OffsetY = value + end function ButtonsHolder:PerformLayout(w, h) for i,v in ipairs(self.buttons) do v:SetPos((i-1)*w/#self.buttons,0) - v:SetSize(w/#self.buttons,h/2) + v:SetSize(w/#self.buttons,h/3) end for i,v in ipairs(self.textboxes) do - v:SetPos((i-1)*w/#self.textboxes,h/2) - v:SetSize(w/#self.textboxes,h/2) + v:SetPos((i-1)*w/#self.textboxes,h/3) + v:SetSize(w/#self.textboxes,h/3) end + TextSetter:SetPos(0,h/3*2) + TextSetter:SetSize(w,h/3) + WangScaleW:SetPos(0,h/3*2) + WangScaleW:SetSize(w/4,h/3) + WangScaleH:SetPos(w/4,h/3*2) + WangScaleH:SetSize(w/4,h/3) + WangOffsetX:SetPos(w/4*2,h/3*2) + WangOffsetX:SetSize(w/4,h/3) + WangOffsetY:SetPos(w/4*3,h/3*2) + WangOffsetY:SetSize(w/4,h/3) end - + WangW:SetVisible(false) + WangH:SetVisible(false) + TextSetter:SetVisible(false) + WangScaleW:SetVisible(false) + WangScaleH:SetVisible(false) + WangOffsetX:SetVisible(false) + WangOffsetY:SetVisible(false) function DisplayData:DoClick(node) @@ -339,19 +416,50 @@ function TOOL.BuildCPanel(panel) WangY:SetValue(group.Y) WangW:SetValue(group.W) WangH:SetValue(group.H) - TextSetter:SetValue("") + WangW:SetVisible(true) + WangH:SetVisible(true) + TextSetter:SetVisible(false) + WangScaleW:SetVisible(false) + WangScaleH:SetVisible(false) + WangOffsetX:SetVisible(false) + WangOffsetY:SetVisible(false) + elseif group.Type == MATRIX then + WangX:SetValue(group.X) + WangY:SetValue(group.Y) + WangW:SetValue(group.W) + WangH:SetValue(group.H) + TextSetter:SetVisible(false) + WangScaleW:SetVisible(true) + WangScaleH:SetVisible(true) + WangOffsetX:SetVisible(true) + WangOffsetY:SetVisible(true) + WangW:SetVisible(true) + WangH:SetVisible(true) + WangScaleW:SetValue(group.ScaleW) + WangScaleH:SetValue(group.ScaleH) + WangOffsetX:SetValue(group.OffsetX) + WangOffsetY:SetValue(group.OffsetY) elseif group.Type == TEXT then WangX:SetValue(group.X) WangY:SetValue(group.Y) - WangW:SetValue(0) - WangH:SetValue(0) + WangW:SetVisible(false) + WangH:SetVisible(false) + TextSetter:SetVisible(true) TextSetter:SetValue(group.Text) + WangScaleW:SetVisible(false) + WangScaleH:SetVisible(false) + WangOffsetX:SetVisible(false) + WangOffsetY:SetVisible(false) else WangX:SetValue(group.X) WangY:SetValue(group.Y) - WangW:SetValue(0) - WangH:SetValue(0) - TextSetter:SetValue("") + WangW:SetVisible(false) + WangH:SetVisible(false) + WangScaleW:SetVisible(false) + WangScaleH:SetVisible(false) + WangOffsetX:SetVisible(false) + WangOffsetY:SetVisible(false) + TextSetter:SetVisible(false) end return true end From a26887d7cef175e888fe84edb45ec44fb7c06723 Mon Sep 17 00:00:00 2001 From: wav3 Date: Sat, 6 Sep 2025 19:20:56 +0200 Subject: [PATCH 16/43] It is amazing --- lua/wire/stools/multisegmentlcd.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index 7a75d5ae00..346ef5e194 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -319,7 +319,7 @@ function TOOL.BuildCPanel(panel) WangW = ButtonsHolder:Add( "DNumberWang" ) function WangW:OnValueChanged(value) local node = DisplayData:GetSelectedItem() - if node == nil or node.group == nil or node.group.Type ~= SEGMENT then + if node == nil or node.group == nil then return end node.group.W = value @@ -328,7 +328,7 @@ function TOOL.BuildCPanel(panel) WangH = ButtonsHolder:Add( "DNumberWang" ) function WangH:OnValueChanged(value) local node = DisplayData:GetSelectedItem() - if node == nil or node.group == nil or node.group.Type ~= SEGMENT then + if node == nil or node.group == nil then return end node.group.H = value From 6fdf855ef3ea3876f7182b48d7d13585e35fcb16 Mon Sep 17 00:00:00 2001 From: wav3 Date: Sat, 6 Sep 2025 20:03:06 +0200 Subject: [PATCH 17/43] colors --- .../gmod_wire_multisegmentlcd/cl_init.lua | 19 ++++++++++++++++--- .../gmod_wire_multisegmentlcd/init.lua | 14 +++++++++++++- lua/wire/stools/multisegmentlcd.lua | 18 +++++++++++++++--- 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index aeffeb5b8a..0dfc176335 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -16,6 +16,13 @@ function ENT:Initialize() end end + self.Fgblue = 45 + self.Fggreen = 91 + self.Fgred = 45 + self.Bgblue = 15 + self.Bggreen = 178 + self.Bgred = 148 + self.GPU = WireGPU(self) self.ResolutionW = 1024 self.ResolutionH = 1024 @@ -74,7 +81,7 @@ function ENT:DrawText(text) if bit.band(self.Memory[bit.rshift(self.BitIndex,3)] or 0,bit.lshift(1,bit.band(self.BitIndex,7))) ~= 0 then surface.SetTextPos(text.X+self.LocalX,text.Y+self.LocalY) surface.SetFont("Default") - surface.SetTextColor(255,255,255,255) + surface.SetTextColor(self.Fgred,self.Fggreen,self.Fgblue,255) surface.DrawText(text.Text) end self.BitIndex = self.BitIndex+1 @@ -142,10 +149,10 @@ end function ENT:Draw() self:DrawModel() self.GPU:RenderToGPU(function() - surface.SetDrawColor(0,0,0,255) + surface.SetDrawColor(self.Bgred,self.Bggreen,self.Bgblue,255) surface.DrawRect(0,0,1024,1024) if self.Tree then - surface.SetDrawColor(255,255,255,255) + surface.SetDrawColor(self.Fgred,self.Fggreen,self.Fgblue,255) self.BitIndex = 0 self.LocalX = 0 self.LocalY = 0 @@ -166,4 +173,10 @@ function ENT:Receive() self.Tree = WireLib.von.deserialize(net.ReadData(sz)) self.ResolutionW = net.ReadUInt(16) self.ResolutionH = net.ReadUInt(16) + self.Fgblue = net.ReadUInt(8) + self.Fggreen = net.ReadUInt(8) + self.Fgred = net.ReadUInt(8) + self.Bgblue = net.ReadUInt(8) + self.Bggreen = net.ReadUInt(8) + self.Bgred = net.ReadUInt(8) end diff --git a/lua/entities/gmod_wire_multisegmentlcd/init.lua b/lua/entities/gmod_wire_multisegmentlcd/init.lua index 737f4669ed..9c5bb9630d 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/init.lua @@ -54,6 +54,12 @@ function ENT:SendSerializedTree(ply) net.WriteData(serialized) net.WriteUInt(self.ResolutionW,16) net.WriteUInt(self.ResolutionH,16) + net.WriteUInt(self.Fgblue,8) + net.WriteUInt(self.Fggreen,8) + net.WriteUInt(self.Fgred,8) + net.WriteUInt(self.Bgblue,8) + net.WriteUInt(self.Bggreen,8) + net.WriteUInt(self.Bgred,8) WireLib.netEnd(ply) end @@ -67,10 +73,16 @@ function ENT:Retransmit(ply) self.Cache:Flush(ply) end -function ENT:Setup(IsInteractive, ResolutionW, ResolutionH) +function ENT:Setup(IsInteractive, ResolutionW, ResolutionH, Bgred,Bggreen,Bgblue,Fgred,Fggreen,Fgblue) self.IsInteractive = WireLib.IsValidInteractiveModel(self:GetModel()) and (IsInteractive == 1) self.ResolutionW = ResolutionW self.ResolutionH = ResolutionH + self.Fgblue = Fgblue or 45 + self.Fggreen = Fggreen or 91 + self.Fgred = Fgred or 45 + self.Bgblue = Bgblue or 15 + self.Bggreen = Bggreen or 178 + self.Bgred = Bgred or 148 self:Retransmit() end diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index 346ef5e194..ed95e17aee 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -50,7 +50,13 @@ WireToolSetup.SetupMax( 20 ) if SERVER then function TOOL:GetConVars() - return self:GetClientNumber("interactive"), math.Clamp(self:GetClientNumber("resw"),0,1024), math.Clamp(self:GetClientNumber("resh"),0,1024) + return self:GetClientNumber("interactive"), math.Clamp(self:GetClientNumber("resw"),0,1024), math.Clamp(self:GetClientNumber("resh"),0,1024), + math.Clamp(self:GetClientNumber("bgred"), 0, 255), + math.Clamp(self:GetClientNumber("bggreen"), 0, 255), + math.Clamp(self:GetClientNumber("bgblue"), 0, 255), + math.Clamp(self:GetClientNumber("fgred"), 0, 255), + math.Clamp(self:GetClientNumber("fggreen"), 0, 255), + math.Clamp(self:GetClientNumber("fgblue"), 0, 255) end util.AddNetworkString("wire_multisegmentlcd_tool_upload_request") @@ -85,8 +91,14 @@ TOOL.ClientConVar = { model = "models/props_lab/monitor01b.mdl", createflat = 0, interactive = 1, - resw = 1024, - resh = 1024, + resw = 1024, + resh = 1024, + bgred = 148, + bggreen = 178, + bgblue = 15, + fgred = 45, + fggreen = 91, + fgblue = 45 } From 0f842715408c6d692345fdc6d6be0832ca806e66 Mon Sep 17 00:00:00 2001 From: wav3 Date: Sat, 6 Sep 2025 22:05:47 +0200 Subject: [PATCH 18/43] Fixes --- lua/wire/stools/multisegmentlcd.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index ed95e17aee..441ad24f12 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -311,6 +311,8 @@ function TOOL.BuildCPanel(panel) end ButtonsHolder.textboxes = {} WangX = ButtonsHolder:Add( "DNumberWang" ) + WangX:SetMin(-1024) + WangX:SetMax(1024) function WangX:OnValueChanged(value) local node = DisplayData:GetSelectedItem() if node == nil or node.group == nil then @@ -320,6 +322,8 @@ function TOOL.BuildCPanel(panel) end ButtonsHolder.textboxes[1] = WangX WangY = ButtonsHolder:Add( "DNumberWang" ) + WangY:SetMin(-1024) + WangY:SetMax(1024) function WangY:OnValueChanged(value) local node = DisplayData:GetSelectedItem() if node == nil or node.group == nil then @@ -329,6 +333,7 @@ function TOOL.BuildCPanel(panel) end ButtonsHolder.textboxes[2] = WangY WangW = ButtonsHolder:Add( "DNumberWang" ) + WangW:SetMax(1024) function WangW:OnValueChanged(value) local node = DisplayData:GetSelectedItem() if node == nil or node.group == nil then @@ -338,6 +343,7 @@ function TOOL.BuildCPanel(panel) end ButtonsHolder.textboxes[3] = WangW WangH = ButtonsHolder:Add( "DNumberWang" ) + WangH:SetMax(1024) function WangH:OnValueChanged(value) local node = DisplayData:GetSelectedItem() if node == nil or node.group == nil then @@ -357,6 +363,7 @@ function TOOL.BuildCPanel(panel) end WangScaleW = ButtonsHolder:Add( "DNumberWang" ) + WangScaleW:SetMax(1024) function WangScaleW:OnValueChanged(value) local node = DisplayData:GetSelectedItem() if node == nil or node.group == nil or node.group.Type ~= MATRIX then @@ -366,6 +373,7 @@ function TOOL.BuildCPanel(panel) end WangScaleH = ButtonsHolder:Add( "DNumberWang" ) + WangScaleH:SetMax(1024) function WangScaleH:OnValueChanged(value) local node = DisplayData:GetSelectedItem() if node == nil or node.group == nil or node.group.Type ~= MATRIX then @@ -375,6 +383,7 @@ function TOOL.BuildCPanel(panel) end WangOffsetX = ButtonsHolder:Add( "DNumberWang" ) + WangOffsetX:SetMax(1024) function WangOffsetX:OnValueChanged(value) local node = DisplayData:GetSelectedItem() if node == nil or node.group == nil or node.group.Type ~= MATRIX then @@ -384,6 +393,7 @@ function TOOL.BuildCPanel(panel) end WangOffsetY = ButtonsHolder:Add( "DNumberWang" ) + WangOffsetY:SetMax(1024) function WangOffsetY:OnValueChanged(value) local node = DisplayData:GetSelectedItem() if node == nil or node.group == nil or node.group.Type ~= MATRIX then From 2e0a7ce6c2d096a9fe0bdf1e9c2e14a7e4a408aa Mon Sep 17 00:00:00 2001 From: wav3 Date: Sun, 7 Sep 2025 00:56:30 +0200 Subject: [PATCH 19/43] Fix --- lua/entities/gmod_wire_multisegmentlcd/cl_init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index 0dfc176335..bd967e2007 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -88,8 +88,8 @@ function ENT:DrawText(text) end function ENT:DrawMatrix(matrix) - for y = 0,matrix.H do - for x = 0,matrix.W do + for y = 0,matrix.H-1 do + for x = 0,matrix.W-1 do if bit.band(self.Memory[bit.rshift(self.BitIndex,3)] or 0,bit.lshift(1,bit.band(self.BitIndex,7))) ~= 0 then surface.DrawRect(matrix.X+self.LocalX+x*matrix.OffsetX,matrix.Y+self.LocalY+y*matrix.OffsetY,matrix.ScaleW,matrix.ScaleH) end From bc419b1ad8753de06cb0d7cc81069a98bbbe5c88 Mon Sep 17 00:00:00 2001 From: wav3 Date: Sun, 7 Sep 2025 01:00:58 +0200 Subject: [PATCH 20/43] add the missing color pickers --- lua/wire/stools/multisegmentlcd.lua | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index 441ad24f12..7da28f18ea 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -22,8 +22,10 @@ if CLIENT then language.Add( "tool.wire_multisegmentlcd.name", "Multi-segment LCD Tool (Wire)" ) language.Add( "tool.wire_multisegmentlcd.desc", "Spawns a Multi-segment LCD, which can be used to display numbers and miscellaneous graphics" ) language.Add( "tool.wire_multisegmentlcd.interactive", "Interactive (if available):" ) - language.Add( "tool.wire_multisegmentlcd.resw", "Canvas Width:" ) - language.Add( "tool.wire_multisegmentlcd.resh", "Canvas Height:" ) + language.Add( "tool.wire_multisegmentlcd.resw", "Canvas width:" ) + language.Add( "tool.wire_multisegmentlcd.resh", "Canvas height:" ) + language.Add( "tool.wire_multisegmentlcd.fgcolor", "Segment color:" ) + language.Add( "tool.wire_multisegmentlcd.bgcolor", "Background color:" ) TOOL.Information = { { name = "left", text = "Create/Update " .. TOOL.Name } } WireToolSetup.setToolMenuIcon("icon16/application_xp_terminal.png") @@ -571,4 +573,25 @@ function TOOL.BuildCPanel(panel) end end) end + + panel:AddControl("Color", { + Label = "#tool.wire_multisegmentlcd.bgcolor", + Red = "wire_multisegmentlcd_bgred", + Green = "wire_multisegmentlcd_bggreen", + Blue = "wire_multisegmentlcd_bgblue", + ShowAlpha = "0", + ShowHSV = "1", + ShowRGB = "1", + Multiplier = "255" + }) + panel:AddControl("Color", { + Label = "#tool.wire_multisegmentlcd.fgcolor", + Red = "wire_multisegmentlcd_fgred", + Green = "wire_multisegmentlcd_fggreen", + Blue = "wire_multisegmentlcd_fgblue", + ShowAlpha = "0", + ShowHSV = "1", + ShowRGB = "1", + Multiplier = "255" + }) end From 7d8770ac6f3aa3d2dd36e542bde5ad181e6cffcd Mon Sep 17 00:00:00 2001 From: wav3 Date: Sun, 7 Sep 2025 11:30:29 +0200 Subject: [PATCH 21/43] make it dupeable --- .../gmod_wire_multisegmentlcd/init.lua | 18 ++++++++++++++++-- .../gmod_wire_multisegmentlcd/shared.lua | 1 + lua/wire/stools/multisegmentlcd.lua | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/init.lua b/lua/entities/gmod_wire_multisegmentlcd/init.lua index 9c5bb9630d..fde06666d9 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/init.lua @@ -2,6 +2,7 @@ AddCSLuaFile("cl_init.lua") AddCSLuaFile("shared.lua") include("shared.lua") +DEFINE_BASECLASS( "base_wire_entity" ) ENT.WireDebugName = "MultiSegmentLcdScreen" @@ -74,7 +75,7 @@ function ENT:Retransmit(ply) end function ENT:Setup(IsInteractive, ResolutionW, ResolutionH, Bgred,Bggreen,Bgblue,Fgred,Fggreen,Fgblue) - self.IsInteractive = WireLib.IsValidInteractiveModel(self:GetModel()) and (IsInteractive == 1) + self.IsInteractive = WireLib.IsValidInteractiveModel(self:GetModel()) and (IsInteractive) self.ResolutionW = ResolutionW self.ResolutionH = ResolutionH self.Fgblue = Fgblue or 45 @@ -168,4 +169,17 @@ function ENT:Unprompt() self.User = nil end -duplicator.RegisterEntityClass("gmod_wire_multisegmentlcd", WireLib.MakeWireEnt, "Data", "IsInteractive") +function ENT:BuildDupeInfo() + local info = BaseClass.BuildDupeInfo( self ) or {} + info.Tree = self.Tree + return info +end + +function ENT:ApplyDupeInfo(ply, ent, info, GetEntByID) + self.Tree = info.Tree + ent.Tree = info.Tree + BaseClass.ApplyDupeInfo(self, ply, ent, info, GetEntByID) + ent:Retransmit() +end + +duplicator.RegisterEntityClass("gmod_wire_multisegmentlcd", WireLib.MakeWireEnt, "Data", "IsInteractive", "ResolutionW", "ResolutionH", "Bgred", "Bggreen", "Bgblue", "Fgred", "Fggreen", "Fgblue") diff --git a/lua/entities/gmod_wire_multisegmentlcd/shared.lua b/lua/entities/gmod_wire_multisegmentlcd/shared.lua index e20f1983b7..735b21d490 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/shared.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/shared.lua @@ -1,6 +1,7 @@ ENT.Type = "anim" ENT.Base = "base_wire_entity" + ENT.PrintName = "Wire Multi-segment LCD" ENT.Author = "" ENT.Contact = "" diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index 7da28f18ea..c12676cf5a 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -52,7 +52,7 @@ WireToolSetup.SetupMax( 20 ) if SERVER then function TOOL:GetConVars() - return self:GetClientNumber("interactive"), math.Clamp(self:GetClientNumber("resw"),0,1024), math.Clamp(self:GetClientNumber("resh"),0,1024), + return self:GetClientNumber("interactive") == 1, math.Clamp(self:GetClientNumber("resw"),0,1024), math.Clamp(self:GetClientNumber("resh"),0,1024), math.Clamp(self:GetClientNumber("bgred"), 0, 255), math.Clamp(self:GetClientNumber("bggreen"), 0, 255), math.Clamp(self:GetClientNumber("bgblue"), 0, 255), From 1f495c919f7c1b286dae0cd0866d1f56295a8ec0 Mon Sep 17 00:00:00 2001 From: wav3 Date: Mon, 8 Sep 2025 08:42:46 +0200 Subject: [PATCH 22/43] Colors --- .../gmod_wire_multisegmentlcd/cl_init.lua | 31 ++++- lua/wire/stools/multisegmentlcd.lua | 117 +++++++++++++----- 2 files changed, 115 insertions(+), 33 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index bd967e2007..70ab720ef0 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -81,7 +81,7 @@ function ENT:DrawText(text) if bit.band(self.Memory[bit.rshift(self.BitIndex,3)] or 0,bit.lshift(1,bit.band(self.BitIndex,7))) ~= 0 then surface.SetTextPos(text.X+self.LocalX,text.Y+self.LocalY) surface.SetFont("Default") - surface.SetTextColor(self.Fgred,self.Fggreen,self.Fgblue,255) + surface.SetTextColor(self.Cr,self.Cg,self.Cb,255) surface.DrawText(text.Text) end self.BitIndex = self.BitIndex+1 @@ -102,6 +102,15 @@ end function ENT:DrawUnion(group) + local oCr = self.Cr + local oCg = self.Cg + local oCb = self.Cb + if group.HasColor then + self.Cr = group.R + self.Cg = group.G + self.Cb = group.B + surface.SetDrawColor(self.Cr,self.Cg,self.Cb) + end self.LocalX = self.LocalX + (group.X or 0) self.LocalY = self.LocalY + (group.Y or 0) local savedindex = self.BitIndex @@ -124,9 +133,22 @@ function ENT:DrawUnion(group) self.BitIndex = biggestindex self.LocalX = self.LocalX - (group.X or 0) self.LocalY = self.LocalY - (group.Y or 0) + self.Cr = oCr + self.Cg = oCg + self.Cb = oCb + surface.SetDrawColor(self.Cr,self.Cg,self.Cb) end function ENT:DrawGroup(group) + local oCr = self.Cr + local oCg = self.Cg + local oCb = self.Cb + if group.HasColor then + self.Cr = group.R + self.Cg = group.G + self.Cb = group.B + surface.SetDrawColor(self.Cr,self.Cg,self.Cb) + end self.LocalX = self.LocalX + (group.X or 0) self.LocalY = self.LocalY + (group.Y or 0) for k,v in ipairs(group.Children) do @@ -144,6 +166,10 @@ function ENT:DrawGroup(group) end self.LocalX = self.LocalX - (group.X or 0) self.LocalY = self.LocalY - (group.Y or 0) + self.Cr = oCr + self.Cg = oCg + self.Cb = oCb + surface.SetDrawColor(self.Cr,self.Cg,self.Cb) end function ENT:Draw() @@ -153,6 +179,9 @@ function ENT:Draw() surface.DrawRect(0,0,1024,1024) if self.Tree then surface.SetDrawColor(self.Fgred,self.Fggreen,self.Fgblue,255) + self.Cr = self.Fgred + self.Cg = self.Fggreen + self.Cb = self.Fgblue self.BitIndex = 0 self.LocalX = 0 self.LocalY = 0 diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index c12676cf5a..b35e2352ba 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -153,6 +153,7 @@ function TOOL.BuildCPanel(panel) TreeDataHolder:SetHeight(480) DisplayData = vgui.Create("DTree", TreeDataHolder) DisplayData:Dock(FILL) + DisplayData:SetClickOnDragHover( true ) DisplayData:DockMargin(0, 0, 0, 0) --DisplayData.RootNode:AddNode( "Root", "icon16/monitor.png" ) DisplayData.RootNode.group = WireLib.SegmentLCD_Tree @@ -259,7 +260,7 @@ function TOOL.BuildCPanel(panel) children = WireLib.SegmentLCD_Tree.Children group = WireLib.SegmentLCD_Tree end - local newgroup = {Type=GROUP,Children={},X=0,Y=0} + local newgroup = {Type=GROUP,Children={},X=0,Y=0,HasColor=false,R=255,G=255,B=255} children[#children+1] = newgroup local new = node:AddNode( "Group", "icon16/text_list_numbers.png" ) new.group = newgroup @@ -284,7 +285,7 @@ function TOOL.BuildCPanel(panel) children = WireLib.SegmentLCD_Tree.Children group = WireLib.SegmentLCD_Tree end - local newgroup = {Type=UNION,Children={},X=0,Y=0} + local newgroup = {Type=UNION,Children={},X=0,Y=0,HasColor=false,R=255,G=255,B=255} children[#children+1] = newgroup local new = node:AddNode( "Union", "icon16/text_list_bullets.png" ) new.group = newgroup @@ -404,6 +405,48 @@ function TOOL.BuildCPanel(panel) node.group.OffsetY = value end + CheckHasColor = ButtonsHolder:Add( "DCheckBox" ) + function CheckHasColor:OnChange(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil then + return + end + node.group.HasColor = value + end + CheckLabel = ButtonsHolder:Add( "DLabel" ) + CheckLabel:SetText("Has color") + CheckLabel:SetTextColor(Color(0,0,0,255)) + + WangColorR = ButtonsHolder:Add( "DNumberWang" ) + WangColorR:SetMax(255) + function WangColorR:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil then + return + end + node.group.R = value + end + + WangColorG = ButtonsHolder:Add( "DNumberWang" ) + WangColorG:SetMax(255) + function WangColorG:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil then + return + end + node.group.G = value + end + + WangColorB = ButtonsHolder:Add( "DNumberWang" ) + WangColorB:SetMax(255) + function WangColorB:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil then + return + end + node.group.B = value + end + function ButtonsHolder:PerformLayout(w, h) for i,v in ipairs(self.buttons) do v:SetPos((i-1)*w/#self.buttons,0) @@ -423,6 +466,16 @@ function TOOL.BuildCPanel(panel) WangOffsetX:SetSize(w/4,h/3) WangOffsetY:SetPos(w/4*3,h/3*2) WangOffsetY:SetSize(w/4,h/3) + + CheckHasColor:SetPos(1,h/3*2+3) + CheckLabel:SetPos(18,h/3*2) + CheckLabel:SetSize(w/4-18,h/3) + WangColorR:SetPos(w/4,h/3*2) + WangColorR:SetSize(w/4,h/3) + WangColorG:SetPos(w/4*2,h/3*2) + WangColorG:SetSize(w/4,h/3) + WangColorB:SetPos(w/4*3,h/3*2) + WangColorB:SetSize(w/4,h/3) end WangW:SetVisible(false) WangH:SetVisible(false) @@ -431,28 +484,34 @@ function TOOL.BuildCPanel(panel) WangScaleH:SetVisible(false) WangOffsetX:SetVisible(false) WangOffsetY:SetVisible(false) - + WangColorR:SetVisible(false) + WangColorG:SetVisible(false) + WangColorB:SetVisible(false) + CheckHasColor:SetVisible(false) + CheckLabel:SetVisible(false) function DisplayData:DoClick(node) group = node.group + TextSetter:SetVisible(false) + WangScaleW:SetVisible(false) + WangScaleH:SetVisible(false) + WangOffsetX:SetVisible(false) + WangOffsetY:SetVisible(false) + WangW:SetVisible(false) + WangH:SetVisible(false) + WangColorR:SetVisible(false) + WangColorG:SetVisible(false) + WangColorB:SetVisible(false) + CheckHasColor:SetVisible(false) + CheckLabel:SetVisible(false) if group.Type == SEGMENT then - WangX:SetValue(group.X) - WangY:SetValue(group.Y) WangW:SetValue(group.W) WangH:SetValue(group.H) WangW:SetVisible(true) WangH:SetVisible(true) - TextSetter:SetVisible(false) - WangScaleW:SetVisible(false) - WangScaleH:SetVisible(false) - WangOffsetX:SetVisible(false) - WangOffsetY:SetVisible(false) elseif group.Type == MATRIX then - WangX:SetValue(group.X) - WangY:SetValue(group.Y) WangW:SetValue(group.W) WangH:SetValue(group.H) - TextSetter:SetVisible(false) WangScaleW:SetVisible(true) WangScaleH:SetVisible(true) WangOffsetX:SetVisible(true) @@ -464,27 +523,21 @@ function TOOL.BuildCPanel(panel) WangOffsetX:SetValue(group.OffsetX) WangOffsetY:SetValue(group.OffsetY) elseif group.Type == TEXT then - WangX:SetValue(group.X) - WangY:SetValue(group.Y) - WangW:SetVisible(false) - WangH:SetVisible(false) TextSetter:SetVisible(true) TextSetter:SetValue(group.Text) - WangScaleW:SetVisible(false) - WangScaleH:SetVisible(false) - WangOffsetX:SetVisible(false) - WangOffsetY:SetVisible(false) - else - WangX:SetValue(group.X) - WangY:SetValue(group.Y) - WangW:SetVisible(false) - WangH:SetVisible(false) - WangScaleW:SetVisible(false) - WangScaleH:SetVisible(false) - WangOffsetX:SetVisible(false) - WangOffsetY:SetVisible(false) - TextSetter:SetVisible(false) - end + elseif group.Type == GROUP or group.Type == UNION then + WangColorR:SetVisible(true) + WangColorG:SetVisible(true) + WangColorB:SetVisible(true) + CheckHasColor:SetVisible(true) + CheckLabel:SetVisible(true) + WangColorR:SetValue(group.R) + WangColorG:SetValue(group.G) + WangColorB:SetValue(group.B) + CheckHasColor:SetValue(group.HasColor) + end + WangX:SetValue(group.X) + WangY:SetValue(group.Y) return true end From 443738c3865af889a15210b2d28c86cfa6c43b52 Mon Sep 17 00:00:00 2001 From: wav3 Date: Mon, 8 Sep 2025 10:21:12 +0200 Subject: [PATCH 23/43] dedup, and segment names --- lua/wire/stools/multisegmentlcd.lua | 156 +++++++++++++++++++--------- 1 file changed, 108 insertions(+), 48 deletions(-) diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index b35e2352ba..12d12b6e86 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -6,6 +6,13 @@ UNION = 0 SEGMENT = 1 TEXT = 2 MATRIX = 3 +SegmentTypeNames = { +[GROUP] = "Group", +[UNION] = "Union", +[SEGMENT] = "Segment", +[TEXT] = "Text", +[MATRIX] = "Matrix", +} WireLib.SegmentLCD_Tree = { Type=GROUP, @@ -107,17 +114,17 @@ TOOL.ClientConVar = { function BuildNode(v,node,group) local new = nil if v.Type == GROUP then - new = node:AddNode( "Group", "icon16/text_list_numbers.png" ) + new = node:AddNode( v.Text or "Group", "icon16/text_list_numbers.png" ) BuildNodes(new,v) elseif v.Type == UNION then - new = node:AddNode( "Union", "icon16/text_list_bullets.png" ) + new = node:AddNode( v.Text or "Union", "icon16/text_list_bullets.png" ) BuildNodes(new,v) elseif v.Type == TEXT then - new = node:AddNode( "Text", "icon16/bullet_yellow.png" ) + new = node:AddNode( v.Text or "Text", "icon16/bullet_yellow.png" ) elseif v.Type == MATRIX then - new = node:AddNode( "Matrix", "icon16/bullet_red.png" ) + new = node:AddNode( v.Text or "Matrix", "icon16/bullet_red.png" ) else - new = node:AddNode( "Segment", "icon16/bullet_green.png" ) + new = node:AddNode( v.Text or "Segment", "icon16/bullet_green.png" ) end new.group = v new.parentgroup = group @@ -162,13 +169,12 @@ function TOOL.BuildCPanel(panel) ButtonsHolder:Dock(TOP) ButtonsHolder:DockMargin(0, 0, 0, 0) ButtonsHolder.buttons = {} - ButtonsHolder:SetHeight(60) + ButtonsHolder:SetHeight(72) AddSegment = ButtonsHolder:Add( "DButton" ) AddSegment:SetText( "Add Segment" ) ButtonsHolder.buttons[1] = AddSegment - function AddSegment:DoClick() - local node = DisplayData:GetSelectedItem() + function AddSegmentI(node) if node == nil then node = DisplayData.RootNode end @@ -189,12 +195,15 @@ function TOOL.BuildCPanel(panel) new.group = newgroup new.parentgroup = group end + function AddSegment:DoClick() + local node = DisplayData:GetSelectedItem() + AddSegmentI(node) + end AddText = ButtonsHolder:Add( "DButton" ) AddText:SetText( "Add Text" ) ButtonsHolder.buttons[2] = AddText - function AddText:DoClick() - local node = DisplayData:GetSelectedItem() + function AddTextI(node) if node == nil then node = DisplayData.RootNode end @@ -209,18 +218,21 @@ function TOOL.BuildCPanel(panel) children = WireLib.SegmentLCD_Tree.Children group = WireLib.SegmentLCD_Tree end - local newgroup = {Type=TEXT, X=30, Y=0, Text="Hello"} + local newgroup = {Type=TEXT, X=30, Y=0, Text="Text"} children[#children+1] = newgroup local new = node:AddNode( "Text", "icon16/bullet_yellow.png" ) new.group = newgroup new.parentgroup = group end + function AddText:DoClick() + local node = DisplayData:GetSelectedItem() + AddTextI(node) + end AddMatrix = ButtonsHolder:Add( "DButton" ) AddMatrix:SetText( "Add Matrix" ) ButtonsHolder.buttons[3] = AddMatrix - function AddMatrix:DoClick() - local node = DisplayData:GetSelectedItem() + function AddMatrixI(node) if node == nil then node = DisplayData.RootNode end @@ -241,12 +253,16 @@ function TOOL.BuildCPanel(panel) new.group = newgroup new.parentgroup = group end + function AddMatrix:DoClick() + local node = DisplayData:GetSelectedItem() + AddMatrixI(node) + end AddGroup = ButtonsHolder:Add( "DButton" ) AddGroup:SetText( "Add Group" ) ButtonsHolder.buttons[4] = AddGroup - function AddGroup:DoClick() - local node = DisplayData:GetSelectedItem() + function AddGroupI(node) + if node == nil then node = DisplayData.RootNode end @@ -263,15 +279,19 @@ function TOOL.BuildCPanel(panel) local newgroup = {Type=GROUP,Children={},X=0,Y=0,HasColor=false,R=255,G=255,B=255} children[#children+1] = newgroup local new = node:AddNode( "Group", "icon16/text_list_numbers.png" ) + new:SetExpanded(true); new.group = newgroup new.parentgroup = group end + function AddGroup:DoClick() + local node = DisplayData:GetSelectedItem() + AddGroupI(node) + end AddUnion = ButtonsHolder:Add( "DButton" ) AddUnion:SetText( "Add Union" ) ButtonsHolder.buttons[5] = AddUnion - function AddUnion:DoClick() - local node = DisplayData:GetSelectedItem() + function AddUnionI(node) if node == nil then node = DisplayData.RootNode end @@ -288,13 +308,34 @@ function TOOL.BuildCPanel(panel) local newgroup = {Type=UNION,Children={},X=0,Y=0,HasColor=false,R=255,G=255,B=255} children[#children+1] = newgroup local new = node:AddNode( "Union", "icon16/text_list_bullets.png" ) + new:SetExpanded(true); new.group = newgroup new.parentgroup = group end + function AddUnion:DoClick() + local node = DisplayData:GetSelectedItem() + AddUnionI(node) + end Remove = ButtonsHolder:Add( "DButton" ) Remove:SetText( "Remove" ) ButtonsHolder.buttons[6] = Remove + function RemoveI(node) + if node == nil then + return + end + local parentgroup = node.parentgroup + if parentgroup == nil then + return + end + for i,v in pairs(parentgroup.Children) do + if v == node.group then + table.remove(parentgroup.Children,i) + node:Remove() + return + end + end + end function Remove:DoClick() local node = DisplayData:GetSelectedItem() if node == nil then @@ -359,10 +400,17 @@ function TOOL.BuildCPanel(panel) TextSetter = ButtonsHolder:Add( "DTextEntry" ) function TextSetter:OnValueChange(value) local node = DisplayData:GetSelectedItem() - if node == nil or node.group == nil or node.group.Type ~= TEXT then + if node == nil or node.group == nil then return end - node.group.Text = value + if value == "" then + node:SetText(SegmentTypeNames[node.group.Type]) + node.group.Text = nil + else + node:SetText(value) + node.group.Text = value + end + end WangScaleW = ButtonsHolder:Add( "DNumberWang" ) @@ -448,38 +496,39 @@ function TOOL.BuildCPanel(panel) end function ButtonsHolder:PerformLayout(w, h) + local rowh = h/4 for i,v in ipairs(self.buttons) do v:SetPos((i-1)*w/#self.buttons,0) - v:SetSize(w/#self.buttons,h/3) + v:SetSize(w/#self.buttons,rowh) end for i,v in ipairs(self.textboxes) do - v:SetPos((i-1)*w/#self.textboxes,h/3) - v:SetSize(w/#self.textboxes,h/3) - end - TextSetter:SetPos(0,h/3*2) - TextSetter:SetSize(w,h/3) - WangScaleW:SetPos(0,h/3*2) - WangScaleW:SetSize(w/4,h/3) - WangScaleH:SetPos(w/4,h/3*2) - WangScaleH:SetSize(w/4,h/3) - WangOffsetX:SetPos(w/4*2,h/3*2) - WangOffsetX:SetSize(w/4,h/3) - WangOffsetY:SetPos(w/4*3,h/3*2) - WangOffsetY:SetSize(w/4,h/3) + v:SetPos((i-1)*w/#self.textboxes,rowh) + v:SetSize(w/#self.textboxes,rowh) + end + + TextSetter:SetPos(0,rowh*3) + TextSetter:SetSize(w,rowh) + WangScaleW:SetPos(0,rowh*2) + WangScaleW:SetSize(w/4,rowh) + WangScaleH:SetPos(w/4,rowh*2) + WangScaleH:SetSize(w/4,rowh) + WangOffsetX:SetPos(w/4*2,rowh*2) + WangOffsetX:SetSize(w/4,rowh) + WangOffsetY:SetPos(w/4*3,rowh*2) + WangOffsetY:SetSize(w/4,rowh) - CheckHasColor:SetPos(1,h/3*2+3) - CheckLabel:SetPos(18,h/3*2) - CheckLabel:SetSize(w/4-18,h/3) - WangColorR:SetPos(w/4,h/3*2) - WangColorR:SetSize(w/4,h/3) - WangColorG:SetPos(w/4*2,h/3*2) - WangColorG:SetSize(w/4,h/3) - WangColorB:SetPos(w/4*3,h/3*2) - WangColorB:SetSize(w/4,h/3) + CheckHasColor:SetPos(1,rowh*2+3) + CheckLabel:SetPos(18,rowh*2) + CheckLabel:SetSize(w/4-18,rowh) + WangColorR:SetPos(w/4,rowh*2) + WangColorR:SetSize(w/4,rowh) + WangColorG:SetPos(w/4*2,rowh*2) + WangColorG:SetSize(w/4,rowh) + WangColorB:SetPos(w/4*3,rowh*2) + WangColorB:SetSize(w/4,rowh) end WangW:SetVisible(false) WangH:SetVisible(false) - TextSetter:SetVisible(false) WangScaleW:SetVisible(false) WangScaleH:SetVisible(false) WangOffsetX:SetVisible(false) @@ -492,7 +541,6 @@ function TOOL.BuildCPanel(panel) function DisplayData:DoClick(node) group = node.group - TextSetter:SetVisible(false) WangScaleW:SetVisible(false) WangScaleH:SetVisible(false) WangOffsetX:SetVisible(false) @@ -522,9 +570,6 @@ function TOOL.BuildCPanel(panel) WangScaleH:SetValue(group.ScaleH) WangOffsetX:SetValue(group.OffsetX) WangOffsetY:SetValue(group.OffsetY) - elseif group.Type == TEXT then - TextSetter:SetVisible(true) - TextSetter:SetValue(group.Text) elseif group.Type == GROUP or group.Type == UNION then WangColorR:SetVisible(true) WangColorG:SetVisible(true) @@ -538,16 +583,29 @@ function TOOL.BuildCPanel(panel) end WangX:SetValue(group.X) WangY:SetValue(group.Y) + TextSetter:SetValue(group.Text or "") return true end function DisplayData:DoRightClick(node) local Menu = DermaMenu() + Menu:AddOption( "Rename" ) Menu:AddOption( "Copy" ) Menu:AddOption( "Paste" ) + local InsertM, MMOption = Menu:AddSubMenu( "Insert" ) + InsertM:AddOption( "Union", function() AddUnionI(node) end ) + InsertM:AddOption( "Group", function() AddGroupI(node) end ) + InsertM:AddOption( "Segment", function() AddSegmentI(node) end ) + InsertM:AddOption( "Matrix", function() AddMatrixI(node) end ) + InsertM:AddOption( "Text", function() AddTextI(node) end ) + Menu:AddSpacer() + Menu:AddOption( "Remove" ) Menu:Open() + print("AAA") function Menu:OptionSelected(option, optionText) - if optionText == "Copy" then + if optionText == "Rename" then + + elseif optionText == "Copy" then SegmentLCD_Clipboard = table.Copy(node.group) elseif optionText == "Paste" then if node.group.Children then @@ -559,6 +617,8 @@ function TOOL.BuildCPanel(panel) WireLib.SegmentLCD_Tree.Children[#WireLib.SegmentLCD_Tree.Children+1] = newgroup BuildNode(newgroup,DisplayData.RootNode,WireLib.SegmentLCD_Tree) end + elseif optionText == "Remove" then + RemoveI(node) end end return true From 83b4edfd2b5f68defa4e03585ddb1518e088c631 Mon Sep 17 00:00:00 2001 From: wav3 Date: Mon, 8 Sep 2025 10:30:34 +0200 Subject: [PATCH 24/43] no more enter --- lua/wire/stools/multisegmentlcd.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index 12d12b6e86..f018700706 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -398,7 +398,8 @@ function TOOL.BuildCPanel(panel) ButtonsHolder.textboxes[4] = WangH TextSetter = ButtonsHolder:Add( "DTextEntry" ) - function TextSetter:OnValueChange(value) + function TextSetter:OnChange() + local value = TextSetter:GetText() local node = DisplayData:GetSelectedItem() if node == nil or node.group == nil then return From a8abd904b5515a8ca521a1acdaeb72ece914d035 Mon Sep 17 00:00:00 2001 From: wav3 Date: Mon, 8 Sep 2025 19:01:38 +0200 Subject: [PATCH 25/43] Fading --- .../gmod_wire_multisegmentlcd/cl_init.lua | 54 +++++++++++++++---- lua/wire/stools/multisegmentlcd.lua | 48 +++++++++++++++++ 2 files changed, 91 insertions(+), 11 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index 70ab720ef0..6f7173835a 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -3,6 +3,7 @@ include("shared.lua") function ENT:Initialize() self.Memory = {} + self.Fade = {} self.InteractiveData = {} self.LastButtons = {} @@ -70,29 +71,56 @@ function ENT:WriteCell(Address,value) self.Memory[math.floor(Address)] = value end +function ENT:Transform(x,y) + return { + x=x*self.LocalXX+y*self.LocalXY+self.LocalX, + y=x*self.LocalYX+y*self.LocalYY+self.LocalY + } +end + function ENT:DrawSegment(segment) + self.Fade[self.BitIndex] = (self.Fade[self.BitIndex] or 0)*0.92 if bit.band(self.Memory[bit.rshift(self.BitIndex,3)] or 0,bit.lshift(1,bit.band(self.BitIndex,7))) ~= 0 then - surface.DrawRect(segment.X+self.LocalX,segment.Y+self.LocalY,segment.W,segment.H) + self.Fade[self.BitIndex] = self.Fade[self.BitIndex] + 0.8 end + surface.SetDrawColor(self.Cr,self.Cg,self.Cb,self.Fade[self.BitIndex]*255) + self.LocalX = self.LocalX + segment.X + self.LocalY = self.LocalY + segment.Y + --[[local Rect = { + self:Transform(0,segment.H), + self:Transform(0,0), + self:Transform(segment.W,0), + self:Transform(segment.W,segment.H) + } + surface.DrawPoly(Rect) + ]] + surface.DrawRect(self.LocalX,self.LocalY,segment.W,segment.H) + self.LocalX = self.LocalX - segment.X + self.LocalY = self.LocalY - segment.Y self.BitIndex = self.BitIndex+1 end function ENT:DrawText(text) + self.Fade[self.BitIndex] = (self.Fade[self.BitIndex] or 0)*0.92 if bit.band(self.Memory[bit.rshift(self.BitIndex,3)] or 0,bit.lshift(1,bit.band(self.BitIndex,7))) ~= 0 then - surface.SetTextPos(text.X+self.LocalX,text.Y+self.LocalY) - surface.SetFont("Default") - surface.SetTextColor(self.Cr,self.Cg,self.Cb,255) - surface.DrawText(text.Text) + self.Fade[self.BitIndex] = self.Fade[self.BitIndex] + 0.08 end + surface.SetTextPos(text.X+self.LocalX,text.Y+self.LocalY) + surface.SetFont("Default") + surface.SetTextColor(self.Cr,self.Cg,self.Cb,self.Fade[self.BitIndex]*255) + surface.DrawText(text.Text) self.BitIndex = self.BitIndex+1 end function ENT:DrawMatrix(matrix) for y = 0,matrix.H-1 do for x = 0,matrix.W-1 do + self.Fade[self.BitIndex] = (self.Fade[self.BitIndex] or 0)*0.92 if bit.band(self.Memory[bit.rshift(self.BitIndex,3)] or 0,bit.lshift(1,bit.band(self.BitIndex,7))) ~= 0 then - surface.DrawRect(matrix.X+self.LocalX+x*matrix.OffsetX,matrix.Y+self.LocalY+y*matrix.OffsetY,matrix.ScaleW,matrix.ScaleH) + self.Fade[self.BitIndex] = self.Fade[self.BitIndex] + 0.08 end + surface.SetDrawColor(self.Cr,self.Cg,self.Cb,self.Fade[self.BitIndex]*255) + surface.DrawRect(matrix.X+self.LocalX+x*matrix.OffsetX,matrix.Y+self.LocalY+y*matrix.OffsetY,matrix.ScaleW,matrix.ScaleH) self.BitIndex = self.BitIndex+1 end end @@ -109,7 +137,7 @@ function ENT:DrawUnion(group) self.Cr = group.R self.Cg = group.G self.Cb = group.B - surface.SetDrawColor(self.Cr,self.Cg,self.Cb) + --surface.SetDrawColor(self.Cr,self.Cg,self.Cb,255) end self.LocalX = self.LocalX + (group.X or 0) self.LocalY = self.LocalY + (group.Y or 0) @@ -136,7 +164,7 @@ function ENT:DrawUnion(group) self.Cr = oCr self.Cg = oCg self.Cb = oCb - surface.SetDrawColor(self.Cr,self.Cg,self.Cb) + --surface.SetDrawColor(self.Cr,self.Cg,self.Cb,255) end function ENT:DrawGroup(group) @@ -147,7 +175,7 @@ function ENT:DrawGroup(group) self.Cr = group.R self.Cg = group.G self.Cb = group.B - surface.SetDrawColor(self.Cr,self.Cg,self.Cb) + --surface.SetDrawColor(self.Cr,self.Cg,self.Cb,255) end self.LocalX = self.LocalX + (group.X or 0) self.LocalY = self.LocalY + (group.Y or 0) @@ -169,7 +197,7 @@ function ENT:DrawGroup(group) self.Cr = oCr self.Cg = oCg self.Cb = oCb - surface.SetDrawColor(self.Cr,self.Cg,self.Cb) + --surface.SetDrawColor(self.Cr,self.Cg,self.Cb,255) end function ENT:Draw() @@ -182,9 +210,13 @@ function ENT:Draw() self.Cr = self.Fgred self.Cg = self.Fggreen self.Cb = self.Fgblue - self.BitIndex = 0 + self.LocalXX = 1 + self.LocalXY = 0 + self.LocalYX = 0 + self.LocalYY = 1 self.LocalX = 0 self.LocalY = 0 + self.BitIndex = 0 self:DrawGroup(self.Tree) end end) diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index f018700706..fb75fe72c3 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -496,6 +496,37 @@ function TOOL.BuildCPanel(panel) node.group.B = value end + WangRotation = ButtonsHolder:Add( "DNumberWang" ) + WangRotation:SetMax(360) + WangRotation:SetMin(-360) + function WangRotation:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil then + return + end + node.group.Rotation = value + end + + WangSkewX = ButtonsHolder:Add( "DNumberWang" ) + WangSkewX:SetMax(4096) + function WangSkewX:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil then + return + end + node.group.SkewX = value + end + + WangSkewY = ButtonsHolder:Add( "DNumberWang" ) + WangSkewY:SetMax(4096) + function WangSkewY:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil then + return + end + node.group.SkewY = value + end + function ButtonsHolder:PerformLayout(w, h) local rowh = h/4 for i,v in ipairs(self.buttons) do @@ -527,6 +558,13 @@ function TOOL.BuildCPanel(panel) WangColorG:SetSize(w/4,rowh) WangColorB:SetPos(w/4*3,rowh*2) WangColorB:SetSize(w/4,rowh) + + WangRotation:SetPos(0,rowh*2) + WangRotation:SetSize(w/4,rowh) + WangSkewX:SetPos(w/4,rowh*2) + WangSkewX:SetSize(w/4,rowh) + WangSkewY:SetPos(w/4*2,rowh*2) + WangSkewY:SetSize(w/4,rowh) end WangW:SetVisible(false) WangH:SetVisible(false) @@ -539,6 +577,10 @@ function TOOL.BuildCPanel(panel) WangColorB:SetVisible(false) CheckHasColor:SetVisible(false) CheckLabel:SetVisible(false) + WangRotation:SetVisible(false) + WangSkewX:SetVisible(false) + WangSkewY:SetVisible(false) + function DisplayData:DoClick(node) group = node.group @@ -553,11 +595,17 @@ function TOOL.BuildCPanel(panel) WangColorB:SetVisible(false) CheckHasColor:SetVisible(false) CheckLabel:SetVisible(false) + WangRotation:SetVisible(false) + WangSkewX:SetVisible(false) + WangSkewY:SetVisible(false) if group.Type == SEGMENT then WangW:SetValue(group.W) WangH:SetValue(group.H) WangW:SetVisible(true) WangH:SetVisible(true) + WangRotation:SetVisible(true) + WangSkewX:SetVisible(true) + WangSkewY:SetVisible(true) elseif group.Type == MATRIX then WangW:SetValue(group.W) WangH:SetValue(group.H) From 0e761557357071165dde827cff39e6c2770a95a5 Mon Sep 17 00:00:00 2001 From: wav3 Date: Mon, 8 Sep 2025 19:42:09 +0200 Subject: [PATCH 26/43] in the bad bad code there are bad bad practices with bad bad perf --- .../gmod_wire_multisegmentlcd/cl_init.lua | 100 +++++++++++++++--- lua/wire/stools/multisegmentlcd.lua | 45 ++++---- 2 files changed, 107 insertions(+), 38 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index 6f7173835a..ca5696d9b0 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -78,25 +78,61 @@ function ENT:Transform(x,y) } end +function ENT:TransformOffset(x,y) + return { + x=x*self.LocalXX+y*self.LocalXY, + y=x*self.LocalYX+y*self.LocalYY + } +end + +function ENT:PushTransform(XX,XY,YX,YY) + self.TransformStack[#self.TransformStack + 1] = {self.LocalXX,self.LocalXY,self.LocalYX,self.LocalYY} + local oXX = self.LocalXX + local oXY = self.LocalXY + local oYX = self.LocalYX + local oYY = self.LocalYY + + local nXX = oXX*XX + oXY*YX + local nXY = oXY*YY + oXX*XY + local nYX = oYX*XX + oYY*YX + local nYY = oYY*YY + oYX*XY + + self.LocalXX = nXX + self.LocalXY = nXY + self.LocalYX = nYX + self.LocalYY = nYY +end + +function ENT:PopTransform() + self.LocalXX,self.LocalXY,self.LocalYX,self.LocalYY = unpack(self.TransformStack[#self.TransformStack]) + self.TransformStack[#self.TransformStack] = nil +end + function ENT:DrawSegment(segment) self.Fade[self.BitIndex] = (self.Fade[self.BitIndex] or 0)*0.92 if bit.band(self.Memory[bit.rshift(self.BitIndex,3)] or 0,bit.lshift(1,bit.band(self.BitIndex,7))) ~= 0 then self.Fade[self.BitIndex] = self.Fade[self.BitIndex] + 0.8 end surface.SetDrawColor(self.Cr,self.Cg,self.Cb,self.Fade[self.BitIndex]*255) - self.LocalX = self.LocalX + segment.X - self.LocalY = self.LocalY + segment.Y - --[[local Rect = { + local transformedLocal = self:TransformOffset(segment.X or 0,segment.Y or 0) + self.LocalX = self.LocalX + transformedLocal.x + self.LocalY = self.LocalY + transformedLocal.y + local angle = math.rad(segment.Rotation or 0) + self:PushTransform(math.cos(angle), + math.sin(angle)-(segment.SkewX or 0), + -math.sin(angle)+(segment.SkewY or 0), + math.cos(angle)) + local Rect = { self:Transform(0,segment.H), self:Transform(0,0), self:Transform(segment.W,0), self:Transform(segment.W,segment.H) } surface.DrawPoly(Rect) - ]] - surface.DrawRect(self.LocalX,self.LocalY,segment.W,segment.H) - self.LocalX = self.LocalX - segment.X - self.LocalY = self.LocalY - segment.Y + self:PopTransform() + --surface.DrawRect(self.LocalX,self.LocalY,segment.W,segment.H) + self.LocalX = self.LocalX - transformedLocal.x + self.LocalY = self.LocalY - transformedLocal.y self.BitIndex = self.BitIndex+1 end @@ -105,10 +141,15 @@ function ENT:DrawText(text) if bit.band(self.Memory[bit.rshift(self.BitIndex,3)] or 0,bit.lshift(1,bit.band(self.BitIndex,7))) ~= 0 then self.Fade[self.BitIndex] = self.Fade[self.BitIndex] + 0.08 end - surface.SetTextPos(text.X+self.LocalX,text.Y+self.LocalY) + local transformedLocal = self:TransformOffset(text.X or 0,text.Y or 0) + self.LocalX = self.LocalX + transformedLocal.x + self.LocalY = self.LocalY + transformedLocal.y + surface.SetTextPos(self.LocalX,self.LocalY) surface.SetFont("Default") surface.SetTextColor(self.Cr,self.Cg,self.Cb,self.Fade[self.BitIndex]*255) surface.DrawText(text.Text) + self.LocalX = self.LocalX - transformedLocal.x + self.LocalY = self.LocalY - transformedLocal.y self.BitIndex = self.BitIndex+1 end @@ -119,8 +160,23 @@ function ENT:DrawMatrix(matrix) if bit.band(self.Memory[bit.rshift(self.BitIndex,3)] or 0,bit.lshift(1,bit.band(self.BitIndex,7))) ~= 0 then self.Fade[self.BitIndex] = self.Fade[self.BitIndex] + 0.08 end + + local transformedLocal = self:TransformOffset(matrix.X+x*matrix.OffsetX,matrix.Y+y*matrix.OffsetY) + self.LocalX = self.LocalX + transformedLocal.x + self.LocalY = self.LocalY + transformedLocal.y surface.SetDrawColor(self.Cr,self.Cg,self.Cb,self.Fade[self.BitIndex]*255) - surface.DrawRect(matrix.X+self.LocalX+x*matrix.OffsetX,matrix.Y+self.LocalY+y*matrix.OffsetY,matrix.ScaleW,matrix.ScaleH) + local Rect = { + self:Transform(0,matrix.ScaleH), + self:Transform(0,0), + self:Transform(matrix.ScaleW,0), + self:Transform(matrix.ScaleW,matrix.ScaleH) + } + surface.DrawPoly(Rect) + + + --surface.DrawRect(self.LocalX,self.LocalY,matrix.ScaleW,matrix.ScaleH) + self.LocalX = self.LocalX - transformedLocal.x + self.LocalY = self.LocalY - transformedLocal.y self.BitIndex = self.BitIndex+1 end end @@ -139,8 +195,9 @@ function ENT:DrawUnion(group) self.Cb = group.B --surface.SetDrawColor(self.Cr,self.Cg,self.Cb,255) end - self.LocalX = self.LocalX + (group.X or 0) - self.LocalY = self.LocalY + (group.Y or 0) + local transformedLocal = self:TransformOffset(group.X or 0,group.Y or 0) + self.LocalX = self.LocalX + transformedLocal.x + self.LocalY = self.LocalY + transformedLocal.y local savedindex = self.BitIndex local biggestindex = savedindex for k,v in ipairs(group.Children) do @@ -159,8 +216,8 @@ function ENT:DrawUnion(group) self.BitIndex = savedindex end self.BitIndex = biggestindex - self.LocalX = self.LocalX - (group.X or 0) - self.LocalY = self.LocalY - (group.Y or 0) + self.LocalX = self.LocalX - transformedLocal.x + self.LocalY = self.LocalY - transformedLocal.y self.Cr = oCr self.Cg = oCg self.Cb = oCb @@ -177,8 +234,14 @@ function ENT:DrawGroup(group) self.Cb = group.B --surface.SetDrawColor(self.Cr,self.Cg,self.Cb,255) end - self.LocalX = self.LocalX + (group.X or 0) - self.LocalY = self.LocalY + (group.Y or 0) + local transformedLocal = self:TransformOffset(group.X or 0,group.Y or 0) + self.LocalX = self.LocalX + transformedLocal.x + self.LocalY = self.LocalY + transformedLocal.y + local angle = math.rad(group.Rotation or 0) + self:PushTransform(math.cos(angle), + math.sin(angle)-(group.SkewX or 0), + -math.sin(angle)+(group.SkewY or 0), + math.cos(angle)) for k,v in ipairs(group.Children) do if v.Type == GROUP then self:DrawGroup(v) @@ -192,8 +255,9 @@ function ENT:DrawGroup(group) self:DrawMatrix(v) end end - self.LocalX = self.LocalX - (group.X or 0) - self.LocalY = self.LocalY - (group.Y or 0) + self:PopTransform() + self.LocalX = self.LocalX - transformedLocal.x + self.LocalY = self.LocalY - transformedLocal.y self.Cr = oCr self.Cg = oCg self.Cb = oCb @@ -217,6 +281,8 @@ function ENT:Draw() self.LocalX = 0 self.LocalY = 0 self.BitIndex = 0 + draw.NoTexture() + self.TransformStack = {} self:DrawGroup(self.Tree) end end) diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index fb75fe72c3..4371d12a42 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -528,6 +528,7 @@ function TOOL.BuildCPanel(panel) end function ButtonsHolder:PerformLayout(w, h) + local roww = w/7 local rowh = h/4 for i,v in ipairs(self.buttons) do v:SetPos((i-1)*w/#self.buttons,0) @@ -537,34 +538,33 @@ function TOOL.BuildCPanel(panel) v:SetPos((i-1)*w/#self.textboxes,rowh) v:SetSize(w/#self.textboxes,rowh) end - TextSetter:SetPos(0,rowh*3) TextSetter:SetSize(w,rowh) WangScaleW:SetPos(0,rowh*2) - WangScaleW:SetSize(w/4,rowh) - WangScaleH:SetPos(w/4,rowh*2) - WangScaleH:SetSize(w/4,rowh) - WangOffsetX:SetPos(w/4*2,rowh*2) - WangOffsetX:SetSize(w/4,rowh) - WangOffsetY:SetPos(w/4*3,rowh*2) - WangOffsetY:SetSize(w/4,rowh) + WangScaleW:SetSize(roww,rowh) + WangScaleH:SetPos(roww,rowh*2) + WangScaleH:SetSize(roww,rowh) + WangOffsetX:SetPos(roww*2,rowh*2) + WangOffsetX:SetSize(roww,rowh) + WangOffsetY:SetPos(roww*3,rowh*2) + WangOffsetY:SetSize(roww,rowh) CheckHasColor:SetPos(1,rowh*2+3) CheckLabel:SetPos(18,rowh*2) - CheckLabel:SetSize(w/4-18,rowh) - WangColorR:SetPos(w/4,rowh*2) - WangColorR:SetSize(w/4,rowh) - WangColorG:SetPos(w/4*2,rowh*2) - WangColorG:SetSize(w/4,rowh) - WangColorB:SetPos(w/4*3,rowh*2) - WangColorB:SetSize(w/4,rowh) + CheckLabel:SetSize(roww-18,rowh) + WangColorR:SetPos(roww,rowh*2) + WangColorR:SetSize(roww,rowh) + WangColorG:SetPos(roww*2,rowh*2) + WangColorG:SetSize(roww,rowh) + WangColorB:SetPos(roww*3,rowh*2) + WangColorB:SetSize(roww,rowh) - WangRotation:SetPos(0,rowh*2) - WangRotation:SetSize(w/4,rowh) - WangSkewX:SetPos(w/4,rowh*2) - WangSkewX:SetSize(w/4,rowh) - WangSkewY:SetPos(w/4*2,rowh*2) - WangSkewY:SetSize(w/4,rowh) + WangRotation:SetPos(roww*4,rowh*2) + WangRotation:SetSize(roww,rowh) + WangSkewX:SetPos(roww*5,rowh*2) + WangSkewX:SetSize(roww,rowh) + WangSkewY:SetPos(roww*6,rowh*2) + WangSkewY:SetSize(roww,rowh) end WangW:SetVisible(false) WangH:SetVisible(false) @@ -629,6 +629,9 @@ function TOOL.BuildCPanel(panel) WangColorG:SetValue(group.G) WangColorB:SetValue(group.B) CheckHasColor:SetValue(group.HasColor) + WangRotation:SetVisible(true) + WangSkewX:SetVisible(true) + WangSkewY:SetVisible(true) end WangX:SetValue(group.X) WangY:SetValue(group.Y) From 60c1fe265fcc674777e74e8969a150fc816ea3d3 Mon Sep 17 00:00:00 2001 From: wav3 Date: Mon, 8 Sep 2025 20:45:17 +0200 Subject: [PATCH 27/43] oh my --- .../gmod_wire_multisegmentlcd/cl_init.lua | 29 +++++++++----- lua/wire/stools/multisegmentlcd.lua | 39 ++++++++++++++++++- 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index ca5696d9b0..f0ab815796 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -122,11 +122,17 @@ function ENT:DrawSegment(segment) math.sin(angle)-(segment.SkewX or 0), -math.sin(angle)+(segment.SkewY or 0), math.cos(angle)) + --self:Transform(,segment.H/2+(segment.H*(segment.BevelSkew or 0))), + local bevel = math.min(segment.H,segment.W)/2*(segment.Bevel or 0) local Rect = { - self:Transform(0,segment.H), - self:Transform(0,0), - self:Transform(segment.W,0), - self:Transform(segment.W,segment.H) + self:Transform(bevel,segment.H), + self:Transform(0,segment.H-bevel), + self:Transform(0,bevel), + self:Transform(bevel,0), + self:Transform(segment.W-bevel,0), + self:Transform(segment.W,bevel), + self:Transform(segment.W,segment.H-bevel), + self:Transform(segment.W-bevel,segment.H) } surface.DrawPoly(Rect) self:PopTransform() @@ -266,10 +272,12 @@ end function ENT:Draw() self:DrawModel() - self.GPU:RenderToGPU(function() + self.GPU:RenderToWorld(nil, self.ResolutionH, function(x, y, w, h) + draw.NoTexture() surface.SetDrawColor(self.Bgred,self.Bggreen,self.Bgblue,255) - surface.DrawRect(0,0,1024,1024) + surface.DrawRect(x,y,w,h) if self.Tree then + --render.SetScissorRect(x,y,w,h, true) surface.SetDrawColor(self.Fgred,self.Fggreen,self.Fgblue,255) self.Cr = self.Fgred self.Cg = self.Fggreen @@ -278,15 +286,16 @@ function ENT:Draw() self.LocalXY = 0 self.LocalYX = 0 self.LocalYY = 1 - self.LocalX = 0 - self.LocalY = 0 + self.LocalX = x + self.LocalY = y self.BitIndex = 0 - draw.NoTexture() + self.TransformStack = {} self:DrawGroup(self.Tree) + --render.SetScissorRect( 0, 0, 0, 0, false ) end end) - self.GPU:Render(0,0,1024,1024,nil,-(1024-self.ResolutionW)/1024,-(1024-self.ResolutionH)/1024) + --self.GPU:Render(0,0,1024,1024,nil,-(1024-self.ResolutionW)/1024,-(1024-self.ResolutionH)/1024) Wire_Render(self) end diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index 4371d12a42..d7e6c91db3 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -517,6 +517,27 @@ function TOOL.BuildCPanel(panel) node.group.SkewX = value end + WangBevel = ButtonsHolder:Add( "DNumberWang" ) + WangBevel:SetMax(1024) + function WangBevel:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil then + return + end + node.group.Bevel = value + end + + WangBevelSkew = ButtonsHolder:Add( "DNumberWang" ) + WangBevelSkew:SetMax(1024) + WangBevelSkew:SetMin(-1024) + function WangBevelSkew:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil then + return + end + node.group.BevelSkew = value + end + WangSkewY = ButtonsHolder:Add( "DNumberWang" ) WangSkewY:SetMax(4096) function WangSkewY:OnValueChanged(value) @@ -565,6 +586,11 @@ function TOOL.BuildCPanel(panel) WangSkewX:SetSize(roww,rowh) WangSkewY:SetPos(roww*6,rowh*2) WangSkewY:SetSize(roww,rowh) + + WangBevel:SetPos(0,rowh*2) + WangBevel:SetSize(roww,rowh) + WangBevelSkew:SetPos(roww,rowh*2) + WangBevelSkew:SetSize(roww,rowh) end WangW:SetVisible(false) WangH:SetVisible(false) @@ -580,7 +606,8 @@ function TOOL.BuildCPanel(panel) WangRotation:SetVisible(false) WangSkewX:SetVisible(false) WangSkewY:SetVisible(false) - + WangBevel:SetVisible(false) + WangBevelSkew:SetVisible(false) function DisplayData:DoClick(node) group = node.group @@ -598,6 +625,8 @@ function TOOL.BuildCPanel(panel) WangRotation:SetVisible(false) WangSkewX:SetVisible(false) WangSkewY:SetVisible(false) + WangBevel:SetVisible(false) + WangBevelSkew:SetVisible(false) if group.Type == SEGMENT then WangW:SetValue(group.W) WangH:SetValue(group.H) @@ -606,6 +635,14 @@ function TOOL.BuildCPanel(panel) WangRotation:SetVisible(true) WangSkewX:SetVisible(true) WangSkewY:SetVisible(true) + WangBevel:SetVisible(true) + WangBevelSkew:SetVisible(true) + + WangRotation:SetValue(group.Rotation or 0) + WangSkewX:SetValue(group.SkewX or 0) + WangSkewY:SetValue(group.SkewY or 0) + WangBevel:SetValue(group.Bevel or 0) + WangBevelSkew:SetValue(group.BevelSkew or 0) elseif group.Type == MATRIX then WangW:SetValue(group.W) WangH:SetValue(group.H) From bf9bed0557bbba903492f89775b35cf6121514a3 Mon Sep 17 00:00:00 2001 From: wav3 Date: Tue, 9 Sep 2025 11:32:10 +0200 Subject: [PATCH 28/43] Begin --- .../gmod_wire_multisegmentlcd/cl_init.lua | 106 ++++++++++++------ 1 file changed, 73 insertions(+), 33 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index f0ab815796..0897fe9278 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -31,6 +31,8 @@ function ENT:Initialize() GPULib.ClientCacheCallback(self,function(Address,Value) self:WriteCell(Address,Value) end) + + self.TreeMesh = Mesh() WireLib.netRegister(self) end @@ -73,15 +75,15 @@ end function ENT:Transform(x,y) return { - x=x*self.LocalXX+y*self.LocalXY+self.LocalX, - y=x*self.LocalYX+y*self.LocalYY+self.LocalY + x*self.LocalXX+y*self.LocalXY+self.LocalX, + x*self.LocalYX+y*self.LocalYY+self.LocalY } end function ENT:TransformOffset(x,y) return { - x=x*self.LocalXX+y*self.LocalXY, - y=x*self.LocalYX+y*self.LocalYY + x*self.LocalXX+y*self.LocalXY, + x*self.LocalYX+y*self.LocalYY } end @@ -108,15 +110,27 @@ function ENT:PopTransform() self.TransformStack[#self.TransformStack] = nil end +function ENT:AddPoly(poly) + local u = ((self.BitIndex%1024)+0.5)/1024 + local v = (math.floor(self.BitIndex/1024)+0.5)/1024 + mesh.Begin(MATERIAL_POLYGON,#poly) + for i = 1,#poly do + mesh.Position(Vector(poly[i][1],poly[i][2],0)) + mesh.TexCoord(0, u, v) + mesh.AdvanceVertex() + end + mesh.End() +end + function ENT:DrawSegment(segment) self.Fade[self.BitIndex] = (self.Fade[self.BitIndex] or 0)*0.92 if bit.band(self.Memory[bit.rshift(self.BitIndex,3)] or 0,bit.lshift(1,bit.band(self.BitIndex,7))) ~= 0 then self.Fade[self.BitIndex] = self.Fade[self.BitIndex] + 0.8 end - surface.SetDrawColor(self.Cr,self.Cg,self.Cb,self.Fade[self.BitIndex]*255) + --surface.SetDrawColor(self.Cr,self.Cg,self.Cb,self.Fade[self.BitIndex]*255) local transformedLocal = self:TransformOffset(segment.X or 0,segment.Y or 0) - self.LocalX = self.LocalX + transformedLocal.x - self.LocalY = self.LocalY + transformedLocal.y + self.LocalX = self.LocalX + transformedLocal[1] + self.LocalY = self.LocalY + transformedLocal[2] local angle = math.rad(segment.Rotation or 0) self:PushTransform(math.cos(angle), math.sin(angle)-(segment.SkewX or 0), @@ -134,11 +148,12 @@ function ENT:DrawSegment(segment) self:Transform(segment.W,segment.H-bevel), self:Transform(segment.W-bevel,segment.H) } - surface.DrawPoly(Rect) + self:AddPoly(Rect) + --surface.DrawPoly(Rect) self:PopTransform() --surface.DrawRect(self.LocalX,self.LocalY,segment.W,segment.H) - self.LocalX = self.LocalX - transformedLocal.x - self.LocalY = self.LocalY - transformedLocal.y + self.LocalX = self.LocalX - transformedLocal[1] + self.LocalY = self.LocalY - transformedLocal[2] self.BitIndex = self.BitIndex+1 end @@ -148,14 +163,14 @@ function ENT:DrawText(text) self.Fade[self.BitIndex] = self.Fade[self.BitIndex] + 0.08 end local transformedLocal = self:TransformOffset(text.X or 0,text.Y or 0) - self.LocalX = self.LocalX + transformedLocal.x - self.LocalY = self.LocalY + transformedLocal.y - surface.SetTextPos(self.LocalX,self.LocalY) - surface.SetFont("Default") - surface.SetTextColor(self.Cr,self.Cg,self.Cb,self.Fade[self.BitIndex]*255) - surface.DrawText(text.Text) - self.LocalX = self.LocalX - transformedLocal.x - self.LocalY = self.LocalY - transformedLocal.y + self.LocalX = self.LocalX + transformedLocal[1] + self.LocalY = self.LocalY + transformedLocal[2] + --surface.SetTextPos(self.LocalX,self.LocalY) + --surface.SetFont("Default") + --surface.SetTextColor(self.Cr,self.Cg,self.Cb,self.Fade[self.BitIndex]*255) + --surface.DrawText(text.Text) + self.LocalX = self.LocalX - transformedLocal[1] + self.LocalY = self.LocalY - transformedLocal[2] self.BitIndex = self.BitIndex+1 end @@ -168,21 +183,21 @@ function ENT:DrawMatrix(matrix) end local transformedLocal = self:TransformOffset(matrix.X+x*matrix.OffsetX,matrix.Y+y*matrix.OffsetY) - self.LocalX = self.LocalX + transformedLocal.x - self.LocalY = self.LocalY + transformedLocal.y - surface.SetDrawColor(self.Cr,self.Cg,self.Cb,self.Fade[self.BitIndex]*255) + self.LocalX = self.LocalX + transformedLocal[1] + self.LocalY = self.LocalY + transformedLocal[2] + --surface.SetDrawColor(self.Cr,self.Cg,self.Cb,self.Fade[self.BitIndex]*255) local Rect = { self:Transform(0,matrix.ScaleH), self:Transform(0,0), self:Transform(matrix.ScaleW,0), self:Transform(matrix.ScaleW,matrix.ScaleH) } - surface.DrawPoly(Rect) + self:AddPoly(Rect) --surface.DrawRect(self.LocalX,self.LocalY,matrix.ScaleW,matrix.ScaleH) - self.LocalX = self.LocalX - transformedLocal.x - self.LocalY = self.LocalY - transformedLocal.y + self.LocalX = self.LocalX - transformedLocal[1] + self.LocalY = self.LocalY - transformedLocal[2] self.BitIndex = self.BitIndex+1 end end @@ -202,8 +217,8 @@ function ENT:DrawUnion(group) --surface.SetDrawColor(self.Cr,self.Cg,self.Cb,255) end local transformedLocal = self:TransformOffset(group.X or 0,group.Y or 0) - self.LocalX = self.LocalX + transformedLocal.x - self.LocalY = self.LocalY + transformedLocal.y + self.LocalX = self.LocalX + transformedLocal[1] + self.LocalY = self.LocalY + transformedLocal[2] local savedindex = self.BitIndex local biggestindex = savedindex for k,v in ipairs(group.Children) do @@ -222,8 +237,8 @@ function ENT:DrawUnion(group) self.BitIndex = savedindex end self.BitIndex = biggestindex - self.LocalX = self.LocalX - transformedLocal.x - self.LocalY = self.LocalY - transformedLocal.y + self.LocalX = self.LocalX - transformedLocal[1] + self.LocalY = self.LocalY - transformedLocal[2] self.Cr = oCr self.Cg = oCg self.Cb = oCb @@ -241,8 +256,8 @@ function ENT:DrawGroup(group) --surface.SetDrawColor(self.Cr,self.Cg,self.Cb,255) end local transformedLocal = self:TransformOffset(group.X or 0,group.Y or 0) - self.LocalX = self.LocalX + transformedLocal.x - self.LocalY = self.LocalY + transformedLocal.y + self.LocalX = self.LocalX + transformedLocal[1] + self.LocalY = self.LocalY + transformedLocal[2] local angle = math.rad(group.Rotation or 0) self:PushTransform(math.cos(angle), math.sin(angle)-(group.SkewX or 0), @@ -262,8 +277,8 @@ function ENT:DrawGroup(group) end end self:PopTransform() - self.LocalX = self.LocalX - transformedLocal.x - self.LocalY = self.LocalY - transformedLocal.y + self.LocalX = self.LocalX - transformedLocal[1] + self.LocalY = self.LocalY - transformedLocal[2] self.Cr = oCr self.Cg = oCg self.Cb = oCb @@ -272,6 +287,7 @@ end function ENT:Draw() self:DrawModel() + --[[ self.GPU:RenderToWorld(nil, self.ResolutionH, function(x, y, w, h) draw.NoTexture() surface.SetDrawColor(self.Bgred,self.Bggreen,self.Bgblue,255) @@ -294,7 +310,29 @@ function ENT:Draw() self:DrawGroup(self.Tree) --render.SetScissorRect( 0, 0, 0, 0, false ) end - end) + end)]] + local mat = Material( "models/debug/debugwhite" ) + render.SetMaterial( mat ) + cam.PushModelMatrix( self:GetWorldTransformMatrix() ) + if self.Tree then + --surface.SetDrawColor(self.Fgred,self.Fggreen,self.Fgblue,255) + self.Cr = self.Fgred + self.Cg = self.Fggreen + self.Cb = self.Fgblue + self.LocalXX = 1 + self.LocalXY = 0 + self.LocalYX = 0 + self.LocalYY = 1 + self.LocalX = 0 + self.LocalY = 0 + self.BitIndex = 0 + + self.TransformStack = {} + self:DrawGroup(self.Tree) + --render.SetScissorRect( 0, 0, 0, 0, false ) + end + --self.TreeMesh:Draw() + cam.PopModelMatrix() --self.GPU:Render(0,0,1024,1024,nil,-(1024-self.ResolutionW)/1024,-(1024-self.ResolutionH)/1024) Wire_Render(self) end @@ -315,4 +353,6 @@ function ENT:Receive() self.Bgblue = net.ReadUInt(8) self.Bggreen = net.ReadUInt(8) self.Bgred = net.ReadUInt(8) + + end From 776fa0ef680e0959b6f44dc1fc3b500601c13802 Mon Sep 17 00:00:00 2001 From: wav3 Date: Tue, 9 Sep 2025 13:30:11 +0200 Subject: [PATCH 29/43] very messy code, but it works! --- .../gmod_wire_multisegmentlcd/cl_init.lua | 124 ++++++++++++++---- 1 file changed, 100 insertions(+), 24 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index 0897fe9278..45324aaf82 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -63,6 +63,7 @@ end function ENT:OnRemove() self.GPU:Finalize() + self.TreeMesh:Destroy() end function ENT:ReadCell(Address) @@ -113,13 +114,12 @@ end function ENT:AddPoly(poly) local u = ((self.BitIndex%1024)+0.5)/1024 local v = (math.floor(self.BitIndex/1024)+0.5)/1024 - mesh.Begin(MATERIAL_POLYGON,#poly) for i = 1,#poly do mesh.Position(Vector(poly[i][1],poly[i][2],0)) - mesh.TexCoord(0, u, v) + mesh.TexCoord(0, u, v, u ,v) + mesh.Color(255,255,255,255) mesh.AdvanceVertex() end - mesh.End() end function ENT:DrawSegment(segment) @@ -138,7 +138,7 @@ function ENT:DrawSegment(segment) math.cos(angle)) --self:Transform(,segment.H/2+(segment.H*(segment.BevelSkew or 0))), local bevel = math.min(segment.H,segment.W)/2*(segment.Bevel or 0) - local Rect = { + local rect = { self:Transform(bevel,segment.H), self:Transform(0,segment.H-bevel), self:Transform(0,bevel), @@ -148,7 +148,15 @@ function ENT:DrawSegment(segment) self:Transform(segment.W,segment.H-bevel), self:Transform(segment.W-bevel,segment.H) } - self:AddPoly(Rect) + local poly = { + rect[1],rect[2],rect[3], + rect[1],rect[3],rect[4], + rect[1],rect[4],rect[5], + rect[1],rect[5],rect[6], + rect[1],rect[6],rect[7], + rect[1],rect[7],rect[8] + } + self:AddPoly(poly) --surface.DrawPoly(Rect) self:PopTransform() --surface.DrawRect(self.LocalX,self.LocalY,segment.W,segment.H) @@ -186,13 +194,17 @@ function ENT:DrawMatrix(matrix) self.LocalX = self.LocalX + transformedLocal[1] self.LocalY = self.LocalY + transformedLocal[2] --surface.SetDrawColor(self.Cr,self.Cg,self.Cb,self.Fade[self.BitIndex]*255) - local Rect = { + local rect = { self:Transform(0,matrix.ScaleH), self:Transform(0,0), self:Transform(matrix.ScaleW,0), self:Transform(matrix.ScaleW,matrix.ScaleH) } - self:AddPoly(Rect) + local poly = { + rect[1],rect[2],rect[3], + rect[1],rect[3],rect[4], + } + self:AddPoly(poly) --surface.DrawRect(self.LocalX,self.LocalY,matrix.ScaleW,matrix.ScaleH) @@ -285,6 +297,19 @@ function ENT:DrawGroup(group) --surface.SetDrawColor(self.Cr,self.Cg,self.Cb,255) end +function ENT:CountTris(node) + if node.Type == GROUP or node.Type == UNION then + local sum = 0 + for i=1,#node.Children do + sum = sum + self:CountTris(node.Children[i]) + end + return sum + elseif node.Type == MATRIX then + return node.W*node.H*2 + end + return 6 +end + function ENT:Draw() self:DrawModel() --[[ @@ -311,28 +336,62 @@ function ENT:Draw() --render.SetScissorRect( 0, 0, 0, 0, false ) end end)]] - local mat = Material( "models/debug/debugwhite" ) - render.SetMaterial( mat ) - cam.PushModelMatrix( self:GetWorldTransformMatrix() ) + + + + if self.Tree then + + local oldw = ScrW() + local oldh = ScrH() + + local NewRT = self.GPU.RT + local OldRT = render.GetRenderTarget() + + render.SetRenderTarget(NewRT) + render.SetViewPort(0, 0, 1024, 1024) + cam.Start2D() + for i=0,self.BitIndex do + local x = ((i%1024)+0.5) + local y = (math.floor(i/1024)+0.5) + self.Fade[i] = (self.Fade[i] or 0)*0.92 + if bit.band(self.Memory[bit.rshift(i,3)] or 0,bit.lshift(1,bit.band(i,7))) ~= 0 then + self.Fade[i] = self.Fade[i] + 0.08 + end + surface.SetDrawColor(self.Cr,self.Cg,self.Cb,self.Fade[i]*255) + surface.DrawRect( x, y, 1, 1 ) + end + cam.End2D() + render.SetViewPort(0, 0, oldw, oldh) + render.SetRenderTarget(OldRT) + + + local OldTex = WireGPU_matScreen:GetTexture("$basetexture") + WireGPU_matScreen:SetTexture("$basetexture", self.GPU.RT) + render.SetMaterial( WireGPU_matScreen ) + + local monitor, pos, ang = self.GPU:GetInfo() + local h = self.ResolutionH + local scale = monitor.RS*1024/h + local m = Matrix() + m:SetAngles( ang ) + m:SetTranslation( pos ) + m:SetScale( Vector( scale, -scale, 1 ) ) + cam.PushModelMatrix( self:GetWorldTransformMatrix() ) + cam.PushModelMatrix( m ) + --surface.SetDrawColor(self.Fgred,self.Fggreen,self.Fgblue,255) - self.Cr = self.Fgred - self.Cg = self.Fggreen - self.Cb = self.Fgblue - self.LocalXX = 1 - self.LocalXY = 0 - self.LocalYX = 0 - self.LocalYY = 1 - self.LocalX = 0 - self.LocalY = 0 - self.BitIndex = 0 - self.TransformStack = {} - self:DrawGroup(self.Tree) + + self.TreeMesh:Draw() + cam.PopModelMatrix() + cam.PopModelMatrix() + + WireGPU_matScreen:SetTexture("$basetexture", OldTex) --render.SetScissorRect( 0, 0, 0, 0, false ) end - --self.TreeMesh:Draw() - cam.PopModelMatrix() + -- + --self.GPU:Render(0,0,1024,1024,nil,-(1024-self.ResolutionW)/1024,-(1024-self.ResolutionH)/1024) Wire_Render(self) end @@ -354,5 +413,22 @@ function ENT:Receive() self.Bggreen = net.ReadUInt(8) self.Bgred = net.ReadUInt(8) + self.Cr = self.Fgred + self.Cg = self.Fggreen + self.Cb = self.Fgblue + self.LocalXX = 1 + self.LocalXY = 0 + self.LocalYX = 0 + self.LocalYY = 1 + self.BitIndex = 0 + self.TransformStack = {} + local monitor, pos, ang = self.GPU:GetInfo() + local h = self.ResolutionH + local w = h/monitor.RatioX + self.LocalX = -w/2 + self.LocalY = -h/2 + mesh.Begin(self.TreeMesh,MATERIAL_TRIANGLES,self:CountTris(self.Tree)) + self:DrawGroup(self.Tree) + mesh.End() end From ffe8be03e963f3d9d9486047112e4972a303ebd5 Mon Sep 17 00:00:00 2001 From: wav3 Date: Tue, 9 Sep 2025 14:06:43 +0200 Subject: [PATCH 30/43] It is working, except for text --- .../gmod_wire_multisegmentlcd/cl_init.lua | 54 ++++++++++--------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index 45324aaf82..e87deff883 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -112,21 +112,23 @@ function ENT:PopTransform() end function ENT:AddPoly(poly) - local u = ((self.BitIndex%1024)+0.5)/1024 - local v = (math.floor(self.BitIndex/1024)+0.5)/1024 + local u = (((self.BitIndex+1)%1024)+0.5)/1024 + local v = (math.floor((self.BitIndex+1)/1024)+0.5)/1024 for i = 1,#poly do - mesh.Position(Vector(poly[i][1],poly[i][2],0)) + mesh.Position(Vector(poly[i][1],poly[i][2],0.1)) mesh.TexCoord(0, u, v, u ,v) mesh.Color(255,255,255,255) mesh.AdvanceVertex() end + for i = 1,#poly do + mesh.Position(Vector(poly[i][1],poly[i][2],0)) + mesh.TexCoord(0, u, v, u ,v) + mesh.Color(127,127,127,127) + mesh.AdvanceVertex() + end end function ENT:DrawSegment(segment) - self.Fade[self.BitIndex] = (self.Fade[self.BitIndex] or 0)*0.92 - if bit.band(self.Memory[bit.rshift(self.BitIndex,3)] or 0,bit.lshift(1,bit.band(self.BitIndex,7))) ~= 0 then - self.Fade[self.BitIndex] = self.Fade[self.BitIndex] + 0.8 - end --surface.SetDrawColor(self.Cr,self.Cg,self.Cb,self.Fade[self.BitIndex]*255) local transformedLocal = self:TransformOffset(segment.X or 0,segment.Y or 0) self.LocalX = self.LocalX + transformedLocal[1] @@ -162,14 +164,11 @@ function ENT:DrawSegment(segment) --surface.DrawRect(self.LocalX,self.LocalY,segment.W,segment.H) self.LocalX = self.LocalX - transformedLocal[1] self.LocalY = self.LocalY - transformedLocal[2] + self.Colors[self.BitIndex] = {self.Cr,self.Cg,self.Cb} self.BitIndex = self.BitIndex+1 end function ENT:DrawText(text) - self.Fade[self.BitIndex] = (self.Fade[self.BitIndex] or 0)*0.92 - if bit.band(self.Memory[bit.rshift(self.BitIndex,3)] or 0,bit.lshift(1,bit.band(self.BitIndex,7))) ~= 0 then - self.Fade[self.BitIndex] = self.Fade[self.BitIndex] + 0.08 - end local transformedLocal = self:TransformOffset(text.X or 0,text.Y or 0) self.LocalX = self.LocalX + transformedLocal[1] self.LocalY = self.LocalY + transformedLocal[2] @@ -179,16 +178,13 @@ function ENT:DrawText(text) --surface.DrawText(text.Text) self.LocalX = self.LocalX - transformedLocal[1] self.LocalY = self.LocalY - transformedLocal[2] + self.Colors[self.BitIndex] = {self.Cr,self.Cg,self.Cb} self.BitIndex = self.BitIndex+1 end function ENT:DrawMatrix(matrix) for y = 0,matrix.H-1 do for x = 0,matrix.W-1 do - self.Fade[self.BitIndex] = (self.Fade[self.BitIndex] or 0)*0.92 - if bit.band(self.Memory[bit.rshift(self.BitIndex,3)] or 0,bit.lshift(1,bit.band(self.BitIndex,7))) ~= 0 then - self.Fade[self.BitIndex] = self.Fade[self.BitIndex] + 0.08 - end local transformedLocal = self:TransformOffset(matrix.X+x*matrix.OffsetX,matrix.Y+y*matrix.OffsetY) self.LocalX = self.LocalX + transformedLocal[1] @@ -210,6 +206,7 @@ function ENT:DrawMatrix(matrix) --surface.DrawRect(self.LocalX,self.LocalY,matrix.ScaleW,matrix.ScaleH) self.LocalX = self.LocalX - transformedLocal[1] self.LocalY = self.LocalY - transformedLocal[2] + self.Colors[self.BitIndex] = {self.Cr,self.Cg,self.Cb} self.BitIndex = self.BitIndex+1 end end @@ -226,7 +223,6 @@ function ENT:DrawUnion(group) self.Cr = group.R self.Cg = group.G self.Cb = group.B - --surface.SetDrawColor(self.Cr,self.Cg,self.Cb,255) end local transformedLocal = self:TransformOffset(group.X or 0,group.Y or 0) self.LocalX = self.LocalX + transformedLocal[1] @@ -254,7 +250,6 @@ function ENT:DrawUnion(group) self.Cr = oCr self.Cg = oCg self.Cb = oCb - --surface.SetDrawColor(self.Cr,self.Cg,self.Cb,255) end function ENT:DrawGroup(group) @@ -294,7 +289,6 @@ function ENT:DrawGroup(group) self.Cr = oCr self.Cg = oCg self.Cb = oCb - --surface.SetDrawColor(self.Cr,self.Cg,self.Cb,255) end function ENT:CountTris(node) @@ -305,9 +299,9 @@ function ENT:CountTris(node) end return sum elseif node.Type == MATRIX then - return node.W*node.H*2 + return node.W*node.H*4 end - return 6 + return 12 end function ENT:Draw() @@ -351,14 +345,17 @@ function ENT:Draw() render.SetRenderTarget(NewRT) render.SetViewPort(0, 0, 1024, 1024) cam.Start2D() - for i=0,self.BitIndex do - local x = ((i%1024)+0.5) - local y = (math.floor(i/1024)+0.5) + surface.SetDrawColor(self.Bgred,self.Bggreen,self.Bgblue,255) + surface.DrawRect( 0, 0, 1, 1 ) + for i=0,self.BitIndex-1 do + local x = (((i+1)%1024)+0.5) + local y = (math.floor((i+1)/1024)+0.5) self.Fade[i] = (self.Fade[i] or 0)*0.92 if bit.band(self.Memory[bit.rshift(i,3)] or 0,bit.lshift(1,bit.band(i,7))) ~= 0 then self.Fade[i] = self.Fade[i] + 0.08 end - surface.SetDrawColor(self.Cr,self.Cg,self.Cb,self.Fade[i]*255) + local color = self.Colors[i] + surface.SetDrawColor(color[1],color[2],color[3],self.Fade[i]*255) surface.DrawRect( x, y, 1, 1 ) end cam.End2D() @@ -422,12 +419,21 @@ function ENT:Receive() self.LocalYY = 1 self.BitIndex = 0 self.TransformStack = {} + self.Colors = {} local monitor, pos, ang = self.GPU:GetInfo() local h = self.ResolutionH local w = h/monitor.RatioX self.LocalX = -w/2 self.LocalY = -h/2 mesh.Begin(self.TreeMesh,MATERIAL_TRIANGLES,self:CountTris(self.Tree)) + + mesh.Position(self.LocalX,self.LocalY,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 0, 0, 0, 0) mesh.AdvanceVertex() + mesh.Position(self.LocalX+w,self.LocalY,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 0, 0, 0, 0)mesh.AdvanceVertex() + mesh.Position(self.LocalX+w,self.LocalY+h,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 0, 0, 0, 0) mesh.AdvanceVertex() + + mesh.Position(self.LocalX,self.LocalY,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 0, 0, 0, 0) mesh.AdvanceVertex() + mesh.Position(self.LocalX+w,self.LocalY+h,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 0, 0, 0, 0) mesh.AdvanceVertex() + mesh.Position(self.LocalX,self.LocalY+h,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 0, 0, 0, 0) mesh.AdvanceVertex() self:DrawGroup(self.Tree) mesh.End() From 3825caef5ece8048e615bd4d23b61fc8e8dc8c10 Mon Sep 17 00:00:00 2001 From: wav3 Date: Wed, 10 Sep 2025 11:13:40 +0200 Subject: [PATCH 31/43] Change rotation and skew order --- .../gmod_wire_multisegmentlcd/cl_init.lua | 97 ++++++++++++++----- .../gmod_wire_multisegmentlcd/init.lua | 4 +- lua/wire/stools/multisegmentlcd.lua | 54 ++++++++--- 3 files changed, 115 insertions(+), 40 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index e87deff883..d944f526de 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -32,7 +32,7 @@ function ENT:Initialize() self:WriteCell(Address,Value) end) - self.TreeMesh = Mesh() + self.TreeMesh = {} WireLib.netRegister(self) end @@ -63,7 +63,9 @@ end function ENT:OnRemove() self.GPU:Finalize() - self.TreeMesh:Destroy() + for i=1,#self.TreeMesh do + self.TreeMesh[i]:Destroy() + end end function ENT:ReadCell(Address) @@ -112,19 +114,35 @@ function ENT:PopTransform() end function ENT:AddPoly(poly) - local u = (((self.BitIndex+1)%1024)+0.5)/1024 + local u = (((bit.bxor(self.BitIndex,self.XorMask)+1)%1024)+0.5)/1024 local v = (math.floor((self.BitIndex+1)/1024)+0.5)/1024 for i = 1,#poly do + if self.CurTris > 10922 then + mesh.End() + self.TreeMesh[#self.TreeMesh + 1] = Mesh() + mesh.Begin(self.TreeMesh[#self.TreeMesh],MATERIAL_TRIANGLES,math.min(10922,self.Tris)) + self.Tris = self.Tris - 10922 + self.CurTris = 0 + end mesh.Position(Vector(poly[i][1],poly[i][2],0.1)) mesh.TexCoord(0, u, v, u ,v) mesh.Color(255,255,255,255) mesh.AdvanceVertex() + self.CurTris = self.CurTris + 1 end for i = 1,#poly do + if self.CurTris > 10922 then + mesh.End() + self.TreeMesh[#self.TreeMesh + 1] = Mesh() + mesh.Begin(self.TreeMesh[#self.TreeMesh],MATERIAL_TRIANGLES,math.min(10922,self.Tris)) + self.Tris = self.Tris - 10922 + self.CurTris = 0 + end mesh.Position(Vector(poly[i][1],poly[i][2],0)) mesh.TexCoord(0, u, v, u ,v) mesh.Color(127,127,127,127) mesh.AdvanceVertex() + self.CurTris = self.CurTris + 1 end end @@ -164,7 +182,7 @@ function ENT:DrawSegment(segment) --surface.DrawRect(self.LocalX,self.LocalY,segment.W,segment.H) self.LocalX = self.LocalX - transformedLocal[1] self.LocalY = self.LocalY - transformedLocal[2] - self.Colors[self.BitIndex] = {self.Cr,self.Cg,self.Cb} + self.Colors[self.BitIndex] = {self.Cr,self.Cg,self.Cb,self.Ca} self.BitIndex = self.BitIndex+1 end @@ -178,7 +196,7 @@ function ENT:DrawText(text) --surface.DrawText(text.Text) self.LocalX = self.LocalX - transformedLocal[1] self.LocalY = self.LocalY - transformedLocal[2] - self.Colors[self.BitIndex] = {self.Cr,self.Cg,self.Cb} + self.Colors[self.BitIndex] = {self.Cr,self.Cg,self.Cb,self.Ca} self.BitIndex = self.BitIndex+1 end @@ -206,7 +224,7 @@ function ENT:DrawMatrix(matrix) --surface.DrawRect(self.LocalX,self.LocalY,matrix.ScaleW,matrix.ScaleH) self.LocalX = self.LocalX - transformedLocal[1] self.LocalY = self.LocalY - transformedLocal[2] - self.Colors[self.BitIndex] = {self.Cr,self.Cg,self.Cb} + self.Colors[self.BitIndex] = {self.Cr,self.Cg,self.Cb,self.Ca} self.BitIndex = self.BitIndex+1 end end @@ -219,10 +237,12 @@ function ENT:DrawUnion(group) local oCr = self.Cr local oCg = self.Cg local oCb = self.Cb + local oCa = self.Ca if group.HasColor then self.Cr = group.R self.Cg = group.G self.Cb = group.B + self.Ca = group.A or 255 end local transformedLocal = self:TransformOffset(group.X or 0,group.Y or 0) self.LocalX = self.LocalX + transformedLocal[1] @@ -247,29 +267,37 @@ function ENT:DrawUnion(group) self.BitIndex = biggestindex self.LocalX = self.LocalX - transformedLocal[1] self.LocalY = self.LocalY - transformedLocal[2] - self.Cr = oCr + self.Cr = oCrq self.Cg = oCg self.Cb = oCb + self.Ca = oCa end function ENT:DrawGroup(group) local oCr = self.Cr local oCg = self.Cg local oCb = self.Cb + local oCa = self.Ca if group.HasColor then self.Cr = group.R self.Cg = group.G self.Cb = group.B + self.Ca = group.A or 255 --surface.SetDrawColor(self.Cr,self.Cg,self.Cb,255) end + + local angle = math.rad(group.Rotation or 0) local transformedLocal = self:TransformOffset(group.X or 0,group.Y or 0) self.LocalX = self.LocalX + transformedLocal[1] self.LocalY = self.LocalY + transformedLocal[2] - local angle = math.rad(group.Rotation or 0) self:PushTransform(math.cos(angle), - math.sin(angle)-(group.SkewX or 0), - -math.sin(angle)+(group.SkewY or 0), + math.sin(angle), + -math.sin(angle), math.cos(angle)) + self:PushTransform(1, + -(group.SkewX or 0), + (group.SkewY or 0), + 1) for k,v in ipairs(group.Children) do if v.Type == GROUP then self:DrawGroup(v) @@ -289,6 +317,7 @@ function ENT:DrawGroup(group) self.Cr = oCr self.Cg = oCg self.Cb = oCb + self.Ca = oCa end function ENT:CountTris(node) @@ -299,7 +328,7 @@ function ENT:CountTris(node) end return sum elseif node.Type == MATRIX then - return node.W*node.H*4 + return node.W*node.H*16 end return 12 end @@ -345,17 +374,21 @@ function ENT:Draw() render.SetRenderTarget(NewRT) render.SetViewPort(0, 0, 1024, 1024) cam.Start2D() + render.ClearRenderTarget(self.GPU.RT, Color(0, 0, 0, 0)) surface.SetDrawColor(self.Bgred,self.Bggreen,self.Bgblue,255) surface.DrawRect( 0, 0, 1, 1 ) for i=0,self.BitIndex-1 do - local x = (((i+1)%1024)+0.5) - local y = (math.floor((i+1)/1024)+0.5) - self.Fade[i] = (self.Fade[i] or 0)*0.92 + local x = (i+1)%1024 + local y = math.floor((i+1)/1024) + self.Fade[i] = (self.Fade[i] or 0)*0.92 + 0.01 if bit.band(self.Memory[bit.rshift(i,3)] or 0,bit.lshift(1,bit.band(i,7))) ~= 0 then - self.Fade[i] = self.Fade[i] + 0.08 + self.Fade[i] = self.Fade[i] + 0.07 end local color = self.Colors[i] - surface.SetDrawColor(color[1],color[2],color[3],self.Fade[i]*255) + surface.SetDrawColor(color[1]*self.Fade[i]+self.Bgred*(1-self.Fade[i]),color[2]*self.Fade[i]+self.Bggreen*(1-self.Fade[i]),color[3]*self.Fade[i]+self.Bgblue*(1-self.Fade[i]),self.Fade[i]*color[4]) + if x == 0 and y == 0 then + break + end surface.DrawRect( x, y, 1, 1 ) end cam.End2D() @@ -379,8 +412,9 @@ function ENT:Draw() --surface.SetDrawColor(self.Fgred,self.Fggreen,self.Fgblue,255) - - self.TreeMesh:Draw() + for i=1,#self.TreeMesh do + self.TreeMesh[i]:Draw() + end cam.PopModelMatrix() cam.PopModelMatrix() @@ -409,10 +443,12 @@ function ENT:Receive() self.Bgblue = net.ReadUInt(8) self.Bggreen = net.ReadUInt(8) self.Bgred = net.ReadUInt(8) + self.XorMask = net.ReadUInt(8) self.Cr = self.Fgred self.Cg = self.Fggreen self.Cb = self.Fgblue + self.Ca = 255 self.LocalXX = 1 self.LocalXY = 0 self.LocalYX = 0 @@ -425,15 +461,24 @@ function ENT:Receive() local w = h/monitor.RatioX self.LocalX = -w/2 self.LocalY = -h/2 - mesh.Begin(self.TreeMesh,MATERIAL_TRIANGLES,self:CountTris(self.Tree)) - - mesh.Position(self.LocalX,self.LocalY,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 0, 0, 0, 0) mesh.AdvanceVertex() - mesh.Position(self.LocalX+w,self.LocalY,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 0, 0, 0, 0)mesh.AdvanceVertex() - mesh.Position(self.LocalX+w,self.LocalY+h,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 0, 0, 0, 0) mesh.AdvanceVertex() + self.TreeMesh = self.TreeMesh or {} + for i=#self.TreeMesh,1,-1 do + self.TreeMesh[i]:Destroy() + self.TreeMesh[i] = nil + end + self.TreeMesh[#self.TreeMesh + 1] = Mesh() + self.Tris = self:CountTris(self.Tree) + mesh.Begin(self.TreeMesh[#self.TreeMesh],MATERIAL_TRIANGLES,math.min(10922,self.Tris)) + self.Tris = self.Tris - 10922 + + mesh.Position(self.LocalX,self.LocalY,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 1/2048, 1/2048, 1/2048, 1/2048) mesh.AdvanceVertex() + mesh.Position(self.LocalX+w,self.LocalY,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 1/2048, 1/2048, 1/2048, 1/2048) mesh.AdvanceVertex() + mesh.Position(self.LocalX+w,self.LocalY+h,0) mesh.Color(255,255,255,255)mesh.TexCoord(0, 1/2048, 1/2048, 1/2048, 1/2048) mesh.AdvanceVertex() - mesh.Position(self.LocalX,self.LocalY,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 0, 0, 0, 0) mesh.AdvanceVertex() - mesh.Position(self.LocalX+w,self.LocalY+h,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 0, 0, 0, 0) mesh.AdvanceVertex() - mesh.Position(self.LocalX,self.LocalY+h,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 0, 0, 0, 0) mesh.AdvanceVertex() + mesh.Position(self.LocalX,self.LocalY,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 1/2048, 1/2048, 1/2048, 1/2048) mesh.AdvanceVertex() + mesh.Position(self.LocalX+w,self.LocalY+h,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 1/2048, 1/2048, 1/2048, 1/2048) mesh.AdvanceVertex() + mesh.Position(self.LocalX,self.LocalY+h,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 1/2048, 1/2048, 1/2048, 1/2048) mesh.AdvanceVertex() + self.CurTris = 6 self:DrawGroup(self.Tree) mesh.End() diff --git a/lua/entities/gmod_wire_multisegmentlcd/init.lua b/lua/entities/gmod_wire_multisegmentlcd/init.lua index fde06666d9..4d6c579596 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/init.lua @@ -61,6 +61,7 @@ function ENT:SendSerializedTree(ply) net.WriteUInt(self.Bgblue,8) net.WriteUInt(self.Bggreen,8) net.WriteUInt(self.Bgred,8) + net.WriteUInt(self.XorMask,8) WireLib.netEnd(ply) end @@ -74,7 +75,7 @@ function ENT:Retransmit(ply) self.Cache:Flush(ply) end -function ENT:Setup(IsInteractive, ResolutionW, ResolutionH, Bgred,Bggreen,Bgblue,Fgred,Fggreen,Fgblue) +function ENT:Setup(IsInteractive, ResolutionW, ResolutionH, Bgred,Bggreen,Bgblue,Fgred,Fggreen,Fgblue,XorMask) self.IsInteractive = WireLib.IsValidInteractiveModel(self:GetModel()) and (IsInteractive) self.ResolutionW = ResolutionW self.ResolutionH = ResolutionH @@ -84,6 +85,7 @@ function ENT:Setup(IsInteractive, ResolutionW, ResolutionH, Bgred,Bggreen,Bgblue self.Bgblue = Bgblue or 15 self.Bggreen = Bggreen or 178 self.Bgred = Bgred or 148 + self.XorMask = XorMask or 0 self:Retransmit() end diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index d7e6c91db3..7b50285838 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -31,6 +31,7 @@ if CLIENT then language.Add( "tool.wire_multisegmentlcd.interactive", "Interactive (if available):" ) language.Add( "tool.wire_multisegmentlcd.resw", "Canvas width:" ) language.Add( "tool.wire_multisegmentlcd.resh", "Canvas height:" ) + language.Add( "tool.wire_multisegmentlcd.xormask", "Xor segment order mask:" ) language.Add( "tool.wire_multisegmentlcd.fgcolor", "Segment color:" ) language.Add( "tool.wire_multisegmentlcd.bgcolor", "Background color:" ) TOOL.Information = { { name = "left", text = "Create/Update " .. TOOL.Name } } @@ -65,7 +66,8 @@ if SERVER then math.Clamp(self:GetClientNumber("bgblue"), 0, 255), math.Clamp(self:GetClientNumber("fgred"), 0, 255), math.Clamp(self:GetClientNumber("fggreen"), 0, 255), - math.Clamp(self:GetClientNumber("fgblue"), 0, 255) + math.Clamp(self:GetClientNumber("fgblue"), 0, 255), + math.Clamp(self:GetClientNumber("xormask"), 0, 255) end util.AddNetworkString("wire_multisegmentlcd_tool_upload_request") @@ -107,7 +109,8 @@ TOOL.ClientConVar = { bgblue = 15, fgred = 45, fggreen = 91, - fgblue = 45 + fgblue = 45, + xormask = 0 } @@ -153,6 +156,7 @@ function TOOL.BuildCPanel(panel) panel:CheckBox("#Create Flat to Surface", "wire_multisegmentlcd_createflat") panel:TextEntry("#tool.wire_multisegmentlcd.resw", "wire_multisegmentlcd_resw") panel:TextEntry("#tool.wire_multisegmentlcd.resh", "wire_multisegmentlcd_resh") + panel:TextEntry("#tool.wire_multisegmentlcd.xormask", "wire_multisegmentlcd_xormask") TreeDataHolder = vgui.Create("DPanel", panel) panel:AddPanel(TreeDataHolder) TreeDataHolder:DockMargin(0, 0, 0, 0) @@ -496,6 +500,16 @@ function TOOL.BuildCPanel(panel) node.group.B = value end + WangColorA = ButtonsHolder:Add( "DNumberWang" ) + WangColorA:SetMax(255) + function WangColorA:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil then + return + end + node.group.A = value + end + WangRotation = ButtonsHolder:Add( "DNumberWang" ) WangRotation:SetMax(360) WangRotation:SetMin(-360) @@ -508,6 +522,7 @@ function TOOL.BuildCPanel(panel) end WangSkewX = ButtonsHolder:Add( "DNumberWang" ) + WangSkewX:SetMin(-4096) WangSkewX:SetMax(4096) function WangSkewX:OnValueChanged(value) local node = DisplayData:GetSelectedItem() @@ -517,7 +532,19 @@ function TOOL.BuildCPanel(panel) node.group.SkewX = value end + WangSkewY = ButtonsHolder:Add( "DNumberWang" ) + WangSkewY:SetMin(-4096) + WangSkewY:SetMax(4096) + function WangSkewY:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil then + return + end + node.group.SkewY = value + end + WangBevel = ButtonsHolder:Add( "DNumberWang" ) + WangBevel:SetMin(-1024) WangBevel:SetMax(1024) function WangBevel:OnValueChanged(value) local node = DisplayData:GetSelectedItem() @@ -538,18 +565,8 @@ function TOOL.BuildCPanel(panel) node.group.BevelSkew = value end - WangSkewY = ButtonsHolder:Add( "DNumberWang" ) - WangSkewY:SetMax(4096) - function WangSkewY:OnValueChanged(value) - local node = DisplayData:GetSelectedItem() - if node == nil or node.group == nil then - return - end - node.group.SkewY = value - end - function ButtonsHolder:PerformLayout(w, h) - local roww = w/7 + local roww = w/8 local rowh = h/4 for i,v in ipairs(self.buttons) do v:SetPos((i-1)*w/#self.buttons,0) @@ -579,6 +596,8 @@ function TOOL.BuildCPanel(panel) WangColorG:SetSize(roww,rowh) WangColorB:SetPos(roww*3,rowh*2) WangColorB:SetSize(roww,rowh) + WangColorA:SetPos(roww*4,rowh*2) + WangColorA:SetSize(roww,rowh) WangRotation:SetPos(roww*4,rowh*2) WangRotation:SetSize(roww,rowh) @@ -601,6 +620,7 @@ function TOOL.BuildCPanel(panel) WangColorR:SetVisible(false) WangColorG:SetVisible(false) WangColorB:SetVisible(false) + WangColorA:SetVisible(false) CheckHasColor:SetVisible(false) CheckLabel:SetVisible(false) WangRotation:SetVisible(false) @@ -620,6 +640,7 @@ function TOOL.BuildCPanel(panel) WangColorR:SetVisible(false) WangColorG:SetVisible(false) WangColorB:SetVisible(false) + WangColorA:SetVisible(false) CheckHasColor:SetVisible(false) CheckLabel:SetVisible(false) WangRotation:SetVisible(false) @@ -660,15 +681,22 @@ function TOOL.BuildCPanel(panel) WangColorR:SetVisible(true) WangColorG:SetVisible(true) WangColorB:SetVisible(true) + WangColorA:SetVisible(true) CheckHasColor:SetVisible(true) CheckLabel:SetVisible(true) WangColorR:SetValue(group.R) WangColorG:SetValue(group.G) WangColorB:SetValue(group.B) + WangColorA:SetValue(group.A) CheckHasColor:SetValue(group.HasColor) WangRotation:SetVisible(true) WangSkewX:SetVisible(true) WangSkewY:SetVisible(true) + WangRotation:SetValue(group.Rotation or 0) + WangSkewX:SetValue(group.SkewX or 0) + WangSkewY:SetValue(group.SkewY or 0) + WangBevel:SetValue(group.Bevel or 0) + WangBevelSkew:SetValue(group.BevelSkew or 0) end WangX:SetValue(group.X) WangY:SetValue(group.Y) From 5f2244ef1f4e1b3ccf13f527841aa1d8b41d7233 Mon Sep 17 00:00:00 2001 From: wav3 Date: Wed, 10 Sep 2025 11:24:08 +0200 Subject: [PATCH 32/43] alpha --- lua/entities/gmod_wire_multisegmentlcd/cl_init.lua | 8 +++++--- lua/entities/gmod_wire_multisegmentlcd/init.lua | 6 +++++- lua/wire/stools/multisegmentlcd.lua | 10 ++++++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index d944f526de..96ca4071b3 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -375,7 +375,7 @@ function ENT:Draw() render.SetViewPort(0, 0, 1024, 1024) cam.Start2D() render.ClearRenderTarget(self.GPU.RT, Color(0, 0, 0, 0)) - surface.SetDrawColor(self.Bgred,self.Bggreen,self.Bgblue,255) + surface.SetDrawColor(self.Bgred,self.Bggreen,self.Bgblue,self.Bgalpha) surface.DrawRect( 0, 0, 1, 1 ) for i=0,self.BitIndex-1 do local x = (i+1)%1024 @@ -385,7 +385,7 @@ function ENT:Draw() self.Fade[i] = self.Fade[i] + 0.07 end local color = self.Colors[i] - surface.SetDrawColor(color[1]*self.Fade[i]+self.Bgred*(1-self.Fade[i]),color[2]*self.Fade[i]+self.Bggreen*(1-self.Fade[i]),color[3]*self.Fade[i]+self.Bgblue*(1-self.Fade[i]),self.Fade[i]*color[4]) + surface.SetDrawColor(color[1]*self.Fade[i]+self.Bgred*(1-self.Fade[i]),color[2]*self.Fade[i]+self.Bggreen*(1-self.Fade[i]),color[3]*self.Fade[i]+self.Bgblue*(1-self.Fade[i]),self.Fade[i]*color[4]+self.Bgalpha*(1-self.Fade[i])) if x == 0 and y == 0 then break end @@ -440,15 +440,17 @@ function ENT:Receive() self.Fgblue = net.ReadUInt(8) self.Fggreen = net.ReadUInt(8) self.Fgred = net.ReadUInt(8) + self.Fgalpha = net.ReadUInt(8) self.Bgblue = net.ReadUInt(8) self.Bggreen = net.ReadUInt(8) self.Bgred = net.ReadUInt(8) + self.Bgalpha = net.ReadUInt(8) self.XorMask = net.ReadUInt(8) self.Cr = self.Fgred self.Cg = self.Fggreen self.Cb = self.Fgblue - self.Ca = 255 + self.Ca = self.Fgalpha self.LocalXX = 1 self.LocalXY = 0 self.LocalYX = 0 diff --git a/lua/entities/gmod_wire_multisegmentlcd/init.lua b/lua/entities/gmod_wire_multisegmentlcd/init.lua index 4d6c579596..c0d5ea8d24 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/init.lua @@ -58,9 +58,11 @@ function ENT:SendSerializedTree(ply) net.WriteUInt(self.Fgblue,8) net.WriteUInt(self.Fggreen,8) net.WriteUInt(self.Fgred,8) + net.WriteUInt(self.Fgalpha,8) net.WriteUInt(self.Bgblue,8) net.WriteUInt(self.Bggreen,8) net.WriteUInt(self.Bgred,8) + net.WriteUInt(self.Bgalpha,8) net.WriteUInt(self.XorMask,8) WireLib.netEnd(ply) end @@ -75,16 +77,18 @@ function ENT:Retransmit(ply) self.Cache:Flush(ply) end -function ENT:Setup(IsInteractive, ResolutionW, ResolutionH, Bgred,Bggreen,Bgblue,Fgred,Fggreen,Fgblue,XorMask) +function ENT:Setup(IsInteractive, ResolutionW, ResolutionH, Bgred,Bggreen,Bgblue,Bgalpha,Fgred,Fggreen,Fgblue,Fgalpha,XorMask) self.IsInteractive = WireLib.IsValidInteractiveModel(self:GetModel()) and (IsInteractive) self.ResolutionW = ResolutionW self.ResolutionH = ResolutionH self.Fgblue = Fgblue or 45 self.Fggreen = Fggreen or 91 self.Fgred = Fgred or 45 + self.Fgalpha = Fgalpha or 255 self.Bgblue = Bgblue or 15 self.Bggreen = Bggreen or 178 self.Bgred = Bgred or 148 + self.Bgalpha = Bgalpha or 255 self.XorMask = XorMask or 0 self:Retransmit() end diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index 7b50285838..b5e0ac436d 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -64,9 +64,11 @@ if SERVER then math.Clamp(self:GetClientNumber("bgred"), 0, 255), math.Clamp(self:GetClientNumber("bggreen"), 0, 255), math.Clamp(self:GetClientNumber("bgblue"), 0, 255), + math.Clamp(self:GetClientNumber("bgalpha"), 0, 255), math.Clamp(self:GetClientNumber("fgred"), 0, 255), math.Clamp(self:GetClientNumber("fggreen"), 0, 255), math.Clamp(self:GetClientNumber("fgblue"), 0, 255), + math.Clamp(self:GetClientNumber("fgalpha"), 0, 255), math.Clamp(self:GetClientNumber("xormask"), 0, 255) end @@ -107,9 +109,11 @@ TOOL.ClientConVar = { bgred = 148, bggreen = 178, bgblue = 15, + bgalpha = 255, fgred = 45, fggreen = 91, fgblue = 45, + fgalpha = 255, xormask = 0 } @@ -809,7 +813,8 @@ function TOOL.BuildCPanel(panel) Red = "wire_multisegmentlcd_bgred", Green = "wire_multisegmentlcd_bggreen", Blue = "wire_multisegmentlcd_bgblue", - ShowAlpha = "0", + Alpha = "wire_multisegmentlcd_bgalpha", + ShowAlpha = "1", ShowHSV = "1", ShowRGB = "1", Multiplier = "255" @@ -819,7 +824,8 @@ function TOOL.BuildCPanel(panel) Red = "wire_multisegmentlcd_fgred", Green = "wire_multisegmentlcd_fggreen", Blue = "wire_multisegmentlcd_fgblue", - ShowAlpha = "0", + Alpha = "wire_multisegmentlcd_fgalpha", + ShowAlpha = "1", ShowHSV = "1", ShowRGB = "1", Multiplier = "255" From 2b75bcb464ef908f2af1c564550b942092d73432 Mon Sep 17 00:00:00 2001 From: wav3 Date: Wed, 10 Sep 2025 11:35:11 +0200 Subject: [PATCH 33/43] fix layout --- lua/wire/stools/multisegmentlcd.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index b5e0ac436d..6f0e51663a 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -603,11 +603,11 @@ function TOOL.BuildCPanel(panel) WangColorA:SetPos(roww*4,rowh*2) WangColorA:SetSize(roww,rowh) - WangRotation:SetPos(roww*4,rowh*2) + WangRotation:SetPos(roww*5,rowh*2) WangRotation:SetSize(roww,rowh) - WangSkewX:SetPos(roww*5,rowh*2) + WangSkewX:SetPos(roww*6,rowh*2) WangSkewX:SetSize(roww,rowh) - WangSkewY:SetPos(roww*6,rowh*2) + WangSkewY:SetPos(roww*7,rowh*2) WangSkewY:SetSize(roww,rowh) WangBevel:SetPos(0,rowh*2) From 40941e9f88cf91910df1df3ca98053dee3eda454 Mon Sep 17 00:00:00 2001 From: wav3 Date: Thu, 11 Sep 2025 16:36:08 +0200 Subject: [PATCH 34/43] ungroup --- lua/wire/stools/multisegmentlcd.lua | 250 +++++++++++++++++++++++++--- 1 file changed, 227 insertions(+), 23 deletions(-) diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index 6f0e51663a..50b7accff9 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -161,6 +161,12 @@ function TOOL.BuildCPanel(panel) panel:TextEntry("#tool.wire_multisegmentlcd.resw", "wire_multisegmentlcd_resw") panel:TextEntry("#tool.wire_multisegmentlcd.resh", "wire_multisegmentlcd_resh") panel:TextEntry("#tool.wire_multisegmentlcd.xormask", "wire_multisegmentlcd_xormask") + PreviewPanel = vgui.Create("DPanel", panel) + panel:AddPanel(PreviewPanel) + PreviewPanel:SetHeight(256) + PreviewPanel:Dock(TOP) + PreviewPanel.Paint = DrawSegmentLCDPreview + TreeDataHolder = vgui.Create("DPanel", panel) panel:AddPanel(TreeDataHolder) TreeDataHolder:DockMargin(0, 0, 0, 0) @@ -334,7 +340,7 @@ function TOOL.BuildCPanel(panel) end local parentgroup = node.parentgroup if parentgroup == nil then - return + parentgroup = WireLib.SegmentLCD_Tree end for i,v in pairs(parentgroup.Children) do if v == node.group then @@ -346,20 +352,7 @@ function TOOL.BuildCPanel(panel) end function Remove:DoClick() local node = DisplayData:GetSelectedItem() - if node == nil then - return - end - local parentgroup = node.parentgroup - if parentgroup == nil then - return - end - for i,v in pairs(parentgroup.Children) do - if v == node.group then - table.remove(parentgroup.Children,i) - node:Remove() - return - end - end + RemoveI(node) end ButtonsHolder.textboxes = {} WangX = ButtonsHolder:Add( "DNumberWang" ) @@ -426,7 +419,7 @@ function TOOL.BuildCPanel(panel) WangScaleW:SetMax(1024) function WangScaleW:OnValueChanged(value) local node = DisplayData:GetSelectedItem() - if node == nil or node.group == nil or node.group.Type ~= MATRIX then + if node == nil or node.group == nil then return end node.group.ScaleW = value @@ -436,7 +429,7 @@ function TOOL.BuildCPanel(panel) WangScaleH:SetMax(1024) function WangScaleH:OnValueChanged(value) local node = DisplayData:GetSelectedItem() - if node == nil or node.group == nil or node.group.Type ~= MATRIX then + if node == nil or node.group == nil then return end node.group.ScaleH = value @@ -446,7 +439,7 @@ function TOOL.BuildCPanel(panel) WangOffsetX:SetMax(1024) function WangOffsetX:OnValueChanged(value) local node = DisplayData:GetSelectedItem() - if node == nil or node.group == nil or node.group.Type ~= MATRIX then + if node == nil or node.group == nil then return end node.group.OffsetX = value @@ -456,7 +449,7 @@ function TOOL.BuildCPanel(panel) WangOffsetY:SetMax(1024) function WangOffsetY:OnValueChanged(value) local node = DisplayData:GetSelectedItem() - if node == nil or node.group == nil or node.group.Type ~= MATRIX then + if node == nil or node.group == nil then return end node.group.OffsetY = value @@ -710,7 +703,7 @@ function TOOL.BuildCPanel(panel) function DisplayData:DoRightClick(node) local Menu = DermaMenu() - Menu:AddOption( "Rename" ) + Menu:AddOption( "Ungroup" ) Menu:AddOption( "Copy" ) Menu:AddOption( "Paste" ) local InsertM, MMOption = Menu:AddSubMenu( "Insert" ) @@ -722,10 +715,52 @@ function TOOL.BuildCPanel(panel) Menu:AddSpacer() Menu:AddOption( "Remove" ) Menu:Open() - print("AAA") function Menu:OptionSelected(option, optionText) - if optionText == "Rename" then - + if optionText == "Ungroup" then + if node.group.Children then + local parentgroup = node.parentgroup + if parentgroup == nil then + parentgroup = WireLib.SegmentLCD_Tree + end + local indexofnode = 0 + for i,v in pairs(parentgroup.Children) do + if v == node.group then + table.remove(parentgroup.Children,i) + indexofnode = i + break + end + end + + + local children = node:GetChildNodes() + local parent = node:GetParent() + local parentnode = node:GetParentNode() + + local root = node:GetRoot() + for i=1,#children do + children[i]:SetParent(parent) + children[i]:SetParentNode(parentnode) + children[i]:SetRoot(root) + --parentnode:Insert(children[i],insertbefore,true) + table.insert(parentgroup.Children,indexofnode+i-1,node.group.Children[i]) + end + + local parentchildren = parentnode:GetChildNodes() + for j=1,#parentgroup.Children do + for i=1,#parentchildren do + if parentgroup.Children[j] == parentchildren[i].group then + parentchildren[i]:SetParent(node) -- required for it to reparent + parentchildren[i]:SetParentNode(parentnode) + parentchildren[i]:SetParent(parent) + parentchildren[i]:SetRoot(root) + break + end + end + end + + + node:Remove() + end elseif optionText == "Copy" then SegmentLCD_Clipboard = table.Copy(node.group) elseif optionText == "Paste" then @@ -831,3 +866,172 @@ function TOOL.BuildCPanel(panel) Multiplier = "255" }) end + +function Transform(self,x,y) + return { + x=x*self.LocalXX+y*self.LocalXY+self.LocalX, + y=x*self.LocalYX+y*self.LocalYY+self.LocalY + } +end + +function TransformOffset(self,x,y) + return { + x*self.LocalXX+y*self.LocalXY, + x*self.LocalYX+y*self.LocalYY + } +end + + +function PushTransform(self,XX,XY,YX,YY) + self.TransformStack[#self.TransformStack + 1] = {self.LocalXX,self.LocalXY,self.LocalYX,self.LocalYY} + local oXX = self.LocalXX + local oXY = self.LocalXY + local oYX = self.LocalYX + local oYY = self.LocalYY + + local nXX = oXX*XX + oXY*YX + local nXY = oXY*YY + oXX*XY + local nYX = oYX*XX + oYY*YX + local nYY = oYY*YY + oYX*XY + + self.LocalXX = nXX + self.LocalXY = nXY + self.LocalYX = nYX + self.LocalYY = nYY +end + +function PopTransform(self) + self.LocalXX,self.LocalXY,self.LocalYX,self.LocalYY = unpack(self.TransformStack[#self.TransformStack]) + self.TransformStack[#self.TransformStack] = nil +end + +function DrawSegment(self,segment) + local transformedLocal = TransformOffset(self,segment.X or 0,segment.Y or 0) + self.LocalX = self.LocalX + transformedLocal[1] + self.LocalY = self.LocalY + transformedLocal[2] + local angle = math.rad(segment.Rotation or 0) + PushTransform(self,math.cos(angle), + math.sin(angle)-(segment.SkewX or 0), + -math.sin(angle)+(segment.SkewY or 0), + math.cos(angle)) + --self:Transform(,segment.H/2+(segment.H*(segment.BevelSkew or 0))), + local bevel = math.min(segment.H,segment.W)/2*(segment.Bevel or 0) + local rect = { + Transform(self,bevel,segment.H), + Transform(self,0,segment.H-bevel), + Transform(self,0,bevel), + Transform(self,bevel,0), + Transform(self,segment.W-bevel,0), + Transform(self,segment.W,bevel), + Transform(self,segment.W,segment.H-bevel), + Transform(self,segment.W-bevel,segment.H) + } + surface.DrawPoly(rect) + PopTransform(self) + --surface.DrawRect(self.LocalX,self.LocalY,segment.W,segment.H) + self.LocalX = self.LocalX - transformedLocal[1] + self.LocalY = self.LocalY - transformedLocal[2] +end + +function DrawText(self,text) + +end + +function DrawMatrix(self,matrix) + +end + +function DrawUnion(self,union) + for k,v in ipairs(union.Children) do + if v.Type == GROUP then + DrawGroup(self,v) + elseif v.Type == UNION then + DrawUnion(self,v) + elseif v.Type == SEGMENT then + DrawSegment(self,v) + elseif v.Type == TEXT then + DrawText(self,v) + elseif v.Type == MATRIX then + DrawMatrix(self,v) + end + end +end + +function DrawGroup(self,group) + local oCr = self.Cr + local oCg = self.Cg + local oCb = self.Cb + local oCa = self.Ca + if group.HasColor then + self.Cr = group.R or 255 + self.Cg = group.G or 255 + self.Cb = group.B or 255 + self.Ca = group.A or 255 + surface.SetDrawColor(self.Cr,self.Cg,self.Cb,self.Ca) + end + + local angle = math.rad(group.Rotation or 0) + local transformedLocal = TransformOffset(self,group.X or 0,group.Y or 0) + self.LocalX = self.LocalX + transformedLocal[1] + self.LocalY = self.LocalY + transformedLocal[2] + PushTransform(self,math.cos(angle), + math.sin(angle), + -math.sin(angle), + math.cos(angle)) + PushTransform(self,1, + -(group.SkewX or 0), + (group.SkewY or 0), + 1) + for k,v in ipairs(group.Children) do + if v.Type == GROUP then + DrawGroup(self,v) + elseif v.Type == UNION then + DrawUnion(self,v) + elseif v.Type == SEGMENT then + DrawSegment(self,v) + elseif v.Type == TEXT then + DrawText(self,v) + elseif v.Type == MATRIX then + DrawMatrix(self,v) + end + end + PopTransform(self) + self.LocalX = self.LocalX - transformedLocal[1] + self.LocalY = self.LocalY - transformedLocal[2] + self.Cr = oCr + self.Cg = oCg + self.Cb = oCb + self.Ca = oCa +end + +function DrawSegmentLCDPreview(self,width, height) + surface.SetDrawColor(0, 0, 0, 255) + draw.NoTexture() + surface.DrawRect(0, 0, width, height) + + resw = GetConVar( "wire_multisegmentlcd_resw" ):GetInt() + resh = GetConVar( "wire_multisegmentlcd_resh" ):GetInt() + + + local maxres = math.min(width/resw,height/resh) + + self.Cr = 255 + self.Cg = 255 + self.Cb = 255 + self.LocalXX = maxres + self.LocalXY = 0 + self.LocalYX = 0 + self.LocalYY = maxres + self.LocalX = 0 + self.LocalY = 0 + self.BitIndex = 0 + + surface.SetDrawColor(255, 255, 255, 255) + self.TransformStack = {} + + DrawGroup(self,WireLib.SegmentLCD_Tree) +end + +function TOOL:DrawToolScreen(width, height) + DrawSegmentLCDPreview(self,width,height) +end \ No newline at end of file From 8037ddd5bc75d3b97a880b4e6e29e74616379adb Mon Sep 17 00:00:00 2001 From: wav3 Date: Fri, 12 Sep 2025 16:58:42 +0200 Subject: [PATCH 35/43] Fix dupe --- lua/entities/gmod_wire_multisegmentlcd/cl_init.lua | 10 ++++++---- lua/entities/gmod_wire_multisegmentlcd/init.lua | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index 96ca4071b3..eab463ff45 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -124,9 +124,9 @@ function ENT:AddPoly(poly) self.Tris = self.Tris - 10922 self.CurTris = 0 end - mesh.Position(Vector(poly[i][1],poly[i][2],0.1)) + mesh.Position(Vector(poly[i][1],poly[i][2],0)) mesh.TexCoord(0, u, v, u ,v) - mesh.Color(255,255,255,255) + mesh.Color(255,255,255,127) mesh.AdvanceVertex() self.CurTris = self.CurTris + 1 end @@ -138,9 +138,9 @@ function ENT:AddPoly(poly) self.Tris = self.Tris - 10922 self.CurTris = 0 end - mesh.Position(Vector(poly[i][1],poly[i][2],0)) + mesh.Position(Vector(poly[i][1],poly[i][2],self.ZOffset)) mesh.TexCoord(0, u, v, u ,v) - mesh.Color(127,127,127,127) + mesh.Color(255,255,255,255) mesh.AdvanceVertex() self.CurTris = self.CurTris + 1 end @@ -461,6 +461,8 @@ function ENT:Receive() local monitor, pos, ang = self.GPU:GetInfo() local h = self.ResolutionH local w = h/monitor.RatioX + + self.ZOffset = monitor.RS*1024/h self.LocalX = -w/2 self.LocalY = -h/2 self.TreeMesh = self.TreeMesh or {} diff --git a/lua/entities/gmod_wire_multisegmentlcd/init.lua b/lua/entities/gmod_wire_multisegmentlcd/init.lua index c0d5ea8d24..9761d0ec6b 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/init.lua @@ -188,4 +188,4 @@ function ENT:ApplyDupeInfo(ply, ent, info, GetEntByID) ent:Retransmit() end -duplicator.RegisterEntityClass("gmod_wire_multisegmentlcd", WireLib.MakeWireEnt, "Data", "IsInteractive", "ResolutionW", "ResolutionH", "Bgred", "Bggreen", "Bgblue", "Fgred", "Fggreen", "Fgblue") +duplicator.RegisterEntityClass("gmod_wire_multisegmentlcd", WireLib.MakeWireEnt, "Data", "IsInteractive", "ResolutionW", "ResolutionH", "Bgred", "Bggreen", "Bgblue", "Bgalpha", "Fgred", "Fggreen", "Fgblue", "Fgalpha", "XorMask") From da7e46a51ae44847575d32dc0b59b100cef531cb Mon Sep 17 00:00:00 2001 From: wav3 Date: Sat, 13 Sep 2025 14:18:57 +0200 Subject: [PATCH 36/43] Fix Z and optimize rendering --- .../gmod_wire_multisegmentlcd/cl_init.lua | 71 +++++++------------ lua/wire/gpulib.lua | 10 ++- 2 files changed, 32 insertions(+), 49 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index eab463ff45..24e5b90292 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -335,73 +335,53 @@ end function ENT:Draw() self:DrawModel() - --[[ - self.GPU:RenderToWorld(nil, self.ResolutionH, function(x, y, w, h) - draw.NoTexture() - surface.SetDrawColor(self.Bgred,self.Bggreen,self.Bgblue,255) - surface.DrawRect(x,y,w,h) - if self.Tree then - --render.SetScissorRect(x,y,w,h, true) - surface.SetDrawColor(self.Fgred,self.Fggreen,self.Fgblue,255) - self.Cr = self.Fgred - self.Cg = self.Fggreen - self.Cb = self.Fgblue - self.LocalXX = 1 - self.LocalXY = 0 - self.LocalYX = 0 - self.LocalYY = 1 - self.LocalX = x - self.LocalY = y - self.BitIndex = 0 - - self.TransformStack = {} - self:DrawGroup(self.Tree) - --render.SetScissorRect( 0, 0, 0, 0, false ) - end - end)]] + local self2 = self:GetTable() - if self.Tree then + if self2.Tree then local oldw = ScrW() local oldh = ScrH() - local NewRT = self.GPU.RT + local NewRT = self2.GPU.RT local OldRT = render.GetRenderTarget() render.SetRenderTarget(NewRT) render.SetViewPort(0, 0, 1024, 1024) cam.Start2D() - render.ClearRenderTarget(self.GPU.RT, Color(0, 0, 0, 0)) - surface.SetDrawColor(self.Bgred,self.Bggreen,self.Bgblue,self.Bgalpha) + render.OverrideBlend( true, BLEND_ONE, BLEND_ZERO, BLENDFUNC_ADD ) + surface.SetDrawColor(self2.Bgred,self2.Bggreen,self2.Bgblue,self2.Bgalpha) surface.DrawRect( 0, 0, 1, 1 ) - for i=0,self.BitIndex-1 do + for i=0,self2.BitIndex-1 do local x = (i+1)%1024 local y = math.floor((i+1)/1024) - self.Fade[i] = (self.Fade[i] or 0)*0.92 + 0.01 - if bit.band(self.Memory[bit.rshift(i,3)] or 0,bit.lshift(1,bit.band(i,7))) ~= 0 then - self.Fade[i] = self.Fade[i] + 0.07 + self2.Fade[i] = (self2.Fade[i] or 0)*0.92 + 0.01 + if bit.band(self2.Memory[bit.rshift(i,3)] or 0,bit.lshift(1,bit.band(i,7))) ~= 0 then + self2.Fade[i] = self2.Fade[i] + 0.07 end - local color = self.Colors[i] - surface.SetDrawColor(color[1]*self.Fade[i]+self.Bgred*(1-self.Fade[i]),color[2]*self.Fade[i]+self.Bggreen*(1-self.Fade[i]),color[3]*self.Fade[i]+self.Bgblue*(1-self.Fade[i]),self.Fade[i]*color[4]+self.Bgalpha*(1-self.Fade[i])) - if x == 0 and y == 0 then - break + if self2.Fade[i] > 0.05 and self2.Fade[i] < 0.98 then + local color = self2.Colors[i] + surface.SetDrawColor(color[1]*self2.Fade[i]+self2.Bgred*(1-self2.Fade[i]),color[2]*self2.Fade[i]+self2.Bggreen*(1-self2.Fade[i]),color[3]*self2.Fade[i]+self2.Bgblue*(1-self2.Fade[i]),self2.Fade[i]*color[4]+self2.Bgalpha*(1-self2.Fade[i])*0.15) + if x == 0 and y == 0 then + break + end + surface.DrawRect( x, y, 1, 1 ) end - surface.DrawRect( x, y, 1, 1 ) end + render.OverrideBlend( false ) cam.End2D() render.SetViewPort(0, 0, oldw, oldh) render.SetRenderTarget(OldRT) - local OldTex = WireGPU_matScreen:GetTexture("$basetexture") - WireGPU_matScreen:SetTexture("$basetexture", self.GPU.RT) - render.SetMaterial( WireGPU_matScreen ) + local OldTex = WireGPU_matSegment:GetTexture("$basetexture") + WireGPU_matSegment:SetTexture("$basetexture", self2.GPU.RT) + render.SetMaterial( WireGPU_matSegment ) - local monitor, pos, ang = self.GPU:GetInfo() - local h = self.ResolutionH + local monitor, pos, ang = self2.GPU:GetInfo() + local h = self2.ResolutionH local scale = monitor.RS*1024/h local m = Matrix() m:SetAngles( ang ) @@ -413,17 +393,14 @@ function ENT:Draw() --surface.SetDrawColor(self.Fgred,self.Fggreen,self.Fgblue,255) for i=1,#self.TreeMesh do - self.TreeMesh[i]:Draw() + self2.TreeMesh[i]:Draw() end cam.PopModelMatrix() cam.PopModelMatrix() - WireGPU_matScreen:SetTexture("$basetexture", OldTex) - --render.SetScissorRect( 0, 0, 0, 0, false ) + WireGPU_matSegment:SetTexture("$basetexture", OldTex) end - -- - --self.GPU:Render(0,0,1024,1024,nil,-(1024-self.ResolutionW)/1024,-(1024-self.ResolutionH)/1024) Wire_Render(self) end diff --git a/lua/wire/gpulib.lua b/lua/wire/gpulib.lua index 62d625cf86..1b44e1d2e5 100644 --- a/lua/wire/gpulib.lua +++ b/lua/wire/gpulib.lua @@ -154,17 +154,23 @@ if CLIENT then WireGPU_matScreen = CreateMaterial("sprites/GPURT","UnlitGeneric",{ ["$vertexcolor"] = 1, ["$vertexalpha"] = 1, - ["$translucent"] = 1, + ["$translucent"] = 1, ["$ignorez"] = 1, ["$nolod"] = 1, }) WireGPU_matBuffer = CreateMaterial("sprites/GPUBUF","UnlitGeneric",{ ["$vertexcolor"] = 1, ["$vertexalpha"] = 1, - ["$translucent"] = 1, + ["$translucent"] = 1, ["$ignorez"] = 1, ["$nolod"] = 1, }) + WireGPU_matSegment = CreateMaterial("sprites/SEGRT","UnlitGeneric",{ + ["$vertexcolor"] = 1, + ["$vertexalpha"] = 1, + ["$translucent"] = 1, + ["$nolod"] = 1, + }) function GPU:Initialize(no_rendertarget) From ec6f6db8ecad02ea207f1caa3cac0239017ca462 Mon Sep 17 00:00:00 2001 From: wav3 Date: Sat, 13 Sep 2025 14:21:28 +0200 Subject: [PATCH 37/43] change minimum --- lua/entities/gmod_wire_multisegmentlcd/cl_init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index 24e5b90292..bb0ee1b4e9 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -361,7 +361,7 @@ function ENT:Draw() if bit.band(self2.Memory[bit.rshift(i,3)] or 0,bit.lshift(1,bit.band(i,7))) ~= 0 then self2.Fade[i] = self2.Fade[i] + 0.07 end - if self2.Fade[i] > 0.05 and self2.Fade[i] < 0.98 then + if self2.Fade[i] > 0.15 and self2.Fade[i] < 0.9 then local color = self2.Colors[i] surface.SetDrawColor(color[1]*self2.Fade[i]+self2.Bgred*(1-self2.Fade[i]),color[2]*self2.Fade[i]+self2.Bggreen*(1-self2.Fade[i]),color[3]*self2.Fade[i]+self2.Bgblue*(1-self2.Fade[i]),self2.Fade[i]*color[4]+self2.Bgalpha*(1-self2.Fade[i])*0.15) if x == 0 and y == 0 then From 3060dfe80e1d86a378cb9d208f010f7ff0896b55 Mon Sep 17 00:00:00 2001 From: wav3 Date: Sat, 13 Sep 2025 15:08:09 +0200 Subject: [PATCH 38/43] Optimizations --- .../gmod_wire_multisegmentlcd/cl_init.lua | 45 ++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index bb0ee1b4e9..a0732f1a01 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -335,6 +335,7 @@ end function ENT:Draw() self:DrawModel() + local self2 = self:GetTable() @@ -350,28 +351,32 @@ function ENT:Draw() render.SetRenderTarget(NewRT) render.SetViewPort(0, 0, 1024, 1024) - cam.Start2D() - render.OverrideBlend( true, BLEND_ONE, BLEND_ZERO, BLENDFUNC_ADD ) - surface.SetDrawColor(self2.Bgred,self2.Bggreen,self2.Bgblue,self2.Bgalpha) - surface.DrawRect( 0, 0, 1, 1 ) - for i=0,self2.BitIndex-1 do - local x = (i+1)%1024 - local y = math.floor((i+1)/1024) - self2.Fade[i] = (self2.Fade[i] or 0)*0.92 + 0.01 - if bit.band(self2.Memory[bit.rshift(i,3)] or 0,bit.lshift(1,bit.band(i,7))) ~= 0 then - self2.Fade[i] = self2.Fade[i] + 0.07 - end - if self2.Fade[i] > 0.15 and self2.Fade[i] < 0.9 then - local color = self2.Colors[i] - surface.SetDrawColor(color[1]*self2.Fade[i]+self2.Bgred*(1-self2.Fade[i]),color[2]*self2.Fade[i]+self2.Bggreen*(1-self2.Fade[i]),color[3]*self2.Fade[i]+self2.Bgblue*(1-self2.Fade[i]),self2.Fade[i]*color[4]+self2.Bgalpha*(1-self2.Fade[i])*0.15) - if x == 0 and y == 0 then - break + if self:GetPos():DistToSqr(EyePos()) < 262144 then + local fade = self2.Fade + cam.Start2D() + render.OverrideBlend( true, BLEND_ONE, BLEND_ZERO, BLENDFUNC_ADD ) + surface.SetDrawColor(self2.Bgred,self2.Bggreen,self2.Bgblue,self2.Bgalpha) + surface.DrawRect( 0, 0, 1, 1 ) + for i=0,self2.BitIndex-1 do + local x = (i+1)%1024 + local y = math.floor((i+1)/1024) + fade[i] = (fade[i] or 0)*0.92 + 0.01 + if bit.band(self2.Memory[bit.rshift(i,3)] or 0,bit.lshift(1,bit.band(i,7))) ~= 0 then + fade[i] = fade[i] + 0.07 + end + + if fade[i] > 0.14 and fade[i] < 0.95 then + local color = self2.Colors[i] + surface.SetDrawColor(color[1]*fade[i]+self2.Bgred*(1-fade[i]),color[2]*fade[i]+self2.Bggreen*(1-fade[i]),color[3]*fade[i]+self2.Bgblue*(1-fade[i]),fade[i]*color[4]+self2.Bgalpha*(1-fade[i])*0.15) + if x == 0 and y == 0 then + break + end + surface.DrawRect( x, y, 1, 1 ) end - surface.DrawRect( x, y, 1, 1 ) end - end - render.OverrideBlend( false ) - cam.End2D() + render.OverrideBlend( false ) + cam.End2D() + end render.SetViewPort(0, 0, oldw, oldh) render.SetRenderTarget(OldRT) From 174155625b8c14884cab27cdae9a525c5a0c2c2b Mon Sep 17 00:00:00 2001 From: wav3 Date: Sat, 13 Sep 2025 19:07:25 +0200 Subject: [PATCH 39/43] text --- .../gmod_wire_multisegmentlcd/cl_init.lua | 49 +++++++++++++++---- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index a0732f1a01..71cf4bc0dd 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -33,6 +33,7 @@ function ENT:Initialize() end) self.TreeMesh = {} + self.Texts = {} WireLib.netRegister(self) end @@ -90,6 +91,15 @@ function ENT:TransformOffset(x,y) } end +function ENT:GetTransformMatrix(x,y) + return Matrix({ + {x*self.LocalXX,y*self.LocalXY,0,self.LocalX}, + {x*self.LocalYX,y*self.LocalYY,0,self.LocalY}, + {0,0,1,0}, + {0,0,0,1} + }) +end + function ENT:PushTransform(XX,XY,YX,YY) self.TransformStack[#self.TransformStack + 1] = {self.LocalXX,self.LocalXY,self.LocalYX,self.LocalYY} local oXX = self.LocalXX @@ -186,14 +196,19 @@ function ENT:DrawSegment(segment) self.BitIndex = self.BitIndex+1 end +_TEXT_MATRIX = 0 +_TEXT_TEXT = 1 +_TEXT_BITINDEX = 2 + function ENT:DrawText(text) local transformedLocal = self:TransformOffset(text.X or 0,text.Y or 0) self.LocalX = self.LocalX + transformedLocal[1] self.LocalY = self.LocalY + transformedLocal[2] - --surface.SetTextPos(self.LocalX,self.LocalY) - --surface.SetFont("Default") - --surface.SetTextColor(self.Cr,self.Cg,self.Cb,self.Fade[self.BitIndex]*255) - --surface.DrawText(text.Text) + self.Texts[#self.Texts+1] = { + [_TEXT_MATRIX] = self:GetTransformMatrix(text.W or 1,text.H or 1), + [_TEXT_TEXT] = text.Text, + [_TEXT_BITINDEX] = self.BitIndex + } self.LocalX = self.LocalX - transformedLocal[1] self.LocalY = self.LocalY - transformedLocal[2] self.Colors[self.BitIndex] = {self.Cr,self.Cg,self.Cb,self.Ca} @@ -365,7 +380,7 @@ function ENT:Draw() fade[i] = fade[i] + 0.07 end - if fade[i] > 0.14 and fade[i] < 0.95 then + if fade[i] < 0.1 or fade[i] > 0.14 and fade[i] < 0.95 then local color = self2.Colors[i] surface.SetDrawColor(color[1]*fade[i]+self2.Bgred*(1-fade[i]),color[2]*fade[i]+self2.Bggreen*(1-fade[i]),color[3]*fade[i]+self2.Bgblue*(1-fade[i]),fade[i]*color[4]+self2.Bgalpha*(1-fade[i])*0.15) if x == 0 and y == 0 then @@ -392,16 +407,29 @@ function ENT:Draw() m:SetAngles( ang ) m:SetTranslation( pos ) m:SetScale( Vector( scale, -scale, 1 ) ) - cam.PushModelMatrix( self:GetWorldTransformMatrix() ) + --cam.PushModelMatrix( self:GetWorldTransformMatrix() ) cam.PushModelMatrix( m ) - - --surface.SetDrawColor(self.Fgred,self.Fggreen,self.Fgblue,255) + - for i=1,#self.TreeMesh do + for i=1,#self2.TreeMesh do self2.TreeMesh[i]:Draw() end cam.PopModelMatrix() - cam.PopModelMatrix() + + for i=1,#self2.Texts do + local text = self2.Texts[i] + local newm = text[_TEXT_MATRIX] + + surface.SetFont( "Default" ) + cam.Start3D2D(pos, ang, scale) + cam.PushModelMatrix( newm, true ) + draw.DrawText( text[_TEXT_TEXT], "Default" ) + cam.PopModelMatrix() + cam.End3D2D() + end + + + --cam.PopModelMatrix() WireGPU_matSegment:SetTexture("$basetexture", OldTex) end @@ -448,6 +476,7 @@ function ENT:Receive() self.LocalX = -w/2 self.LocalY = -h/2 self.TreeMesh = self.TreeMesh or {} + self.Texts = {} for i=#self.TreeMesh,1,-1 do self.TreeMesh[i]:Destroy() self.TreeMesh[i] = nil From 56e38df219d8c87311dd2b6310c2516c393c571b Mon Sep 17 00:00:00 2001 From: wav3 Date: Sun, 14 Sep 2025 14:50:42 +0200 Subject: [PATCH 40/43] Fix segment begin count --- lua/entities/gmod_wire_multisegmentlcd/cl_init.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index 71cf4bc0dd..f31f1089af 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -127,7 +127,7 @@ function ENT:AddPoly(poly) local u = (((bit.bxor(self.BitIndex,self.XorMask)+1)%1024)+0.5)/1024 local v = (math.floor((self.BitIndex+1)/1024)+0.5)/1024 for i = 1,#poly do - if self.CurTris > 10922 then + if self.CurTris > 10922*3 then mesh.End() self.TreeMesh[#self.TreeMesh + 1] = Mesh() mesh.Begin(self.TreeMesh[#self.TreeMesh],MATERIAL_TRIANGLES,math.min(10922,self.Tris)) @@ -141,7 +141,7 @@ function ENT:AddPoly(poly) self.CurTris = self.CurTris + 1 end for i = 1,#poly do - if self.CurTris > 10922 then + if self.CurTris > 10922*3 then mesh.End() self.TreeMesh[#self.TreeMesh + 1] = Mesh() mesh.Begin(self.TreeMesh[#self.TreeMesh],MATERIAL_TRIANGLES,math.min(10922,self.Tris)) @@ -483,6 +483,7 @@ function ENT:Receive() end self.TreeMesh[#self.TreeMesh + 1] = Mesh() self.Tris = self:CountTris(self.Tree) + print(self.Tris) mesh.Begin(self.TreeMesh[#self.TreeMesh],MATERIAL_TRIANGLES,math.min(10922,self.Tris)) self.Tris = self.Tris - 10922 @@ -493,7 +494,7 @@ function ENT:Receive() mesh.Position(self.LocalX,self.LocalY,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 1/2048, 1/2048, 1/2048, 1/2048) mesh.AdvanceVertex() mesh.Position(self.LocalX+w,self.LocalY+h,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 1/2048, 1/2048, 1/2048, 1/2048) mesh.AdvanceVertex() mesh.Position(self.LocalX,self.LocalY+h,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 1/2048, 1/2048, 1/2048, 1/2048) mesh.AdvanceVertex() - self.CurTris = 6 + self.CurTris = 2 self:DrawGroup(self.Tree) mesh.End() From 9339203ebcfd5fdd2ccafd91c4950810da8a8f10 Mon Sep 17 00:00:00 2001 From: wav3 Date: Sun, 14 Sep 2025 15:37:48 +0200 Subject: [PATCH 41/43] remove print --- lua/entities/gmod_wire_multisegmentlcd/cl_init.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index f31f1089af..ff2974120c 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -483,7 +483,6 @@ function ENT:Receive() end self.TreeMesh[#self.TreeMesh + 1] = Mesh() self.Tris = self:CountTris(self.Tree) - print(self.Tris) mesh.Begin(self.TreeMesh[#self.TreeMesh],MATERIAL_TRIANGLES,math.min(10922,self.Tris)) self.Tris = self.Tris - 10922 From d8cc8088a8c153386fbf6644d67a876542e7fcb7 Mon Sep 17 00:00:00 2001 From: wav3 Date: Wed, 17 Sep 2025 15:46:17 +0200 Subject: [PATCH 42/43] fix segment rendering --- lua/entities/gmod_wire_multisegmentlcd/cl_init.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index ff2974120c..340e9bc29b 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -127,7 +127,7 @@ function ENT:AddPoly(poly) local u = (((bit.bxor(self.BitIndex,self.XorMask)+1)%1024)+0.5)/1024 local v = (math.floor((self.BitIndex+1)/1024)+0.5)/1024 for i = 1,#poly do - if self.CurTris > 10922*3 then + if self.CurTris >= 10922*3 then mesh.End() self.TreeMesh[#self.TreeMesh + 1] = Mesh() mesh.Begin(self.TreeMesh[#self.TreeMesh],MATERIAL_TRIANGLES,math.min(10922,self.Tris)) @@ -141,7 +141,7 @@ function ENT:AddPoly(poly) self.CurTris = self.CurTris + 1 end for i = 1,#poly do - if self.CurTris > 10922*3 then + if self.CurTris >= 10922*3 then mesh.End() self.TreeMesh[#self.TreeMesh + 1] = Mesh() mesh.Begin(self.TreeMesh[#self.TreeMesh],MATERIAL_TRIANGLES,math.min(10922,self.Tris)) @@ -343,7 +343,7 @@ function ENT:CountTris(node) end return sum elseif node.Type == MATRIX then - return node.W*node.H*16 + return node.W*node.H*4 end return 12 end @@ -493,7 +493,7 @@ function ENT:Receive() mesh.Position(self.LocalX,self.LocalY,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 1/2048, 1/2048, 1/2048, 1/2048) mesh.AdvanceVertex() mesh.Position(self.LocalX+w,self.LocalY+h,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 1/2048, 1/2048, 1/2048, 1/2048) mesh.AdvanceVertex() mesh.Position(self.LocalX,self.LocalY+h,0) mesh.Color(255,255,255,255) mesh.TexCoord(0, 1/2048, 1/2048, 1/2048, 1/2048) mesh.AdvanceVertex() - self.CurTris = 2 + self.CurTris = 0 self:DrawGroup(self.Tree) mesh.End() From 04ab2c3aee9323221d06ce52663a54d0fa738857 Mon Sep 17 00:00:00 2001 From: wav3 Date: Wed, 24 Sep 2025 11:01:16 +0200 Subject: [PATCH 43/43] Offset and Align --- .../gmod_wire_multisegmentlcd/cl_init.lua | 12 ++- .../gmod_wire_multisegmentlcd/shared.lua | 2 + lua/wire/stools/multisegmentlcd.lua | 96 ++++++++++++++++++- 3 files changed, 106 insertions(+), 4 deletions(-) diff --git a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua index 340e9bc29b..2966659883 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -275,6 +275,10 @@ function ENT:DrawUnion(group) self:DrawText(v) elseif v.Type == MATRIX then self:DrawMatrix(v) + elseif v.Type == ALIGN then + self.BitIndex = math.ceil(self.BitIndex/v.Size)*v.Size + elseif v.Type == OFFSET then + self.BitIndex = self.BitIndex + v.Size end biggestindex = math.max(biggestindex,self.BitIndex) self.BitIndex = savedindex @@ -324,6 +328,10 @@ function ENT:DrawGroup(group) self:DrawText(v) elseif v.Type == MATRIX then self:DrawMatrix(v) + elseif v.Type == ALIGN then + self.BitIndex = math.ceil(self.BitIndex/v.Size)*v.Size + elseif v.Type == OFFSET then + self.BitIndex = self.BitIndex + v.Size end end self:PopTransform() @@ -412,7 +420,9 @@ function ENT:Draw() for i=1,#self2.TreeMesh do - self2.TreeMesh[i]:Draw() + if self2.TreeMesh[i] then + self2.TreeMesh[i]:Draw() + end end cam.PopModelMatrix() diff --git a/lua/entities/gmod_wire_multisegmentlcd/shared.lua b/lua/entities/gmod_wire_multisegmentlcd/shared.lua index 735b21d490..971661f7d0 100644 --- a/lua/entities/gmod_wire_multisegmentlcd/shared.lua +++ b/lua/entities/gmod_wire_multisegmentlcd/shared.lua @@ -12,6 +12,8 @@ ENT.Spawnable = false ENT.RenderGroup = RENDERGROUP_BOTH +OFFSET = -3 +ALIGN = -2 GROUP = -1 UNION = 0 SEGMENT = 1 diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua index 50b7accff9..943c348326 100644 --- a/lua/wire/stools/multisegmentlcd.lua +++ b/lua/wire/stools/multisegmentlcd.lua @@ -1,6 +1,8 @@ WireToolSetup.setCategory( "Visuals/Screens" ) WireToolSetup.open( "multisegmentlcd", "Multi-segment LCD", "gmod_wire_multisegmentlcd", nil, "Multi-segment LCDs" ) +OFFSET = -3 +ALIGN = -2 GROUP = -1 UNION = 0 SEGMENT = 1 @@ -12,6 +14,8 @@ SegmentTypeNames = { [SEGMENT] = "Segment", [TEXT] = "Text", [MATRIX] = "Matrix", +[ALIGN] = "Align", +[OFFSET] = "Offset", } WireLib.SegmentLCD_Tree = { @@ -130,6 +134,10 @@ function BuildNode(v,node,group) new = node:AddNode( v.Text or "Text", "icon16/bullet_yellow.png" ) elseif v.Type == MATRIX then new = node:AddNode( v.Text or "Matrix", "icon16/bullet_red.png" ) + elseif v.Type == ALIGN then + new = node:AddNode( v.Text or "Text", "icon16/bullet_pink.png" ) + elseif v.Type == OFFSET then + new = node:AddNode( v.Text or "Text", "icon16/bullet_white.png" ) else new = node:AddNode( v.Text or "Segment", "icon16/bullet_green.png" ) end @@ -562,6 +570,61 @@ function TOOL.BuildCPanel(panel) node.group.BevelSkew = value end + WangSize = ButtonsHolder:Add( "DNumberWang" ) + WangSize:SetMax(1024) + WangSize:SetMin(1) + function WangSize:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil then + return + end + node.group.Size = value + end + + function AddOffsetI(node) + if node == nil then + node = DisplayData.RootNode + end + local group = node.group + local children = nil + if group ~= nil then + children = group.Children + end + + if children == nil then + node = DisplayData.RootNode + children = WireLib.SegmentLCD_Tree.Children + group = WireLib.SegmentLCD_Tree + end + local newgroup = {Type=OFFSET, Size=1} + children[#children+1] = newgroup + local new = node:AddNode( "Offset", "icon16/bullet_white.png" ) + new.group = newgroup + new.parentgroup = group + end + + function AddAlignI(node) + if node == nil then + node = DisplayData.RootNode + end + local group = node.group + local children = nil + if group ~= nil then + children = group.Children + end + + if children == nil then + node = DisplayData.RootNode + children = WireLib.SegmentLCD_Tree.Children + group = WireLib.SegmentLCD_Tree + end + local newgroup = {Type=ALIGN, Size=8} + children[#children+1] = newgroup + local new = node:AddNode( "Align", "icon16/bullet_pink.png" ) + new.group = newgroup + new.parentgroup = group + end + function ButtonsHolder:PerformLayout(w, h) local roww = w/8 local rowh = h/4 @@ -584,6 +647,9 @@ function TOOL.BuildCPanel(panel) WangOffsetY:SetPos(roww*3,rowh*2) WangOffsetY:SetSize(roww,rowh) + WangSize:SetPos(0,rowh) + WangSize:SetSize(w,rowh) + CheckHasColor:SetPos(1,rowh*2+3) CheckLabel:SetPos(18,rowh*2) CheckLabel:SetSize(roww-18,rowh) @@ -625,6 +691,9 @@ function TOOL.BuildCPanel(panel) WangSkewY:SetVisible(false) WangBevel:SetVisible(false) WangBevelSkew:SetVisible(false) + WangSize:SetVisible(false) + WangX:SetVisible(false) + WangY:SetVisible(false) function DisplayData:DoClick(node) group = node.group @@ -645,6 +714,9 @@ function TOOL.BuildCPanel(panel) WangSkewY:SetVisible(false) WangBevel:SetVisible(false) WangBevelSkew:SetVisible(false) + WangSize:SetVisible(false) + WangX:SetVisible(false) + WangY:SetVisible(false) if group.Type == SEGMENT then WangW:SetValue(group.W) WangH:SetValue(group.H) @@ -655,12 +727,16 @@ function TOOL.BuildCPanel(panel) WangSkewY:SetVisible(true) WangBevel:SetVisible(true) WangBevelSkew:SetVisible(true) - + WangX:SetVisible(true) + WangY:SetVisible(true) + WangRotation:SetValue(group.Rotation or 0) WangSkewX:SetValue(group.SkewX or 0) WangSkewY:SetValue(group.SkewY or 0) WangBevel:SetValue(group.Bevel or 0) WangBevelSkew:SetValue(group.BevelSkew or 0) + WangX:SetValue(group.X) + WangY:SetValue(group.Y) elseif group.Type == MATRIX then WangW:SetValue(group.W) WangH:SetValue(group.H) @@ -670,10 +746,15 @@ function TOOL.BuildCPanel(panel) WangOffsetY:SetVisible(true) WangW:SetVisible(true) WangH:SetVisible(true) + WangX:SetVisible(true) + WangY:SetVisible(true) + WangScaleW:SetValue(group.ScaleW) WangScaleH:SetValue(group.ScaleH) WangOffsetX:SetValue(group.OffsetX) WangOffsetY:SetValue(group.OffsetY) + WangX:SetValue(group.X) + WangY:SetValue(group.Y) elseif group.Type == GROUP or group.Type == UNION then WangColorR:SetVisible(true) WangColorG:SetVisible(true) @@ -681,6 +762,9 @@ function TOOL.BuildCPanel(panel) WangColorA:SetVisible(true) CheckHasColor:SetVisible(true) CheckLabel:SetVisible(true) + WangX:SetVisible(true) + WangY:SetVisible(true) + WangColorR:SetValue(group.R) WangColorG:SetValue(group.G) WangColorB:SetValue(group.B) @@ -694,9 +778,13 @@ function TOOL.BuildCPanel(panel) WangSkewY:SetValue(group.SkewY or 0) WangBevel:SetValue(group.Bevel or 0) WangBevelSkew:SetValue(group.BevelSkew or 0) + WangX:SetValue(group.X) + WangY:SetValue(group.Y) + elseif group.Type == ALIGN or group.Type == OFFSET then + WangSize:SetVisible(true) + WangSize:SetValue(group.Size) end - WangX:SetValue(group.X) - WangY:SetValue(group.Y) + TextSetter:SetValue(group.Text or "") return true end @@ -712,6 +800,8 @@ function TOOL.BuildCPanel(panel) InsertM:AddOption( "Segment", function() AddSegmentI(node) end ) InsertM:AddOption( "Matrix", function() AddMatrixI(node) end ) InsertM:AddOption( "Text", function() AddTextI(node) end ) + InsertM:AddOption( "Align", function() AddAlignI(node) end ) + InsertM:AddOption( "Offset", function() AddOffsetI(node) end ) Menu:AddSpacer() Menu:AddOption( "Remove" ) Menu:Open()