diff --git a/lua/autorun/wire_load.lua b/lua/autorun/wire_load.lua index 82dd80f2..6fbca622 100644 --- a/lua/autorun/wire_load.lua +++ b/lua/autorun/wire_load.lua @@ -84,6 +84,8 @@ if SERVER then if CreateConVar("wire_force_workshop", 1, {FCVAR_ARCHIVE}, "Should Wire force all clients to download the Workshop edition of Wire, for models? (requires restart to disable)"):GetBool() then resource.AddWorkshop("160250458") end + resource.AddFile("resource/fonts/alphalcd.ttf") + end -- shared includes @@ -129,6 +131,7 @@ if CLIENT then include("wire/client/rendertarget_fix.lua") include("wire/client/hlzasm/hc_compiler.lua") include("wire/client/customspawnmenu.lua") + end diff --git a/lua/entities/gmod_wire_characterlcd/cl_init.lua b/lua/entities/gmod_wire_characterlcd/cl_init.lua new file mode 100644 index 00000000..7c642b99 --- /dev/null +++ b/lua/entities/gmod_wire_characterlcd/cl_init.lua @@ -0,0 +1,548 @@ +include("shared.lua") + +function ENT:Initialize() + local mem = {} + self.Memory = mem + for i = 0, 1023 do + mem[i] = 0 + end + + -- Screen control: + -- [1003] - Background red + -- [1004] - Background green + -- [1005] - Background blue + -- [1006] - Text red + -- [1007] - Text green + -- [1008] - Text blue + -- [1009] - Width + -- [1010] - Height + + -- Character control: + -- [1011] - Write char at cursor (Writing puts character and shifts) + -- + -- Caching control: + -- [1012] - Force cache refresh + -- [1013] - Cached blocks size (up to 28, 0 if disabled) + -- + -- + -- Shifting control: + -- [1014] - Shift cursor 1:backwards 0:forwards + -- [1015] - Shift screen with cursor + -- + -- Character output control: + -- [1016] - Contrast + -- + -- Control registers: + -- [1017] - Hardware Clear Row (Writing clears row) + -- [1018] - Hardware Clear Screen + -- + -- Cursor control: + -- [1019] - Cursor Blink Rate (0.50) + -- [1020] - Cursor Size (0.25) + -- [1021] - Cursor Address + -- [1022] - Cursor Enabled + -- + -- [1023] - Clk + mem[1003] = 148 + mem[1004] = 178 + mem[1005] = 15 + mem[1006] = 45 + mem[1007] = 91 + mem[1008] = 45 + mem[1012] = 0 + mem[1013] = 0 + mem[1014] = 0 + mem[1015] = 0 + mem[1016] = 1 + mem[1017] = 0 + mem[1018] = 0 + mem[1019] = 0.5 + mem[1020] = 0.25 + mem[1021] = 0 + mem[1022] = 1 + mem[1023] = 1 + + self.IntTimer = 0 + self.Flash = false + + self.GPU = WireGPU(self) + mem[1009] = 16 + mem[1010] = 2 + + -- Setup caching + GPULib.ClientCacheCallback(self,function(Address,Value) + self:WriteCell(Address,Value) + end) + + WireLib.netRegister(self) +end + +function ENT:OnRemove() + self.GPU:Finalize() +end + +function ENT:ReadCell(Address,value) + return self.Memory[math.floor(Address)] +end + +function ENT:ShiftScreenRight() + local mem = self.Memory + for y=0,mem[1010]-1 do + for x=mem[1009]-1,1,-1 do + mem[x+y*mem[1009]] = mem[x+y*mem[1009]-1] + end + mem[y*mem[1009]] = 0 + end +end + +function ENT:ShiftScreenLeft() + local mem = self.Memory + for y=0,mem[1010]-1 do + for x=0,mem[1009]-2 do + mem[x+y*mem[1009]] = mem[x+y*mem[1009]+1] + end + mem[y*mem[1009]+mem[1009]-1] = 0 + end +end + +function ENT:WriteCell(Address,value) + Address = math.floor(Address) + if Address < 0 or Address >= 1024 then return false end + if value ~= value then return false end + + local mem = self.Memory + + if Address == 1009 then -- Screen width + value = math.floor(value) + if (value*mem[1010] > 1003 or value*18 > 1024) then return false end + elseif Address == 1010 then -- Screen height + value = math.floor(value) + if (value*mem[1009] > 1003 or value*24 > 1024) then return false end + elseif Address == 1011 then -- Write char at cursor + value = math.floor(value) + if mem[1015] >= 1 then + if mem[1014] >= 1 then + self:ShiftScreenRight() + else + self:ShiftScreenLeft() + end + mem[mem[1021]%(mem[1010]*mem[1009])] = value + else + mem[mem[1021]%(mem[1010]*mem[1009])] = value + if mem[1014] >= 1 then + mem[1021] = (mem[1021] - 1)%(mem[1010]*mem[1009]) + else + mem[1021] = (mem[1021] + 1)%(mem[1010]*mem[1009]) + end + end + elseif Address == 1017 then + value = math.floor(value) + if value<0 or value >= mem[1010] then return false end + for i = 0, mem[1009]-1 do + mem[value*mem[1009]+i] = 0 + end + elseif Address == 1018 then + for i = 0, mem[1009]*mem[1010]-1 do + mem[i] = 0 + end + elseif Address == 1021 then + value = math.floor(value)%(mem[1010]*mem[1009]) + end + + mem[Address] = value + + return true +end + +local specialCharacters = { + [128] = { + { x = 0, y = 1 }, + { x = 1, y = 1 }, + { x = 1, y = 0 }, + }, + [129] = { + { x = 0, y = 1 }, + { x = 0, y = 0 }, + { x = 1, y = 1 }, + }, + [130] = { + { x = 0, y = 1 }, + { x = 1, y = 0 }, + { x = 0, y = 0 }, + }, + [131] = { + { x = 0, y = 0 }, + { x = 1, y = 0 }, + { x = 1, y = 1 }, + }, + [132] = { + { x = 0, y = 0 }, + { x = 0.5, y = 0 }, + { x = 0.5, y = 0.5 }, + { x = 0, y = 0.5 }, + }, + [133] = { + { x = 0.5, y = 0 }, + { x = 1, y = 0 }, + { x = 1, y = 0.5 }, + { x = 0.5, y = 0.5 }, + }, + [134] = { + { x = 0, y = 0 }, + { x = 1, y = 0 }, + { x = 1, y = 0.5 }, + { x = 0, y = 0.5 }, + }, + [135] = { + { x = 0, y = 0.5 }, + { x = 0.5, y = 0.5 }, + { x = 0.5, y = 1 }, + { x = 0, y = 1 }, + }, + + + + + + [136] = { + { x = 0, y = 0 }, + { x = 0.5, y = 0 }, + { x = 0.5, y = 1 }, + { x = 0, y = 1 }, + }, + [137] = { + { x = 0.5, y = 0.5 }, + { x = 0.5, y = 0 }, + { x = 1, y = 0 }, + { x = 1, y = 0.5 }, + { x = 0.5, y = 0.5 }, + { x = 0.5, y = 1 }, + { x = 0, y = 1 }, + { x = 0, y = 0.5 }, + }, + [138] = { + { x = 0, y = 0 }, + { x = 1, y = 0 }, + { x = 1, y = 0.5 }, + { x = 0.5, y = 0.5 }, + { x = 0.5, y = 1 }, + { x = 0, y = 1 }, + }, + [139] = { + { x = 0.5, y = 0.5 }, + { x = 1, y = 0.5 }, + { x = 1, y = 1 }, + { x = 0.5, y = 1 }, + }, + [140] = { + { x = 0.5, y = 0.5 }, + { x = 1, y = 0.5 }, + { x = 1, y = 1 }, + { x = 0.5, y = 1 }, + { x = 0.5, y = 0.5 }, + { x = 0, y = 0.5 }, + { x = 0, y = 0 }, + { x = 0.5, y = 0 }, + }, + [141] = { + { x = 0.5, y = 0 }, + { x = 1, y = 0 }, + { x = 1, y = 1 }, + { x = 0.5, y = 1 }, + }, + [142] = { + + { x = 1, y = 0 }, + { x = 1, y = 1 }, + { x = 0.5, y = 1 }, + { x = 0.5, y = 0.5 }, + { x = 0, y = 0.5}, + { x = 0, y = 0 }, + }, + + [143] = { + { x = 0, y = 0.5 }, + { x = 1, y = 0.5 }, + { x = 1, y = 1 }, + { x = 0, y = 1 }, + }, + [144] = { + { x = 0, y = 1 }, + { x = 0, y = 0 }, + { x = 0.5, y = 0 }, + { x = 0.5, y = 0.5 }, + { x = 1, y = 0.5 }, + { x = 1, y = 1 }, + }, + [145] = { + { x = 1, y = 1 }, + { x = 0, y = 1 }, + { x = 0, y = 0.5 }, + { x = 0.5, y = 0.5 }, + { x = 0.5, y = 0 }, + { x = 1, y = 0 }, + }, + [146] = { + { x = 0, y = 0 }, + { x = 1, y = 0 }, + { x = 1, y = 1 }, + { x = 0, y = 1 }, + }, + [147] = { + { x = 0.33, y = 0.66 }, + { x = 0.33, y = 0 }, + { x = 0.66, y = 0 }, + { x = 0.66, y = 0.33 }, + { x = 1, y = 0.33 }, + { x = 1, y = 0.66 }, + }, + [148] = { + { x = 0.33, y = 0}, + { x = 0.66, y = 0}, + { x = 0.66, y = 1}, + { x = 0.33, y = 1}, + }, + [149] = { + { x = 0.66, y = 0.66 }, + { x = 0, y = 0.66 }, + { x = 0, y = 0.33 }, + { x = 0.33, y = 0.33 }, + { x = 0.33, y = 0 }, + { x = 0.66, y = 0 }, + }, + [150] = { + { x = 0, y = 0.33}, + { x = 1, y = 0.33}, + { x = 1, y = 0.66}, + { x = 0, y = 0.66}, + }, + [151] = { + { x = 0.66, y = 0.33 }, + { x = 1, y = 0.33 }, + { x = 1, y = 0.66 }, + { x = 0, y = 0.66 }, + { x = 0, y = 0.33 }, + { x = 0.33, y = 0.33 }, + { x = 0.33, y = 0 }, + { x = 0.66, y = 0 }, + }, + [152] = { + { x = 0.66, y = 0.33 }, + { x = 1, y = 0.33 }, + { x = 1, y = 0.66 }, + { x = 0.66, y = 0.66 }, + { x = 0.66, y = 1 }, + { x = 0.33, y = 1 }, + { x = 0.33, y = 0 }, + { x = 0.66, y = 0 }, + }, + [153] = { + { x = 0.66, y = 0.66 }, + { x = 1, y = 0.66 }, + { x = 1, y = 0.33 }, + { x = 0, y = 0.33 }, + { x = 0, y = 0.66 }, + { x = 0.33, y = 0.66 }, + { x = 0.33, y = 1 }, + { x = 0.66, y = 1 }, + }, + [154] = { + { x = 0.33, y = 0.33 }, + { x = 0, y = 0.33 }, + { x = 0, y = 0.66 }, + { x = 0.33, y = 0.66 }, + { x = 0.33, y = 1 }, + { x = 0.66, y = 1 }, + { x = 0.66, y = 0 }, + { x = 0.33, y = 0 }, + }, + [155] = { + { x = 0.66, y = 0.33 }, + { x = 1, y = 0.33 }, + { x = 1, y = 0.66 }, + { x = 0.66, y = 0.66 }, + { x = 0.66, y = 1 }, + { x = 0.33, y = 1 }, + { x = 0.33, y = 0.66 }, + { x = 0, y = 0.66 }, + { x = 0, y = 0.33 }, + { x = 0.33, y = 0.33 }, + { x = 0.33, y = 0 }, + { x = 0.66, y = 0 }, + }, + [156] = { + { x = 0.33, y = 0 }, + { x = 0.66, y = 0 }, + { x = 0.66, y = 0.33 }, + { x = 0.33, y = 0.33 }, + }, + [157] = { + { x = 0.66, y = 0.33 }, + { x = 1, y = 0.33 }, + { x = 1, y = 0.66 }, + { x = 0.66, y = 0.66 }, + }, + [158] = { + { x = 0.33, y = 0.66 }, + { x = 0.66, y = 0.66 }, + { x = 0.66, y = 1 }, + { x = 0.33, y = 1 }, + }, + [159] = { + { x = 0, y = 0.33 }, + { x = 0.33, y = 0.33 }, + { x = 0.33, y = 0.66 }, + { x = 0, y = 0.66 }, + }, + [160] = { + { x = 0.33, y = 0.33 }, + { x = 0.66, y = 0.33 }, + { x = 0.66, y = 0.66 }, + { x = 0.33, y = 0.66 }, + } +} + +function ENT:DrawSpecialCharacter(c,x,y,w,h,r,g,b) + surface.SetDrawColor(r,g,b,255) + surface.SetTexture(0) + + local vertices = specialCharacters[c] + if vertices then + local tf = Matrix() tf:SetScale(Vector(w, h, 1)) tf:SetTranslation(Vector(x, y, 0)) + cam.PushModelMatrix(tf, true) + surface.DrawPoly(vertices) + cam.PopModelMatrix() + end +end + +function ENT:Draw() + self:DrawModel() + + local szx = 18 + local szy = 24 + local mem = self.Memory + + if mem[1023] >= 1 then + mem[1023] = 0 + + self.GPU:RenderToGPU(function() + -- Draw terminal here + -- W/H = 16 + + local bc = math.min(1,math.max(0,mem[1016]-1.8)) + local br = (1-bc)*mem[1003]+bc*mem[1006] + local bg = (1-bc)*mem[1004]+bc*mem[1007] + local bb = (1-bc)*mem[1005]+bc*mem[1008] + + local sqc = math.min(1,math.max(0,mem[1016]-0.9)) + local sqr = (1-sqc)*mem[1003]+sqc*mem[1006] + local sqg = (1-sqc)*mem[1004]+sqc*mem[1007] + local sqb = (1-sqc)*mem[1005]+sqc*mem[1008] + + local fc = math.min(1,math.max(sqc,mem[1016])) + local fr = (1-fc)*mem[1003]+fc*mem[1006] + local fg = (1-fc)*mem[1004]+fc*mem[1007] + local fb = (1-fc)*mem[1005]+fc*mem[1008] + surface.SetDrawColor(br,bg,bb,255) + surface.DrawRect(0,0,1024,1024) + + for ty = 0, mem[1010]-1 do + for tx = 0, mem[1009]-1 do + local a = tx + ty*mem[1009] + + --if (self.Flash == true) then + -- fb,bb = bb,fb + -- fg,bg = bg,fg + -- fr,br = br,fr + --end + local c1 = mem[a] + + if c1 >= 2097152 then c1 = 0 end + if c1 < 0 then c1 = 0 end + + surface.SetDrawColor(sqr,sqg,sqb,255) + surface.DrawRect((tx)*szx+1,(ty)*szy+1,szx-2,szy-2) + surface.SetDrawColor(sqr,sqg,sqb,127) + surface.DrawRect((tx)*szx+2,(ty)*szy+2,szx-2,szy-2) + + if (c1 ~= 0) then + -- Note: the source engine does not handle unicode characters above 65535 properly. + local utf8 = "" + if c1 <= 127 then + utf8 = string.char (c1) + elseif c1 < 2048 then + utf8 = string.format("%c%c", 192 + math.floor (c1 / 64), 128 + (c1 % 64)) + elseif c1 < 65536 then + utf8 = string.format("%c%c%c", 224 + math.floor (c1 / 4096), 128 + (math.floor (c1 / 64) % 64), 128 + (c1 % 64)) + elseif c1 < 2097152 then + utf8 = string.format("%c%c%c%c", 240 + math.floor (c1 / 262144), 128 + (math.floor (c1 / 4096) % 64), 128 + (math.floor (c1 / 64) % 64), 128 + (c1 % 64)) + end + + if specialCharacters[c1] then + self:DrawSpecialCharacter( + c1, (tx)*szx+1, (ty)*szy+1, szx-1, szy-1, + fr,fg,fb + ) + else + draw.DrawText( + utf8, + "LCDFontBlur", + tx * szx + 2, ty * szy, + Color(fr,fg,fb,255),0 + ) + draw.DrawText( + utf8, + "LCDFont", + tx * szx + 1, ty * szy -1 , + Color(fr,fg,fb,255),0 + ) + end + end + end + end + end) + end + + self.GPU:Render(0,0,1024,1024,nil,-(1024-mem[1009]*szx)/1024,-(1024-mem[1010]*szy)/1024) + + if mem[1022] >= 1 then + self.IntTimer = self.IntTimer + FrameTime() + if self.IntTimer >= mem[1019] then + if self.IntTimer >= mem[1019]*2 then + self.IntTimer = (self.IntTimer - mem[1019]*2) % math.max(mem[1019]*2,0.01) + else + self.GPU:RenderToWorld(mem[1009]*szx, mem[1010]*szy, function() + local a = math.floor(mem[1021]) + + local tx = a - math.floor(a / mem[1009])*mem[1009] + local ty = math.floor(a / mem[1009]) + + local sqc = math.min(1,math.max(0,mem[1016]-0.9)) + local fc = math.min(1,math.max(sqc,mem[1016])) + local fr = (1-fc)*mem[1003]+fc*mem[1006] + local fg = (1-fc)*mem[1004]+fc*mem[1007] + local fb = (1-fc)*mem[1005]+fc*mem[1008] + + surface.SetDrawColor( + fr, + fg, + fb, + 255 + ) + surface.DrawRect( + (tx)*szx+1, + (ty)*szy+szy*(1-mem[1020]), + szx-2, + szy*mem[1020] + ) + end, nil, true) + end + end + end + + Wire_Render(self) +end + +function ENT:IsTranslucent() + return true +end diff --git a/lua/entities/gmod_wire_characterlcd/init.lua b/lua/entities/gmod_wire_characterlcd/init.lua new file mode 100644 index 00000000..6f30cfdd --- /dev/null +++ b/lua/entities/gmod_wire_characterlcd/init.lua @@ -0,0 +1,180 @@ +AddCSLuaFile("cl_init.lua") +AddCSLuaFile("shared.lua") +include('shared.lua') + +ENT.WireDebugName = "CharacterLcdScreen" + +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.Memory = {} + + for i = 0, 1023 do + self.Memory[i] = 0 + end + + self.CharAddress = 0 + self.Char = 0 + self.CharParam = 0 + self.Memory[1009] = 16 + self.Memory[1010] = 2 + self.Memory[1012] = 0 + self.Memory[1013] = 0 + self.Memory[1014] = 0 + self.Memory[1015] = 0 + self.Memory[1016] = 1 + self.Memory[1017] = 0 + self.Memory[1018] = 0 + self.Memory[1019] = 0.5 + self.Memory[1020] = 0.25 + self.Memory[1021] = 0 + self.Memory[1022] = 1 + + self.ScreenWidth = 16 + self.ScreenHeight = 2 + + self.Cache = GPUCacheManager(self,true) +end +function ENT:Setup(ScreenWidth, ScreenHeight, bgred,bggreen,bgblue,fgred,fggreen,fgblue) + self:WriteCell(1010, tonumber(ScreenHeight) or 2) + self:WriteCell(1009, tonumber(ScreenWidth) or 16) + self:WriteCell(1008, tonumber(fgblue) or 45) + self:WriteCell(1007, tonumber(fggreen) or 91) + self:WriteCell(1006, tonumber(fgred) or 45) + self:WriteCell(1005, tonumber(bgblue) or 15) + self:WriteCell(1004, tonumber(bggreen) or 178) + self:WriteCell(1003, tonumber(bgred) or 148) +end +function ENT:SendPixel() + if (self.Memory[1023] ~= 0) and (self.CharAddress >= 0) and (self.CharAddress < self.ScreenWidth*self.ScreenHeight) then + local pixelno = math.floor(self.CharAddress) + + self:WriteCell(pixelno, self.Char) + + end +end + +function ENT:ReadCell(Address) + Address = math.floor(Address) + if Address < 0 then return nil end + if Address >= 1024 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 + if Address >= 1024 then return false end + if Address < 1003 then -- text/attribute data + if self.Memory[Address] == value then return true end + else + if Address == 1009 and value*self.ScreenHeight < 1003 and value*18 <= 1024 then + self.ScreenWidth = value + end + if Address == 1010 and value*self.ScreenWidth < 1003 and value*24 <= 1024 then + self.ScreenHeight = value + end +-- 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 +end + +function ENT:Retransmit(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:TriggerInput(iname, value) + if iname == "CharAddress" then + self.CharAddress = value + self:WriteCell(1021, value) + elseif iname == "Char" then + self.Char = value + self:WriteCell(1011,value) + elseif iname == "Contrast" then + self.Contrast = value + self:WriteCell(1016, self.Contrast) + elseif iname == "Clk" then + self:WriteCell(1023, value) + self:SendPixel() + elseif iname == "Reset" then + self:WriteCell(1018,0) + end +end + +function ENT:ShiftScreenRight() + for y=0,self.ScreenHeight-1 do + for x=self.ScreenWidth-1,1 do + self.Memory[x+y*self.ScreenWidth] = self.Memory[x+y*self.ScreenWidth-1] + end + self.Memory[y*self.ScreenWidth] = 0 + end +end + +function ENT:ShiftScreenLeft() + for y=0,self.ScreenHeight-1 do + for x=0,self.ScreenWidth-2 do + self.Memory[x+y*self.ScreenWidth] = self.Memory[x+y*self.ScreenWidth+1] + end + self.Memory[y*self.ScreenWidth+self.ScreenWidth-1] = 0 + end +end + +function ENT:ClientWriteCell(Address, value) + if Address == 1009 and (value*self.Memory[1010] > 1003 or value*18 > 1024) then return false end + if Address == 1010 and (value*self.Memory[1009] > 1003 or value*24 > 1024) then return false end + if Address == 1011 then + + if self.Memory[1015] >= 1 then + if self.Memory[1014] >= 1 then + self:ShiftScreenRight() + else + self:ShiftScreenLeft() + end + self.Memory[self.Memory[1021]] = value + else + self.Memory[self.Memory[1021]] = value + if self.Memory[1014] >= 1 then + self.Memory[1021] = math.max(0,self.Memory[1021] - 1) + else + self.Memory[1021] = math.min(1023,self.Memory[1021] + 1) + end + end + + end + if Address == 1017 then + for i = 0, self.ScreenWidth-1 do + self.Memory[value*self.ScreenWidth+i] = 0 + end + self.NeedRefresh = true + end + if Address == 1018 then + for i = 0, self.ScreenWidth*self.ScreenHeight-1 do + self.Memory[i] = 0 + end + self.NeedRefresh = true + end +end + +duplicator.RegisterEntityClass("gmod_wire_characterlcd", WireLib.MakeWireEnt, "Data", "ScreenWidth", "ScreenHeight") diff --git a/lua/entities/gmod_wire_characterlcd/shared.lua b/lua/entities/gmod_wire_characterlcd/shared.lua new file mode 100644 index 00000000..c291b146 --- /dev/null +++ b/lua/entities/gmod_wire_characterlcd/shared.lua @@ -0,0 +1,12 @@ +ENT.Type = "anim" +ENT.Base = "base_wire_entity" + +ENT.PrintName = "Wire Character LCD" +ENT.Author = "" +ENT.Contact = "" +ENT.Purpose = "" +ENT.Instructions = "" + +ENT.Spawnable = false + +ENT.RenderGroup = RENDERGROUP_BOTH diff --git a/lua/entities/gmod_wire_consolescreen/cl_init.lua b/lua/entities/gmod_wire_consolescreen/cl_init.lua index b4769bcc..9fe34175 100644 --- a/lua/entities/gmod_wire_consolescreen/cl_init.lua +++ b/lua/entities/gmod_wire_consolescreen/cl_init.lua @@ -1,470 +1,692 @@ include("shared.lua") function ENT:Initialize() - self.Memory1 = {} - self.Memory2 = {} - for i = 0, 2047 do - self.Memory1[i] = 0 - end + self.Memory1 = {} + self.Memory2 = {} + for i = 0, 2047 do + self.Memory1[i] = 0 + end - -- Caching control: - -- [2020] - Force cache refresh - -- [2021] - Cached blocks size (up to 28, 0 if disabled) - -- - -- Hardware image control: - -- [2019] - Clear viewport defined by 2031-2034 - -- [2022] - Screen ratio (read only) - -- [2023] - Hardware scale - -- [2024] - Rotation (0 - 0*, 1 - 90*, 2 - 180*, 3 - 270*) - -- [2025] - Brightness White - -- [2026] - Brightness B - -- [2027] - Brightness G - -- [2028] - Brightness R - -- [2029] - Vertical scale (1) - -- [2030] - Horizontal scale (1) - -- - -- Shifting control: - -- [2031] - Low shift column - -- [2032] - High shift column - -- [2033] - Low shift row - -- [2034] - High shift row - -- - -- Character output control: - -- [2035] - Charset, always 0 - -- [2036] - Brightness (additive) - -- - -- Control registers: - -- [2037] - Shift cells (number of cells, >0 right, <0 left) - -- [2038] - Shift rows (number of rows, >0 shift up, <0 shift down) - -- [2039] - Hardware Clear Row (Writing clears row) - -- [2040] - Hardware Clear Column (Writing clears column) - -- [2041] - Hardware Clear Screen - -- [2042] - Hardware Background Color (000) - -- - -- Cursor control: - -- [2043] - Cursor Blink Rate (0.50) - -- [2044] - Cursor Size (0.25) - -- [2045] - Cursor Address - -- [2046] - Cursor Enabled - -- - -- [2047] - Clk + -- Caching control: + -- [2020] - Force cache refresh + -- [2021] - Cached blocks size (up to 28, 0 if disabled) + -- + -- Hardware image control: + -- [2019] - Clear viewport defined by 2031-2034 + -- [2022] - Screen ratio (read only) + -- [2023] - Hardware scale + -- [2024] - Rotation (0 - 0*, 1 - 90*, 2 - 180*, 3 - 270*) + -- [2025] - Brightness White + -- [2026] - Brightness B + -- [2027] - Brightness G + -- [2028] - Brightness R + -- [2029] - Vertical scale (1) + -- [2030] - Horizontal scale (1) + -- + -- Shifting control: + -- [2031] - Low shift column + -- [2032] - High shift column + -- [2033] - Low shift row + -- [2034] - High shift row + -- + -- Character output control: + -- [2035] - Charset, always 0 + -- [2036] - Brightness (additive) + -- + -- Control registers: + -- [2037] - Shift cells (number of cells, >0 right, <0 left) + -- [2038] - Shift rows (number of rows, >0 shift up, <0 shift down) + -- [2039] - Hardware Clear Row (Writing clears row) + -- [2040] - Hardware Clear Column (Writing clears column) + -- [2041] - Hardware Clear Screen + -- [2042] - Hardware Background Color (000) + -- + -- Cursor control: + -- [2043] - Cursor Blink Rate (0.50) + -- [2044] - Cursor Size (0.25) + -- [2045] - Cursor Address + -- [2046] - Cursor Enabled + -- + -- [2047] - Clk - self.Memory1[2022] = 3/4 - self.Memory1[2023] = 0 - self.Memory1[2024] = 0 - self.Memory1[2025] = 1 - self.Memory1[2026] = 1 - self.Memory1[2027] = 1 - self.Memory1[2028] = 1 - self.Memory1[2029] = 1 - self.Memory1[2030] = 1 - self.Memory1[2031] = 0 - self.Memory1[2032] = 29 - self.Memory1[2033] = 0 - self.Memory1[2034] = 17 - self.Memory1[2035] = 0 - self.Memory1[2036] = 0 + self.Memory1[2022] = 3/4 + self.Memory1[2023] = 0 + self.Memory1[2024] = 0 + self.Memory1[2025] = 1 + self.Memory1[2026] = 1 + self.Memory1[2027] = 1 + self.Memory1[2028] = 1 + self.Memory1[2029] = 1 + self.Memory1[2030] = 1 + self.Memory1[2031] = 0 + self.Memory1[2032] = 29 + self.Memory1[2033] = 0 + self.Memory1[2034] = 17 + self.Memory1[2035] = 0 + self.Memory1[2036] = 0 - self.Memory1[2042] = 0 - self.Memory1[2043] = 0.5 - self.Memory1[2044] = 0.25 - self.Memory1[2045] = 0 - self.Memory1[2046] = 0 + self.Memory1[2042] = 0 + self.Memory1[2043] = 0.5 + self.Memory1[2044] = 0.25 + self.Memory1[2045] = 0 + self.Memory1[2046] = 0 - for i = 0, 2047 do - self.Memory2[i] = self.Memory1[i] - end + for i = 0, 2047 do + self.Memory2[i] = self.Memory1[i] + end - self.LastClk = false + self.LastClk = false - self.PrevTime = CurTime() - self.IntTimer = 0 + self.PrevTime = CurTime() + self.IntTimer = 0 - self.NeedRefresh = true - self.Flash = false - self.FrameNeedsFlash = false + self.NeedRefresh = true + self.Flash = false + self.FrameNeedsFlash = false - self.FramesSinceRedraw = 0 - self.NewClk = true + self.FramesSinceRedraw = 0 + self.NewClk = true - self.GPU = WireGPU(self) + self.GPU = WireGPU(self) - -- Setup caching - GPULib.ClientCacheCallback(self,function(Address,Value) - self:WriteCell(Address,Value) - end) + -- Setup caching + GPULib.ClientCacheCallback(self,function(Address,Value) + self:WriteCell(Address,Value) + end) - WireLib.netRegister(self) + WireLib.netRegister(self) end - function ENT:OnRemove() - self.GPU:Finalize() - self.NeedRefresh = true + self.GPU:Finalize() + self.NeedRefresh = true end function ENT:ReadCell(Address,value) - Address = math.floor(Address) - if Address < 0 then return nil end - if Address >= 2048 then return nil end + Address = math.floor(Address) + if Address < 0 then return nil end + if Address >= 2048 then return nil end - return self.Memory2[Address] + return self.Memory2[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 + Address = math.floor(Address) + if Address < 0 then return false end + if Address >= 2048 then return false end - if Address == 2047 then self.NewClk = value ~= 0 end + if Address == 2047 then self.NewClk = value ~= 0 end - if self.NewClk then - self.Memory1[Address] = value -- Vis mem - self.NeedRefresh = true - end - self.Memory2[Address] = value -- Invis mem + if self.NewClk then + self.Memory1[Address] = value -- Vis mem + self.NeedRefresh = true + end + self.Memory2[Address] = value -- Invis mem - -- 2038 - Shift rows (number of rows, >0 shift down, <0 shift up) - -- 2039 - Hardware Clear Row (Writing clears row) - -- 2040 - Hardware Clear Column (Writing clears column) - -- 2041 - Hardware Clear Screen + -- 2038 - Shift rows (number of rows, >0 shift down, <0 shift up) + -- 2039 - Hardware Clear Row (Writing clears row) + -- 2040 - Hardware Clear Column (Writing clears column) + -- 2041 - Hardware Clear Screen - if (Address == 2025) or - (Address == 2026) or - (Address == 2027) or - (Address == 2028) or - (Address == 2036) then - self.NeedRefresh = true - end + if (Address == 2025) or + (Address == 2026) or + (Address == 2027) or + (Address == 2028) or + (Address == 2036) then + self.NeedRefresh = true + end - if Address == 2019 then - local low = math.floor(math.Clamp(self.Memory1[2033],0,17)) - local high = math.floor(math.Clamp(self.Memory1[2034],0,17)) - local lowc = math.floor(math.Clamp(self.Memory1[2031],0,29)) - local highc = math.floor(math.Clamp(self.Memory1[2032],0,29)) - for j = low, high do - for i = 2*lowc, 2*highc+1 do - self.Memory1[60*j+i] = 0 - self.Memory2[60*j+i] = 0 - end - end - self.NeedRefresh = true - end - if Address == 2037 then - local delta = math.floor(math.Clamp(math.abs(value),-30,30)) - local low = math.floor(math.Clamp(self.Memory1[2033],0,17)) - local high = math.floor(math.Clamp(self.Memory1[2034],0,17)) - local lowc = math.floor(math.Clamp(self.Memory1[2031],0,29)) - local highc = math.floor(math.Clamp(self.Memory1[2032],0,29)) - if (value > 0) then - for j = low,high do - for i = highc,lowc+delta,-1 do - if (self.NewClk) then - self.Memory1[j*60+i*2] = self.Memory1[j*60+(i-delta)*2] - self.Memory1[j*60+i*2+1] = self.Memory1[j*60+(i-delta)*2+1] - end - self.Memory2[j*60+i*2] = self.Memory2[j*60+(i-delta)*2] - self.Memory2[j*60+i*2+1] = self.Memory2[j*60+(i-delta)*2+1] - end - end - for j = low,high do - for i = lowc, lowc+delta-1 do - if (self.NewClk) then - self.Memory1[j*60+i*2] = 0 - self.Memory1[j*60+i*2+1] = 0 - end - self.Memory2[j*60+i*2] = 0 - self.Memory2[j*60+i*2+1] = 0 - end - end - else - for j = low,high do - for i = lowc,highc-delta do - if (self.NewClk) then - self.Memory1[j*60+i*2] = self.Memory1[j*60+i*2+delta*2] - self.Memory1[j*60+i*2+1] = self.Memory1[j*60+i*2+1+delta*2] - end - self.Memory2[j*60+i*2] = self.Memory2[j*60+i*2+delta*2] - self.Memory2[j*60+i*2+1] = self.Memory2[j*60+i*2+1+delta*2] - end - end - for j = low,high do - for i = highc-delta+1,highc do - if (self.NewClk) then - self.Memory1[j*60+i*2] = 0 - self.Memory1[j*60+i*2+1] = 0 - end - self.Memory2[j*60+i*2] = 0 - self.Memory2[j*60+i*2+1] = 0 - end - end - end - end - if Address == 2038 then - local delta = math.floor(math.Clamp(math.abs(value),-30,30)) - local low = math.floor(math.Clamp(self.Memory1[2033],0,17)) - local high = math.floor(math.Clamp(self.Memory1[2034],0,17)) - local lowc = math.floor(math.Clamp(self.Memory1[2031],0,29)) - local highc = math.floor(math.Clamp(self.Memory1[2032],0,29)) - if (value > 0) then - for j = low, high-delta do - for i = 2*lowc,2*highc+1 do - if (self.NewClk) then - self.Memory1[j*60+i] = self.Memory1[(j+delta)*60+i] - end - self.Memory2[j*60+i] = self.Memory2[(j+delta)*60+i] - end - end - for j = high-delta+1,high do - for i = 2*lowc, 2*highc+1 do - if (self.NewClk) then - self.Memory1[j*60+i] = 0 - end - self.Memory2[j*60+i] = 0 - end - end - else - for j = high,low+delta,-1 do - for i = 2*lowc, 2*highc+1 do - if (self.NewClk) then - self.Memory1[j*60+i] = self.Memory1[(j-delta)*60+i] - end - self.Memory2[j*60+i] = self.Memory2[(j-delta)*60+i] - end - end - for j = low,low+delta-1 do - for i = 2*lowc, 2*highc+1 do - if (self.NewClk) then - self.Memory1[j*60+i] = 0 - end - self.Memory2[j*60+i] = 0 - end - end - end - end - if Address == 2039 then - for i = 0, 59 do - self.Memory1[value*60+i] = 0 - self.Memory2[value*60+i] = 0 - end - self.NeedRefresh = true - end - if Address == 2040 then - for i = 0, 17 do - self.Memory1[i*60+value] = 0 - self.Memory2[i*60+value] = 0 - end - self.NeedRefresh = true - end - if Address == 2041 then - for i = 0, 18*30*2-1 do - self.Memory1[i] = 0 - self.Memory2[i] = 0 - end - self.NeedRefresh = true - end + if Address == 2019 then + local low = math.floor(math.Clamp(self.Memory1[2033],0,17)) + local high = math.floor(math.Clamp(self.Memory1[2034],0,17)) + local lowc = math.floor(math.Clamp(self.Memory1[2031],0,29)) + local highc = math.floor(math.Clamp(self.Memory1[2032],0,29)) + for j = low, high do + for i = 2*lowc, 2*highc+1 do + self.Memory1[60*j+i] = 0 + self.Memory2[60*j+i] = 0 + end + end + self.NeedRefresh = true + end + if Address == 2037 then + local delta = math.floor(math.Clamp(math.abs(value),-30,30)) + local low = math.floor(math.Clamp(self.Memory1[2033],0,17)) + local high = math.floor(math.Clamp(self.Memory1[2034],0,17)) + local lowc = math.floor(math.Clamp(self.Memory1[2031],0,29)) + local highc = math.floor(math.Clamp(self.Memory1[2032],0,29)) + if (value > 0) then + for j = low,high do + for i = highc,lowc+delta,-1 do + if (self.NewClk) then + self.Memory1[j*60+i*2] = self.Memory1[j*60+(i-delta)*2] + self.Memory1[j*60+i*2+1] = self.Memory1[j*60+(i-delta)*2+1] + end + self.Memory2[j*60+i*2] = self.Memory2[j*60+(i-delta)*2] + self.Memory2[j*60+i*2+1] = self.Memory2[j*60+(i-delta)*2+1] + end + end + for j = low,high do + for i = lowc, lowc+delta-1 do + if (self.NewClk) then + self.Memory1[j*60+i*2] = 0 + self.Memory1[j*60+i*2+1] = 0 + end + self.Memory2[j*60+i*2] = 0 + self.Memory2[j*60+i*2+1] = 0 + end + end + else + for j = low,high do + for i = lowc,highc-delta do + if (self.NewClk) then + self.Memory1[j*60+i*2] = self.Memory1[j*60+i*2+delta*2] + self.Memory1[j*60+i*2+1] = self.Memory1[j*60+i*2+1+delta*2] + end + self.Memory2[j*60+i*2] = self.Memory2[j*60+i*2+delta*2] + self.Memory2[j*60+i*2+1] = self.Memory2[j*60+i*2+1+delta*2] + end + end + for j = low,high do + for i = highc-delta+1,highc do + if (self.NewClk) then + self.Memory1[j*60+i*2] = 0 + self.Memory1[j*60+i*2+1] = 0 + end + self.Memory2[j*60+i*2] = 0 + self.Memory2[j*60+i*2+1] = 0 + end + end + end + end + if Address == 2038 then + local delta = math.floor(math.Clamp(math.abs(value),-30,30)) + local low = math.floor(math.Clamp(self.Memory1[2033],0,17)) + local high = math.floor(math.Clamp(self.Memory1[2034],0,17)) + local lowc = math.floor(math.Clamp(self.Memory1[2031],0,29)) + local highc = math.floor(math.Clamp(self.Memory1[2032],0,29)) + if (value > 0) then + for j = low, high-delta do + for i = 2*lowc,2*highc+1 do + if (self.NewClk) then + self.Memory1[j*60+i] = self.Memory1[(j+delta)*60+i] + end + self.Memory2[j*60+i] = self.Memory2[(j+delta)*60+i] + end + end + for j = high-delta+1,high do + for i = 2*lowc, 2*highc+1 do + if (self.NewClk) then + self.Memory1[j*60+i] = 0 + end + self.Memory2[j*60+i] = 0 + end + end + else + for j = high,low+delta,-1 do + for i = 2*lowc, 2*highc+1 do + if (self.NewClk) then + self.Memory1[j*60+i] = self.Memory1[(j-delta)*60+i] + end + self.Memory2[j*60+i] = self.Memory2[(j-delta)*60+i] + end + end + for j = low,low+delta-1 do + for i = 2*lowc, 2*highc+1 do + if (self.NewClk) then + self.Memory1[j*60+i] = 0 + end + self.Memory2[j*60+i] = 0 + end + end + end + end + if Address == 2039 then + for i = 0, 59 do + self.Memory1[value*60+i] = 0 + self.Memory2[value*60+i] = 0 + end + self.NeedRefresh = true + end + if Address == 2040 then + for i = 0, 17 do + self.Memory1[i*60+value] = 0 + self.Memory2[i*60+value] = 0 + end + self.NeedRefresh = true + end + if Address == 2041 then + for i = 0, 18*30*2-1 do + self.Memory1[i] = 0 + self.Memory2[i] = 0 + end + self.NeedRefresh = true + end - if self.LastClk ~= self.NewClk then - self.LastClk = self.NewClk - self.Memory1 = table.Copy(self.Memory2) -- swap the memory if clock changes - self.NeedRefresh = true - end - return true + if self.LastClk ~= self.NewClk then + self.LastClk = self.NewClk + self.Memory1 = table.Copy(self.Memory2) -- swap the memory if clock changes + self.NeedRefresh = true + end + return true end local specialCharacters = { - [128] = { - { x = 0, y = 1 }, - { x = 1, y = 1 }, - { x = 1, y = 0 }, - }, - [129] = { - { x = 0, y = 1 }, - { x = 0, y = 0 }, - { x = 1, y = 1 }, - }, - [130] = { - { x = 0, y = 1 }, - { x = 1, y = 0 }, - { x = 0, y = 0 }, - }, - [131] = { - { x = 0, y = 0 }, - { x = 1, y = 0 }, - { x = 1, y = 1 }, - }, + [128] = { + { x = 0, y = 1 }, + { x = 1, y = 1 }, + { x = 1, y = 0 }, + }, + [129] = { + { x = 0, y = 1 }, + { x = 0, y = 0 }, + { x = 1, y = 1 }, + }, + [130] = { + { x = 0, y = 1 }, + { x = 1, y = 0 }, + { x = 0, y = 0 }, + }, + [131] = { + { x = 0, y = 0 }, + { x = 1, y = 0 }, + { x = 1, y = 1 }, + }, + [132] = { + { x = 0, y = 0 }, + { x = 0.5, y = 0 }, + { x = 0.5, y = 0.5 }, + { x = 0, y = 0.5 }, + }, + [133] = { + { x = 0.5, y = 0 }, + { x = 1, y = 0 }, + { x = 1, y = 0.5 }, + { x = 0.5, y = 0.5 }, + }, + [134] = { + { x = 0, y = 0 }, + { x = 1, y = 0 }, + { x = 1, y = 0.5 }, + { x = 0, y = 0.5 }, + }, + [135] = { + { x = 0, y = 0.5 }, + { x = 0.5, y = 0.5 }, + { x = 0.5, y = 1 }, + { x = 0, y = 1 }, + }, + + + + + + [136] = { + { x = 0, y = 0 }, + { x = 0.5, y = 0 }, + { x = 0.5, y = 1 }, + { x = 0, y = 1 }, + }, + [137] = { + { x = 0.5, y = 0.5 }, + { x = 0.5, y = 0 }, + { x = 1, y = 0 }, + { x = 1, y = 0.5 }, + { x = 0.5, y = 0.5 }, + { x = 0.5, y = 1 }, + { x = 0, y = 1 }, + { x = 0, y = 0.5 }, + }, + [138] = { + { x = 0, y = 0 }, + { x = 1, y = 0 }, + { x = 1, y = 0.5 }, + { x = 0.5, y = 0.5 }, + { x = 0.5, y = 1 }, + { x = 0, y = 1 }, + }, + [139] = { + { x = 0.5, y = 0.5 }, + { x = 1, y = 0.5 }, + { x = 1, y = 1 }, + { x = 0.5, y = 1 }, + }, + [140] = { + { x = 0.5, y = 0.5 }, + { x = 1, y = 0.5 }, + { x = 1, y = 1 }, + { x = 0.5, y = 1 }, + { x = 0.5, y = 0.5 }, + { x = 0, y = 0.5 }, + { x = 0, y = 0 }, + { x = 0.5, y = 0 }, + }, + [141] = { + { x = 0.5, y = 0 }, + { x = 1, y = 0 }, + { x = 1, y = 1 }, + { x = 0.5, y = 1 }, + }, + [142] = { + + { x = 1, y = 0 }, + { x = 1, y = 1 }, + { x = 0.5, y = 1 }, + { x = 0.5, y = 0.5 }, + { x = 0, y = 0.5}, + { x = 0, y = 0 }, + }, + + [143] = { + { x = 0, y = 0.5 }, + { x = 1, y = 0.5 }, + { x = 1, y = 1 }, + { x = 0, y = 1 }, + }, + [144] = { + { x = 0, y = 1 }, + { x = 0, y = 0 }, + { x = 0.5, y = 0 }, + { x = 0.5, y = 0.5 }, + { x = 1, y = 0.5 }, + { x = 1, y = 1 }, + }, + [145] = { + { x = 1, y = 1 }, + { x = 0, y = 1 }, + { x = 0, y = 0.5 }, + { x = 0.5, y = 0.5 }, + { x = 0.5, y = 0 }, + { x = 1, y = 0 }, + }, + [146] = { + { x = 0, y = 0 }, + { x = 1, y = 0 }, + { x = 1, y = 1 }, + { x = 0, y = 1 }, + }, + [147] = { + { x = 0.33, y = 0.66 }, + { x = 0.33, y = 0 }, + { x = 0.66, y = 0 }, + { x = 0.66, y = 0.33 }, + { x = 1, y = 0.33 }, + { x = 1, y = 0.66 }, + }, + [148] = { + { x = 0.33, y = 0}, + { x = 0.66, y = 0}, + { x = 0.66, y = 1}, + { x = 0.33, y = 1}, + }, + [149] = { + { x = 0.66, y = 0.66 }, + { x = 0, y = 0.66 }, + { x = 0, y = 0.33 }, + { x = 0.33, y = 0.33 }, + { x = 0.33, y = 0 }, + { x = 0.66, y = 0 }, + }, + [150] = { + { x = 0, y = 0.33}, + { x = 1, y = 0.33}, + { x = 1, y = 0.66}, + { x = 0, y = 0.66}, + }, + [151] = { + { x = 0.66, y = 0.33 }, + { x = 1, y = 0.33 }, + { x = 1, y = 0.66 }, + { x = 0, y = 0.66 }, + { x = 0, y = 0.33 }, + { x = 0.33, y = 0.33 }, + { x = 0.33, y = 0 }, + { x = 0.66, y = 0 }, + }, + [152] = { + { x = 0.66, y = 0.33 }, + { x = 1, y = 0.33 }, + { x = 1, y = 0.66 }, + { x = 0.66, y = 0.66 }, + { x = 0.66, y = 1 }, + { x = 0.33, y = 1 }, + { x = 0.33, y = 0 }, + { x = 0.66, y = 0 }, + }, + [153] = { + { x = 0.66, y = 0.66 }, + { x = 1, y = 0.66 }, + { x = 1, y = 0.33 }, + { x = 0, y = 0.33 }, + { x = 0, y = 0.66 }, + { x = 0.33, y = 0.66 }, + { x = 0.33, y = 1 }, + { x = 0.66, y = 1 }, + }, + [154] = { + { x = 0.33, y = 0.33 }, + { x = 0, y = 0.33 }, + { x = 0, y = 0.66 }, + { x = 0.33, y = 0.66 }, + { x = 0.33, y = 1 }, + { x = 0.66, y = 1 }, + { x = 0.66, y = 0 }, + { x = 0.33, y = 0 }, + }, + [155] = { + { x = 0.66, y = 0.33 }, + { x = 1, y = 0.33 }, + { x = 1, y = 0.66 }, + { x = 0.66, y = 0.66 }, + { x = 0.66, y = 1 }, + { x = 0.33, y = 1 }, + { x = 0.33, y = 0.66 }, + { x = 0, y = 0.66 }, + { x = 0, y = 0.33 }, + { x = 0.33, y = 0.33 }, + { x = 0.33, y = 0 }, + { x = 0.66, y = 0 }, + }, + [156] = { + { x = 0.33, y = 0 }, + { x = 0.66, y = 0 }, + { x = 0.66, y = 0.33 }, + { x = 0.33, y = 0.33 }, + }, + [157] = { + { x = 0.66, y = 0.33 }, + { x = 1, y = 0.33 }, + { x = 1, y = 0.66 }, + { x = 0.66, y = 0.66 }, + }, + [158] = { + { x = 0.33, y = 0.66 }, + { x = 0.66, y = 0.66 }, + { x = 0.66, y = 1 }, + { x = 0.33, y = 1 }, + }, + [159] = { + { x = 0, y = 0.33 }, + { x = 0.33, y = 0.33 }, + { x = 0.33, y = 0.66 }, + { x = 0, y = 0.66 }, + }, + [160] = { + { x = 0.33, y = 0.33 }, + { x = 0.66, y = 0.33 }, + { x = 0.66, y = 0.66 }, + { x = 0.33, y = 0.66 }, + } } function ENT:DrawSpecialCharacter(c,x,y,w,h,r,g,b) - surface.SetDrawColor(r,g,b,255) - surface.SetTexture(0) + surface.SetDrawColor(r,g,b,255) + surface.SetTexture(0) - local vertices = specialCharacters[c] - if vertices then - local vertexData = { - { x = vertices[1].x*w+x, y = vertices[1].y*h+y }, - { x = vertices[2].x*w+x, y = vertices[2].y*h+y }, - { x = vertices[3].x*w+x, y = vertices[3].y*h+y }, - } - surface.DrawPoly(vertexData) - end + local vertices = specialCharacters[c] + if vertices then + local tf = Matrix() tf:SetScale(Vector(w, h, 1)) tf:SetTranslation(Vector(x, y, 0)) + cam.PushModelMatrix(tf, true) + surface.DrawPoly(vertices) + cam.PopModelMatrix() + end end function ENT:Draw() - self:DrawModel() + self:DrawModel() - local curtime = CurTime() - local DeltaTime = curtime - self.PrevTime - self.PrevTime = curtime - self.IntTimer = self.IntTimer + DeltaTime - self.FramesSinceRedraw = self.FramesSinceRedraw + 1 + local curtime = CurTime() + local DeltaTime = curtime - self.PrevTime + self.PrevTime = curtime + self.IntTimer = self.IntTimer + DeltaTime + self.FramesSinceRedraw = self.FramesSinceRedraw + 1 - if self.NeedRefresh == true then - self.FramesSinceRedraw = 0 - self.NeedRefresh = false - self.FrameNeedsFlash = false + if self.NeedRefresh == true then + self.FramesSinceRedraw = 0 + self.NeedRefresh = false + self.FrameNeedsFlash = false - if self.Memory1[2046] >= 1 then self.FrameNeedsFlash = true end + if self.Memory1[2046] >= 1 then self.FrameNeedsFlash = true end - self.GPU:RenderToGPU(function() - -- Draw terminal here - -- W/H = 16 - local szx = 512/31 - local szy = 512/19 + self.GPU:RenderToGPU(function() + -- Draw terminal here + -- W/H = 16 + local szx = 1024/31 + local szy = 1024/19 - local ch = self.Memory1[2042] + local ch = self.Memory1[2042] - local hb = 28*math.fmod(ch, 10)*self.Memory1[2026]*self.Memory1[2025] + self.Memory1[2036] - local hg = 28*math.fmod(math.floor(ch / 10), 10)*self.Memory1[2027]*self.Memory1[2025] + self.Memory1[2036] - local hr = 28*math.fmod(math.floor(ch / 100),10)*self.Memory1[2028]*self.Memory1[2025] + self.Memory1[2036] - surface.SetDrawColor(hr,hg,hb,255) - surface.DrawRect(0,0,512,512) + local hb = 28*math.fmod(ch, 10)*self.Memory1[2026]*self.Memory1[2025] + self.Memory1[2036] + local hg = 28*math.fmod(math.floor(ch / 10), 10)*self.Memory1[2027]*self.Memory1[2025] + self.Memory1[2036] + local hr = 28*math.fmod(math.floor(ch / 100),10)*self.Memory1[2028]*self.Memory1[2025] + self.Memory1[2036] + surface.SetDrawColor(hr,hg,hb,255) + surface.DrawRect(0,0,1024,1024) - for ty = 0, 17 do - for tx = 0, 29 do - local a = tx + ty*30 - local c1 = self.Memory1[2*a] - local c2 = self.Memory1[2*a+1] + for ty = 0, 17 do + for tx = 0, 29 do + local a = tx + ty*30 + local c1 = self.Memory1[2*a] + local c2 = self.Memory1[2*a+1] - local cback = math.floor(c2 / 1000) - local cfrnt = c2 - math.floor(c2 / 1000)*1000 + local cback = math.floor(c2 / 1000) + local cfrnt = c2 - math.floor(c2 / 1000)*1000 - local fb = math.Clamp(28*math.fmod(cfrnt, 10)*self.Memory1[2026]*self.Memory1[2025] + self.Memory1[2036],0,255) - local fg = math.Clamp(28*math.fmod(math.floor(cfrnt / 10), 10)*self.Memory1[2027]*self.Memory1[2025] + self.Memory1[2036],0,255) - local fr = math.Clamp(28*math.fmod(math.floor(cfrnt / 100),10)*self.Memory1[2028]*self.Memory1[2025] + self.Memory1[2036],0,255) - local bb = math.Clamp(28*math.fmod(cback, 10)*self.Memory1[2026]*self.Memory1[2025] + self.Memory1[2036],0,255) - local bg = math.Clamp(28*math.fmod(math.floor(cback / 10), 10)*self.Memory1[2027]*self.Memory1[2025] + self.Memory1[2036],0,255) - local br = math.Clamp(28*math.fmod(math.floor(cback / 100),10)*self.Memory1[2028]*self.Memory1[2025] + self.Memory1[2036],0,255) + local fb = math.Clamp(28*math.fmod(cfrnt, 10)*self.Memory1[2026]*self.Memory1[2025] + self.Memory1[2036],0,255) + local fg = math.Clamp(28*math.fmod(math.floor(cfrnt / 10), 10)*self.Memory1[2027]*self.Memory1[2025] + self.Memory1[2036],0,255) + local fr = math.Clamp(28*math.fmod(math.floor(cfrnt / 100),10)*self.Memory1[2028]*self.Memory1[2025] + self.Memory1[2036],0,255) + local bb = math.Clamp(28*math.fmod(cback, 10)*self.Memory1[2026]*self.Memory1[2025] + self.Memory1[2036],0,255) + local bg = math.Clamp(28*math.fmod(math.floor(cback / 10), 10)*self.Memory1[2027]*self.Memory1[2025] + self.Memory1[2036],0,255) + local br = math.Clamp(28*math.fmod(math.floor(cback / 100),10)*self.Memory1[2028]*self.Memory1[2025] + self.Memory1[2036],0,255) - if (self.Flash == true) and (cback > 999) then - fb,bb = bb,fb - fg,bg = bg,fg - fr,br = br,fr - end + if (self.Flash == true) and (cback > 999) then + fb,bb = bb,fb + fg,bg = bg,fg + fr,br = br,fr + end - if cback > 999 then - self.FrameNeedsFlash = true - end + if cback > 999 then + self.FrameNeedsFlash = true + end - if c1 >= 2097152 then c1 = 0 end - if c1 < 0 then c1 = 0 end + if c1 >= 2097152 then c1 = 0 end + if c1 < 0 then c1 = 0 end - if cback ~= 0 then - surface.SetDrawColor(br,bg,bb,255) - surface.DrawRect(tx*szx+szx/2,ty*szy+szy/2,szx*1.2,szy*1.2) - else - surface.SetDrawColor(hr,hg,hb,255) - surface.DrawRect(tx*szx+szx/2,ty*szy+szy/2,szx*1.2,szy*1.2) - end + if cback ~= 0 then + surface.SetDrawColor(br,bg,bb,255) + surface.DrawRect(tx*szx+szx/2,ty*szy+szy/2,szx*1.2,szy*1.2) + else + surface.SetDrawColor(hr,hg,hb,255) + surface.DrawRect(tx*szx+szx/2,ty*szy+szy/2,szx*1.2,szy*1.2) + end - if (c1 ~= 0) and (cfrnt ~= 0) then - -- Note: the source engine does not handle unicode characters above 65535 properly. - local utf8 = "" - if c1 <= 127 then - utf8 = string.char (c1) - elseif c1 < 2048 then - utf8 = string.format("%c%c", 192 + math.floor (c1 / 64), 128 + (c1 % 64)) - elseif c1 < 65536 then - utf8 = string.format("%c%c%c", 224 + math.floor (c1 / 4096), 128 + (math.floor (c1 / 64) % 64), 128 + (c1 % 64)) - elseif c1 < 2097152 then - utf8 = string.format("%c%c%c%c", 240 + math.floor (c1 / 262144), 128 + (math.floor (c1 / 4096) % 64), 128 + (math.floor (c1 / 64) % 64), 128 + (c1 % 64)) - end + if (c1 ~= 0) and (cfrnt ~= 0) then + -- Note: the source engine does not handle unicode characters above 65535 properly. + local utf8 = "" + if c1 <= 127 then + utf8 = string.char (c1) + elseif c1 < 2048 then + utf8 = string.format("%c%c", 192 + math.floor (c1 / 64), 128 + (c1 % 64)) + elseif c1 < 65536 then + utf8 = string.format("%c%c%c", 224 + math.floor (c1 / 4096), 128 + (math.floor (c1 / 64) % 64), 128 + (c1 % 64)) + elseif c1 < 2097152 then + utf8 = string.format("%c%c%c%c", 240 + math.floor (c1 / 262144), 128 + (math.floor (c1 / 4096) % 64), 128 + (math.floor (c1 / 64) % 64), 128 + (c1 % 64)) + end - if specialCharacters[c1] then - self:DrawSpecialCharacter( - c1, (tx+0.5)*szx, (ty+0.5)*szy, szx, szy, - fr,fg,fb - ) - else - draw.DrawText( - utf8, - "WireGPU_ConsoleFont", - (tx + 0.625) * szx, (ty + 0.75) * szy, - Color(fr,fg,fb,255),0 - ) - end - end - end - end + if specialCharacters[c1] then + self:DrawSpecialCharacter( + c1, (tx+0.5)*szx, (ty+0.5)*szy, szx, szy, + fr,fg,fb + ) + else + draw.DrawText( + utf8, + "WireGPU_ConsoleFont", + (tx + 0.625) * szx, (ty + 0.75) * szy, + Color(fr,fg,fb,255),0 + ) + end + end + end + end - if self.Memory1[2045] > 1080 then self.Memory1[2045] = 1080 end - if self.Memory1[2045] < 0 then self.Memory1[2045] = 0 end - if self.Memory1[2044] > 1 then self.Memory1[2044] = 1 end - if self.Memory1[2044] < 0 then self.Memory1[2044] = 0 end + if self.Memory1[2045] > 1080 then self.Memory1[2045] = 1080 end + if self.Memory1[2045] < 0 then self.Memory1[2045] = 0 end + if self.Memory1[2044] > 1 then self.Memory1[2044] = 1 end + if self.Memory1[2044] < 0 then self.Memory1[2044] = 0 end - if self.Memory1[2046] >= 1 then - if self.Flash == true then - local a = math.floor(self.Memory1[2045] / 2) + if self.Memory1[2046] >= 1 then + if self.Flash == true then + local a = math.floor(self.Memory1[2045] / 2) - local tx = a - math.floor(a / 30)*30 - local ty = math.floor(a / 30) + local tx = a - math.floor(a / 30)*30 + local ty = math.floor(a / 30) - local c = self.Memory1[2*a+1] - local cback = 999-math.floor(c / 1000) - local bb = 28*math.fmod(cback,10) - local bg = 28*math.fmod(math.floor(cback / 10),10) - local br = 28*math.fmod(math.floor(cback / 100),10) + local c = self.Memory1[2*a+1] + local cback = 999-math.floor(c / 1000) + local bb = 28*math.fmod(cback,10) + local bg = 28*math.fmod(math.floor(cback / 10),10) + local br = 28*math.fmod(math.floor(cback / 100),10) - surface.SetDrawColor( - math.Clamp(br*self.Memory1[2028]*self.Memory1[2025],0,255), - math.Clamp(bg*self.Memory1[2027]*self.Memory1[2025],0,255), - math.Clamp(bb*self.Memory1[2026]*self.Memory1[2025],0,255), - 255 - ) - surface.DrawRect( - tx*szx+szx/2, - ty*szy+szy/2+szy*1.2*(1-self.Memory1[2044]), - szx*1.2, - szy*1.2*self.Memory1[2044] - ) - end - end - end) - end + surface.SetDrawColor( + math.Clamp(br*self.Memory1[2028]*self.Memory1[2025],0,255), + math.Clamp(bg*self.Memory1[2027]*self.Memory1[2025],0,255), + math.Clamp(bb*self.Memory1[2026]*self.Memory1[2025],0,255), + 255 + ) + surface.DrawRect( + tx*szx+szx/2, + ty*szy+szy/2+szy*1.2*(1-self.Memory1[2044]), + szx*1.2, + szy*1.2*self.Memory1[2044] + ) + end + end + end) + end - if self.FrameNeedsFlash == true then - if self.IntTimer < self.Memory1[2043] then - if (self.Flash == false) then - self.NeedRefresh = true - end - self.Flash = true - end + if self.FrameNeedsFlash == true then + if self.IntTimer < self.Memory1[2043] then + if (self.Flash == false) then + self.NeedRefresh = true + end + self.Flash = true + end - if self.IntTimer >= self.Memory1[2043] then - if self.Flash == true then - self.NeedRefresh = true - end - self.Flash = false - end + if self.IntTimer >= self.Memory1[2043] then + if self.Flash == true then + self.NeedRefresh = true + end + self.Flash = false + end - if self.IntTimer >= self.Memory1[2043]*2 then - self.IntTimer = 0 - end - end + if self.IntTimer >= self.Memory1[2043]*2 then + self.IntTimer = 0 + end + end - self.GPU:Render(self.Memory1[2024],self.Memory1[2023]) - Wire_Render(self) + self.GPU:Render(self.Memory1[2024],self.Memory1[2023]) + Wire_Render(self) end function ENT:IsTranslucent() - return true + return true end diff --git a/lua/entities/gmod_wire_digitalscreen/cl_init.lua b/lua/entities/gmod_wire_digitalscreen/cl_init.lua index bca93cea..36a6f941 100644 --- a/lua/entities/gmod_wire_digitalscreen/cl_init.lua +++ b/lua/entities/gmod_wire_digitalscreen/cl_init.lua @@ -248,17 +248,12 @@ function ENT:RedrawPixel(a) cr, cg, cb = (transformcolor[colormode] or transformcolor[0])(c) end - local xstep = (512/self.ScreenWidth) - local ystep = (512/self.ScreenHeight) surface.SetDrawColor(cr,cg,cb,255) - local tx, ty = floor(x*xstep), floor(y*ystep) - surface.DrawRect( tx, ty, floor((x+1)*xstep-tx), floor((y+1)*ystep-ty) ) + surface.DrawRect( x, y, 1, 1 ) end function ENT:RedrawRow(y) - local xstep = (512/self.ScreenWidth) - local ystep = (512/self.ScreenHeight) if y >= self.ScreenHeight then return end local a = y*self.ScreenWidth @@ -277,8 +272,7 @@ function ENT:RedrawRow(y) end surface.SetDrawColor(cr,cg,cb,255) - local tx, ty = floor(x*xstep), floor(y*ystep) - surface.DrawRect( tx, ty, floor((x+1)*xstep-tx), floor((y+1)*ystep-ty) ) + surface.DrawRect( x, y, 1, 1 ) end end @@ -294,7 +288,7 @@ function ENT:Draw() if self.ClearQueued then surface.SetDrawColor(0,0,0,255) - surface.DrawRect(0,0, 512,512) + surface.DrawRect(0,0, 1024,1024) self.ClearQueued = false return end @@ -320,7 +314,7 @@ function ENT:Draw() end) end - self.GPU:Render() + self.GPU:Render(0,0,1024,1024,nil,-(1024-self.ScreenWidth)/1024,-(1024-self.ScreenHeight)/1024) Wire_Render(self) end diff --git a/lua/entities/gmod_wire_egp/cl_init.lua b/lua/entities/gmod_wire_egp/cl_init.lua index 4b960b49..66a6ee1d 100644 --- a/lua/entities/gmod_wire_egp/cl_init.lua +++ b/lua/entities/gmod_wire_egp/cl_init.lua @@ -83,7 +83,7 @@ function ENT:Draw() self:_EGP_Update() end - self.GPU:Render() + self.GPU:Render(0,0,1024,1024,nil,-0.5,-0.5) end function ENT:OnRemove() diff --git a/lua/entities/gmod_wire_gpu/cl_init.lua b/lua/entities/gmod_wire_gpu/cl_init.lua index 7749fdf9..4b54b492 100644 --- a/lua/entities/gmod_wire_gpu/cl_init.lua +++ b/lua/entities/gmod_wire_gpu/cl_init.lua @@ -292,8 +292,8 @@ function ENT:RenderMisc(pos, ang, resolution, aspect, monitor) if (dist < 256) then local pos = WorldToLocal( trace.HitPos, Angle(), pos, ang ) - local x = 0.5+pos.x/(monitor.RS*(512/monitor.RatioX)) - local y = 0.5-pos.y/(monitor.RS*512) + local x = 0.5+pos.x/(monitor.RS*(1024/monitor.RatioX)) + local y = 0.5-pos.y/(monitor.RS*1024) local cursorOffset = 0 if self.VM:ReadCell(65532) == 1 then -- Check for vertex mode to counter the faulty offset @@ -308,7 +308,7 @@ function ENT:RenderMisc(pos, ang, resolution, aspect, monitor) surface.SetTexture(surface.GetTextureID("gui/arrow")) x = math.Clamp(x,0 + cursorOffset, 1 + cursorOffset) y = math.Clamp(y,0 + cursorOffset, 1 + cursorOffset) - surface.DrawTexturedRectRotated(-256*aspect+x*512*aspect+10,-256+y*512+12,32,32,45) + surface.DrawTexturedRectRotated(-512*aspect+x*1024*aspect+10,-512+y*1024+12,32,32,45) end end end @@ -376,10 +376,10 @@ function ENT:Draw() if self.VM.Memory[65532] == 0 then self.GPU:Render( self.VM:ReadCell(65522), self.VM:ReadCell(65523)-self.VM:ReadCell(65518)/512, -- rotation, scale - 512*math.Clamp(self.VM:ReadCell(65525),0,1), 512*math.Clamp(self.VM:ReadCell(65524),0,1), -- width, height + 1024*math.Clamp(self.VM:ReadCell(65525),0,1), 1024*math.Clamp(self.VM:ReadCell(65524),0,1), -- width, height function(pos, ang, resolution, aspect, monitor) -- postrenderfunction self:RenderMisc(pos, ang, resolution, aspect, monitor) - end + end,-0.5,-0.5 ) else -- Custom render to world @@ -389,20 +389,20 @@ function ENT:Draw() pos = pos - ang:Right()*(monitor.y2-monitor.y1)/2 pos = pos - ang:Forward()*(monitor.x2-monitor.x1)/2 - local width,height = 512*math.Clamp(self.VM.Memory[65525],0,1), - 512*math.Clamp(self.VM.Memory[65524],0,1) + local width,height = 1024*math.Clamp(self.VM.Memory[65525],0,1), + 1024*math.Clamp(self.VM.Memory[65524],0,1) - local h = width and width*monitor.RatioX or height or 512 + local h = width and width*monitor.RatioX or height or 1024 local w = width or h/monitor.RatioX local x = -w/2 local y = -h/2 - local res = monitor.RS*512/h + local res = monitor.RS*1024/h self.VertexCamSettings = { pos, ang, res } cam.Start3D2D(pos, ang, res) self.In3D2D = true local ok, err = xpcall(function() - self:RenderVertex(512,512*monitor.RatioX) + self:RenderVertex(1024,1024*monitor.RatioX) self:RenderMisc(pos, ang, res, 1/monitor.RatioX, monitor) end, debug.traceback) if not ok then WireLib.ErrorNoHalt(err) end diff --git a/lua/entities/gmod_wire_interactiveprop.lua b/lua/entities/gmod_wire_interactiveprop.lua new file mode 100644 index 00000000..89658e7a --- /dev/null +++ b/lua/entities/gmod_wire_interactiveprop.lua @@ -0,0 +1,476 @@ +AddCSLuaFile() +DEFINE_BASECLASS( "base_wire_entity" ) +ENT.PrintName = "Interactive Prop (Wire)" +ENT.WireDebugName = "Interactive Prop" + +local InteractiveModels + +local function copyPropUI(prop, newName) + local new = table.Copy( InteractiveModels[prop] ) + new.title = newName + return new +end + +InteractiveModels = { + + ["models/props_lab/reciever01a.mdl"] = { + width=220, + height=100, + title="Reciever01a", + widgets={ + {type="DCheckBox", x=20, y=50,name="Switch1"}, + {type="DCheckBox", x=40, y=50,name="Switch2"}, + {type="DNumberScratch", x=60, y=40,name="Knob1" }, + {type="DNumberScratch", x=80, y=40,name="Knob2" }, + {type="DNumberScratch", x=100, y=40,name="Knob3" }, + {type="DNumberScratch", x=120, y=40,name="Knob4" }, + {type="DNumberScratch", x=140, y=40,name="Knob5" }, + {type="DNumberScratch", x=160, y=40,name="Knob6" }, + {type="DNumberScratch", x=180, y=40,name="Knob7" }, + {type="DNumberScratch", x=60, y=60,name="Knob8" }, + {type="DNumberScratch", x=80, y=60,name="Knob9" }, + {type="DNumberScratch", x=100, y=60,name="Knob10" }, + {type="DNumberScratch", x=120, y=60,name="Knob11" }, + {type="DNumberScratch", x=140, y=60,name="Knob12" }, + {type="DNumberScratch", x=160, y=60,name="Knob13" }, + {type="DNumberScratch", x=180, y=60,name="Knob14" } + } + }, + + ["models/props_lab/reciever01b.mdl"] = { + width=190, + height=100, + title="Reciever01b", + widgets={ + {type="DButton", x=28, y=40,name="Button1"}, + {type="DButton", x=58, y=40,name="Button2"}, + {type="DButton", x=88, y=40,name="Button3"}, + {type="DButton", x=118, y=40,name="Button4"}, + {type="DNumberScratch", x=30, y=70,name="Knob1" }, + {type="DNumberScratch", x=60, y=70,name="Knob2" }, + {type="DNumberScratch", x=90, y=70,name="Knob3" }, + {type="DNumberScratch", x=120, y=70,name="Knob4" }, + {type="DNumberScratch", x=150, y=43,name="Knob5" }, + {type="DNumberScratch", x=150, y=67,name="Knob6" }, + } + }, + + ["models/props_lab/keypad.mdl"] = { + width=100, + height=120, + title="Keypad", + widgets={ + {type="DButton", x=10, y=30, text="1", name="1"}, + {type="DButton", x=40, y=30, text="2", name="2"}, + {type="DButton", x=70, y=30, text="3", name="3"}, + {type="DButton", x=10, y=60, text="4", name="4"}, + {type="DButton", x=40, y=60, text="5", name="5"}, + {type="DButton", x=70, y=60, text="6", name="6"}, + {type="DButton", x=10, y=90, text="7", name="7"}, + {type="DButton", x=40, y=90, text="8", name="8"}, + {type="DButton", x=70, y=90, text="9", name="9"}, + } + }, + + ["models/beer/wiremod/numpad.mdl"] = { + width=130, + height=180, + title="Numpad", + widgets={ + {type="DButton", x=10, y=150, text="0", name="0", width = 50}, + {type="DButton", x=10, y=120, text="1", name="1"}, + {type="DButton", x=40, y=120, text="2", name="2"}, + {type="DButton", x=70, y=120, text="3", name="3"}, + {type="DButton", x=10, y=90, text="4", name="4"}, + {type="DButton", x=40, y=90, text="5", name="5"}, + {type="DButton", x=70, y=90, text="6", name="6"}, + {type="DButton", x=10, y=60, text="7", name="7"}, + {type="DButton", x=40, y=60, text="8", name="8"}, + {type="DButton", x=70, y=60, text="9", name="9"}, + {type="DButton", x=100, y=120, text="E", name="Enter", height = 50}, + {type="DButton", x=100, y=60, text="+", name="+", height = 50}, + {type="DButton", x=100, y=30, text="-", name="-"}, + {type="DButton", x=70, y=30, text="*", name="*"}, + {type="DButton", x=40, y=30, text="/", name="/"}, + {type="DButton", x=70, y=150, text=".", name="."}, + {type="DButton", x=10, y=30, text="N", name="Numlock"}, + } + }, + + ["models/props_interiors/bathtub01a.mdl"] = { + width=100, + height=60, + title="BathTub01a", + widgets={ + {type="DNumberScratch", x=10, y=32, name="Hot", color=Color(237, 59, 59)}, + {type="DNumberScratch", x=74, y=32, name="Cold", color=Color(59, 79, 235)}, + } + }, + ["models/props_lab/citizenradio.mdl"] = { + width=160, + height=90, + title="citizenradio", + widgets={ + {type="DNumberScratch", x=10,y=30, name="Knob1"}, + {type="DNumberScratch", x=80,y=30, name="Knob2"}, + {type="DNumberScratch", x=120,y=30, name="Knob3"}, + {type="DNumberScratch", x=10,y=60, name="Knob4"}, + {type="DNumberScratch", x=40,y=60, name="Knob5"}, + {type="DNumberScratch", x=65,y=60, name="Knob6"}, + {type="DNumberScratch", x=90,y=60, name="Knob7"}, + {type="DNumberScratch", x=130,y=60, name="Knob8"}, + } + }, + ["models/props_lab/reciever01c.mdl"] = { + width = 112, + height = 80, + title="reciever01c", + widgets={ + {type="DNumberScratch", x = 10, y = 30, name="Knob1", color=Color(128,64,64)}, + {type="DNumberScratch", x = 35, y = 30, name="Knob2", color=Color(128,64,64)}, + {type="DNumberScratch", x = 10, y = 55, name="Knob3"}, + {type="DNumberScratch", x = 35, y = 55, name="Knob4"}, + {type="DNumberScratch", x = 60, y = 55, name="Knob5"}, + {type="DNumberScratch", x = 85, y = 55, name="Knob6"}, + } + }, + ["models/props_interiors/vendingmachinesoda01a.mdl"] = { + width = 60, + height = 200, + title = "vendingmachinesoda01a", + widgets = { + {type="DButton", x = 10, y = 30, name="1", width = 40, text = "1"}, + {type="DButton", x = 10, y = 50, name="2", width = 40, text = "2"}, + {type="DButton", x = 10, y = 70, name="3", width = 40, text = "3"}, + {type="DButton", x = 10, y = 90, name="4", width = 40, text = "4"}, + {type="DButton", x = 10, y = 110, name="5", width = 40, text = "5"}, + {type="DButton", x = 10, y = 130, name="6", width = 40, text = "6"}, + {type="DButton", x = 10, y = 150, name="7", width = 40, text = "7"}, + {type="DButton", x = 10, y = 170, name="8", width = 40, text = "8"}, + } + }, + ["models/props_c17/furniturewashingmachine001a.mdl"] = { + width = 36, + height = 66, + title="washingmachine001a", + widgets = { + {type="DNumberScratch", x=10,y=30,name="Knob"} + } + }, + ["models/props_trainstation/payphone001a.mdl"] = { + width = 100, + height = 150, + title="payphone001a", + widgets={ + {type="DButton", x=10, y=30, text="1", name="1"}, + {type="DButton", x=40, y=30, text="2", name="2"}, + {type="DButton", x=70, y=30, text="3", name="3"}, + {type="DButton", x=10, y=60, text="4", name="4"}, + {type="DButton", x=40, y=60, text="5", name="5"}, + {type="DButton", x=70, y=60, text="6", name="6"}, + {type="DButton", x=10, y=90, text="7", name="7"}, + {type="DButton", x=40, y=90, text="8", name="8"}, + {type="DButton", x=70, y=90, text="9", name="9"}, + {type="DButton", x=10, y=120, text="*", name="*"}, + {type="DButton", x=40, y=120, text="0", name="0"}, + {type="DButton", x=70, y=120, text="##", name="#"}, + } + }, + ["models/props_lab/plotter.mdl"] = { + width = 190, + height = 90, + title = "plotter", + widgets={ + {type="DButton", x=10, y=30, name="Button1"}, + {type="DButton", x=35, y=30, name="Button2"}, + {type="DButton", x=60, y=30, name="Button3"}, + {type="DButton", x=85, y=30, name="Button4"}, + {type="DButton", x=110, y=30, name="Button5"}, + {type="DButton", x=10, y=60, name="Button6"}, + {type="DButton", x=35, y=60, name="Button7"}, + {type="DButton", x=60, y=60, name="Button8"}, + {type="DButton", x=85, y=60, name="Button9"}, + {type="DButton", x=110, y=60, name="Button10"}, + {type="DButton", x=135, y=60, name="Button11"}, + {type="DButton", x=160, y=60, name="Button12"}, + } + } + +} + +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 = { + + DCheckBox = function(self, data, body, index) + local checkbox = vgui.Create("DCheckBox", body) + checkbox:SetPos(data.x, data.y) + checkbox:SetValue(self.InteractiveData[index]) + checkbox.OnChange = function(box,value) + surface.PlaySound("buttons/lightswitch2.wav") + self.InteractiveData[index] = value and 1 or 0 + self:SendData() + end + end, + + DNumberScratch = function(self, data, body, index) + local numberscratch = vgui.Create("DNumberScratch", body) + numberscratch.color = data.color or Color( 128, 128, 128 ) + numberscratch:SetMin(-1) + numberscratch:SetMax(1) + numberscratch:SetDecimals(4) + numberscratch:SetPos(data.x, data.y) + numberscratch:SetValue(self.InteractiveData[index]) + numberscratch.OnValueChanged = function(scratch,value) + self.InteractiveData[index] = value + self:SendData() + end + numberscratch:SetImageVisible( false ) + numberscratch:SetSize( 17, 17 ) + numberscratch.Paint = function( self, w, h ) + draw.RoundedBox( 8.5, 0, 0, w, h, numberscratch.color ) + local value = self:GetFloatValue() + surface.SetDrawColor(255, 255, 255) + surface.DrawLine( + w/2, + h/2, + math.sin(value * math.pi*0.75)*w/2+w/2, + -math.cos(value * math.pi*0.75)*h/2+h/2 + ) + end + end, + + DButton = function(self, data, body, index) + local button = vgui.Create("DButton", body) + button:SetPos(data.x, data.y) + button:SetText(data.text or "") + button:SetSize(data.width or 20, data.height or 20) + self:AddButton(index,button) + end + +} + +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 +end + + +function ENT:AddButton(id,button) + self.Buttons[id] = button +end + +function ENT:SendData() + net.Start("wire_interactiveprop_action") + local data = InteractiveModels[self:GetModel()].widgets + net.WriteEntity(self) + for i=1, #data do + net.WriteFloat(self.InteractiveData[i]) + end + net.SendToServer() +end + +if CLIENT then + + local panel + + ---------------------------------------------------- + -- Show the prompt + ---------------------------------------------------- + function ENT:Initialize() + self.InteractiveData = {} + self.LastButtons = {} + self.Buttons = {} + for i=1, #InteractiveModels[ self:GetModel() ].widgets do + self.InteractiveData[i] = 0 + 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 + panel = self:GetPanel() + panel.OnClose = function(panel) + net.Start("wire_interactiveprop_close") + self.Buttons = {} + self.LastButtons = {} + net.WriteEntity(self) + net.SendToServer() + end + end) + + net.Receive( "wire_interactiveprop_kick", function() + self.Buttons = {} + self.LastButtons = {} + if IsValid( panel ) then + panel:Remove() + end + end) + + return + +end + +function ENT:InitData() + local model = self:GetModel() + local outputs = {} + for i=1, #InteractiveModels[model].widgets do + outputs[i] = InteractiveModels[model].widgets[i].name + end + self.Outputs=WireLib.CreateOutputs(self,outputs) +end + + +---------------------------------------------------- +-- UpdateOverlay +---------------------------------------------------- +function ENT:UpdateOverlay() + txt = "" + if IsValid(self.User) then + txt = "In use by: " .. self.User:Nick() + end + + self:SetOverlayText(txt) +end + + + + + + + +---------------------------------------------------- +-- Initialize +---------------------------------------------------- +function ENT:Initialize() + self:PhysicsInit(SOLID_VPHYSICS) + self:SetUseType(SIMPLE_USE) + + self.InteractiveData = {} + + self:InitData() + + + self.BlockInput=false + self.NextPrompt = 0 + + self:UpdateOverlay() + + +end + + + +function ENT:OnRemove() + self:Unprompt( true ) +end + + +function ENT:ReceiveData() + local data = InteractiveModels[self:GetModel()].widgets + for i = 1, #data do + WireLib.TriggerOutput(self, data[i].name, net.ReadFloat()) + end +end +---------------------------------------------------- +-- Receiving data from client +---------------------------------------------------- +util.AddNetworkString("wire_interactiveprop_action") +net.Receive("wire_interactiveprop_action",function(len,ply) + self = net.ReadEntity() + if not IsValid( self ) or not IsValid( ply ) or ply ~= self.User then return end + + self:ReceiveData() + + + self:UpdateOverlay() +end) + +---------------------------------------------------- +-- Prompt +-- Sends prompt to user etc +---------------------------------------------------- +util.AddNetworkString("wire_interactiveprop_show") +function ENT:Prompt( ply ) + 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 ) + + self:UpdateOverlay() + else + self:Prompt( self:GetPlayer() ) -- prompt for owner + end +end + +util.AddNetworkString("wire_interactiveprop_close") +net.Receive("wire_interactiveprop_close",function(len,ply) +local self = net.ReadEntity() +self:Unprompt() +end) + +util.AddNetworkString("wire_interactiveprop_kick") +function ENT:Unprompt( ) + + self.User = nil + self:UpdateOverlay() +end + + +---------------------------------------------------- +-- Use +---------------------------------------------------- +function ENT:Use(ply) + if not IsValid( ply ) then return end + + self:Prompt( ply ) +end + +duplicator.RegisterEntityClass("gmod_wire_interactiveprop",WireLib.MakeWireEnt,"Data") diff --git a/lua/entities/gmod_wire_oscilloscope.lua b/lua/entities/gmod_wire_oscilloscope.lua index 17b28864..ee44bf7d 100644 --- a/lua/entities/gmod_wire_oscilloscope.lua +++ b/lua/entities/gmod_wire_oscilloscope.lua @@ -50,19 +50,19 @@ if CLIENT then self.GPU:RenderToGPU(function() surface.SetDrawColor(10,20,5,255) - surface.DrawRect(0,0,512,512) + surface.DrawRect(0,0,1024,1024) local nodes = self:GetNodeList() for i=1,length do local i_next = i+1 if not nodes[i_next] then continue end - local nx1 = nodes[i].X*256+256 - local ny1 = -nodes[i].Y*256+256 - local nx2 = nodes[i_next].X*256+256 - local ny2 = -nodes[i_next].Y*256+256 + local nx1 = nodes[i].X*512+512 + local ny1 = -nodes[i].Y*512+512 + local nx2 = nodes[i_next].X*512+512 + local ny2 = -nodes[i_next].Y*512+512 - if ((nx1-nx2)*(nx1-nx2) + (ny1-ny2)*(ny1-ny2) < 256*256) then + if ((nx1-nx2)*(nx1-nx2) + (ny1-ny2)*(ny1-ny2) < 512*512) then local a = math.max(1, 3.75-(3*i)/length)^1.33 local a2 = math.max(1, a/2) @@ -79,14 +79,14 @@ if CLIENT then end surface.SetDrawColor(30, 120, 10, 255) - surface.DrawLine(0, 128, 512, 128) - surface.DrawLine(0, 384, 512, 384) - surface.DrawLine(128, 0, 128, 512) - surface.DrawLine(384, 0, 384, 512) + surface.DrawLine(0, 256, 1024, 256) + surface.DrawLine(0, 768, 1024, 768) + surface.DrawLine(256, 0, 256, 1024) + surface.DrawLine(768, 0, 768, 1024) surface.SetDrawColor(180, 200, 10, 255) - surface.DrawLine(0, 256, 512, 256) - surface.DrawLine(256, 0, 256, 512) + surface.DrawLine(0, 512, 1024, 512) + surface.DrawLine(512, 0, 512, 1024) end) self.GPU:Render() diff --git a/lua/entities/gmod_wire_textscreen.lua b/lua/entities/gmod_wire_textscreen.lua index 8ead52b2..857e7066 100644 --- a/lua/entities/gmod_wire_textscreen.lua +++ b/lua/entities/gmod_wire_textscreen.lua @@ -142,8 +142,8 @@ if CLIENT then if self.NeedRefresh then self.NeedRefresh = nil self.GPU:RenderToGPU(function() - local w = 512 - local h = 512 + local w = 1024 + local h = 1024 surface.SetDrawColor(self.bgcolor.r, self.bgcolor.g, self.bgcolor.b, 255) surface.DrawRect(0, 0, w, h) @@ -197,7 +197,7 @@ if CLIENT then local fontData = { font = font, - size = 380 / chrPerLine, + size = 760 / chrPerLine, weight = 400, antialias = true, additive = false diff --git a/lua/wire/client/cl_modelplug.lua b/lua/wire/client/cl_modelplug.lua index c838f716..d5581c52 100644 --- a/lua/wire/client/cl_modelplug.lua +++ b/lua/wire/client/cl_modelplug.lua @@ -49,17 +49,62 @@ list.Set( "WireScreenModels", "models/props/cs_office/computer_monitor.mdl", tru list.Set( "WireScreenModels", "models/kobilica/wiremonitorbig.mdl", true ) list.Set( "WireScreenModels", "models/kobilica/wiremonitorsmall.mdl", true ) list.Set( "WireScreenModels", "models/props/cs_assault/Billboard.mdl", true ) +list.Set( "WireScreenModels", "models/cheeze/pcb/pcb0.mdl", true ) +list.Set( "WireScreenModels", "models/cheeze/pcb/pcb1.mdl", true ) +list.Set( "WireScreenModels", "models/cheeze/pcb/pcb2.mdl", true ) +list.Set( "WireScreenModels", "models/cheeze/pcb/pcb3.mdl", true ) list.Set( "WireScreenModels", "models/cheeze/pcb/pcb4.mdl", true ) list.Set( "WireScreenModels", "models/cheeze/pcb/pcb6.mdl", true ) list.Set( "WireScreenModels", "models/cheeze/pcb/pcb5.mdl", true ) list.Set( "WireScreenModels", "models/cheeze/pcb/pcb7.mdl", true ) list.Set( "WireScreenModels", "models/cheeze/pcb/pcb8.mdl", true ) list.Set( "WireScreenModels", "models/cheeze/pcb2/pcb8.mdl", true ) +list.Set( "WireScreenModels", "models/cheeze/pcb2/pcb1.mdl", true ) +list.Set( "WireScreenModels", "models/cheeze/pcb2/pcb2.mdl", true ) +list.Set( "WireScreenModels", "models/cheeze/pcb2/pcb3.mdl", true ) +list.Set( "WireScreenModels", "models/cheeze/pcb2/pcb4.mdl", true ) +list.Set( "WireScreenModels", "models/cheeze/pcb2/pcb5.mdl", true ) +list.Set( "WireScreenModels", "models/cheeze/pcb2/pcb6.mdl", true ) +list.Set( "WireScreenModels", "models/cheeze/pcb2/pcb7.mdl", true ) list.Set( "WireScreenModels", "models/props_lab/monitor01a.mdl", true ) list.Set( "WireScreenModels", "models/props_lab/monitor02.mdl", true ) list.Set( "WireScreenModels", "models/props/cs_militia/reload_bullet_tray.mdl", true ) list.Set( "WireScreenModels", "models/props_lab/workspace002.mdl", true ) list.Set( "WireScreenModels", "models/props_lab/reciever01b.mdl", true ) +list.Set( "WireScreenModels","models/props_c17/consolebox05a.mdl", true ) +list.Set( "WireScreenModels","models/props_lab/reciever01c.mdl", true ) +list.Set( "WireScreenModels","models/props_lab/reciever01d.mdl", true ) +list.Set( "WireScreenModels","models/props_c17/consolebox01a.mdl", true ) +list.Set( "WireScreenModels","models/props_combine/combine_interface001.mdl", true ) +list.Set( "WireScreenModels","models/props_c17/cashregister01a.mdl", true ) +list.Set( "WireScreenModels","models/props_combine/combine_monitorbay.mdl", true ) +list.Set( "WireScreenModels","models/props_lab/workspace001.mdl", true ) +list.Set( "WireScreenModels","models/props_lab/citizenradio.mdl", true ) +list.Set( "WireScreenModels","models/props_lab/securitybank.mdl", true ) +list.Set( "WireScreenModels","models/beer/wiremod/gate_e2.mdl", true ) +list.Set( "WireScreenModels","models/beer/wiremod/targetfinder.mdl", true ) +list.Set( "WireScreenModels","models/bull/gates/microcontroller1.mdl", true ) +list.Set( "WireScreenModels","models/bull/gates/microcontroller2.mdl", true ) +list.Set( "WireScreenModels","models/jaanus/wiretool/wiretool_gate.mdl", true ) +list.Set( "WireScreenModels","models/jaanus/wiretool/wiretool_controlchip.mdl",true ) +list.Set( "WireScreenModels","models/props_lab/keypad.mdl", true ) +list.Set( "WireScreenModels","models/weapons/w_c4_planted.mdl", true ) +list.Set( "WireScreenModels","models/weapons/w_toolgun.mdl", true ) +list.Set( "WireScreenModels","models/xqm/panel1x1.mdl", true ) +list.Set( "WireScreenModels","models/xqm/panel1x2.mdl", true ) +list.Set( "WireScreenModels","models/xqm/box5s.mdl", true ) +list.Set( "WireScreenModels","models/props_lab/miniteleport.mdl", true ) +list.Set( "WireScreenModels","models/props_lab/plotter.mdl", true ) +list.Set( "WireScreenModels","models/props_combine/combine_interface002.mdl", true ) +list.Set( "WireScreenModels","models/props_combine/combine_interface003.mdl", true ) +list.Set( "WireScreenModels","models/props_combine/combine_intmonitor003.mdl", true ) +list.Set( "WireScreenModels","models/props_combine/combine_intmonitor001.mdl", true ) +list.Set( "WireScreenModels","models/props_lab/workspace003.mdl", true ) +list.Set( "WireScreenModels","models/props_lab/workspace004.mdl", true ) +list.Set( "WireScreenModels","models/props_lab/servers.mdl", true ) +list.Set( "WireScreenModels","models/props_phx/rt_screen.mdl", true ) + + --list.Set( "WireScreenModels", "models/blacknecro/ledboard60.mdl", true ) --broken list.Set( "WireScreenModels", "models/props_wasteland/controlroom_monitor001b.mdl", true ) --TF2 Billboards @@ -67,12 +112,28 @@ list.Set( "WireScreenModels", "models/props_mining/billboard001.mdl", true ) list.Set( "WireScreenModels", "models/props_mining/billboard002.mdl", true ) --PHX3 +list.Set( "WireScreenModels", "models/hunter/plates/plate025.mdl", true ) +list.Set( "WireScreenModels", "models/hunter/plates/plate025x025.mdl", true ) +list.Set( "WireScreenModels", "models/hunter/plates/plate025x05.mdl", true ) +list.Set( "WireScreenModels", "models/hunter/plates/plate05x075.mdl", true ) +list.Set( "WireScreenModels", "models/hunter/plates/plate05x1.mdl", true ) list.Set( "WireScreenModels", "models/hunter/plates/plate1x1.mdl", true ) + + list.Set( "WireScreenModels", "models/hunter/plates/plate2x2.mdl", true ) list.Set( "WireScreenModels", "models/hunter/plates/plate4x4.mdl", true ) list.Set( "WireScreenModels", "models/hunter/plates/plate8x8.mdl", true ) list.Set( "WireScreenModels", "models/hunter/plates/plate05x05.mdl", true ) list.Set( "WireScreenModels", "models/hunter/blocks/cube1x1x1.mdl", true ) +list.Set( "WireScreenModels","models/props_lab/reciever01b.mdl", true ) +list.Set( "WireScreenModels","models/fasteroid/bull/lcd1.mdl", true ) +list.Set( "WireScreenModels","models/fasteroid/bull/lcd2.mdl", true ) +list.Set( "WireScreenModels","models/fasteroid/bull/lcd3.mdl", true ) +list.Set( "WireScreenModels","models/fasteroid/bull/lcd4.mdl", true ) +list.Set( "WireScreenModels","models/fasteroid/bull/lcd5.mdl", true ) + + + --screens that are transparent list.Set( "WireScreenModels", "models/props_phx/construct/windows/window1x1.mdl", true ) @@ -405,6 +466,21 @@ list.Set( "Wire_Keyboard_Models", "models/jaanus/wiretool/wiretool_input.mdl", t list.Set( "Wire_Keyboard_Models", "models/props/kb_mouse/keyboard.mdl", true ) list.Set( "Wire_Keyboard_Models", "models/props_c17/computer01_keyboard.mdl", true ) +list.Set( "Wire_InteractiveProp_Models", "models/props_lab/reciever01a.mdl", true ) +list.Set( "Wire_InteractiveProp_Models", "models/props_lab/reciever01b.mdl", true ) +list.Set( "Wire_InteractiveProp_Models", "models/props_lab/keypad.mdl", true ) +list.Set( "Wire_InteractiveProp_Models", "models/beer/wiremod/numpad.mdl", true ) +list.Set( "Wire_InteractiveProp_Models", "models/props_interiors/bathtub01a.mdl", true ) +list.Set( "Wire_InteractiveProp_Models", "models/props_c17/furnituresink001a.mdl", true ) +list.Set( "Wire_InteractiveProp_Models", "models/props_interiors/sinkkitchen01a.mdl", true ) +list.Set( "Wire_InteractiveProp_Models", "models/props_wasteland/prison_sink001a.mdl", true ) +list.Set( "Wire_InteractiveProp_Models", "models/props_lab/citizenradio.mdl", true ) +list.Set( "Wire_InteractiveProp_Models", "models/props_c17/furniturewashingmachine001a.mdl", true ) +list.Set( "Wire_InteractiveProp_Models", "models/props_lab/plotter.mdl", true ) +list.Set( "Wire_InteractiveProp_Models", "models/props_interiors/vendingmachinesoda01a.mdl", true ) +list.Set( "Wire_InteractiveProp_Models", "models/props_lab/reciever01c.mdl", true ) +list.Set( "Wire_InteractiveProp_Models", "models/props_trainstation/payphone001a.mdl", true ) + --Hydraulic list.Set( "Wire_Hydraulic_Models", "models/beer/wiremod/hydraulic.mdl", true ) list.Set( "Wire_Hydraulic_Models", "models/jaanus/wiretool/wiretool_siren.mdl", true ) diff --git a/lua/wire/gpulib.lua b/lua/wire/gpulib.lua index ce851dc5..b3f4eaa8 100644 --- a/lua/wire/gpulib.lua +++ b/lua/wire/gpulib.lua @@ -84,7 +84,6 @@ if CLIENT then -- Returns a render target from the cache pool and marks it as used local function GetRT() - for i, RT in pairs( RenderTargetCache ) do if not RT[1] then -- not used @@ -101,7 +100,7 @@ if CLIENT then for i, RT in pairs( RenderTargetCache ) do if not RT[1] and RT[2] == false then -- not used and doesn't exist, let's create the render target. - local rendertarget = GetRenderTarget("WireGPU_RT_"..i, 512, 512) + local rendertarget = GetRenderTarget("WireGPU_RT_"..i, 1024, 1024) if rendertarget then RT[1] = true -- Mark as used @@ -141,12 +140,23 @@ if CLIENT then local fontData = { font="lucida console", - size=20, + size=40, weight=800, antialias= true, additive = false, } surface.CreateFont("WireGPU_ConsoleFont", fontData) + surface.CreateFont("LCDFontBlur", { + font = "Alphanumeric LCD", + size = 26, + antialias = false, + blursize = 1 + }) + surface.CreateFont("LCDFont", { + font = "Alphanumeric LCD", + size = 26, + antialias = false + }) // // Create screen textures and materials // @@ -245,7 +255,7 @@ if CLIENT then }, } -- helper function for GPU:Render - function GPU.DrawScreen(x, y, w, h, rotation, scale) + function GPU.DrawScreen(x, y, w, h, rotation, scale, uvclipx, uvclipy) -- generate vertex data local vertices = { --[[ @@ -267,12 +277,12 @@ if CLIENT then if tex.u == 0 then vertex.u = tex.u-scale else - vertex.u = tex.u+scale + vertex.u = tex.u+scale+uvclipx end if tex.v == 0 then vertex.v = tex.v-scale else - vertex.v = tex.v+scale + vertex.v = tex.v+scale+uvclipy end end @@ -295,7 +305,7 @@ if CLIENT then local OldRT = render.GetRenderTarget() render.SetRenderTarget(NewRT) - render.SetViewPort(0, 0, 512, 512) + render.SetViewPort(0, 0, 1024, 1024) cam.Start2D() local ok, err = xpcall(renderfunction, debug.traceback) if not ok then WireLib.ErrorNoHalt(err) end @@ -317,19 +327,19 @@ if CLIENT then pos = pos - ang:Forward()*(monitor.x2-monitor.x1)/2 end - local h = width and width*monitor.RatioX or height or 512 + local h = width and width*monitor.RatioX or height or 1024 local w = width or h/monitor.RatioX local x = -w/2 local y = -h/2 - local res = monitor.RS*512/h + local res = monitor.RS*1024/h cam.Start3D2D(pos, ang, res) local ok, err = xpcall(renderfunction, debug.traceback, x, y, w, h, monitor, pos, ang, res) if not ok then WireLib.ErrorNoHalt(err) end cam.End3D2D() end - function GPU:Render(rotation, scale, width, height, postrenderfunction) + function GPU:Render(rotation, scale, width, height, postrenderfunction, uvclipx, uvclipy) if not self.RT then return end local monitor, pos, ang = self:GetInfo() @@ -341,8 +351,8 @@ if CLIENT then cam.Start3D2D(pos, ang, res) local ok, err = xpcall(function() local aspect = 1/monitor.RatioX - local w = (width or 512)*aspect - local h = (height or 512) + local w = (width or 1024)*aspect + local h = (height or 1024) local x = -w/2 local y = -h/2 @@ -354,7 +364,7 @@ if CLIENT then if not translucent then surface.SetDrawColor(0,0,0,255) - surface.DrawRect(-256*aspect,-256,512*aspect,512) + surface.DrawRect(-512*aspect,-512,1024*aspect,1024) end surface.SetDrawColor(255,255,255,255) @@ -363,7 +373,7 @@ if CLIENT then render.PushFilterMag(self.texture_filtering or TEXFILTER.POINT) render.PushFilterMin(self.texture_filtering or TEXFILTER.POINT) - self.DrawScreen(x, y, w, h, rotation or 0, scale or 0) + self.DrawScreen(x, y, w, h, rotation or 0, scale or 0, uvclipx or 0, uvclipy or 0) render.PopFilterMin() render.PopFilterMag() @@ -423,7 +433,7 @@ if CLIENT then local model = ent:GetModel() local monitor = WireGPU_Monitors[model] - local h = 512*monitor.RS + local h = 1024*monitor.RS local w = h/monitor.RatioX local x = -w/2 local y = -h/2 diff --git a/lua/wire/stools/characterlcd.lua b/lua/wire/stools/characterlcd.lua new file mode 100644 index 00000000..f49f71b1 --- /dev/null +++ b/lua/wire/stools/characterlcd.lua @@ -0,0 +1,67 @@ +WireToolSetup.setCategory( "Visuals/Screens" ) +WireToolSetup.open( "characterlcd", "Character LCD", "gmod_wire_characterlcd", nil, "Character LCDs" ) + +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:" ) + TOOL.Information = { { name = "left", text = "Create/Update " .. TOOL.Name } } +end +WireToolSetup.BaseLang() +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("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 +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, + +} + +function TOOL.BuildCPanel(panel) + WireToolHelpers.MakePresetControl(panel, "wire_characterlcd") + WireDermaExts.ModelSelect(panel, "wire_characterlcd_model", list.Get( "WireScreenModels" ), 5) + panel:AddControl("Color", { + Label = "#tool.wire_characterlcd.bgcolor", + Red = "wire_characterlcd_bgred", + Green = "wire_characterlcd_bggreen", + Blue = "wire_characterlcd_bgblue", + ShowAlpha = "0", + ShowHSV = "1", + ShowRGB = "1", + Multiplier = "255" + }) + panel:AddControl("Color", { + Label = "#tool.wire_characterlcd.fgcolor", + Red = "wire_characterlcd_fgred", + Green = "wire_characterlcd_fggreen", + Blue = "wire_characterlcd_fgblue", + ShowAlpha = "0", + ShowHSV = "1", + ShowRGB = "1", + Multiplier = "255" + }) + panel:NumSlider("Width", "wire_characterlcd_width", 1, 56, 0) + panel:NumSlider("Height", "wire_characterlcd_height", 1, 16, 0) + panel:CheckBox("#Create Flat to Surface", "wire_characterlcd_createflat") + +end diff --git a/lua/wire/stools/interactiveprop.lua b/lua/wire/stools/interactiveprop.lua new file mode 100644 index 00000000..2702954f --- /dev/null +++ b/lua/wire/stools/interactiveprop.lua @@ -0,0 +1,29 @@ +-- Author: mitterdoo (with help from Divran) + +WireToolSetup.setCategory("Input, Output") +WireToolSetup.open("interactiveprop","Interactive Prop","gmod_wire_interactiveprop",nil,"Interactive Props") +if CLIENT then + language.Add( "Tool.wire_interactiveprop.name", "Wire Interactive Prop" ) + language.Add( "Tool.wire_interactiveprop.desc", "Opens a UI panel which controls outputs for use with wire system." ) +end + + + +TOOL.ClientConVar = { + model = "models/props_lab/receiver01a.mdl" +} + +if SERVER then + function TOOL:GetDataTables() + return {} + end +end + +WireToolSetup.BaseLang() +WireToolSetup.SetupMax(20) + + +function TOOL.BuildCPanel(panel) + panel:AddControl("Header",{Description="Opens a UI panel which controls outputs for use with the wire system."}) + ModelPlug_AddToCPanel(panel, "InteractiveProp", "wire_interactiveprop", true) +end diff --git a/lua/wire/wiremonitors.lua b/lua/wire/wiremonitors.lua index 7ea64913..c779c200 100644 --- a/lua/wire/wiremonitors.lua +++ b/lua/wire/wiremonitors.lua @@ -11,7 +11,7 @@ function WireGPU_AddMonitor(name,model,tof,tou,tor,trs,x1,x2,y1,y2,rot,transluce local monitor = { Name = name, offset = Vector(tof, -tor, tou), - RS = trs or (y2 - y1) / 512, + RS = (trs or (y2 - y1) / 512)/2, RatioX = RatioX, x1 = x1, @@ -116,7 +116,7 @@ function WireGPU_FromBox_Helper(name, model, boxmin, boxmax, rot, translucent) local monitor = { Name = name, offset = offset, - RS = (y2-y1)/512, + RS = (y2-y1)/1024, RatioX = (y2-y1)/(x2-x1), x1 = x1, @@ -181,6 +181,47 @@ WireGPU_AddMonitor("Panel 0.5x0.5", "models/hunter/plates/plate05x05.mdl", WireGPU_AddMonitor("Tray", "models/props/cs_militia/reload_bullet_tray.mdl", 0 , 0.8 , 0 , nil , 0 , 7.68 , 0 , 4.608 , true) WireGPU_FromBox_Helper("Wall-mounted TV", "models/props_wasteland/controlroom_monitor001b.mdl", Vector(-10.2,-12.6,-3), Vector(10.7,4.7,15.38), Angle(0, 90, 103.2)) WireGPU_FromBox_Helper("Oscilloscope", "models/props_lab/reciever01b.mdl", Vector(-5.93,-2,-3), Vector(-1.74,2.1,6.225), Angle(0, 90, 90)) +WireGPU_FromBox_Helper("Oscilloscope 2", "models/props_c17/consolebox03a.mdl", Vector(4,2,-10), Vector(10.6,7.1,10), Angle(0, 90, 90)) +WireGPU_FromBox_Helper("Oscilloscope 3", "models/props_c17/consolebox05a.mdl", Vector(-6,0,-10), Vector(0.9,5.1,11), Angle(0, 90, 87)) +WireGPU_FromBox_Helper("Receiver", "models/props_lab/reciever01c.mdl", Vector(-5.2,-1.7,-3), Vector(-0.2,0.8,5.5), Angle(0, 90, 90)) +WireGPU_FromBox_Helper("Receiver 2", "models/props_lab/reciever01d.mdl", Vector(-5.2,-1.7,-3), Vector(-0.2,0.8,5.5), Angle(0, 90, 90)) +WireGPU_FromBox_Helper("Oscilloscope 4", "models/props_c17/consolebox01a.mdl", Vector(8.5,7.2,-10), Vector(15,9.4,16.4), Angle(0, 90, 90)) +WireGPU_FromBox_Helper("Combine Console", "models/props_combine/combine_interface001.mdl", Vector(-9.9,25.6,-10), Vector(5.7,33.5,34.2), Angle(0, 90, 41.5)) +WireGPU_FromBox_Helper("Cash Register", "models/props_c17/cashregister01a.mdl", Vector(-9.2,8.5,-10), Vector(4.4,11.6,-5.9), Angle(0, 180, 90)) +WireGPU_FromBox_Helper("Combine Monitor", "models/props_combine/combine_monitorbay.mdl", Vector(-30.7,-26,-10), Vector(38,34.7,-4.31), Angle(0, 90, 90)) +WireGPU_FromBox_Helper("Workspace 001", "models/props_lab/workspace001.mdl", Vector(4,37,0), Vector(21.2,52,11.1), Angle(0, 15, 83)) +WireGPU_FromBox_Helper("Radio", "models/props_lab/citizenradio.mdl", Vector(-5.8,11.7,-3), Vector(11.3,15.3,8.2), Angle(0, 90, 90)) +WireGPU_FromBox_Helper("Security Bank", "models/props_lab/securitybank.mdl", Vector(-4.6,66,-3), Vector(25,86.5,12), Angle(0, 90, 90)) +WireGPU_FromBox_Helper("GPS", "models/beer/wiremod/gps.mdl", Vector(-2.9,-2.1,-3), Vector(2.9,2.9,1.18), Angle(0, 90, 0)) + +WireGPU_FromBox_Helper("E2", "models/beer/wiremod/gate_e2.mdl", Vector(-2.8,-2.8,-3), Vector(2.8,2.8,0.55), Angle(0, 90, 0)) +WireGPU_FromBox_Helper("Target Finder", "models/beer/wiremod/targetfinder.mdl", Vector(-3.2,-2.3,-3), Vector(3.2,1.2,1.5), Angle(0, 90, 0)) +WireGPU_FromBox_Helper("4-pin DIP", "models/bull/gates/microcontroller1.mdl", Vector(-2.3,-1.2,-3), Vector(2.3,1.2,0.96), Angle(0, 90, 0)) +WireGPU_FromBox_Helper("8-pin DIP", "models/bull/gates/microcontroller2.mdl", Vector(-4.3,-1.2,-3), Vector(4.3,1.2,0.96), Angle(0, 90, 0)) +WireGPU_FromBox_Helper("Gate", "models/jaanus/wiretool/wiretool_gate.mdl", Vector(-2.9,-2.9,-3), Vector(2.9,2.9,0.82), Angle(0, 90, 0)) +WireGPU_FromBox_Helper("Controller", "models/jaanus/wiretool/wiretool_controlchip.mdl",Vector(-3.4,-1.5,-3), Vector(3.4,1.5,0.82), Angle(0, 90, 0)) +WireGPU_FromBox_Helper("Keypad", "models/props_lab/keypad.mdl", Vector(-1.7,2,-3), Vector(1.7,4,0.68), Angle(0, 90, 90)) +WireGPU_FromBox_Helper("C4", "models/weapons/w_c4_planted.mdl", Vector(1.5,1.35,-3), Vector(7.8,4.6,8.65), Angle(0, -90, 0)) +WireGPU_FromBox_Helper("Toolgun", "models/weapons/w_toolgun.mdl", Vector(-1.4,4.7,-3), Vector(1.05,7.16,-0.14), Angle(0, -90, 45)) +WireGPU_FromBox_Helper("Blue Panel 1x1", "models/xqm/panel1x1.mdl", Vector(-9.2,-9.2,-3), Vector(9.2,9.2,-0.3), Angle(0, -90, 0)) +WireGPU_FromBox_Helper("Blue Panel 1x2", "models/xqm/panel1x2.mdl", Vector(-9.2,-31.2,-3), Vector(9.2,9.2,-0.3), Angle(0, -90, 0)) +WireGPU_FromBox_Helper("Blue Box", "models/xqm/box5s.mdl", Vector(-9.2,-9.2,-3), Vector(9.2,9.2,9.3), Angle(0, -90, 90)) +WireGPU_FromBox_Helper("Teleporter", "models/props_lab/miniteleport.mdl", Vector(20.8,-8.1,-3), Vector(30.2,-3.7,17.8), Angle(0, 90, 55)) +WireGPU_FromBox_Helper("Printer", "models/props_lab/plotter.mdl", Vector(-10.2,-19.5,-3), Vector(-6.7,-18.3,39.6), Angle(0, 90, 0)) +WireGPU_FromBox_Helper("Combine Console 2", "models/props_combine/combine_interface002.mdl", Vector(-14.15,27.5,-10), Vector(11.5,32.3,34.2), Angle(0, 90, 41.5)) +WireGPU_FromBox_Helper("Combine Console 3", "models/props_combine/combine_interface003.mdl", Vector(-20.3,48.7,-10), Vector(19.9,50.9,13), Angle(0.5, 91, 70)) +WireGPU_FromBox_Helper("Combine Monitor 2", "models/props_combine/combine_intmonitor003.mdl", Vector(-17,0,-10), Vector(15,48.5,22.8), Angle(0, 90, 90)) +WireGPU_FromBox_Helper("Combine Monitor 3", "models/props_combine/combine_intmonitor001.mdl", Vector(-16,3,-10), Vector(10,48.5,-4.1), Angle(0, 90, 90)) +WireGPU_FromBox_Helper("Workspace 003", "models/props_lab/workspace003.mdl", Vector(110,73.3,-3), Vector(149,96,-1), Angle(0, 90, 101)) +WireGPU_FromBox_Helper("Workspace 004", "models/props_lab/workspace004.mdl", Vector(4.2,37,0), Vector(21.4,52,11.1), Angle(0, 15, 83)) +WireGPU_FromBox_Helper("Servers", "models/props_lab/servers.mdl", Vector(-18.2,7.8,0), Vector(-4.7,19.1,12.1), Angle(0, 90, 82)) +WireGPU_AddMonitor("Plasma TV (16:10) 2", "models/props_phx/rt_screen.mdl", 6.1 , 18.93, 0 , 0.065 , -28.5 , 28.5 , 2 , 36 ) +WireGPU_FromBox_Helper("8x2 LCD", "models/fasteroid/bull/lcd1.mdl", Vector(-4.91,-1.02,-3), Vector(1.31,1.02,0.8), Angle(0, 90, 0)) +WireGPU_FromBox_Helper("16x2 LCD", "models/fasteroid/bull/lcd2.mdl", Vector(-4.91,-1.02,-3), Vector(7.52,1.02,0.8), Angle(0, 90, 0)) +WireGPU_FromBox_Helper("16x4 LCD", "models/fasteroid/bull/lcd3.mdl", Vector(-4.91,-3.11,-3), Vector(7.52,1.02,0.8), Angle(0, 90, 0)) +WireGPU_FromBox_Helper("40x4 LCD", "models/fasteroid/bull/lcd4.mdl", Vector(-4.91,-3.11,-3), Vector(26.22,1.02,0.8), Angle(0, 90, 0)) +WireGPU_FromBox_Helper("20x4 LCD", "models/fasteroid/bull/lcd5.mdl", Vector(-4.91,-3.11,-3), Vector(10.65,1.02,0.8), Angle(0, 90, 0)) + -- Offset front, offset up, offset right, resolution/scale OF OU OR SCALE LOWX HIGHX LOWY HIGHY ROTATE90 --WireGPU_AddMonitor("LED Board (1:1)", "models/blacknecro/ledboard60.mdl", 6.1, 18.5 , 11 , 0.065 , -60 , 60 , -60 , 60 ) -- broken @@ -226,3 +267,4 @@ local function fallback(self, model) end setmetatable(WireGPU_Monitors, { __index = fallback }) + diff --git a/models/fasteroid/bull/lcd1.dx80.vtx b/models/fasteroid/bull/lcd1.dx80.vtx new file mode 100644 index 00000000..ffbed260 Binary files /dev/null and b/models/fasteroid/bull/lcd1.dx80.vtx differ diff --git a/models/fasteroid/bull/lcd1.dx90.vtx b/models/fasteroid/bull/lcd1.dx90.vtx new file mode 100644 index 00000000..9fb21d2e Binary files /dev/null and b/models/fasteroid/bull/lcd1.dx90.vtx differ diff --git a/models/fasteroid/bull/lcd1.mdl b/models/fasteroid/bull/lcd1.mdl new file mode 100644 index 00000000..1b0b979f Binary files /dev/null and b/models/fasteroid/bull/lcd1.mdl differ diff --git a/models/fasteroid/bull/lcd1.phy b/models/fasteroid/bull/lcd1.phy new file mode 100644 index 00000000..d7df85a5 Binary files /dev/null and b/models/fasteroid/bull/lcd1.phy differ diff --git a/models/fasteroid/bull/lcd1.sw.vtx b/models/fasteroid/bull/lcd1.sw.vtx new file mode 100644 index 00000000..182267a8 Binary files /dev/null and b/models/fasteroid/bull/lcd1.sw.vtx differ diff --git a/models/fasteroid/bull/lcd1.vvd b/models/fasteroid/bull/lcd1.vvd new file mode 100644 index 00000000..b3a55052 Binary files /dev/null and b/models/fasteroid/bull/lcd1.vvd differ diff --git a/models/fasteroid/bull/lcd2.dx80.vtx b/models/fasteroid/bull/lcd2.dx80.vtx new file mode 100644 index 00000000..285a9f7e Binary files /dev/null and b/models/fasteroid/bull/lcd2.dx80.vtx differ diff --git a/models/fasteroid/bull/lcd2.dx90.vtx b/models/fasteroid/bull/lcd2.dx90.vtx new file mode 100644 index 00000000..3dbcca6a Binary files /dev/null and b/models/fasteroid/bull/lcd2.dx90.vtx differ diff --git a/models/fasteroid/bull/lcd2.mdl b/models/fasteroid/bull/lcd2.mdl new file mode 100644 index 00000000..291cfc11 Binary files /dev/null and b/models/fasteroid/bull/lcd2.mdl differ diff --git a/models/fasteroid/bull/lcd2.phy b/models/fasteroid/bull/lcd2.phy new file mode 100644 index 00000000..719ddbc4 Binary files /dev/null and b/models/fasteroid/bull/lcd2.phy differ diff --git a/models/fasteroid/bull/lcd2.sw.vtx b/models/fasteroid/bull/lcd2.sw.vtx new file mode 100644 index 00000000..e258a41e Binary files /dev/null and b/models/fasteroid/bull/lcd2.sw.vtx differ diff --git a/models/fasteroid/bull/lcd2.vvd b/models/fasteroid/bull/lcd2.vvd new file mode 100644 index 00000000..4204ebc7 Binary files /dev/null and b/models/fasteroid/bull/lcd2.vvd differ diff --git a/models/fasteroid/bull/lcd3.dx80.vtx b/models/fasteroid/bull/lcd3.dx80.vtx new file mode 100644 index 00000000..f8e78f31 Binary files /dev/null and b/models/fasteroid/bull/lcd3.dx80.vtx differ diff --git a/models/fasteroid/bull/lcd3.dx90.vtx b/models/fasteroid/bull/lcd3.dx90.vtx new file mode 100644 index 00000000..96045d06 Binary files /dev/null and b/models/fasteroid/bull/lcd3.dx90.vtx differ diff --git a/models/fasteroid/bull/lcd3.mdl b/models/fasteroid/bull/lcd3.mdl new file mode 100644 index 00000000..0ee7bee0 Binary files /dev/null and b/models/fasteroid/bull/lcd3.mdl differ diff --git a/models/fasteroid/bull/lcd3.phy b/models/fasteroid/bull/lcd3.phy new file mode 100644 index 00000000..6b1111ad Binary files /dev/null and b/models/fasteroid/bull/lcd3.phy differ diff --git a/models/fasteroid/bull/lcd3.sw.vtx b/models/fasteroid/bull/lcd3.sw.vtx new file mode 100644 index 00000000..64948611 Binary files /dev/null and b/models/fasteroid/bull/lcd3.sw.vtx differ diff --git a/models/fasteroid/bull/lcd3.vvd b/models/fasteroid/bull/lcd3.vvd new file mode 100644 index 00000000..78c9e07b Binary files /dev/null and b/models/fasteroid/bull/lcd3.vvd differ diff --git a/models/fasteroid/bull/lcd4.dx80.vtx b/models/fasteroid/bull/lcd4.dx80.vtx new file mode 100644 index 00000000..125169c7 Binary files /dev/null and b/models/fasteroid/bull/lcd4.dx80.vtx differ diff --git a/models/fasteroid/bull/lcd4.dx90.vtx b/models/fasteroid/bull/lcd4.dx90.vtx new file mode 100644 index 00000000..c9bf5b46 Binary files /dev/null and b/models/fasteroid/bull/lcd4.dx90.vtx differ diff --git a/models/fasteroid/bull/lcd4.mdl b/models/fasteroid/bull/lcd4.mdl new file mode 100644 index 00000000..179015db Binary files /dev/null and b/models/fasteroid/bull/lcd4.mdl differ diff --git a/models/fasteroid/bull/lcd4.phy b/models/fasteroid/bull/lcd4.phy new file mode 100644 index 00000000..90d81bf7 Binary files /dev/null and b/models/fasteroid/bull/lcd4.phy differ diff --git a/models/fasteroid/bull/lcd4.sw.vtx b/models/fasteroid/bull/lcd4.sw.vtx new file mode 100644 index 00000000..f6380bf6 Binary files /dev/null and b/models/fasteroid/bull/lcd4.sw.vtx differ diff --git a/models/fasteroid/bull/lcd4.vvd b/models/fasteroid/bull/lcd4.vvd new file mode 100644 index 00000000..7566392e Binary files /dev/null and b/models/fasteroid/bull/lcd4.vvd differ diff --git a/models/fasteroid/bull/lcd5.dx80.vtx b/models/fasteroid/bull/lcd5.dx80.vtx new file mode 100644 index 00000000..fec88ee1 Binary files /dev/null and b/models/fasteroid/bull/lcd5.dx80.vtx differ diff --git a/models/fasteroid/bull/lcd5.dx90.vtx b/models/fasteroid/bull/lcd5.dx90.vtx new file mode 100644 index 00000000..a2348ffb Binary files /dev/null and b/models/fasteroid/bull/lcd5.dx90.vtx differ diff --git a/models/fasteroid/bull/lcd5.mdl b/models/fasteroid/bull/lcd5.mdl new file mode 100644 index 00000000..816567bd Binary files /dev/null and b/models/fasteroid/bull/lcd5.mdl differ diff --git a/models/fasteroid/bull/lcd5.phy b/models/fasteroid/bull/lcd5.phy new file mode 100644 index 00000000..462c3779 Binary files /dev/null and b/models/fasteroid/bull/lcd5.phy differ diff --git a/models/fasteroid/bull/lcd5.sw.vtx b/models/fasteroid/bull/lcd5.sw.vtx new file mode 100644 index 00000000..2a0736b6 Binary files /dev/null and b/models/fasteroid/bull/lcd5.sw.vtx differ diff --git a/models/fasteroid/bull/lcd5.vvd b/models/fasteroid/bull/lcd5.vvd new file mode 100644 index 00000000..4fbefdb3 Binary files /dev/null and b/models/fasteroid/bull/lcd5.vvd differ diff --git a/resource/fonts/alphalcd.ttf b/resource/fonts/alphalcd.ttf new file mode 100644 index 00000000..d800c63c Binary files /dev/null and b/resource/fonts/alphalcd.ttf differ