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..2966659883 --- /dev/null +++ b/lua/entities/gmod_wire_multisegmentlcd/cl_init.lua @@ -0,0 +1,510 @@ +include("shared.lua") + + +function ENT:Initialize() + self.Memory = {} + self.Fade = {} + + 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.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 + + GPULib.ClientCacheCallback(self,function(Address,Value) + self:WriteCell(Address,Value) + end) + + self.TreeMesh = {} + self.Texts = {} + + 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() + for i=1,#self.TreeMesh do + self.TreeMesh[i]:Destroy() + end +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:Transform(x,y) + return { + x*self.LocalXX+y*self.LocalXY+self.LocalX, + x*self.LocalYX+y*self.LocalYY+self.LocalY + } +end + +function ENT:TransformOffset(x,y) + return { + x*self.LocalXX+y*self.LocalXY, + x*self.LocalYX+y*self.LocalYY + } +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 + 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: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 + 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(255,255,255,127) + mesh.AdvanceVertex() + self.CurTris = self.CurTris + 1 + end + for i = 1,#poly do + 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)) + self.Tris = self.Tris - 10922 + self.CurTris = 0 + end + mesh.Position(Vector(poly[i][1],poly[i][2],self.ZOffset)) + mesh.TexCoord(0, u, v, u ,v) + mesh.Color(255,255,255,255) + mesh.AdvanceVertex() + self.CurTris = self.CurTris + 1 + end +end + +function ENT:DrawSegment(segment) + --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] + 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), + -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(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) + } + 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) + self.LocalX = self.LocalX - transformedLocal[1] + self.LocalY = self.LocalY - transformedLocal[2] + self.Colors[self.BitIndex] = {self.Cr,self.Cg,self.Cb,self.Ca} + 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] + 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} + self.BitIndex = self.BitIndex+1 +end + +function ENT:DrawMatrix(matrix) + for y = 0,matrix.H-1 do + for x = 0,matrix.W-1 do + + local transformedLocal = self:TransformOffset(matrix.X+x*matrix.OffsetX,matrix.Y+y*matrix.OffsetY) + 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) + } + 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) + self.LocalX = self.LocalX - transformedLocal[1] + self.LocalY = self.LocalY - transformedLocal[2] + self.Colors[self.BitIndex] = {self.Cr,self.Cg,self.Cb,self.Ca} + self.BitIndex = self.BitIndex+1 + end + end + + +end + + +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] + self.LocalY = self.LocalY + transformedLocal[2] + 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) + elseif v.Type == TEXT then + 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 + end + self.BitIndex = biggestindex + self.LocalX = self.LocalX - transformedLocal[1] + self.LocalY = self.LocalY - transformedLocal[2] + 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] + self:PushTransform(math.cos(angle), + 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) + elseif v.Type == UNION then + self:DrawUnion(v) + elseif v.Type == SEGMENT then + self:DrawSegment(v) + elseif v.Type == TEXT then + 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() + 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 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*4 + end + return 12 +end + +function ENT:Draw() + self:DrawModel() + + local self2 = self:GetTable() + + + + + if self2.Tree then + + local oldw = ScrW() + local oldh = ScrH() + + local NewRT = self2.GPU.RT + local OldRT = render.GetRenderTarget() + + render.SetRenderTarget(NewRT) + render.SetViewPort(0, 0, 1024, 1024) + 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.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 + break + end + surface.DrawRect( x, y, 1, 1 ) + end + end + render.OverrideBlend( false ) + cam.End2D() + end + render.SetViewPort(0, 0, oldw, oldh) + render.SetRenderTarget(OldRT) + + + local OldTex = WireGPU_matSegment:GetTexture("$basetexture") + WireGPU_matSegment:SetTexture("$basetexture", self2.GPU.RT) + render.SetMaterial( WireGPU_matSegment ) + + local monitor, pos, ang = self2.GPU:GetInfo() + local h = self2.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 ) + + + for i=1,#self2.TreeMesh do + if self2.TreeMesh[i] then + self2.TreeMesh[i]:Draw() + end + end + 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 + + Wire_Render(self) +end + +function ENT:IsTranslucent() + return true +end + +function ENT:Receive() + local ent = net.ReadEntity() + local sz = net.ReadUInt(16) + 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.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 = self.Fgalpha + self.LocalXX = 1 + self.LocalXY = 0 + self.LocalYX = 0 + 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.ZOffset = monitor.RS*1024/h + 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 + 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, 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 = 0 + + self:DrawGroup(self.Tree) + mesh.End() +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..9761d0ec6b --- /dev/null +++ b/lua/entities/gmod_wire_multisegmentlcd/init.lua @@ -0,0 +1,191 @@ +AddCSLuaFile("cl_init.lua") +AddCSLuaFile("shared.lua") +include("shared.lua") + +DEFINE_BASECLASS( "base_wire_entity" ) +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.ResolutionW = 1024 + self.ResolutionH = 1024 + + self.Memory = {} + self.Cache = GPUCacheManager(self,true) +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.WriteUInt(#serialized,16) + 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.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 + +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, 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 + +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 + +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", "Bgalpha", "Fgred", "Fggreen", "Fgblue", "Fgalpha", "XorMask") diff --git a/lua/entities/gmod_wire_multisegmentlcd/shared.lua b/lua/entities/gmod_wire_multisegmentlcd/shared.lua new file mode 100644 index 0000000000..971661f7d0 --- /dev/null +++ b/lua/entities/gmod_wire_multisegmentlcd/shared.lua @@ -0,0 +1,21 @@ +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 + +OFFSET = -3 +ALIGN = -2 +GROUP = -1 +UNION = 0 +SEGMENT = 1 +TEXT = 2 +MATRIX = 3 \ No newline at end of file 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) diff --git a/lua/wire/stools/multisegmentlcd.lua b/lua/wire/stools/multisegmentlcd.lua new file mode 100644 index 0000000000..943c348326 --- /dev/null +++ b/lua/wire/stools/multisegmentlcd.lua @@ -0,0 +1,1127 @@ +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 +TEXT = 2 +MATRIX = 3 +SegmentTypeNames = { +[GROUP] = "Group", +[UNION] = "Union", +[SEGMENT] = "Segment", +[TEXT] = "Text", +[MATRIX] = "Matrix", +[ALIGN] = "Align", +[OFFSET] = "Offset", +} + +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):" ) + 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 } } + + WireToolSetup.setToolMenuIcon("icon16/application_xp_terminal.png") + + + + 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.WriteUInt(#serialized,16) + net.WriteData(serialized) + 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") == 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), + 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 + + 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()) + trace.Entity:Setup(self:GetConVars()) + end + + net.Receive("wire_multisegmentlcd_tool_upload", function(len, ply) + local ent = ents.GetByIndex(net.ReadUInt(16)) + local sz = net.ReadUInt(16) + ent.Tree = WireLib.von.deserialize(net.ReadData(sz)) + 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, + resw = 1024, + resh = 1024, + bgred = 148, + bggreen = 178, + bgblue = 15, + bgalpha = 255, + fgred = 45, + fggreen = 91, + fgblue = 45, + fgalpha = 255, + xormask = 0 +} + + +function BuildNode(v,node,group) + local new = nil + if v.Type == GROUP then + new = node:AddNode( v.Text or "Group", "icon16/text_list_numbers.png" ) + BuildNodes(new,v) + elseif v.Type == UNION then + new = node:AddNode( v.Text or "Union", "icon16/text_list_bullets.png" ) + BuildNodes(new,v) + elseif v.Type == TEXT then + 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 + 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") + 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) + TreeDataHolder:Dock(TOP) + 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 + BuildNodes(DisplayData.RootNode,WireLib.SegmentLCD_Tree) + ButtonsHolder = TreeDataHolder:Add( "DPanel" ) + ButtonsHolder:Dock(TOP) + ButtonsHolder:DockMargin(0, 0, 0, 0) + ButtonsHolder.buttons = {} + ButtonsHolder:SetHeight(72) + + AddSegment = ButtonsHolder:Add( "DButton" ) + AddSegment:SetText( "Add Segment" ) + ButtonsHolder.buttons[1] = AddSegment + function AddSegmentI(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=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 + function AddSegment:DoClick() + local node = DisplayData:GetSelectedItem() + AddSegmentI(node) + end + + AddText = ButtonsHolder:Add( "DButton" ) + AddText:SetText( "Add Text" ) + ButtonsHolder.buttons[2] = AddText + function AddTextI(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=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 AddMatrixI(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=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 + function AddMatrix:DoClick() + local node = DisplayData:GetSelectedItem() + AddMatrixI(node) + end + + AddGroup = ButtonsHolder:Add( "DButton" ) + AddGroup:SetText( "Add Group" ) + ButtonsHolder.buttons[4] = AddGroup + function AddGroupI(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=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 AddUnionI(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=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 + parentgroup = WireLib.SegmentLCD_Tree + 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() + RemoveI(node) + 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 + return + end + node.group.X = value + 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 + return + end + node.group.Y = value + 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 + return + end + node.group.W = value + 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 + return + end + node.group.H = value + end + ButtonsHolder.textboxes[4] = WangH + + TextSetter = ButtonsHolder:Add( "DTextEntry" ) + function TextSetter:OnChange() + local value = TextSetter:GetText() + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil then + return + end + 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" ) + WangScaleW:SetMax(1024) + function WangScaleW:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil then + return + end + node.group.ScaleW = value + end + + WangScaleH = ButtonsHolder:Add( "DNumberWang" ) + WangScaleH:SetMax(1024) + function WangScaleH:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil then + return + end + node.group.ScaleH = value + end + + WangOffsetX = ButtonsHolder:Add( "DNumberWang" ) + WangOffsetX:SetMax(1024) + function WangOffsetX:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil then + return + end + node.group.OffsetX = value + end + + WangOffsetY = ButtonsHolder:Add( "DNumberWang" ) + WangOffsetY:SetMax(1024) + function WangOffsetY:OnValueChanged(value) + local node = DisplayData:GetSelectedItem() + if node == nil or node.group == nil then + return + end + 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 + + 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) + 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:SetMin(-4096) + 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: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() + 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 + + 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 + for i,v in ipairs(self.buttons) do + v:SetPos((i-1)*w/#self.buttons,0) + v:SetSize(w/#self.buttons,rowh) + end + for i,v in ipairs(self.textboxes) do + 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(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) + + WangSize:SetPos(0,rowh) + WangSize:SetSize(w,rowh) + + CheckHasColor:SetPos(1,rowh*2+3) + CheckLabel:SetPos(18,rowh*2) + 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) + WangColorA:SetPos(roww*4,rowh*2) + WangColorA:SetSize(roww,rowh) + + WangRotation:SetPos(roww*5,rowh*2) + WangRotation:SetSize(roww,rowh) + WangSkewX:SetPos(roww*6,rowh*2) + WangSkewX:SetSize(roww,rowh) + WangSkewY:SetPos(roww*7,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) + WangScaleW:SetVisible(false) + WangScaleH:SetVisible(false) + WangOffsetX:SetVisible(false) + WangOffsetY:SetVisible(false) + WangColorR:SetVisible(false) + WangColorG:SetVisible(false) + WangColorB:SetVisible(false) + WangColorA:SetVisible(false) + CheckHasColor:SetVisible(false) + CheckLabel:SetVisible(false) + WangRotation:SetVisible(false) + WangSkewX:SetVisible(false) + 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 + 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) + WangColorA:SetVisible(false) + CheckHasColor:SetVisible(false) + CheckLabel:SetVisible(false) + WangRotation:SetVisible(false) + WangSkewX:SetVisible(false) + 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) + WangW:SetVisible(true) + WangH:SetVisible(true) + WangRotation:SetVisible(true) + WangSkewX:SetVisible(true) + 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) + WangScaleW:SetVisible(true) + WangScaleH:SetVisible(true) + WangOffsetX:SetVisible(true) + 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) + WangColorB:SetVisible(true) + 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) + 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) + 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 + + TextSetter:SetValue(group.Text or "") + return true + end + + function DisplayData:DoRightClick(node) + local Menu = DermaMenu() + Menu:AddOption( "Ungroup" ) + 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 ) + InsertM:AddOption( "Align", function() AddAlignI(node) end ) + InsertM:AddOption( "Offset", function() AddOffsetI(node) end ) + Menu:AddSpacer() + Menu:AddOption( "Remove" ) + Menu:Open() + function Menu:OptionSelected(option, optionText) + 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 + 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 + elseif optionText == "Remove" then + RemoveI(node) + 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 + + panel:AddControl("Color", { + Label = "#tool.wire_multisegmentlcd.bgcolor", + Red = "wire_multisegmentlcd_bgred", + Green = "wire_multisegmentlcd_bggreen", + Blue = "wire_multisegmentlcd_bgblue", + Alpha = "wire_multisegmentlcd_bgalpha", + ShowAlpha = "1", + 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", + Alpha = "wire_multisegmentlcd_fgalpha", + ShowAlpha = "1", + ShowHSV = "1", + ShowRGB = "1", + 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