From ebb2ba9688df304637fa6fcac28243f853a0169a Mon Sep 17 00:00:00 2001 From: Denneisk Date: Wed, 7 Jun 2023 17:29:22 -0400 Subject: [PATCH 01/28] Create EGP object type, objectify EGP functions. --- lua/entities/gmod_wire_egp/cl_init.lua | 12 +- .../lib/egplib/objectcontrol.lua | 35 +- .../gmod_wire_egp/lib/egplib/parenting.lua | 166 +++--- .../lib/egplib/transmitreceive.lua | 10 +- .../lib/egplib/usefulfunctions.lua | 28 +- .../gmod_wire_egp/lib/objects/box.lua | 6 +- .../gmod_wire_egp/lib/objects/circle.lua | 4 +- .../gmod_wire_egp/lib/objects/poly.lua | 54 +- .../gmod_wire_egp/lib/objects/polyoutline.lua | 38 +- .../gmod_wire_egp/lib/objects/roundedbox.lua | 6 +- .../gmod_wire_egp/lib/objects/wedge.lua | 4 +- .../core/egpfunctions.lua | 116 ++-- .../gmod_wire_expression2/core/egpobjects.lua | 501 ++++++++++++++++++ .../gmod_wire_expression2/core/extloader.lua | 1 + 14 files changed, 786 insertions(+), 195 deletions(-) create mode 100644 lua/entities/gmod_wire_expression2/core/egpobjects.lua diff --git a/lua/entities/gmod_wire_egp/cl_init.lua b/lua/entities/gmod_wire_egp/cl_init.lua index 66a6ee1dc0..6e702031e6 100644 --- a/lua/entities/gmod_wire_egp/cl_init.lua +++ b/lua/entities/gmod_wire_egp/cl_init.lua @@ -33,12 +33,12 @@ function ENT:_EGP_Update( bool ) for k,v in pairs( Table ) do if (v.parent == -1) then self.UpdateConstantly = true end -- Check if an object is parented to the cursor - if (v.parent and v.parent ~= 0) then - if (not v.IsParented) then EGP:SetParent( self, v.index, v.parent ) end - local _, data = EGP:GetGlobalPos( self, v.index ) - EGP:EditObject( v, data ) - elseif ((not v.parent or v.parent == 0) and v.IsParented) then - EGP:UnParent( self, v.index ) + if v.parent and v.parent ~= 0 then + if (not v.IsParented) then EGP:SetParent(self, v, v.parent) end + local _, data = EGP:GetGlobalPos(self, v) + v:EditObject(data) + elseif v.parent == 0 and v.IsParented then + EGP:UnParent(self, v.index) end local oldtex = EGP:SetMaterial( v.material ) diff --git a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua index 27fb123217..47c0dd1e38 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua @@ -22,6 +22,7 @@ EGP.Objects.Base.filtering = TEXFILTER.ANISOTROPIC EGP.Objects.Base.material = "" if CLIENT then EGP.Objects.Base.material = false end EGP.Objects.Base.parent = 0 +EGP.Objects.Base.EGP = NULL -- EGP entity parent EGP.Objects.Base.Transmit = function( self ) EGP:SendPosSize( self ) EGP:SendColor( self ) @@ -41,9 +42,34 @@ end EGP.Objects.Base.DataStreamInfo = function( self ) return { x = self.x, y = self.y, w = self.w, h = self.h, r = self.r, g = self.g, b = self.b, a = self.a, material = self.material, filtering = self.filtering, parent = self.parent } end -function EGP.Objects.Base:Contains(point) +function EGP.Objects.Base:Contains(x, y) return false end +function EGP.Objects.Base:EditObject(args) + local ret = false + for k, v in pairs(args) do + if self[k] ~= nil and self[k] ~= v then + self[k] = v + ret = true + end + end + return ret +end +EGP.Objects.Base.Initialize = EGP.Objects.Base.EditObject +function EGP.Objects.Base:SetPos(x, y) + local ret = false + if self.x ~= x then self.x, ret = x, true end + if self.y ~= y then self.y, ret = y, true end + return ret +end +function EGP.Objects.Base:Set(member, value) + if self[member] and self[member] ~= value then + self[member] = value + return true + else + return false + end +end ---------------------------- -- Get Object @@ -201,21 +227,22 @@ function EGP:CreateObject( Ent, ObjID, Settings ) end if SERVER then Settings.index = math.Round(math.Clamp(Settings.index or 1, 1, self.ConVars.MaxObjects:GetInt())) end + Settings.EGP = Ent local bool, k, v = self:HasObject( Ent, Settings.index ) if (bool) then -- Already exists. Change settings: if v.ID ~= ObjID then -- Not the same kind of object, create new local Obj = self:GetObjectByID( ObjID ) - self:EditObject( Obj, Settings ) + Obj:Initialize(Settings) Obj.index = Settings.index Ent.RenderTable[k] = Obj return true, Obj else - return self:EditObject( v, Settings ), v + return v:EditObject(Settings), v end else -- Did not exist. Create: local Obj = self:GetObjectByID( ObjID ) - self:EditObject( Obj, Settings ) + Obj:Initialize(Settings) Obj.index = Settings.index table.insert( Ent.RenderTable, Obj ) return true, Obj diff --git a/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua b/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua index 73b9fd16c1..5d2e69242d 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua @@ -91,94 +91,87 @@ EGP.ParentingFuncs.getCenterFromPos = getCenterFromPos -- (returns true if obj has vertices, false if not, followed by the new position data) function EGP:GetGlobalPos( Ent, index ) - local bool, k, v = self:HasObject( Ent, index ) - if (bool) then - if (v.verticesindex) then -- Object has vertices - if (v.parent and v.parent ~= 0) then -- Object is parented - if (v.parent == -1) then -- object is parented to the cursor - local xy = {0,0} - if (CLIENT) then - xy = self:EGPCursor( Ent, LocalPlayer() ) + local bool, obj + if istable(index) then + obj = index + bool = true + else + bool, _, obj = self:HasObject(Ent, index) + end + if bool then + if obj.verticesindex then -- Object has vertices + if obj.parent and obj.parent ~= 0 then -- Object is parented + local data, ret + if obj.parent == -1 then -- object is parented to the cursor + local xy = { 0, 0 } + if CLIENT then + xy = self:EGPCursor(Ent, LocalPlayer()) end local x, y = xy[1], xy[2] - local r = makeArray( v ) - for i=1,#r,2 do + local r = makeArray(obj) + for i = 1, #r, 2 do local x_ = r[i] - local y_ = r[i+1] - local vec, ang = LocalToWorld( Vector( x_, y_, 0 ), Angle(), Vector( x, y, 0 ), Angle() ) + local y_ = r[i + 1] + local vec = LocalToWorld(Vector(x_, y_, 0), Angle(0, obj._angle or 0, 0), Vector(x, y, 0), angle_zero) r[i] = vec.x - r[i+1] = vec.y + r[i + 1] = vec.y end - local ret = {} - if isstring(v.verticesindex) then - local temp = makeTable( v, r ) - addUV( v, temp ) - ret = { [v.verticesindex] = temp } - else ret = makeTable( v, r ) end + + if isstring(obj.verticesindex) then + local temp = makeTable( obj, r ) + addUV( obj, temp ) + ret = { [obj.verticesindex] = temp } + else ret = makeTable(obj, r) end + local vec, ang = LocalToWorld(Vector(obj._x, obj._y, 0), Angle(0, obj._angle or 0, 0), Vector(x, y, 0), Angle(0, -data.angle or 0, 0)) + ret.x, ret.y, ret.angle = vec.x, vec.y, -ang.y return true, ret else - local hasVertices, data = self:GetGlobalPos( Ent, v.parent ) - if (hasVertices) then -- obj and parent have vertices - local _, _, prnt = self:HasObject( Ent, v.parent ) - local centerx, centery = getCenter( makeArray( prnt, true ) ) - local temp = makeArray( v ) - for i=1,#temp,2 do - temp[i] = centerx + temp[i] - temp[i+1] = centery + temp[i+1] - end - local ret = {} - if isstring(v.verticesindex) then ret = { [v.verticesindex] = makeTable( v, temp ) } else ret = makeTable( v, temp ) end - return true, ret - else -- obj has vertices, parent does not - local x, y, ang = data.x, data.y, data.angle - local r = makeArray( v ) - for i=1,#r,2 do - local x_ = r[i] - local y_ = r[i+1] - local vec, ang = LocalToWorld( Vector( x_, y_, 0 ), Angle( 0, 0, 0 ), Vector( x, y, 0 ), Angle( 0, -ang, 0 ) ) - r[i] = vec.x - r[i+1] = vec.y - end - local ret = {} - if isstring(v.verticesindex) then - local temp = makeTable( v, r ) - addUV( v, temp ) - ret = { [v.verticesindex] = temp } - else ret = makeTable( v, r ) end - return true, ret + local _, _, prnt = self:HasObject(Ent, obj.parent) + local _, data = self:GetGlobalPos(Ent, prnt) + local x, y, ang = data.x, data.y, data.angle or 0 + local objang = obj._angle or 0 + local temp = makeArray( obj ) + for i = 1, #temp, 2 do + local x_ = temp[i] + local y_ = temp[i + 1] + local vec = LocalToWorld(Vector(x_, y_, 0), Angle(0, objang, 0), Vector(x, y, 0), Angle(0, -ang, 0)) + temp[i] = vec.x + temp[i + 1] = vec.y end + + if isstring(obj.verticesindex) then ret = { [obj.verticesindex] = makeTable(obj, temp) } else ret = makeTable(obj, temp) end + local vec, ang = LocalToWorld(Vector(obj._x, obj._y, 0), Angle(0, objang, 0), Vector(x, y, 0), Angle(0, -ang, 0)) + ret.x, ret.y, ret.angle = vec.x, vec.y, -ang.y + return true, ret end - local ret = {} - if isstring(v.verticesindex) then ret = { [v.verticesindex] = makeTable( v, makeArray( v ) ) } else ret = makeTable( v, makeArray( v ) ) end + + if isstring(obj.verticesindex) then ret = { [obj.verticesindex] = makeTable(obj, makeArray(obj)) } else ret = makeTable(obj, makeArray(obj)) end + local vec, ang = LocalToWorld(Vector(obj._x, obj._y, 0), Angle(0, obj._angle or 0, 0), Vector(data.x, data.y, 0), Angle(0, -data.angle, 0)) + ret.x, ret.y, ret.angle = vec.x, vec.y, -ang.y return true, ret end - local ret = {} - if isstring(v.verticesindex) then ret = { [v.verticesindex] = makeTable( v, makeArray( v ) ) } else ret = makeTable( v, makeArray( v ) ) end + local ret + if isstring(obj.verticesindex) then ret = { [obj.verticesindex] = makeTable( obj, makeArray( obj ) ) } else ret = makeTable( obj, makeArray( obj ) ) end + ret.x, ret.y, ret.angle = obj.x, obj.y, obj.angle return true, ret - else -- Object does not have vertices, parent does not - if (v.parent and v.parent ~= 0) then -- Object is parented - if (v.parent == -1) then -- Object is parented to the cursor - local xy = {0,0} + else -- Object does not have vertices + if obj.parent and obj.parent ~= 0 then -- Object is parented + if obj.parent == -1 then -- Object is parented to the cursor + local xy = { 0, 0 } if (CLIENT) then xy = self:EGPCursor( Ent, LocalPlayer() ) end local x, y = xy[1], xy[2] - local vec, ang = LocalToWorld( Vector( v._x, v._y, 0 ), Angle( 0, v._angle or 0, 0 ), Vector( x, y, 0 ), Angle() ) + local vec, ang = LocalToWorld( Vector( obj._x, obj._y, 0 ), Angle( 0, obj._angle or 0, 0 ), Vector( x, y, 0 ), angle_zero ) return false, { x = vec.x, y = vec.y, angle = -ang.y } else - local hasVertices, data = self:GetGlobalPos( Ent, v.parent ) - if (hasVertices) then -- obj does not have vertices, parent does - local _, _, prnt = self:HasObject( Ent, v.parent ) - local centerx, centery = getCenter( makeArray( prnt, true ) ) - return false, { x = (v._x or v.x) + centerx, y = (v._y or v.y) + centery, angle = -(v._angle or v.angle) } - else -- Niether have vertices - local x, y, ang = data.x, data.y, data.angle - local vec, ang = LocalToWorld( Vector( v._x, v._y, 0 ), Angle( 0, v._angle or 0, 0 ), Vector( x, y, 0 ), Angle( 0, -(ang or 0), 0 ) ) - return false, { x = vec.x, y = vec.y, angle = -ang.y } - end + local _, _, prnt = self:HasObject(Ent, obj.parent) + local _, data = self:GetGlobalPos(Ent, prnt) + local vec, ang = LocalToWorld( Vector( obj._x, obj._y, 0 ), Angle( 0, obj._angle or 0, 0 ), Vector( data.x, data.y, 0 ), Angle( 0, -(data.angle or 0), 0 ) ) + return false, { x = vec.x, y = vec.y, angle = -ang.y } end end - return false, { x = v.x, y = v.y, angle = v.angle or 0 } + return false, { x = obj.x, y = obj.y, angle = obj.angle or 0 } end end @@ -200,11 +193,10 @@ function EGP:AddParentIndexes( v ) v["_"..v2[2]] = v[v2[2]] end end - else - v._x = v.x - v._y = v.y - v._angle = v.angle end + v._x = v.x + v._y = v.y + v._angle = v.angle v.IsParented = true end @@ -237,13 +229,22 @@ local function CheckParents( Ent, Obj, parentindex, checked ) end function EGP:SetParent( Ent, index, parentindex ) - local bool, k, v = self:HasObject( Ent, index ) + local bool, v + if isnumber(index) then + bool, _, v = self:HasObject(Ent, index) + else + bool, v = index ~= nil, index + end if (bool) then if (parentindex == -1) then -- Parent to cursor? if (self:EditObject( v, { parent = parentindex } )) then return true, v end else - local bool2, k2, v2 = self:HasObject( Ent, parentindex ) - if (bool2) then + if isnumber(parentindex) then + bool = self:HasObject(Ent, parentindex) + else + bool, parentindex = parentindex ~= nil, parentindex.index + end + if (bool) then self:AddParentIndexes( v ) if (SERVER) then parentindex = math.Clamp(parentindex,1,self.ConVars.MaxObjects:GetInt()) end @@ -272,20 +273,19 @@ function EGP:RemoveParentIndexes( v, hasVertices ) v["_"..v2[2]] = nil end end - else - v._x = nil - v._y = nil - v._angle = nil end + v._x = nil + v._y = nil + v._angle = nil v.IsParented = nil end function EGP:UnParent( Ent, index ) - local bool, k, v = false + local bool, v = false if isnumber(index) then - bool, k, v = self:HasObject( Ent, index ) - elseif istable(index) then - bool = true + bool, _, v = self:HasObject( Ent, index ) + else + bool = istable(index) v = index index = v.index end diff --git a/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua b/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua index c9d97b2cc2..9a97c22d0a 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua @@ -438,7 +438,7 @@ else -- SERVER/CLIENT end end - if (EGP:EditObject( v, { vertices = vertices })) then Ent:EGP_Update() end + if v:EditObject({ vertices = vertices }) then Ent:EGP_Update() end end elseif (Action == "AddVertex") then local index = net.ReadInt(16) @@ -505,7 +505,7 @@ else -- SERVER/CLIENT if (v.OnRemove) then v:OnRemove() end local Obj = self:GetObjectByID( ID ) local data = Obj:Receive() - self:EditObject( Obj, data ) + Obj:Initialize(data) Obj.index = index Ent.RenderTable[k] = Obj if (Obj.OnCreate) then Obj:OnCreate() end @@ -515,7 +515,7 @@ else -- SERVER/CLIENT current_obj = Obj else -- Edit - self:EditObject( v, v:Receive() ) + v:EditObject(v:Receive()) -- If parented, reset the parent indexes if (v.parent and v.parent ~= 0) then @@ -529,7 +529,7 @@ else -- SERVER/CLIENT end else -- Object does not exist. Create new local Obj = self:GetObjectByID( ID ) - self:EditObject( Obj, Obj:Receive() ) + Obj:Initialize(Obj:Receive()) Obj.index = index if (Obj.OnCreate) then Obj:OnCreate() end Ent.RenderTable[#Ent.RenderTable+1] = Obj--table.insert( Ent.RenderTable, Obj ) @@ -680,7 +680,7 @@ else end for _,v in pairs( Objects ) do local Obj = self:GetObjectByID(v.ID) - self:EditObject( Obj, v.Settings ) + Obj:Initialize(v.Settings) -- If parented, reset the parent indexes if (Obj.parent and Obj.parent ~= 0) then self:AddParentIndexes( Obj ) diff --git a/lua/entities/gmod_wire_egp/lib/egplib/usefulfunctions.lua b/lua/entities/gmod_wire_egp/lib/egplib/usefulfunctions.lua index ac8473517b..2753eb2128 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/usefulfunctions.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/usefulfunctions.lua @@ -93,32 +93,16 @@ function EGP:MoveTopLeft(ent, obj) if obj.IsParented then local bool, _, parent = self:HasObject(ent, obj.parent) if bool and parent.CanTopLeft and parent.w and parent.h then - if isstring(obj.verticesindex) then - local vertices = {} - local w, h = parent.w / 2, parent.h / 2 - for i, v in ipairs(obj[obj.verticesindex]) do - vertices[i] = { x = v.x - w, y = v.y - h } - end - t = { vertices = vertices } - elseif obj.verticesindex ~= nil then - t = {} - local w, h = parent.w / 2, parent.h / 2 - for i, v in ipairs(obj.verticesindex) do - t[v[1]] = obj[v[1]] - w - t[v[2]] = obj[v[2]] - h - end - else - if not t then t = { x = obj.x, y = obj.y, angle = obj.angle } end - t.x = t.x - parent.w / 2 - t.y = t.y - parent.h / 2 - end + if not t then t = { x = obj.x, y = obj.y, angle = obj.angle } end + t.x = t.x - parent.w / 2 + t.y = t.y - parent.h / 2 end if not t then t = { angle = obj.angle } end if t.angle then t.angle = -t.angle end end if t then - self:EditObject(obj, t) + obj:EditObject(t) end end @@ -473,8 +457,8 @@ function EGP:EGPCursor( this, ply ) return ReturnFailure( this ) end -function EGP.WorldToLocal(egp, object, x, y) - local _, realpos = EGP:GetGlobalPos(egp, object.index) +function EGP.WorldToLocal(object, x, y) + local _, realpos = EGP:GetGlobalPos(object.EGP, object) x, y = x - realpos.x, y - realpos.y local theta = math.rad(realpos.angle) diff --git a/lua/entities/gmod_wire_egp/lib/objects/box.lua b/lua/entities/gmod_wire_egp/lib/objects/box.lua index e4589988ca..819a6e8d9b 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/box.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/box.lua @@ -24,11 +24,11 @@ Obj.DataStreamInfo = function( self ) table.Merge( tbl, { angle = self.angle } ) return tbl end -function Obj:Contains(egp, x, y) - x, y = EGP.WorldToLocal(egp, self, x, y) +function Obj:Contains(x, y) + x, y = EGP.WorldToLocal(self, x, y) local w, h = self.w / 2, self.h / 2 - if egp.TopLeft then x, y = x - w, y - h end + if self.EGP.TopLeft then x, y = x - w, y - h end return -w <= x and x <= w and -h <= y and y <= h diff --git a/lua/entities/gmod_wire_egp/lib/objects/circle.lua b/lua/entities/gmod_wire_egp/lib/objects/circle.lua index da3a1b6ffa..eafc98153e 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/circle.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/circle.lua @@ -48,9 +48,9 @@ Obj.DataStreamInfo = function( self ) table.Merge( tbl, { angle = self.angle, fidelity = self.fidelity } ) return tbl end -function Obj:Contains(egp, x, y) +function Obj:Contains(x, y) -- Just do this directly since angle doesn't affect circles - local _, realpos = EGP:GetGlobalPos(egp, self.index) + local _, realpos = EGP:GetGlobalPos(self.EGP, self) x, y = (x - realpos.x) / self.w, (y - realpos.y) / self.h return x * x + y * y <= 1 end diff --git a/lua/entities/gmod_wire_egp/lib/objects/poly.lua b/lua/entities/gmod_wire_egp/lib/objects/poly.lua index e0a2355dd2..c88bfa1b16 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/poly.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/poly.lua @@ -2,8 +2,9 @@ local Obj = EGP:NewObject( "Poly" ) Obj.w = nil Obj.h = nil -Obj.x = nil -Obj.y = nil +Obj.x = 0 +Obj.y = 0 +Obj.angle = 0 Obj.vertices = {} Obj.verticesindex = "vertices" Obj.HasUV = true @@ -37,9 +38,14 @@ Obj.Transmit = function( self, Ent, ply ) end net.WriteUInt(math.Clamp(self.filtering,0,3), 2) net.WriteInt( self.parent, 16 ) + net.WriteInt(self.angle % 360, 10) + net.WriteInt(self.x, 16) + net.WriteInt(self.y, 16) EGP:SendMaterial( self ) EGP:SendColor( self ) + end + Obj.Receive = function( self ) local tbl = {} tbl.vertices = {} @@ -48,6 +54,9 @@ Obj.Receive = function( self ) end tbl.filtering = net.ReadUInt(2) tbl.parent = net.ReadInt(16) + tbl.angle = net.ReadInt(10) + tbl.x = net.ReadInt(16) + tbl.y = net.ReadInt(16) EGP:ReceiveMaterial( tbl ) EGP:ReceiveColor( tbl, self ) return tbl @@ -56,11 +65,16 @@ Obj.DataStreamInfo = function( self ) return { vertices = self.vertices, material = self.material, r = self.r, g = self.g, b = self.b, a = self.a, filtering = self.filtering, parent = self.parent } end -function Obj:Contains(egp, x, y) +function Obj:Initialize(args) + self:EditObject(args) + self.x, self.y = EGP.ParentingFuncs.getCenterFromPos(self) +end + +function Obj:Contains(x, y) if #self.vertices < 3 then return false end -- Convert into {x,y} format that poly uses. local point = { x = x, y = y } - local _, realpos = EGP:GetGlobalPos(egp, self.index) + local _, realpos = EGP:GetGlobalPos(self.EGP, self) local vertices = realpos.vertices -- To check whether a point is in the polygon, we check whether it's to the @@ -79,3 +93,35 @@ function Obj:Contains(egp, x, y) end return inside(vertices[#vertices], vertices[1], point) end + +function Obj:EditObject(args) + local ret = false + if args.x or args.y or args.angle then + ret = self:SetPos(args.x or self.x, args.y or self.y, args.angle or self.angle) + args.x = nil + args.y = nil + args.angle = nil + if args._x then args._x = nil args._y = nil args._angle = nil end + end + for k, v in pairs(args) do + if self[k] ~= nil and self[k] ~= v then + self[k] = v + ret = true + end + end + return ret +end + +function Obj:SetPos(x, y, angle) + local sx, sy, sa = self.x, self.y, self.angle + if not angle then angle = sa end + if sx == x and sy == y and sa == angle then return false end + for i, v in ipairs(self.vertices) do + local vec = LocalToWorld(Vector(v.x - sx, v.y - sy, 0), Angle(0, sa, 0), Vector(x, y, 0), Angle(0, sa - angle, 0)) + v.x = vec.x + v.y = vec.y + end + self.x, self.y, self.angle = x, y, angle + if self._x then self._x, self._y, self._angle = x, y, angle end + return true +end diff --git a/lua/entities/gmod_wire_egp/lib/objects/polyoutline.lua b/lua/entities/gmod_wire_egp/lib/objects/polyoutline.lua index d590cd6f8a..7ca405d1c1 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/polyoutline.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/polyoutline.lua @@ -2,11 +2,13 @@ local Obj = EGP:NewObject( "PolyOutline" ) Obj.w = nil Obj.h = nil -Obj.x = nil -Obj.y = nil +Obj.x = 0 +Obj.y = 0 +Obj.angle = 0 Obj.vertices = {} Obj.verticesindex = "vertices" Obj.size = 1 + Obj.Draw = function( self ) local n = #self.vertices if (self.a>0 and n>0 and self.size>0) then @@ -40,3 +42,35 @@ end Obj.DataStreamInfo = function( self ) return { vertices = self.vertices, material = self.material, r = self.r, g = self.g, b = self.b, a = self.a, parent = self.parent } end + +function Obj:Initialize(args) + self:EditObject(args) + self.x, self.y = EGP.ParentingFuncs.getCenterFromPos(self) +end + +function Obj:EditObject(args) + local ret = false + if args.x or args.y then + ret = self:SetPos(args.x or self.x, args.y or self.y) + args.x = nil + args.y = nil + end + for k, v in pairs(args) do + if self[k] ~= nil and self[k] ~= v then + self[k] = v + ret = true + end + end + return ret +end + +function Obj:SetPos(x, y) + local sx, sy = self.x, self.y + if sx == x and sy == y then return false end + for i, v in ipairs(self.vertices) do + v.x = v.x - sx + x + v.y = v.y - sy + y + end + self.x, self.y = x, y + return true +end \ No newline at end of file diff --git a/lua/entities/gmod_wire_egp/lib/objects/roundedbox.lua b/lua/entities/gmod_wire_egp/lib/objects/roundedbox.lua index ef5593f145..7a0fe7c950 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/roundedbox.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/roundedbox.lua @@ -52,11 +52,11 @@ Obj.DataStreamInfo = function( self ) table.Merge( tbl, { angle = self.angle, radius = self.radius, fidelity = self.fidelity } ) return tbl end -function Obj:Contains(egp, x, y) - x, y = EGP.WorldToLocal(egp, self, x, y) +function Obj:Contains(x, y) + x, y = EGP.WorldToLocal(self, x, y) local w, h = self.w / 2, self.h / 2 - if egp.TopLeft then x, y = x - w, y - h end + if self.EGP.TopLeft then x, y = x - w, y - h end local r = math.min(math.min(w, h), self.radius) x, y = math.abs(x), math.abs(y) diff --git a/lua/entities/gmod_wire_egp/lib/objects/wedge.lua b/lua/entities/gmod_wire_egp/lib/objects/wedge.lua index 73f6dd91c2..4f18cea6fc 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/wedge.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/wedge.lua @@ -54,8 +54,8 @@ Obj.DataStreamInfo = function( self ) table.Merge( tbl, { angle = self.angle, size = self.size, fidelity = self.fidelity } ) return tbl end -function Obj:Contains(egp, x, y) - x, y = EGP.WorldToLocal(egp, self, x, y) +function Obj:Contains(x, y) + x, y = EGP.WorldToLocal(self, x, y) x, y = x / self.w, y / self.h if x * x + y * y > 1 then return false end diff --git a/lua/entities/gmod_wire_expression2/core/egpfunctions.lua b/lua/entities/gmod_wire_expression2/core/egpfunctions.lua index 5ba6aa4c8b..bfa56aa46a 100644 --- a/lua/entities/gmod_wire_expression2/core/egpfunctions.lua +++ b/lua/entities/gmod_wire_expression2/core/egpfunctions.lua @@ -128,28 +128,28 @@ __e2setcost(15) -------------------------------------------------------- -- Box -------------------------------------------------------- -e2function void wirelink:egpBox( number index, vector2 pos, vector2 size ) +e2function egpobject wirelink:egpBox( number index, vector2 pos, vector2 size ) if (!EGP:IsAllowed( self, this )) then return end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["Box"], { index = index, w = size[1], h = size[2], x = pos[1], y = pos[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end -------------------------------------------------------- -- BoxOutline -------------------------------------------------------- -e2function void wirelink:egpBoxOutline( number index, vector2 pos, vector2 size ) +e2function egpobject wirelink:egpBoxOutline( number index, vector2 pos, vector2 size ) if (!EGP:IsAllowed( self, this )) then return end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["BoxOutline"], { index = index, w = size[1], h = size[2], x = pos[1], y = pos[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end -------------------------------------------------------- -- RoundedBox -------------------------------------------------------- -e2function void wirelink:egpRoundedBox( number index, vector2 pos, vector2 size ) +e2function egpobject wirelink:egpRoundedBox( number index, vector2 pos, vector2 size ) if (!EGP:IsAllowed( self, this )) then return end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["RoundedBox"], { index = index, w = size[1], h = size[2], x = pos[1], y = pos[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end e2function void wirelink:egpRadius( number index, number radius ) @@ -163,25 +163,25 @@ end -------------------------------------------------------- -- RoundedBoxOutline -------------------------------------------------------- -e2function void wirelink:egpRoundedBoxOutline( number index, vector2 pos, vector2 size ) +e2function egpobject wirelink:egpRoundedBoxOutline( number index, vector2 pos, vector2 size ) if (!EGP:IsAllowed( self, this )) then return end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["RoundedBoxOutline"], { index = index, w = size[1], h = size[2], x = pos[1], y = pos[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end -------------------------------------------------------- -- Text -------------------------------------------------------- -e2function void wirelink:egpText( number index, string text, vector2 pos ) +e2function egpobject wirelink:egpText( number index, string text, vector2 pos ) if (!EGP:IsAllowed( self, this )) then return end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["Text"], { index = index, text = text, x = pos[1], y = pos[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end -e2function void wirelink:egpTextLayout( number index, string text, vector2 pos, vector2 size ) +e2function egpobject wirelink:egpTextLayout( number index, string text, vector2 pos, vector2 size ) if (!EGP:IsAllowed( self, this )) then return end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["TextLayout"], { index = index, text = text, x = pos[1], y = pos[2], w = size[1], h = size[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end __e2setcost(10) @@ -273,7 +273,7 @@ __e2setcost(20) local function maxvertices() return EGP.ConVars.MaxVertices:GetInt() end -e2function void wirelink:egpPoly( number index, ...args ) +e2function egpobject wirelink:egpPoly( number index, ...args ) if (!EGP:IsAllowed( self, this )) then return end if (!EGP:ValidEGP( this )) then return self:throw("Invalid wirelink!", nil) end if #args < 3 then return end -- No less than 3 @@ -295,10 +295,10 @@ e2function void wirelink:egpPoly( number index, ...args ) end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["Poly"], { index = index, vertices = vertices }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end -e2function void wirelink:egpPoly( number index, array args ) +e2function egpobject wirelink:egpPoly( number index, array args ) if (!EGP:IsAllowed( self, this )) then return end if (!EGP:ValidEGP( this )) then return self:throw("Invalid wirelink!", nil) end if (#args<3) then return end -- No less than 3 @@ -320,14 +320,14 @@ e2function void wirelink:egpPoly( number index, array args ) end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["Poly"], { index = index, vertices = vertices }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end -------------------------------------------------------- -- PolyOutline -------------------------------------------------------- -e2function void wirelink:egpPolyOutline( number index, ...args ) +e2function egpobject wirelink:egpPolyOutline( number index, ...args ) if (!EGP:IsAllowed( self, this )) then return end if (!EGP:ValidEGP( this )) then return self:throw("Invalid wirelink!", nil) end if #args < 3 then return end -- No less than 3 @@ -349,10 +349,10 @@ e2function void wirelink:egpPolyOutline( number index, ...args ) end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["PolyOutline"], { index = index, vertices = vertices }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return egpobject end end -e2function void wirelink:egpPolyOutline( number index, array args ) +e2function egpobject wirelink:egpPolyOutline( number index, array args ) if (!EGP:IsAllowed( self, this )) then return end if (!EGP:ValidEGP( this )) then return self:throw("Invalid wirelink!", nil) end if (#args<3) then return end -- No less than 3 @@ -374,7 +374,7 @@ e2function void wirelink:egpPolyOutline( number index, array args ) end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["PolyOutline"], { index = index, vertices = vertices }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end e2function void wirelink:egpAddVertices( number index, array args ) @@ -401,7 +401,7 @@ e2function void wirelink:egpAddVertices( number index, array args ) end end - if (EGP:EditObject( v, { vertices = vertices } )) then + if v:EditObject({ vertices = vertices }) then EGP:InsertQueue( this, self.player, EGP._SetVertex, "SetVertex", index, vertices, true ) Update(self,this) end @@ -412,7 +412,7 @@ end -- egpLineStrip (PolyOutline without the final connecting line) -------------------------------------------------------- -e2function void wirelink:egpLineStrip( number index, ...args ) +e2function egpobject wirelink:egpLineStrip( number index, ...args ) if (!EGP:IsAllowed( self, this )) then return end if (!EGP:ValidEGP( this )) then return self:throw("Invalid wirelink!", nil) end if #args < 2 then return end -- No less than 2 @@ -434,10 +434,10 @@ e2function void wirelink:egpLineStrip( number index, ...args ) end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["LineStrip"], { index = index, vertices = vertices }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end -e2function void wirelink:egpLineStrip( number index, array args ) +e2function egpobject wirelink:egpLineStrip( number index, array args ) if (!EGP:IsAllowed( self, this )) then return end if (!EGP:ValidEGP( this )) then return self:throw("Invalid wirelink!", nil) end if (#args<2) then return end -- No less than 2 @@ -459,7 +459,7 @@ e2function void wirelink:egpLineStrip( number index, array args ) end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["LineStrip"], { index = index, vertices = vertices }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end __e2setcost(15) @@ -467,57 +467,57 @@ __e2setcost(15) -------------------------------------------------------- -- Line -------------------------------------------------------- -e2function void wirelink:egpLine( number index, vector2 pos1, vector2 pos2 ) +e2function egpobject wirelink:egpLine( number index, vector2 pos1, vector2 pos2 ) if (!EGP:IsAllowed( self, this )) then return end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["Line"], { index = index, x = pos1[1], y = pos1[2], x2 = pos2[1], y2 = pos2[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end -------------------------------------------------------- -- Circle -------------------------------------------------------- -e2function void wirelink:egpCircle( number index, vector2 pos, vector2 size ) +e2function egpobject wirelink:egpCircle( number index, vector2 pos, vector2 size ) if (!EGP:IsAllowed( self, this )) then return end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["Circle"], { index = index, x = pos[1], y = pos[2], w = size[1], h = size[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end -------------------------------------------------------- -- Circle Outline -------------------------------------------------------- -e2function void wirelink:egpCircleOutline( number index, vector2 pos, vector2 size ) +e2function egpobject wirelink:egpCircleOutline( number index, vector2 pos, vector2 size ) if (!EGP:IsAllowed( self, this )) then return end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["CircleOutline"], { index = index, x = pos[1], y = pos[2], w = size[1], h = size[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end -------------------------------------------------------- -- Triangle -------------------------------------------------------- -e2function void wirelink:egpTriangle( number index, vector2 v1, vector2 v2, vector2 v3 ) +e2function egpobject wirelink:egpTriangle( number index, vector2 v1, vector2 v2, vector2 v3 ) if (!EGP:IsAllowed( self, this )) then return end local vertices = { { x = v1[1], y = v1[2] }, { x = v2[1], y = v2[2] }, { x = v3[1], y = v3[2] } } local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["Poly"], { index = index, vertices = vertices }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end -------------------------------------------------------- -- Triangle Outline -------------------------------------------------------- -e2function void wirelink:egpTriangleOutline( number index, vector2 v1, vector2 v2, vector2 v3 ) +e2function egpobject wirelink:egpTriangleOutline( number index, vector2 v1, vector2 v2, vector2 v3 ) if (!EGP:IsAllowed( self, this )) then return end local vertices = { { x = v1[1], y = v1[2] }, { x = v2[1], y = v2[2] }, { x = v3[1], y = v3[2] } } local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["PolyOutline"], { index = index, vertices = vertices }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end -------------------------------------------------------- -- Wedge -------------------------------------------------------- -e2function void wirelink:egpWedge( number index, vector2 pos, vector2 size ) +e2function egpobject wirelink:egpWedge( number index, vector2 pos, vector2 size ) if (!EGP:IsAllowed( self, this )) then return end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["Wedge"], { index = index, x = pos[1], y = pos[2], w = size[1], h = size[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end --[[ I'm sticking to my policy of not spamming pointless functions. @@ -531,10 +531,10 @@ end -------------------------------------------------------- -- Wedge Outline -------------------------------------------------------- -e2function void wirelink:egpWedgeOutline( number index, vector2 pos, vector2 size ) +e2function egpobject wirelink:egpWedgeOutline( number index, vector2 pos, vector2 size ) if (!EGP:IsAllowed( self, this )) then return end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["WedgeOutline"], { index = index, x = pos[1], y = pos[2], w = size[1], h = size[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end --[[ I'm sticking to my policy of not spamming pointless functions. @@ -548,13 +548,13 @@ end -------------------------------------------------------- -- 3DTracker -------------------------------------------------------- -e2function void wirelink:egp3DTracker( number index, vector pos ) +e2function egpobject wirelink:egp3DTracker( number index, vector pos ) if (!EGP:IsAllowed( self, this )) then return end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["3DTracker"], { index = index, target_x = pos[1], target_y = pos[2], target_z = pos[3], directionality = 0 }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end -e2function void wirelink:egp3DTracker( number index, vector pos, number directionality ) +e2function egpobject wirelink:egp3DTracker( number index, vector pos, number directionality ) if (!EGP:IsAllowed( self, this )) then return end if directionality > 0 then @@ -564,7 +564,7 @@ e2function void wirelink:egp3DTracker( number index, vector pos, number directio end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["3DTracker"], { index = index, target_x = pos[1], target_y = pos[2], target_z = pos[3], directionality = directionality }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end __e2setcost(10) @@ -573,7 +573,7 @@ e2function void wirelink:egpPos( number index, vector pos ) if (!EGP:IsAllowed( self, this )) then return end local bool, k, v = EGP:HasObject( this, index ) if (bool) then - if (EGP:EditObject( v, { target_x = pos[1], target_y = pos[2], target_z = pos[3] } )) then EGP:DoAction( this, self, "SendObject", v ) Update(self,this) end + if (v:EditObject({ target_x = pos[1], target_y = pos[2], target_z = pos[3] })) then EGP:DoAction( this, self, "SendObject", v ) Update(self,this) end end end @@ -590,7 +590,7 @@ e2function void wirelink:egpSize( number index, vector2 size ) if (!EGP:IsAllowed( self, this )) then return end local bool, k, v = EGP:HasObject( this, index ) if (bool) then - if (EGP:EditObject( v, { w = size[1], h = size[2] } )) then EGP:DoAction( this, self, "SendObject", v ) Update(self,this) end + if v:EditObject({ w = size[1], h = size[2] }) then EGP:DoAction( this, self, "SendObject", v ) Update(self,this) end end end @@ -607,11 +607,8 @@ end ---------------------------- e2function void wirelink:egpPos( number index, vector2 pos ) if (!EGP:IsAllowed( self, this )) then return end - local bool, k, v = EGP:HasObject( this, index ) - if (bool) then - local x, y = pos[1], pos[2] - if (EGP:EditObject( v, { x = x, y = y, _x = x, _y = y } )) then EGP:DoAction( this, self, "SendObject", v ) Update(self,this) end - end + local bool, _, v = EGP:HasObject(this, index) + if bool and v:SetPos(pos[1], pos[2]) then EGP:DoAction( this, self, "SendObject", v ) Update(self,this) end end ---------------------------- @@ -622,7 +619,7 @@ e2function void wirelink:egpAngle( number index, number angle ) if (!EGP:IsAllowed( self, this )) then return end local bool, k, v = EGP:HasObject( this, index ) if (bool) then - if (EGP:EditObject( v, { angle = angle, _angle = angle } )) then EGP:DoAction( this, self, "SendObject", v ) Update(self,this) end + if v:EditObject( { angle = angle, _angle = angle }) then EGP:DoAction( this, self, "SendObject", v ) Update(self,this) end end end @@ -646,7 +643,7 @@ e2function void wirelink:egpAngle( number index, vector2 worldpos, vector2 axisp local t = { x = x, _x = x, y = y, _y = y } if (v.angle) then t.angle, t._angle = angle, angle end - if (EGP:EditObject( v, t )) then EGP:DoAction( this, self, "SendObject", v ) Update(self,this) end + if v:EditObject(t) then EGP:DoAction( this, self, "SendObject", v ) Update(self,this) end end end end @@ -822,10 +819,6 @@ end __e2setcost(20) e2function vector wirelink:egpGlobalPos( number index ) local hasvertices, posang = EGP:GetGlobalPos( this, index ) - if hasvertices then - local x, y = getCenterFromPos(posang) - return Vector(x , y, 0) - end return Vector(posang.x, posang.y, posang.angle) end @@ -992,20 +985,25 @@ e2function string wirelink:egpObjectType(number index) return "" end +e2function egpobject wirelink:egpObject(number index) + local bool, _, obj = EGP:HasObject(this, index) + return bool and obj or nil +end + -------------------------------------------------------- -- Additional Functions -------------------------------------------------------- __e2setcost(15) -e2function void wirelink:egpCopy( index, fromindex ) +e2function egpobject wirelink:egpCopy( index, fromindex ) if (!EGP:IsAllowed( self, this )) then return end local bool, k, v = EGP:HasObject( this, fromindex ) if (bool) then local copy = table.Copy( v ) copy.index = index local bool2, obj = EGP:CreateObject( this, v.ID, copy, self.player ) - if (bool2) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + if (bool2) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end end @@ -1044,7 +1042,7 @@ __e2setcost(20) --- Returns 1 if the object with specified index contains the specified point. e2function number wirelink:egpObjectContainsPoint(number index, vector2 point) local _, _, object = EGP:HasObject(this, index) - return object and object:Contains(this, point[1], point[2]) and 1 or 0 + return object and object:Contains(point[1], point[2]) and 1 or 0 end __e2setcost(10) diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua new file mode 100644 index 0000000000..123c238109 --- /dev/null +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -0,0 +1,501 @@ +-- +-- File for EGP Object handling in E2. +-- + +local function Update(self, this) + self.data.EGP.UpdatesNeeded[this] = true +end + +local getCenter = EGP.ParentingFuncs.getCenter +local getCenterFromPos = EGP.ParentingFuncs.getCenterFromPos +local makeArray = EGP.ParentingFuncs.makeArray + +---- Type defintion + +registerType("egpobject", "xeo", nil, + nil, + nil, + function(retval) + if retval == nil then return end + if not istable(retval) then error("Return value is neither nil nor a table, but a " .. type(retval) .. "!", 0) end + end, + function(v) + return not istable(v) + end +) + +__e2setcost(2) + +registerOperator("ass", "xeo", "xeo", function(self, args) + local lhs, op2, scope = args[2], args[3], args[4] + local rhs = op2[1](self, op2) + if rhs == nil then return nil end + + local Scope = self.Scopes[scope] + local lookup = Scope.lookup + if not lookup then lookup = {} Scope.lookup = lookup end + if lookup[rhs] then lookup[rhs][lhs] = true else lookup[rhs] = {[lhs] = true} end + + Scope[lhs] = rhs + Scope.vclk[lhs] = true + return rhs +end) + +e2function number operator_is(egpobject egpo) + return (egpo ~= nil and isfunction(egpo.DataStreamInfo)) and 1 or 0 +end + +e2function number operator==(egpobject lhs, egpobject rhs) + return (lhs == rhs) and 1 or 0 +end + +e2function number operator!=(egpobject lhs, egpobject rhs) + return (lhs ~= rhs) and 1 or 0 +end + +---- Functions + +__e2setcost(7) + +---------------------------- +-- Set Text +---------------------------- +e2function void egpobject:egpSetText(string text) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:Set("text", text) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +e2function void egpobject:egpSetText(string text, string font, number size) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:EditObject({ text = text, font = font, size = size }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +---------------------------- +-- Alignment +---------------------------- +e2function void egpobject:egpAlign(number halign) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:Set("halign", math.Clamp(halign, 0, 2)) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +e2function void egpobject:egpAlign(number halign, number valign) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:EditObject({ valign = math.Clamp(valign, 0, 2), halign = math.Clamp(halign, 0, 2) }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +---------------------------- +-- Filtering +---------------------------- +e2function void egpobject:egpFiltering(number filtering) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:Set("filtering", math.Clamp(filtering, 0, 3)) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +---------------------------- +-- Font +---------------------------- +e2function void egpobject:egpFont(string font) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if #font > 30 then return self:throw("Font string is too long!", nil) end + if this:Set("font", font) then EGP:DoAction(egp, self, "SendObject", obj) Update(self, this) end +end + +e2function void egpobject:egpFont(string font, number size) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if #font > 30 then return self:throw("Font string is too long!", nil) end + if this:EditObject({ font = font, size = size }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +-------------------------------------------------------- +-- 3DTracker +-------------------------------------------------------- +__e2setcost(10) + +e2function void egpobject:egpPos(vector pos) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:EditObject({ target_x = pos[1], target_y = pos[2], target_z = pos[3] }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +-------------------------------------------------------- +-- Set functions +-------------------------------------------------------- + +__e2setcost(7) + +---------------------------- +-- Size +---------------------------- +e2function void egpobject:egpSize(vector2 size) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:EditObject({ w = size[1], h = size[2] }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +e2function void egpobject:egpSize(number size) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:Set("size", size) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +---------------------------- +-- Position +---------------------------- +e2function void egpobject:egpPos(vector2 pos) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:SetPos(pos[1], pos[2]) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +---------------------------- +-- Angle +---------------------------- +e2function void egpobject:egpAngle(number angle) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:EditObject({ angle = angle, _angle = angle }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +------------- +-- Position & Angle +------------- +e2function void egpobject:egpAngle(vector2 worldpos, vector2 axispos, number angle) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this.x and this.y then + local vec, ang = LocalToWorld(Vector(axispos[1], axispos[2], 0), angle_origin, Vector(worldpos[1], worldpos[2], 0), Angle(0, -angle, 0)) + + local x = vec.x + local y = vec.y + + angle = -ang.yaw + + local t = { x = x, _x = x, y = y, _y = y } + if this.angle then t.angle, t._angle = angle, angle end + + if this:EditObject(t) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end + end +end + +---------------------------- +-- Color +---------------------------- +e2function void egpobject:egpColor(vector4 color) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:EditObject({ r = color[1], g = color[2], b = color[3], a = color[4] }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +e2function void egpobject:egpColor(vector color) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:EditObject({ r = color[1], g = color[2], b = color[3] }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +e2function void egpobject:egpColor(r, g, b, a) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:EditObject({ r = r, g = g, b = b, a = a }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +e2function void egpobject:egpAlpha(number a) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:Set("a", a) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +---------------------------- +-- Material +---------------------------- +e2function void egpobject:egpMaterial(string material) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + material = WireLib.IsValidMaterial(material) + if this:Set("material", material) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +e2function void egpobject:egpMaterialFromScreen(entity gpu) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if gpu and gpu:IsValid() then + if this:Set("material", gpu) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end + end +end + +---------------------------- +-- Fidelity (number of corners for circles and wedges) +---------------------------- +e2function void egpobject:egpFidelity(number fidelity) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:EditObject({ fidelity = math.Clamp(fidelity, 3, 180) }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +e2function number egpobject:egpFidelity() + return this.fidelity or -1 +end + +---------------------------- +-- Parenting +---------------------------- +e2function void egpobject:egpParent(egpobject parent) + if not this or not parent then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if egp ~= parent.EGP then return self:throw("Invalid EGP Object", nil) end + if not EGP:IsAllowed(self, egp) then return end + if EGP:SetParent(egp, this, parent) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +e2function void egpobject:egpParent(number parentindex) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if EGP:SetParent(egp, this, parentindex) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +e2function void wirelink:egpParent(egpobject child, egpobject parent) + if not child or not parent then return self:throw("Invalid EGP Object", nil) end + if not EGP:IsAllowed(self, this) then return end + if EGP:SetParent(this, child, parent) then EGP:DoAction(this, self, "SendObject", child) Update(self, this) end +end + +-- Entity parenting (only for 3Dtracker - does nothing for any other object) +e2function void egpobject:egpParent(entity parent) + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not parent or not parent:IsValid() then return end + if not EGP:IsAllowed(self, egp) then return end + + if this.NeedsConstantUpdate and this.parententity ~= parent then + this.parententity = parent + + EGP:DoAction(egp, self, "SendObject", this) + Update(self, egp) + end +end + +-- Returns the entity a tracker is parented to +e2function entity egpobject:egpTrackerParent() + if not this then return self:throw("Invalid EGP Object", nil) end + return IsValid(this.parententity) and this.parententity or NULL +end + +e2function void egpobject:egpParentToCursor() + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if EGP:SetParent(egp, this, -1) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +e2function void egpobject:egpUnParent() + if not this then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if EGP:UnParent(egp, this) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +e2function number egpobject:egpParentIndex() + if not this then return self:throw("Invalid EGP Object", nil) end + return this.parent or nil +end + +-------------------------------------------------------- +-- Remove +-------------------------------------------------------- +e2function void wirelink:egpRemove(egpobject obj) + if not EGP:IsAllowed(self, this) then return end + if obj then + EGP:DoAction(this, self, "RemoveObject", obj.index) + Update(self, this) + end +end + +e2function void egpobject:egpRemove() + if not this then return end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + + EGP:DoAction(egp, self, "RemoveObject", this.index) + Update(self, egp) +end + +-------------------------------------------------------- +-- Get functions +-------------------------------------------------------- +__e2setcost(20) + +e2function vector egpobject:egpGlobalPos() + if not this then return self:throw("Invalid EGP Object", vector_origin) end + local hasvertices, posang = EGP:GetGlobalPos(this.EGP, this) + if hasvertices then + local x, y = getCenterFromPos(posang) + return Vector(x, y, 0) + end + return Vector(posang.x, posang.y, posang.angle) +end + +e2function array egpobject:egpGlobalVertices() + if not this then return self:throw("Invalid EGP Object", {}) end + local hasvertices, data = EGP:GetGlobalPos(this.EGP, this) + if hasvertices then + if data.vertices then + local ret = {} + for i = 1, #data.vertices do + local v = data.vertices[i] + ret[i] = {v.x, v.y} + self.prf = self.prf + 0.1 + end + return ret + elseif data.x and data.y and data.x2 and data.y2 and data.x3 and data.y3 then + return { { data.x, data.y }, { data.x2, data.y2 }, { data.x3, data.y3 } } + elseif data.x and data.y and data.x2 and data.y2 then + return { {data.x, data.y}, {data.x2, data.y2} } + end + else + return {} + end +end + + +__e2setcost(3) + +e2function vector2 egpobject:egpPos() + if not this then return self:throw("Invalid EGP Object", { -1, -1 }) end + return (this.x and this.y and { this.x, this.y }) or { -1, -1 } +end + +e2function vector2 egpobject:egpSize() + if not this then return self:throw("Invalid EGP Object", { -1, -1 }) end + return (this.w and this.h and { this.w, this.h }) or { -1, -1 } +end + +e2function number egpobject:egpSizeNum() + if not this then return self:throw("Invalid EGP Object", -1) end + return this.size or -1 +end + +e2function vector4 egpobject:egpColor4() + if not this then return self:throw("Invalid EGP Object", { -1, -1, -1, -1 }) end + return (this.r and this.g and this.b and this.a and { this.r, this.g, this.b, this.a }) or { -1, -1, -1, -1 } +end + +e2function vector egpobject:egpColor() + if not this then return self:throw("Invalid EGP Object", -1) end + return (this.r and this.g and this.b and Vector(this.r, this.g, this.b)) or Vector(-1, -1, -1) +end + +e2function number egpobject:egpAlpha() + if not this then return self:throw("Invalid EGP Object", -1) end + return this.a or -1 +end + +e2function number egpobject:egpAngle() + if not this then return self:throw("Invalid EGP Object", -1) end + return this.angle or -1 +end + +e2function string egpobject:egpMaterial() + if not this then return self:throw("Invalid EGP Object", "") end + return this.material or "" +end + +e2function number egpobject:egpRadius() + if not this then return self:throw("Invalid EGP Object", -1) end + return this.radius or -1 +end + +__e2setcost(10) + +e2function array egpobject:egpVertices() + if (this.vertices) then + local ret = {} + for k, v in ipairs(this.vertices) do + ret[k] = { v.x, v.y } + end + return ret + elseif v.x and v.y and v.x2 and v.y2 and v.x3 and v.y3 then + return { {v.x, v.y}, {v.x2, v.y2 }, { v.x3, v.y3 } } + elseif v.x and v.y and v.x2 and v.y2 then + return { {v.x, v.y}, { v.x2, v.y2 } } + else + return {} + end +end + +-------------------------------------------------------- +-- Object Type +-------------------------------------------------------- +__e2setcost(4) + +e2function string egpobject:egpObjectType() + return EGP.Objects.Names_Inverted[this.ID] or "" +end + +-------------------------------------------------------- +-- Additional Functions +-------------------------------------------------------- + +__e2setcost(15) + +e2function egpobject wirelink:egpCopy(number index, egpobject from) + if not EGP:IsAllowed(self, this) then return end + if from then + local copy = table.Copy(from) + copy.index = index + local bool, obj = EGP:CreateObject(this, from.ID, copy, self.player) + if bool then EGP:DoAction(this, self, "SendObject", obj) Update(self, this) return obj end + end +end + +__e2setcost(10) + +e2function number egpobject:egpObjectContainsPoint(vector2 point) + return this and this:Contains(point[1], point[2]) and 1 or 0 +end + +__e2setcost(5) + +e2function egpobject wirelink:egpobject(number index) + if not EGP:IsAllowed(self, this) then return end + local _, _, obj = EGP:HasObject(this, index) + return obj +end + +__e2setcost(2) + +e2function string egpobject:egpObjectType() + return this and EGP.Objects.Names_Inverted[this.ID] or "" +end + +__e2setcost(1) + +e2function egpobject noegpobject() + return nil +end \ No newline at end of file diff --git a/lua/entities/gmod_wire_expression2/core/extloader.lua b/lua/entities/gmod_wire_expression2/core/extloader.lua index a26939bcd2..7d601e0f64 100644 --- a/lua/entities/gmod_wire_expression2/core/extloader.lua +++ b/lua/entities/gmod_wire_expression2/core/extloader.lua @@ -161,6 +161,7 @@ e2_include("functions.lua") e2_include("strfunc.lua") e2_include("steamidconv.lua") e2_include("easings.lua") +e2_include("egpobjects.lua") -- Load serverside files here, they need additional parsing do From b365402c60965f9f2b126d0f8189308a5b4b7394 Mon Sep 17 00:00:00 2001 From: Denneisk Date: Fri, 23 Jun 2023 00:12:56 -0400 Subject: [PATCH 02/28] Finish the rest of the egpobjects --- .../gmod_wire_egp/lib/egplib/parenting.lua | 4 +- .../gmod_wire_egp/lib/objects/line.lua | 37 +++++++++++++- .../gmod_wire_egp/lib/objects/linestrip.lua | 49 +++++++++++++++++-- .../gmod_wire_egp/lib/objects/poly.lua | 15 +++--- .../gmod_wire_egp/lib/objects/polyoutline.lua | 30 +++++++----- .../core/egpfunctions.lua | 3 +- .../gmod_wire_expression2/core/egpobjects.lua | 4 +- 7 files changed, 115 insertions(+), 27 deletions(-) diff --git a/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua b/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua index 5d2e69242d..f6b11d76ae 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua @@ -77,7 +77,7 @@ end EGP.ParentingFuncs.getCenter = getCenter -- Uses the output of GetGlobalPos instead. -local function getCenterFromPos(data) +local function getCenterFrom(data) local centerx, centery = 0, 0 local vertices = data.vertices local n = #vertices @@ -87,7 +87,7 @@ local function getCenterFromPos(data) end return centerx / n, centery / n end -EGP.ParentingFuncs.getCenterFromPos = getCenterFromPos +EGP.getCenterFrom = getCenterFrom -- (returns true if obj has vertices, false if not, followed by the new position data) function EGP:GetGlobalPos( Ent, index ) diff --git a/lua/entities/gmod_wire_egp/lib/objects/line.lua b/lua/entities/gmod_wire_egp/lib/objects/line.lua index fe38586a72..5751104bb3 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/line.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/line.lua @@ -2,6 +2,7 @@ local Obj = EGP:NewObject( "Line" ) Obj.w = nil Obj.h = nil +Obj.angle = 0 Obj.x2 = 0 Obj.y2 = 0 Obj.size = 1 @@ -19,6 +20,7 @@ Obj.Transmit = function( self ) net.WriteInt( self.y2, 16 ) net.WriteInt( self.size, 16 ) net.WriteInt( self.parent, 16 ) + net.WriteInt(self.angle, 10) EGP:SendMaterial( self ) EGP:SendColor( self ) end @@ -30,10 +32,43 @@ Obj.Receive = function( self ) tbl.y2 = net.ReadInt(16) tbl.size = net.ReadInt(16) tbl.parent = net.ReadInt(16) + tbl.angle = net.ReadInt(10) EGP:ReceiveMaterial( tbl ) EGP:ReceiveColor( tbl, self ) return tbl end Obj.DataStreamInfo = function( self ) - return { x = self.x, y = self.y, x2 = self.x2, y2 = self.y2, r = self.r, g = self.g, b = self.b, a = self.a, size = self.size, parent = self.parent } + return { x = self.x, y = self.y, x2 = self.x2, y2 = self.y2, angle = self.angle, r = self.r, g = self.g, b = self.b, a = self.a, size = self.size, parent = self.parent } end + +function Obj:EditObject(args) + local ret = false + if args.x or args.y or args.angle or args.x2 or args.y2 then + ret = self:SetPos(args.x or self.x, args.y or self.y, args.angle or self.angle, args.x2 or self.x2, args.y2 or self.y2) + args.x = nil + args.x2 = nil + args.y = nil + args.y2 = nil + args.angle = nil + if args._x then args._x, args._x2, args._y, args._y2, args._angle = nil, nil, nil, nil, nil end + end + for k, v in pairs(args) do + if self[k] ~= nil and self[k] ~= v then + self[k] = v + ret = true + end + end + return ret +end + +function Obj:SetPos(x, y, angle, x2, y2) + local sx, sx2, sy, sy2, sa = self.x, self.x2, self.y, self.y2, self.angle + if not angle then angle = sa end + if sx == x and sy == y and sa == angle and sx2 == x2 and sy2 == y2 then return false end + local vec = LocalToWorld(Vector(sx2 - sx, sy2 - sy, 0), angle_zero, Vector(x, y, 0), Angle(0, sa - angle, 0)) + + self.x, self.y, self.angle = x, y, angle + self.x2, self.y2 = vec.x, vec.y + if self._x then self._x, self._y, self._angle, self._x2, self._y2 = x, y, angle, x2, y2 end + return true +end \ No newline at end of file diff --git a/lua/entities/gmod_wire_egp/lib/objects/linestrip.lua b/lua/entities/gmod_wire_egp/lib/objects/linestrip.lua index 0747cfd77e..d1ac95d4de 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/linestrip.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/linestrip.lua @@ -2,8 +2,7 @@ local Obj = EGP:NewObject( "LineStrip" ) Obj.w = nil Obj.h = nil -Obj.x = nil -Obj.y = nil +Obj.angle = 0 Obj.vertices = {} Obj.verticesindex = "vertices" Obj.size = 1 @@ -21,6 +20,7 @@ Obj.Transmit = function( self, Ent, ply ) net.WriteInt( self.vertices[i].x, 16 ) net.WriteInt( self.vertices[i].y, 16 ) end + net.WriteInt(self.angle, 10) net.WriteInt(self.parent, 16) net.WriteInt(self.size, 16) EGP:SendMaterial( self ) @@ -32,6 +32,7 @@ Obj.Receive = function( self ) for i=1,net.ReadUInt(16) do tbl.vertices[ i ] = { x = net.ReadInt(16), y = net.ReadInt(16) } end + tbl.angle = net.ReadInt(10) tbl.parent = net.ReadInt(16) tbl.size = net.ReadInt(16) EGP:ReceiveMaterial( tbl ) @@ -39,5 +40,47 @@ Obj.Receive = function( self ) return tbl end Obj.DataStreamInfo = function( self ) - return { vertices = self.vertices, material = self.material, r = self.r, g = self.g, b = self.b, a = self.a, parent = self.parent } + return { vertices = self.vertices, material = self.material, r = self.r, g = self.g, b = self.b, a = self.a, parent = self.parent, angle = self.angle } end + +function Obj:Initialize(args) + self:EditObject(args) + self.x, self.y = EGP.getCenterFrom(self) +end + +function Obj:EditObject(args) + local ret = false + if args.vertices then + self.vertices = args.vertices + self.x, self.y = EGP.getCenterFrom(self) + args.vertices = nil + end + if args.x or args.y or args.angle then + ret = self:SetPos(args.x or self.x, args.y or self.y, args.angle or self.angle) + args.x = nil + args.y = nil + args.angle = nil + if args._x then args._x = nil args._y = nil args._angle = nil end + end + for k, v in pairs(args) do + if self[k] ~= nil and self[k] ~= v then + self[k] = v + ret = true + end + end + return ret +end + +function Obj:SetPos(x, y, angle) + local sx, sy, sa = self.x, self.y, self.angle + if not angle then angle = sa end + if sx == x and sy == y and sa == angle then return false end + for i, v in ipairs(self.vertices) do + local vec = LocalToWorld(Vector(v.x - sx, v.y - sy, 0), angle_zero, Vector(x, y, 0), Angle(0, sa - angle, 0)) + v.x = vec.x + v.y = vec.y + end + self.x, self.y, self.angle = x, y, angle + if self._x then self._x, self._y, self._angle = x, y, angle end + return true +end \ No newline at end of file diff --git a/lua/entities/gmod_wire_egp/lib/objects/poly.lua b/lua/entities/gmod_wire_egp/lib/objects/poly.lua index c88bfa1b16..ee084210d1 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/poly.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/poly.lua @@ -2,8 +2,6 @@ local Obj = EGP:NewObject( "Poly" ) Obj.w = nil Obj.h = nil -Obj.x = 0 -Obj.y = 0 Obj.angle = 0 Obj.vertices = {} Obj.verticesindex = "vertices" @@ -62,12 +60,12 @@ Obj.Receive = function( self ) return tbl end Obj.DataStreamInfo = function( self ) - return { vertices = self.vertices, material = self.material, r = self.r, g = self.g, b = self.b, a = self.a, filtering = self.filtering, parent = self.parent } + return { vertices = self.vertices, material = self.material, r = self.r, g = self.g, b = self.b, a = self.a, filtering = self.filtering, parent = self.parent, angle = self.angle } end function Obj:Initialize(args) self:EditObject(args) - self.x, self.y = EGP.ParentingFuncs.getCenterFromPos(self) + self.x, self.y = EGP.getCenterFrom(self) end function Obj:Contains(x, y) @@ -96,12 +94,17 @@ end function Obj:EditObject(args) local ret = false + if args.vertices then + self.vertices = args.vertices + self.x, self.y = EGP.getCenterFrom(self) + args.vertices = nil + end if args.x or args.y or args.angle then ret = self:SetPos(args.x or self.x, args.y or self.y, args.angle or self.angle) args.x = nil args.y = nil args.angle = nil - if args._x then args._x = nil args._y = nil args._angle = nil end + if args._x then args._x, args._y, args._angle = nil, nil, nil end end for k, v in pairs(args) do if self[k] ~= nil and self[k] ~= v then @@ -117,7 +120,7 @@ function Obj:SetPos(x, y, angle) if not angle then angle = sa end if sx == x and sy == y and sa == angle then return false end for i, v in ipairs(self.vertices) do - local vec = LocalToWorld(Vector(v.x - sx, v.y - sy, 0), Angle(0, sa, 0), Vector(x, y, 0), Angle(0, sa - angle, 0)) + local vec = LocalToWorld(Vector(v.x - sx, v.y - sy, 0), angle_zero, Vector(x, y, 0), Angle(0, sa - angle, 0)) v.x = vec.x v.y = vec.y end diff --git a/lua/entities/gmod_wire_egp/lib/objects/polyoutline.lua b/lua/entities/gmod_wire_egp/lib/objects/polyoutline.lua index 7ca405d1c1..bb3ca99c2f 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/polyoutline.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/polyoutline.lua @@ -2,8 +2,6 @@ local Obj = EGP:NewObject( "PolyOutline" ) Obj.w = nil Obj.h = nil -Obj.x = 0 -Obj.y = 0 Obj.angle = 0 Obj.vertices = {} Obj.verticesindex = "vertices" @@ -45,15 +43,22 @@ end function Obj:Initialize(args) self:EditObject(args) - self.x, self.y = EGP.ParentingFuncs.getCenterFromPos(self) + self.x, self.y = EGP.getCenterFrom(self) end function Obj:EditObject(args) local ret = false - if args.x or args.y then - ret = self:SetPos(args.x or self.x, args.y or self.y) + if args.vertices then + self.vertices = args.vertices + self.x, self.y = EGP.getCenterFrom(self) + args.vertices = nil + end + if args.x or args.y or args.angle then + ret = self:SetPos(args.x or self.x, args.y or self.y, args.angle or self.angle) args.x = nil args.y = nil + args.angle = nil + if args._x then args._x, args._y, args._angle = nil, nil, nil end end for k, v in pairs(args) do if self[k] ~= nil and self[k] ~= v then @@ -64,13 +69,16 @@ function Obj:EditObject(args) return ret end -function Obj:SetPos(x, y) - local sx, sy = self.x, self.y - if sx == x and sy == y then return false end +function Obj:SetPos(x, y, angle) + local sx, sy, sa = self.x, self.y, self.angle + if not angle then angle = sa end + if sx == x and sy == y and sa == angle then return false end for i, v in ipairs(self.vertices) do - v.x = v.x - sx + x - v.y = v.y - sy + y + local vec = LocalToWorld(Vector(v.x - sx, v.y - sy, 0), angle_zero, Vector(x, y, 0), Angle(0, sa - angle, 0)) + v.x = vec.x + v.y = vec.y end - self.x, self.y = x, y + self.x, self.y, self.angle = x, y, angle + if self._x then self._x, self._y, self._angle = x, y, angle end return true end \ No newline at end of file diff --git a/lua/entities/gmod_wire_expression2/core/egpfunctions.lua b/lua/entities/gmod_wire_expression2/core/egpfunctions.lua index bfa56aa46a..311b5674ca 100644 --- a/lua/entities/gmod_wire_expression2/core/egpfunctions.lua +++ b/lua/entities/gmod_wire_expression2/core/egpfunctions.lua @@ -3,7 +3,6 @@ local function Update(self,this) end local getCenter = EGP.ParentingFuncs.getCenter -local getCenterFromPos = EGP.ParentingFuncs.getCenterFromPos local makeArray = EGP.ParentingFuncs.makeArray -------------------------------------------------------- @@ -349,7 +348,7 @@ e2function egpobject wirelink:egpPolyOutline( number index, ...args ) end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["PolyOutline"], { index = index, vertices = vertices }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return egpobject end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end end e2function egpobject wirelink:egpPolyOutline( number index, array args ) diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index 123c238109..3b0f42c7d5 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -7,7 +7,7 @@ local function Update(self, this) end local getCenter = EGP.ParentingFuncs.getCenter -local getCenterFromPos = EGP.ParentingFuncs.getCenterFromPos +local getCenterFrom = EGP.getCenterFrom local makeArray = EGP.ParentingFuncs.makeArray ---- Type defintion @@ -355,7 +355,7 @@ e2function vector egpobject:egpGlobalPos() if not this then return self:throw("Invalid EGP Object", vector_origin) end local hasvertices, posang = EGP:GetGlobalPos(this.EGP, this) if hasvertices then - local x, y = getCenterFromPos(posang) + local x, y = getCenterFrom(posang) return Vector(x, y, 0) end return Vector(posang.x, posang.y, posang.angle) From 28f74a45d09f3e8d1a6ab02b1b140ccdab3b380d Mon Sep 17 00:00:00 2001 From: Denneisk Date: Tue, 18 Jul 2023 14:04:53 -0400 Subject: [PATCH 03/28] Some lints --- .../gmod_wire_egp/lib/egplib/parenting.lua | 2 +- .../lib/egplib/transmitreceive.lua | 24 +++++++------------ .../lib/egplib/usefulfunctions.lua | 6 ++--- .../gmod_wire_egp/lib/objects/box.lua | 4 ++-- .../core/egpfunctions.lua | 4 +--- .../gmod_wire_expression2/core/egpobjects.lua | 10 +------- 6 files changed, 17 insertions(+), 33 deletions(-) diff --git a/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua b/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua index f6b11d76ae..12ae7d71a4 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua @@ -231,7 +231,7 @@ end function EGP:SetParent( Ent, index, parentindex ) local bool, v if isnumber(index) then - bool, _, v = self:HasObject(Ent, index) + bool, _, v = self:HasObject(Ent, index) else bool, v = index ~= nil, index end diff --git a/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua b/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua index 9a97c22d0a..533ae364a1 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua @@ -91,7 +91,7 @@ if (SERVER) then return end - local bool, k, v = EGP:HasObject( Ent, index ) + local bool, _, v = EGP:HasObject( Ent, index ) if (bool) then if not EGP.umsg.Start("EGP_Transmit_Data", ply) then return end net.WriteEntity( Ent ) @@ -123,7 +123,7 @@ if (SERVER) then return end - local bool, k, v = EGP:HasObject( Ent, index ) + local bool, _, v = EGP:HasObject( Ent, index ) if (bool) then if not EGP.umsg.Start("EGP_Transmit_Data", ply) then return end net.WriteEntity( Ent ) @@ -149,13 +149,12 @@ if (SERVER) then util.AddNetworkString( "AddText" ) local function AddText( Ent, ply, index, text ) if not IsValid(ply) or not ply:IsPlayer() then return end - if (EGP:CheckInterval( ply ) == false) then + if EGP:CheckInterval( ply ) == false then EGP:InsertQueue( Ent, ply, AddText, "AddText", index, text ) return end - local bool, k, v = EGP:HasObject( Ent, index ) - if (bool) then + if EGP:HasObject(Ent, index) then if not EGP.umsg.Start("EGP_Transmit_Data", ply) then return end net.WriteEntity( Ent ) net.WriteString( "AddText" ) @@ -176,8 +175,7 @@ if (SERVER) then return end - local bool, k, v = EGP:HasObject( Ent, index ) - if (bool) then + if EGP:HasObject(Ent, index) then if not EGP.umsg.Start("EGP_Transmit_Data", ply) then return end net.WriteEntity( Ent ) net.WriteString( "SetText" ) @@ -407,31 +405,29 @@ else -- SERVER/CLIENT elseif (Action == "SetText") then local index = net.ReadInt(16) local text = net.ReadString() - local bool,k,v = EGP:HasObject( Ent, index ) + local bool,_,v = EGP:HasObject( Ent, index ) if (bool) then if (EGP:EditObject( v, { text = text } )) then Ent:EGP_Update() end end elseif (Action == "AddText") then local index = net.ReadInt(16) local text = net.ReadString() - local bool,k,v = EGP:HasObject( Ent, index ) + local bool,_,v = EGP:HasObject( Ent, index ) if (bool) then if (EGP:EditObject( v, { text = v.text .. text } )) then Ent:EGP_Update() end end elseif (Action == "SetVertex") then local index = net.ReadInt(16) - local bool, k,v = EGP:HasObject( Ent, index ) + local bool, _, v = EGP:HasObject( Ent, index ) if (bool) then local vertices = {} if (v.HasUV) then - local n = 0 for i=1,net.ReadUInt(8) do local x, y, u, _v = net.ReadInt(16), net.ReadInt(16), net.ReadFloat(), net.ReadFloat() vertices[i] = { x=x, y=y, u=u, v=_v } end else - local n = 0 for i=1,net.ReadUInt(8) do local x, y = net.ReadInt(16), net.ReadInt(16) vertices[i] = { x=x, y=y } @@ -442,18 +438,16 @@ else -- SERVER/CLIENT end elseif (Action == "AddVertex") then local index = net.ReadInt(16) - local bool, k, v = EGP:HasObject( Ent, index ) + local bool, _, v = EGP:HasObject( Ent, index ) if (bool) then local vertices = table.Copy(v.vertices) if (v.HasUV) then - local n = 0 for i=1,net.ReadUInt(8) do local x, y, u, _v = net.ReadInt(16), net.ReadInt(16), net.ReadFloat(), net.ReadFloat() vertices[#vertices+1] = { x=x, y=y, u=u, v=_v } end else - local n = 0 for i=1,net.ReadUInt(8) do local x, y = net.ReadInt(16), net.ReadInt(16) vertices[#vertices+1] = { x=x, y=y } diff --git a/lua/entities/gmod_wire_egp/lib/egplib/usefulfunctions.lua b/lua/entities/gmod_wire_egp/lib/egplib/usefulfunctions.lua index 2753eb2128..8107e4e34f 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/usefulfunctions.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/usefulfunctions.lua @@ -222,7 +222,7 @@ end -- Other -------------------------------------------------------- function EGP:ValidEGP( Ent ) - return (IsValid( Ent ) and (Ent:GetClass() == "gmod_wire_egp" or Ent:GetClass() == "gmod_wire_egp_hud" or Ent:GetClass() == "gmod_wire_egp_emitter")) + return IsValid( Ent ) and (Ent:GetClass() == "gmod_wire_egp" or Ent:GetClass() == "gmod_wire_egp_hud" or Ent:GetClass() == "gmod_wire_egp_emitter") end @@ -460,7 +460,7 @@ end function EGP.WorldToLocal(object, x, y) local _, realpos = EGP:GetGlobalPos(object.EGP, object) x, y = x - realpos.x, y - realpos.y - + local theta = math.rad(realpos.angle) if theta ~= 0 then local cos_theta, sin_theta = math.cos(theta), math.sin(theta) @@ -468,6 +468,6 @@ function EGP.WorldToLocal(object, x, y) x * cos_theta - y * sin_theta, y * cos_theta + x * sin_theta end - + return x, y end \ No newline at end of file diff --git a/lua/entities/gmod_wire_egp/lib/objects/box.lua b/lua/entities/gmod_wire_egp/lib/objects/box.lua index 819a6e8d9b..2bed122116 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/box.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/box.lua @@ -26,10 +26,10 @@ Obj.DataStreamInfo = function( self ) end function Obj:Contains(x, y) x, y = EGP.WorldToLocal(self, x, y) - + local w, h = self.w / 2, self.h / 2 if self.EGP.TopLeft then x, y = x - w, y - h end - + return -w <= x and x <= w and -h <= y and y <= h end diff --git a/lua/entities/gmod_wire_expression2/core/egpfunctions.lua b/lua/entities/gmod_wire_expression2/core/egpfunctions.lua index 7386ffe9f0..efd6b1da47 100644 --- a/lua/entities/gmod_wire_expression2/core/egpfunctions.lua +++ b/lua/entities/gmod_wire_expression2/core/egpfunctions.lua @@ -2,8 +2,6 @@ local function Update(self,this) self.data.EGP.UpdatesNeeded[this] = true end -local getCenterFrom = EGP.getCenterFrom - -------------------------------------------------------- -- Frames -------------------------------------------------------- @@ -816,7 +814,7 @@ end __e2setcost(20) e2function vector wirelink:egpGlobalPos( number index ) - local hasvertices, posang = EGP:GetGlobalPos( this, index ) + local _, posang = EGP:GetGlobalPos( this, index ) return Vector(posang.x, posang.y, posang.angle) end diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index 3b0f42c7d5..ad7a3bfccf 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -6,10 +6,6 @@ local function Update(self, this) self.data.EGP.UpdatesNeeded[this] = true end -local getCenter = EGP.ParentingFuncs.getCenter -local getCenterFrom = EGP.getCenterFrom -local makeArray = EGP.ParentingFuncs.makeArray - ---- Type defintion registerType("egpobject", "xeo", nil, @@ -353,11 +349,7 @@ __e2setcost(20) e2function vector egpobject:egpGlobalPos() if not this then return self:throw("Invalid EGP Object", vector_origin) end - local hasvertices, posang = EGP:GetGlobalPos(this.EGP, this) - if hasvertices then - local x, y = getCenterFrom(posang) - return Vector(x, y, 0) - end + local _, posang = EGP:GetGlobalPos(this.EGP, this) return Vector(posang.x, posang.y, posang.angle) end From 591d84d555008dea335bf219c6ba21ce5f130ab7 Mon Sep 17 00:00:00 2001 From: Denneisk Date: Wed, 2 Aug 2023 09:28:53 -0400 Subject: [PATCH 04/28] Clean up and refactor EGP.Objects.Base initialization --- .../lib/egplib/objectcontrol.lua | 53 ++++++++++--------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua index 47c0dd1e38..3291bea34b 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua @@ -8,29 +8,29 @@ EGP.Objects.Names = {} EGP.Objects.Names_Inverted = {} -- This object is not used. It's only a base -EGP.Objects.Base = {} -EGP.Objects.Base.ID = 0 -EGP.Objects.Base.x = 0 -EGP.Objects.Base.y = 0 -EGP.Objects.Base.w = 0 -EGP.Objects.Base.h = 0 -EGP.Objects.Base.r = 255 -EGP.Objects.Base.g = 255 -EGP.Objects.Base.b = 255 -EGP.Objects.Base.a = 255 -EGP.Objects.Base.filtering = TEXFILTER.ANISOTROPIC -EGP.Objects.Base.material = "" -if CLIENT then EGP.Objects.Base.material = false end -EGP.Objects.Base.parent = 0 -EGP.Objects.Base.EGP = NULL -- EGP entity parent -EGP.Objects.Base.Transmit = function( self ) +local baseObj = {} +baseObj.ID = 0 +baseObj.x = 0 +baseObj.y = 0 +baseObj.w = 0 +baseObj.h = 0 +baseObj.r = 255 +baseObj.g = 255 +baseObj.b = 255 +baseObj.a = 255 +baseObj.filtering = TEXFILTER.ANISOTROPIC +baseObj.material = "" +if CLIENT then baseObj.material = false end +baseObj.parent = 0 +baseObj.EGP = NULL -- EGP entity parent +function baseObj:Transmit() EGP:SendPosSize( self ) EGP:SendColor( self ) EGP:SendMaterial( self ) net.WriteUInt(math.Clamp(self.filtering,0,3), 2) net.WriteInt( self.parent, 16 ) end -EGP.Objects.Base.Receive = function( self ) +function baseObj:Receive() local tbl = {} EGP:ReceivePosSize( tbl ) EGP:ReceiveColor( tbl, self ) @@ -39,13 +39,13 @@ EGP.Objects.Base.Receive = function( self ) tbl.parent = net.ReadInt(16) return tbl end -EGP.Objects.Base.DataStreamInfo = function( self ) +function baseObj:DataStreamInfo() return { x = self.x, y = self.y, w = self.w, h = self.h, r = self.r, g = self.g, b = self.b, a = self.a, material = self.material, filtering = self.filtering, parent = self.parent } end -function EGP.Objects.Base:Contains(x, y) +function baseObj:Contains(x, y) return false end -function EGP.Objects.Base:EditObject(args) +function baseObj:EditObject(args) local ret = false for k, v in pairs(args) do if self[k] ~= nil and self[k] ~= v then @@ -55,14 +55,14 @@ function EGP.Objects.Base:EditObject(args) end return ret end -EGP.Objects.Base.Initialize = EGP.Objects.Base.EditObject -function EGP.Objects.Base:SetPos(x, y) +baseObj.Initialize = baseObj.EditObject +function baseObj:SetPos(x, y) local ret = false if self.x ~= x then self.x, ret = x, true end if self.y ~= y then self.y, ret = y, true end return ret end -function EGP.Objects.Base:Set(member, value) +function baseObj:Set(member, value) if self[member] and self[member] ~= value then self[member] = value return true @@ -70,6 +70,9 @@ function EGP.Objects.Base:Set(member, value) return false end end +local M_EGPObject = {__tostring = function(self) return "[EGPObject] ".. self.Name or nil end} +setmetatable(baseObj, M_EGPObject) +EGP.Objects.Base = baseObj ---------------------------- -- Get Object @@ -93,7 +96,7 @@ function EGP:NewObject( Name ) self.Objects[Name] = {} -- Set info self.Objects[Name].Name = Name - table.Inherit( self.Objects[Name], self.Objects.Base ) + table.Inherit(self.Objects[Name], self.Objects.Base) -- Create lookup table local ID = table.Count(self.Objects) @@ -103,7 +106,7 @@ function EGP:NewObject( Name ) -- Inverted lookup table self.Objects.Names_Inverted[ID] = Name - return self.Objects[Name] + return setmetatable(self.Objects[Name], M_EGPObject) end local folder = "entities/gmod_wire_egp/lib/objects/" From 22c0dc11eba29874e492127f130d6a8798615702 Mon Sep 17 00:00:00 2001 From: Denneisk Date: Wed, 2 Aug 2023 09:50:15 -0400 Subject: [PATCH 05/28] Use metatables for EGPObject Add egpobject:toString() --- .../gmod_wire_expression2/core/egpobjects.lua | 120 ++++++++++-------- 1 file changed, 65 insertions(+), 55 deletions(-) diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index ad7a3bfccf..174e04ee98 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -2,10 +2,17 @@ -- File for EGP Object handling in E2. -- +local NULL_EGPOBJECT = setmetatable({}, {__tostring = function(self) return "[EGPObject] NULL" end, __not = function(self) return false end}) +local M_EGPObject = getmetatable(EGP.Objects.Base) + local function Update(self, this) self.data.EGP.UpdatesNeeded[this] = true end +local function isValid(this) + if this and this ~= NULL_EGPOBJECT then return true else return false end +end + ---- Type defintion registerType("egpobject", "xeo", nil, @@ -14,9 +21,10 @@ registerType("egpobject", "xeo", nil, function(retval) if retval == nil then return end if not istable(retval) then error("Return value is neither nil nor a table, but a " .. type(retval) .. "!", 0) end + if not getmetatable(retval) == M_EGPObject then error("Return value is not an egpobject!", 0) end end, function(v) - return not istable(v) + return not istable(v) or getmetatable(v) ~= M_EGPObject end ) @@ -26,19 +34,14 @@ registerOperator("ass", "xeo", "xeo", function(self, args) local lhs, op2, scope = args[2], args[3], args[4] local rhs = op2[1](self, op2) if rhs == nil then return nil end - - local Scope = self.Scopes[scope] - local lookup = Scope.lookup - if not lookup then lookup = {} Scope.lookup = lookup end - if lookup[rhs] then lookup[rhs][lhs] = true else lookup[rhs] = {[lhs] = true} end - Scope[lhs] = rhs - Scope.vclk[lhs] = true + self.Scopes[scope][lhs] = rhs + self.Scopes[scope].vclk[lhs] = true return rhs end) e2function number operator_is(egpobject egpo) - return (egpo ~= nil and isfunction(egpo.DataStreamInfo)) and 1 or 0 + return (getmetatable(egpo) == M_EGPObject) and 1 or 0 end e2function number operator==(egpobject lhs, egpobject rhs) @@ -57,14 +60,14 @@ __e2setcost(7) -- Set Text ---------------------------- e2function void egpobject:egpSetText(string text) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:Set("text", text) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end e2function void egpobject:egpSetText(string text, string font, number size) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:EditObject({ text = text, font = font, size = size }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -74,14 +77,14 @@ end -- Alignment ---------------------------- e2function void egpobject:egpAlign(number halign) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:Set("halign", math.Clamp(halign, 0, 2)) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end e2function void egpobject:egpAlign(number halign, number valign) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:EditObject({ valign = math.Clamp(valign, 0, 2), halign = math.Clamp(halign, 0, 2) }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -91,7 +94,7 @@ end -- Filtering ---------------------------- e2function void egpobject:egpFiltering(number filtering) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:Set("filtering", math.Clamp(filtering, 0, 3)) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -101,7 +104,7 @@ end -- Font ---------------------------- e2function void egpobject:egpFont(string font) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if #font > 30 then return self:throw("Font string is too long!", nil) end @@ -109,7 +112,7 @@ e2function void egpobject:egpFont(string font) end e2function void egpobject:egpFont(string font, number size) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if #font > 30 then return self:throw("Font string is too long!", nil) end @@ -122,7 +125,7 @@ end __e2setcost(10) e2function void egpobject:egpPos(vector pos) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:EditObject({ target_x = pos[1], target_y = pos[2], target_z = pos[3] }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -138,14 +141,14 @@ __e2setcost(7) -- Size ---------------------------- e2function void egpobject:egpSize(vector2 size) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:EditObject({ w = size[1], h = size[2] }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end e2function void egpobject:egpSize(number size) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:Set("size", size) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -155,7 +158,7 @@ end -- Position ---------------------------- e2function void egpobject:egpPos(vector2 pos) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:SetPos(pos[1], pos[2]) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -165,7 +168,7 @@ end -- Angle ---------------------------- e2function void egpobject:egpAngle(number angle) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:EditObject({ angle = angle, _angle = angle }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -175,7 +178,7 @@ end -- Position & Angle ------------- e2function void egpobject:egpAngle(vector2 worldpos, vector2 axispos, number angle) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this.x and this.y then @@ -197,28 +200,28 @@ end -- Color ---------------------------- e2function void egpobject:egpColor(vector4 color) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:EditObject({ r = color[1], g = color[2], b = color[3], a = color[4] }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end e2function void egpobject:egpColor(vector color) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:EditObject({ r = color[1], g = color[2], b = color[3] }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end e2function void egpobject:egpColor(r, g, b, a) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:EditObject({ r = r, g = g, b = b, a = a }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end e2function void egpobject:egpAlpha(number a) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:Set("a", a) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -228,7 +231,7 @@ end -- Material ---------------------------- e2function void egpobject:egpMaterial(string material) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end material = WireLib.IsValidMaterial(material) @@ -236,7 +239,7 @@ e2function void egpobject:egpMaterial(string material) end e2function void egpobject:egpMaterialFromScreen(entity gpu) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if gpu and gpu:IsValid() then @@ -248,7 +251,7 @@ end -- Fidelity (number of corners for circles and wedges) ---------------------------- e2function void egpobject:egpFidelity(number fidelity) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:EditObject({ fidelity = math.Clamp(fidelity, 3, 180) }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -262,7 +265,7 @@ end -- Parenting ---------------------------- e2function void egpobject:egpParent(egpobject parent) - if not this or not parent then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) or not isValid(parent) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if egp ~= parent.EGP then return self:throw("Invalid EGP Object", nil) end if not EGP:IsAllowed(self, egp) then return end @@ -270,21 +273,21 @@ e2function void egpobject:egpParent(egpobject parent) end e2function void egpobject:egpParent(number parentindex) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if EGP:SetParent(egp, this, parentindex) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end e2function void wirelink:egpParent(egpobject child, egpobject parent) - if not child or not parent then return self:throw("Invalid EGP Object", nil) end + if not isValid(child) or not isValid(parent) then return self:throw("Invalid EGP Object", nil) end if not EGP:IsAllowed(self, this) then return end if EGP:SetParent(this, child, parent) then EGP:DoAction(this, self, "SendObject", child) Update(self, this) end end -- Entity parenting (only for 3Dtracker - does nothing for any other object) e2function void egpobject:egpParent(entity parent) - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not parent or not parent:IsValid() then return end if not EGP:IsAllowed(self, egp) then return end @@ -299,26 +302,26 @@ end -- Returns the entity a tracker is parented to e2function entity egpobject:egpTrackerParent() - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end return IsValid(this.parententity) and this.parententity or NULL end e2function void egpobject:egpParentToCursor() - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if EGP:SetParent(egp, this, -1) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end e2function void egpobject:egpUnParent() - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if EGP:UnParent(egp, this) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end e2function number egpobject:egpParentIndex() - if not this then return self:throw("Invalid EGP Object", nil) end + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end return this.parent or nil end @@ -334,7 +337,7 @@ e2function void wirelink:egpRemove(egpobject obj) end e2function void egpobject:egpRemove() - if not this then return end + if not isValid(this) then return end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end @@ -348,13 +351,13 @@ end __e2setcost(20) e2function vector egpobject:egpGlobalPos() - if not this then return self:throw("Invalid EGP Object", vector_origin) end + if not isValid(this) then return self:throw("Invalid EGP Object", vector_origin) end local _, posang = EGP:GetGlobalPos(this.EGP, this) return Vector(posang.x, posang.y, posang.angle) end e2function array egpobject:egpGlobalVertices() - if not this then return self:throw("Invalid EGP Object", {}) end + if not isValid(this) then return self:throw("Invalid EGP Object", {}) end local hasvertices, data = EGP:GetGlobalPos(this.EGP, this) if hasvertices then if data.vertices then @@ -379,54 +382,54 @@ end __e2setcost(3) e2function vector2 egpobject:egpPos() - if not this then return self:throw("Invalid EGP Object", { -1, -1 }) end + if not isValid(this) then return self:throw("Invalid EGP Object", { -1, -1 }) end return (this.x and this.y and { this.x, this.y }) or { -1, -1 } end e2function vector2 egpobject:egpSize() - if not this then return self:throw("Invalid EGP Object", { -1, -1 }) end + if not isValid(this) then return self:throw("Invalid EGP Object", { -1, -1 }) end return (this.w and this.h and { this.w, this.h }) or { -1, -1 } end e2function number egpobject:egpSizeNum() - if not this then return self:throw("Invalid EGP Object", -1) end + if not isValid(this) then return self:throw("Invalid EGP Object", -1) end return this.size or -1 end e2function vector4 egpobject:egpColor4() - if not this then return self:throw("Invalid EGP Object", { -1, -1, -1, -1 }) end + if not isValid(this) then return self:throw("Invalid EGP Object", { -1, -1, -1, -1 }) end return (this.r and this.g and this.b and this.a and { this.r, this.g, this.b, this.a }) or { -1, -1, -1, -1 } end e2function vector egpobject:egpColor() - if not this then return self:throw("Invalid EGP Object", -1) end + if not isValid(this) then return self:throw("Invalid EGP Object", -1) end return (this.r and this.g and this.b and Vector(this.r, this.g, this.b)) or Vector(-1, -1, -1) end e2function number egpobject:egpAlpha() - if not this then return self:throw("Invalid EGP Object", -1) end + if not isValid(this) then return self:throw("Invalid EGP Object", -1) end return this.a or -1 end e2function number egpobject:egpAngle() - if not this then return self:throw("Invalid EGP Object", -1) end + if not isValid(this) then return self:throw("Invalid EGP Object", -1) end return this.angle or -1 end e2function string egpobject:egpMaterial() - if not this then return self:throw("Invalid EGP Object", "") end + if not isValid(this) then return self:throw("Invalid EGP Object", "") end return this.material or "" end e2function number egpobject:egpRadius() - if not this then return self:throw("Invalid EGP Object", -1) end + if not isValid(this) then return self:throw("Invalid EGP Object", -1) end return this.radius or -1 end __e2setcost(10) e2function array egpobject:egpVertices() - if (this.vertices) then + if this.vertices then local ret = {} for k, v in ipairs(this.vertices) do ret[k] = { v.x, v.y } @@ -447,7 +450,7 @@ end __e2setcost(4) e2function string egpobject:egpObjectType() - return EGP.Objects.Names_Inverted[this.ID] or "" + return EGP.Objects.Names_Inverted[this.ID] or "Unknown" end -------------------------------------------------------- @@ -458,6 +461,7 @@ __e2setcost(15) e2function egpobject wirelink:egpCopy(number index, egpobject from) if not EGP:IsAllowed(self, this) then return end + if not isValid(from) then return self:throw("Invalid EGPObject", NULL_EGPOBJECT) end if from then local copy = table.Copy(from) copy.index = index @@ -469,7 +473,7 @@ end __e2setcost(10) e2function number egpobject:egpObjectContainsPoint(vector2 point) - return this and this:Contains(point[1], point[2]) and 1 or 0 + return isValid(this) and this:Contains(point[1], point[2]) and 1 or 0 end __e2setcost(5) @@ -483,11 +487,17 @@ end __e2setcost(2) e2function string egpobject:egpObjectType() - return this and EGP.Objects.Names_Inverted[this.ID] or "" + return isValid(this) and EGP.Objects.Names_Inverted[this.ID] or "" end __e2setcost(1) e2function egpobject noegpobject() - return nil -end \ No newline at end of file + return NULL_EGPOBJECT +end + +e2function string toString(egpobject egpo) + return tostring(egpo) +end + +e2function string egpobject:toString() = e2function string toString(egpobject egpo) \ No newline at end of file From 62d59773b493eb62efa18ade506f12917622b1f5 Mon Sep 17 00:00:00 2001 From: Denneisk Date: Fri, 4 Aug 2023 00:22:58 -0400 Subject: [PATCH 06/28] Have egpRemove return null egpobject. Remove unnecessary code. --- lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua | 2 +- lua/entities/gmod_wire_expression2/core/egpobjects.lua | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua index 3291bea34b..536faaa7d2 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua @@ -70,7 +70,7 @@ function baseObj:Set(member, value) return false end end -local M_EGPObject = {__tostring = function(self) return "[EGPObject] ".. self.Name or nil end} +local M_EGPObject = {__tostring = function(self) return "[EGPObject] ".. self.Name end} setmetatable(baseObj, M_EGPObject) EGP.Objects.Base = baseObj diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index 174e04ee98..326a2effdd 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -2,7 +2,7 @@ -- File for EGP Object handling in E2. -- -local NULL_EGPOBJECT = setmetatable({}, {__tostring = function(self) return "[EGPObject] NULL" end, __not = function(self) return false end}) +local NULL_EGPOBJECT = setmetatable({}, {__tostring = function(self) return "[EGPObject] NULL" end}) local M_EGPObject = getmetatable(EGP.Objects.Base) local function Update(self, this) @@ -330,9 +330,10 @@ end -------------------------------------------------------- e2function void wirelink:egpRemove(egpobject obj) if not EGP:IsAllowed(self, this) then return end - if obj then + if isValid(obj) then EGP:DoAction(this, self, "RemoveObject", obj.index) Update(self, this) + obj = NULL_EGPOBJECT end end @@ -343,6 +344,7 @@ e2function void egpobject:egpRemove() EGP:DoAction(egp, self, "RemoveObject", this.index) Update(self, egp) + this = NULL_EGPOBJECT end -------------------------------------------------------- From 199baaf80a8df4246282914dd5dcd7bf128846b0 Mon Sep 17 00:00:00 2001 From: Denneisk Date: Fri, 4 Aug 2023 00:59:13 -0400 Subject: [PATCH 07/28] Silly workaround because I forgot how functions work. --- .../gmod_wire_expression2/core/egpobjects.lua | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index 326a2effdd..9ecb25a94e 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -2,7 +2,8 @@ -- File for EGP Object handling in E2. -- -local NULL_EGPOBJECT = setmetatable({}, {__tostring = function(self) return "[EGPObject] NULL" end}) +local M_NULL_EGPOBJECT = { __tostring = function(self) return "[EGPObject] NULL" end } +local NULL_EGPOBJECT = setmetatable({}, M_NULL_EGPOBJECT) local M_EGPObject = getmetatable(EGP.Objects.Base) local function Update(self, this) @@ -10,7 +11,7 @@ local function Update(self, this) end local function isValid(this) - if this and this ~= NULL_EGPOBJECT then return true else return false end + if this and getmetatable(this) ~= M_NULL_EGPOBJECT then return true else return false end end ---- Type defintion @@ -332,8 +333,9 @@ e2function void wirelink:egpRemove(egpobject obj) if not EGP:IsAllowed(self, this) then return end if isValid(obj) then EGP:DoAction(this, self, "RemoveObject", obj.index) + table.Empty(obj) + setmetatable(obj, M_NULL_EGPOBJECT) Update(self, this) - obj = NULL_EGPOBJECT end end @@ -343,8 +345,9 @@ e2function void egpobject:egpRemove() if not EGP:IsAllowed(self, egp) then return end EGP:DoAction(egp, self, "RemoveObject", this.index) + table.Empty(this) + setmetatable(this, M_NULL_EGPOBJECT) Update(self, egp) - this = NULL_EGPOBJECT end -------------------------------------------------------- @@ -483,13 +486,13 @@ __e2setcost(5) e2function egpobject wirelink:egpobject(number index) if not EGP:IsAllowed(self, this) then return end local _, _, obj = EGP:HasObject(this, index) - return obj + return obj or NULL_EGPOBJECT end __e2setcost(2) e2function string egpobject:egpObjectType() - return isValid(this) and EGP.Objects.Names_Inverted[this.ID] or "" + return isValid(this) and EGP.Objects.Names_Inverted[this.ID] or "Unknown" end __e2setcost(1) From 302576a9d32d33496e577e2822ffaa776b2ba2cf Mon Sep 17 00:00:00 2001 From: Denneisk Date: Sat, 26 Aug 2023 13:52:50 -0400 Subject: [PATCH 08/28] Add index operators to EGP objects --- .../gmod_wire_expression2/core/egpobjects.lua | 91 ++++++++++++++++++- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index 9ecb25a94e..d4a9ca0490 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -2,6 +2,7 @@ -- File for EGP Object handling in E2. -- +-- Dumb but simple workaround local M_NULL_EGPOBJECT = { __tostring = function(self) return "[EGPObject] NULL" end } local NULL_EGPOBJECT = setmetatable({}, M_NULL_EGPOBJECT) local M_EGPObject = getmetatable(EGP.Objects.Base) @@ -346,7 +347,7 @@ e2function void egpobject:egpRemove() EGP:DoAction(egp, self, "RemoveObject", this.index) table.Empty(this) - setmetatable(this, M_NULL_EGPOBJECT) + setmetatable(this, M_NULL_EGPOBJECT) -- In an ideal scenario we would probably want this = NULL_EGPOBJECT instead Update(self, egp) end @@ -505,4 +506,90 @@ e2function string toString(egpobject egpo) return tostring(egpo) end -e2function string egpobject:toString() = e2function string toString(egpobject egpo) \ No newline at end of file +e2function string egpobject:toString() = e2function string toString(egpobject egpo) + +-------------------------------------------------------- +-- Array Index Operators +-------------------------------------------------------- + +-- Table of allowed arguments and their types +local EGP_ALLOWED_ARGS = + { + x = "n", + x2 = "n", + y = "n", + y2 = "n", + z = "n", + w = "n", + h = "n", + r = "n", + g = "n", + b = "n", + a = "n", + size = "n", + angle = "n", + fidelity = "n", + radius = "n", + valign = "n", + halign = "n", + text = "s", + font = "s", + material = "s", + } + +registerCallback("postinit", function() + local fixDefault = E2Lib.fixDefault + for _, v in pairs(wire_expression_types) do + local id = v[1] + local default = v[2] + local typecheck = v[6] + + __e2setcost(5) + + -- Getter + registerOperator("idx", id .. "=xeos", id, function(self, args) + local op1, op2 = args[2], args[3] + local this, index = op1[1](self, op1), op2[1](self, op2) + local indexType = EGP_ALLOWED_ARGS[index] + + if not indexType then return fixDefault(default) end + + local obj = this[index] + + if not obj or id ~= indexType then return fixDefault(default) end + if typecheck and typecheck(obj) then return fixDefault(default) end -- Type check + + return obj + end) + + -- Setter + registerOperator("idx", id .. "=xeos" .. id, id, function(self, args) + local op1, op2, op3, scope = args[2], args[3], args[4], args[5] + local this, index, value = op1[1](self, op1), op2[1](self, op2), op3[1](self, op3) + + if not EGP_ALLOWED_ARGS[index] then return fixDefault(default) end + + if not isValid(this) then return self:throw("Tried to acces invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return fixDefault(default) end + if this:Set(index, value) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) self.GlobalScope.vclk[this] = true end + return value + end) + + -- Implicitly typed setter + registerOperator("idx", "xeos" .. id, id, function(self, args) + local op1, op2, op3, scope = args[2], args[3], args[4], args[5] + local this, index, value = op1[1](self, op1), op2[1](self, op2), op3[1](self, op3) + local indexType = EGP_ALLOWED_ARGS[index] + + if not indexType then return end + if indexType ~= id then self:throw(string.format("EGP Object expected '%s' type but got '%s'!", indexType, id)) end + + if not isValid(this) then return self:throw("Tried to acces invalid EGP Object") end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:Set(index, value) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) self.GlobalScope.vclk[this] = true end + return + end) + end +end) From dae9153401db17be58c776db19b871739cdc4c62 Mon Sep 17 00:00:00 2001 From: Denneisk Date: Sat, 26 Aug 2023 14:29:33 -0400 Subject: [PATCH 09/28] Added E2Descriptions Genericized EGP object creation functions (will be used later for indexless functions) Add xwl:egpHasObject(xeo) Fixed removed EGP objects not equal to NULL --- .../gmod_wire_expression2/core/egpobjects.lua | 6 +- lua/wire/client/e2descriptions.lua | 95 +++++++++++++++---- 2 files changed, 81 insertions(+), 20 deletions(-) diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index d4a9ca0490..830554d4fa 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -3,7 +3,7 @@ -- -- Dumb but simple workaround -local M_NULL_EGPOBJECT = { __tostring = function(self) return "[EGPObject] NULL" end } +local M_NULL_EGPOBJECT = { __tostring = function(self) return "[EGPObject] NULL" end, __eq = function(a, b) return getmetatable(a) == getmetatable(b) end } local NULL_EGPOBJECT = setmetatable({}, M_NULL_EGPOBJECT) local M_EGPObject = getmetatable(EGP.Objects.Base) @@ -384,6 +384,10 @@ e2function array egpobject:egpGlobalVertices() end end +e2function number wirelink:egpHasObject(egpobject object) + return this == object.EGP and 1 or 0 +end + __e2setcost(3) diff --git a/lua/wire/client/e2descriptions.lua b/lua/wire/client/e2descriptions.lua index 2f9e7c7063..f189104f34 100644 --- a/lua/wire/client/e2descriptions.lua +++ b/lua/wire/client/e2descriptions.lua @@ -1434,8 +1434,6 @@ E2Helper.Descriptions["egpSizeNum(xwl:n)"] = "Returns the size of the text/line/ E2Helper.Descriptions["egpToWorld(xwl:xv2)"] = "Converts a 2D vector on the screen or emitter into a 3D vector in the world" E2Helper.Descriptions["egpTrackerParent(xwl:n)"] = "Returns the parent entity of the 3D tracker object" ---E2Helper.Descriptions["egpAddVertices(xwl:nr)"] = "" ---E2Helper.Descriptions["egpBytesLeft()"] = "" E2Helper.Descriptions["egpCanSendUmsg()"] = "Returns 1 if you can send an usermessage at the moment, 0 otherwise" E2Helper.Descriptions["egpClear(xwl:)"] = "Clears the EGP screen" E2Helper.Descriptions["egpClearQueue()"] = "Clears your entire queue" @@ -1464,27 +1462,86 @@ E2Helper.Descriptions["egpObjectIndexes(xwl:)"] = "Returns an array containing a E2Helper.Descriptions["egpObjectType(xwl:n)"] = "Returns the type of the object with specified index" E2Helper.Descriptions["egpObjectTypes(xwl:)"] = "Returns an array whose keys are bound to object index, and value being the type of particular object" -E2Helper.Descriptions["egp3DTracker(xwl:nv)"] = "Creates a 3D tracker object at specified world position" +E2Helper.Descriptions["egp3DTracker"] = "Creates a 3D tracker object at specified world position" E2Helper.Descriptions["egp3DTracker(xwl:nvn)"] = "Creates a 3D tracker object at specified world position that is only visible behind (directionality=-1), in front of (directionality=1) the screen/emitter, or both (directionality=0). HUD is unaffected by directionality." -E2Helper.Descriptions["egpBox(xwl:nxv2xv2)"] = "Creates a box. First 2D vector is the position, second is size" -E2Helper.Descriptions["egpBoxOutline(xwl:nxv2xv2)"] = "Creates an outline box. First 2D vector is the position, second is size" -E2Helper.Descriptions["egpCircle(xwl:nxv2xv2)"] = "Creates a circle. First 2D vector is the position, second is size" -E2Helper.Descriptions["egpCircleOutline(xwl:nxv2xv2)"] = "Creates an outline circle. First 2D vector is the position, second is size" -E2Helper.Descriptions["egpLine(xwl:nxv2xv2)"] = "Creates a line. First 2D vector is the start position, second is end position" -E2Helper.Descriptions["egpLineStrip(xwl:n...)"] = "Creates a curve with specified points as 2D/4D vectors (x,y)/(x,y,u,v)" +E2Helper.Descriptions["egpBox"] = "Creates a box. First 2D vector is the position, second is size" +E2Helper.Descriptions["egpBoxOutline"] = "Creates an outline box. First 2D vector is the position, second is size" +E2Helper.Descriptions["egpCircle"] = "Creates a circle. First 2D vector is the position, second is size" +E2Helper.Descriptions["egpCircleOutline"] = "Creates an outline circle. First 2D vector is the position, second is size" +E2Helper.Descriptions["egpLine"] = "Creates a line. First 2D vector is the start position, second is end position" +E2Helper.Descriptions["egpLineStrip"] = "Creates a curve with specified points as 2D/4D vectors (x,y)/(x,y,u,v)" E2Helper.Descriptions["egpLineStrip(xwl:nr)"] = "Creates a curve with specified points as array of 2D/4D vectors (x,y)/(x,y,u,v)" E2Helper.Descriptions["egpPoly(xwl:nr)"] = "Creates a polygon with specified points as array of 2D/4D vectors (x,y)/(x,y,u,v)" -E2Helper.Descriptions["egpPoly(xwl:n...)"] = "Creates a polygon with specified points as 2D/4D vectors (x,y)/(x,y,u,v)" +E2Helper.Descriptions["egpPoly"] = "Creates a polygon with specified points as 2D/4D vectors (x,y)/(x,y,u,v)" E2Helper.Descriptions["egpPolyOutline(xwl:nr)"] = "Creates a outline polygon with specified points as array of 2D/4D vectors (x,y)/(x,y,u,v)" -E2Helper.Descriptions["egpPolyOutline(xwl:n...)"] = "Creates a outline polygon with specified points as 2D/4D vectors (x,y)/(x,y,u,v)" -E2Helper.Descriptions["egpRoundedBox(xwl:nxv2xv2)"] = "Creates a rounded box. First 2D vector is the position, second is size" -E2Helper.Descriptions["egpRoundedBoxOutline(xwl:nxv2xv2)"] = "Creates a rounded outline box. First 2D vector is the position, second is size" -E2Helper.Descriptions["egpText(xwl:nsxv2)"] = "Creates a text object" -E2Helper.Descriptions["egpTextLayout(xwl:nsxv2xv2)"] = "Creates a text layout object" -E2Helper.Descriptions["egpTriangle(xwl:nxv2xv2xv2)"] = "Creates a triangle with specified vertices" -E2Helper.Descriptions["egpTriangleOutline(xwl:nxv2xv2xv2)"] = "Creates a outline triangle with specified vertices" -E2Helper.Descriptions["egpWedge(xwl:nxv2xv2)"] = "Creates a wedge object. Wedge objects are like circles, except they have a cake-piece-like mouth which you can change using egpSize" -E2Helper.Descriptions["egpWedgeOutline(xwl:nxv2xv2)"] = "Creates a outline wedge object. Wedge objects are like circles, except they have a cake-piece-like mouth which you can change using egpSize" +E2Helper.Descriptions["egpPolyOutline"] = "Creates a outline polygon with specified points as 2D/4D vectors (x,y)/(x,y,u,v)" +E2Helper.Descriptions["egpRoundedBox"] = "Creates a rounded box. First 2D vector is the position, second is size" +E2Helper.Descriptions["egpRoundedBoxOutline"] = "Creates a rounded outline box. First 2D vector is the position, second is size" +E2Helper.Descriptions["egpText"] = "Creates a text object" +E2Helper.Descriptions["egpTextLayout"] = "Creates a text layout object" +E2Helper.Descriptions["egpTriangle"] = "Creates a triangle with specified vertices" +E2Helper.Descriptions["egpTriangleOutline"] = "Creates a outline triangle with specified vertices" +E2Helper.Descriptions["egpWedge"] = "Creates a wedge object. Wedge objects are like circles, except they have a cake-piece-like mouth which you can change using egpSize" +E2Helper.Descriptions["egpWedgeOutline"] = "Creates a outline wedge object. Wedge objects are like circles, except they have a cake-piece-like mouth which you can change using egpSize" + +E2Helper.Descriptions["egpAlign(xeo:n)"] = "Changes the horizontal alignment. Works on: text and text layout. Number can be 0, 1 or 2" +E2Helper.Descriptions["egpAlign(xeo:nn)"] = "Changes the horizontal and vertical alignment. Works on: text and text layout. Numbers can be 0, 1 or 2" +E2Helper.Descriptions["egpAlpha(xeo:n)"] = "Changes the alpha (transparency) of an object" +E2Helper.Descriptions["egpAlpha(xeo:)"] = "Returns the alpha of the object" +E2Helper.Descriptions["egpAngle(xeo:n)"] = "Changes the angle of the object" +E2Helper.Descriptions["egpAngle(xeo:)"] = "Returns the angle of the object" +E2Helper.Descriptions["egpAngle(xeo:xv2xv2n)"] = "Rotates the object around the first vec2 with the second vec2 as offset at angle N" +E2Helper.Descriptions["egpColor(xeo:)"] = "Returns the color of the object as 3D vector" +E2Helper.Descriptions["egpColor(xeo:nnnn)"] = "Changes the color and alpha of the object" +E2Helper.Descriptions["egpColor(xeo:xv4)"] = "Changes the color and alpha of the object" +E2Helper.Descriptions["egpColor(xeo:v)"] = "Changes the color of the object" +E2Helper.Descriptions["egpColor4(xeo:)"] = "Returns the color of the object as 4D vector (including alpha)" +E2Helper.Descriptions["egpFidelity(xeo:)"] = "Returns the fidelity of the object" +E2Helper.Descriptions["egpFidelity(xeo:n)"] = "Changes the fidelity of the object (the number of vertices the circle will use)" +E2Helper.Descriptions["egpFont(xeo:sn)"] = "Changes the font and size of the text object" +E2Helper.Descriptions["egpFont(xeo:s)"] = "Changes the font of the text object" +E2Helper.Descriptions["egpMaterial(xeo:)"] = "Returns the material of the object" +E2Helper.Descriptions["egpMaterial(xeo:s)"] = "Changes the material of the object" +E2Helper.Descriptions["egpMaterialFromScreen(xeo:e)"] = "Sets the material of the object to a current snapshot of the target screen. Note that this only works for players which see both the egp as well the target screen at that time" +E2Helper.Descriptions["egpOrder(xeo:n)"] = "Sets the order at which the object will be rendered" +E2Helper.Descriptions["egpOrder(xeo:)"] = "Returns the order at which the object is rendered" +E2Helper.Descriptions["egpParent(xeo:)"] = "Returns the index of the parent object" +E2Helper.Descriptions["egpParent(xeo:e)"] = "Parents the 3D tracker object to an entity" +E2Helper.Descriptions["egpParent(xeo:n)"] = "Parents the object to another object. Parented objects' positions are local to their parent" +E2Helper.Descriptions["egpParent(xeo:xeo)"] = "Parents the object to another object. Parented objects' positions are local to their parent" +E2Helper.Descriptions["egpParent(xeo:xeoxeo)"] = "Parents the object to another object. Parented objects' positions are local to their parent" +E2Helper.Descriptions["egpParentToCursor(xeo:)"] = "Parents the object to player's cursor" +E2Helper.Descriptions["egpParentIndex(xeo:)"] = "Returns the index of the parent object" +E2Helper.Descriptions["egpUnParent(xeo:)"] = "Un-parents the object" +E2Helper.Descriptions["egpPos(xeo:)"] = "Returns the position of the object" +E2Helper.Descriptions["egpPos(xeo:xv2)"] = "Changes the position of the object" +E2Helper.Descriptions["egpPos(xeo:v)"] = "Changes the world position of the 3D tracker object" +E2Helper.Descriptions["egpRadius(xeo:n)"] = "Changes the corner radius of the rounded box object" +E2Helper.Descriptions["egpRadius(xeo:)"] = "Returns the corcner radius of the rounded box object" +E2Helper.Descriptions["egpRemove(xeo:)"] = "Removes the object from the screen" +E2Helper.Descriptions["egpRemove(xwl:xeo)"] = "Removes the object from the screen" +E2Helper.Descriptions["egpSetText(xeo:s)"] = "Changes the text of the text object" +E2Helper.Descriptions["egpSetText(xeo:ssn)"] = "Changes the text, font, and text size of the text object" +E2Helper.Descriptions["egpSize(xeo:)"] = "Returns the size of the object" +E2Helper.Descriptions["egpSize(xeo:n)"] = "Changes the size of the text/line/outline object" +E2Helper.Descriptions["egpSize(xeo:xv2)"] = "Changes the size of the object" +E2Helper.Descriptions["egpSizeNum(xeo:)"] = "Returns the size of the text/line/outline object" +E2Helper.Descriptions["egpTrackerParent(xeo:)"] = "Returns the parent entity of the 3D tracker object" + +E2Helper.Descriptions["egpCopy(xwl:nxeo)"] = "Copies the settings of the second object into the first. If the first object does not exist, it's created" +E2Helper.Descriptions["egpConnectedUsers(xwl:)"] = "Returns an array of players connected to the EGP" +E2Helper.Descriptions["egpCursor(xwl:e)"] = "Returns the specified player's aim position on the screen" +E2Helper.Descriptions["egpGlobalPos(xeo:)"] = "Returns the \"global\" (= it takes the parents' positions into consideration) position as a 3D vector. X and Y being the 2D X,Y coordinates, while Z is the angle" +E2Helper.Descriptions["egpGlobalVertices(xeo:)"] = "Returns an array of 2D vectors with the \"global\" positions of the vertices in the object" +E2Helper.Descriptions["egpHasObject(xwl:xeo)"] = "Returns 1 if the object exists on the screen, 0 if not" +E2Helper.Descriptions["egpObjectContainsPoint(xeo:xv2)"] = "Returns 1 if the object with specified index contains the specified point" +E2Helper.Descriptions["egpFiltering(xeo:n)"] = "Changes the texture filter used to draw the object. Works on objects that draw a material. See _TEXFILTER constants (POINT=sharp, ANISOTROPIC=blurry/default)" +E2Helper.Descriptions["egpVertices(xeo:)"] = "Returns an array of the vertices of the object" +E2Helper.Descriptions["egpObjectType(xeo:)"] = "Returns the type of the object" +E2Helper.Descriptions["egpobject(xwl:n)"] = "Returns the EGPObject at the index" +E2Helper.Descriptions["noegpobject"] = "Returns a NULL egpobject." +E2Helper.Descriptions["toString(xeo:)"] = "Returns a string representation of the EGPObject" +E2Helper.Descriptions["toString(xeo)"] = "Returns a string representation of the EGPObject" -- (de)serialization E2Helper.Descriptions["glonDecode(s)"] = "Decodes a string into an array using GLON" From c7ff1ff7d5fc27777a7e30a82651fd24704f64bb Mon Sep 17 00:00:00 2001 From: Denneisk Date: Tue, 29 Aug 2023 20:44:40 -0400 Subject: [PATCH 10/28] Make EGP:EditObject call Obj:EditObject Method will be removed in a later PR --- .../gmod_wire_egp/lib/egplib/objectcontrol.lua | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua index 5d4729646b..3a7e396206 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua @@ -252,15 +252,8 @@ function EGP:CreateObject( Ent, ObjID, Settings ) end end -function EGP:EditObject( Obj, Settings ) - local ret = false - for k,v in pairs( Settings ) do - if (Obj[k] ~= nil and Obj[k] ~= v) then - Obj[k] = v - ret = true - end - end - return ret +function EGP:EditObject(obj, settings) + return obj:EditObject(settings) end From a0d00e14e85545defb3a1e1fcc5e000c95d0261c Mon Sep 17 00:00:00 2001 From: Denneisk Date: Wed, 6 Sep 2023 23:50:40 -0400 Subject: [PATCH 11/28] Various additions - Added wirelink:egpCreate, creates an EGP Object prototype that is not initialized - Added egpobject:initialize to initialize EGP Object prototypes - Added xeo:unload(), removes the object while keeping its object intact - Added xeo:isLoaded() to see if object is initialized - Added xeo:egpIndex(n) to set and replace indexes of EGP Objects - Added xeo:egpSize(nn), :egpPos(nn), :egpPos(nnn) to better facilitate moving operations - Added xeo:egpPosAng(), returns vector of x, y, angle - Added xeo:egpPos(nnnn), sets x, y, x2, and y2 for lines - Added xeo:egpSetVertices(...), sets vertices of EGP Object - Added xeo:egpCopy(xeo) to copy one EGP object to another - Added angle to EGP baseObj and baseObj:SetPos - Nodiscard a bunch of functions - Changed EGP.Objects to use lowercase name in most cases - Bug fix for xwl:egpParent(xeoxeo) - Deduplicated some E2Descriptions --- .../lib/egplib/objectcontrol.lua | 19 +- .../gmod_wire_expression2/core/egpobjects.lua | 300 ++++++++++++++++-- lua/wire/client/e2descriptions.lua | 75 ++--- 3 files changed, 314 insertions(+), 80 deletions(-) diff --git a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua index 3a7e396206..0b41f4b826 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua @@ -12,6 +12,7 @@ local baseObj = {} baseObj.ID = 0 baseObj.x = 0 baseObj.y = 0 +baseObj.angle = 0 baseObj.w = 0 baseObj.h = 0 baseObj.r = 255 @@ -56,10 +57,11 @@ function baseObj:EditObject(args) return ret end baseObj.Initialize = baseObj.EditObject -function baseObj:SetPos(x, y) +function baseObj:SetPos(x, y, angle) local ret = false if self.x ~= x then self.x, ret = x, true end if self.y ~= y then self.y, ret = y, true end + if angle and self.angle ~= angle then self.angle, ret = angle, true end return ret end function baseObj:Set(member, value) @@ -90,23 +92,24 @@ end ---------------------------- function EGP:NewObject( Name ) - if self.Objects[Name] then return self.Objects[Name] end + local lower = Name:lower() -- Makes my life easier + if self.Objects[lower] then return self.Objects[lower] end -- Create table - self.Objects[Name] = {} + self.Objects[lower] = {} -- Set info - self.Objects[Name].Name = Name - table.Inherit(self.Objects[Name], self.Objects.Base) + self.Objects[lower].Name = Name + table.Inherit(self.Objects[lower], self.Objects.Base) -- Create lookup table local ID = table.Count(self.Objects) - self.Objects[Name].ID = ID + self.Objects[lower].ID = ID self.Objects.Names[Name] = ID -- Inverted lookup table - self.Objects.Names_Inverted[ID] = Name + self.Objects.Names_Inverted[ID] = lower - return setmetatable(self.Objects[Name], M_EGPObject) + return setmetatable(self.Objects[lower], M_EGPObject) end local folder = "entities/gmod_wire_egp/lib/objects/" diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index 830554d4fa..ab630718ad 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -7,6 +7,31 @@ local M_NULL_EGPOBJECT = { __tostring = function(self) return "[EGPObject] NULL" local NULL_EGPOBJECT = setmetatable({}, M_NULL_EGPOBJECT) local M_EGPObject = getmetatable(EGP.Objects.Base) +-- Table of allowed arguments and their types +local EGP_ALLOWED_ARGS = + { + x = "n", + x2 = "n", + y = "n", + y2 = "n", + z = "n", + w = "n", + h = "n", + r = "n", + g = "n", + b = "n", + a = "n", + size = "n", + angle = "n", + fidelity = "n", + radius = "n", + valign = "n", + halign = "n", + text = "s", + font = "s", + material = "s", + } + local function Update(self, this) self.data.EGP.UpdatesNeeded[this] = true end @@ -56,6 +81,84 @@ end ---- Functions +---------------------------- +-- Creation/modification +---------------------------- + +__e2setcost(10) + +local maxobjects = EGP.ConVars.MaxObjects +-- To be implemented when index LUT is implemented/EGP.HasValue is O(1). The following is therefore not conclusive. +--[[ +e2function egpobject wirelink:egpCreate(string type) + local obj = EGP.Objects[type:lower()] + if not obj then return self:throw(string.format("Invalid object type '%d'!", type), NULL_EGPOBJECT) end + obj = table.Copy(obj) + obj.EGP = this + local index = EGP.NextFreeIndex(this) + if not index then return self:throw(string.format("EGP Object limit reached for EGP [%d].", this:EntIndex()), NULL_EGPOBJECT) end + obj._notInitialized = true + obj.index = index + return obj +end +]] +[nodiscard] +e2function egpobject wirelink:egpCreate(string type, index) + local obj = EGP.Objects[type:lower()] + if not obj then return self:throw(string.format("Invalid object type '%d'!", type), NULL_EGPOBJECT) end + obj = table.Copy(obj) + obj.EGP = this + obj._notInitialized = true + obj.index = math.Round(math.Clamp(index, 1, maxobjects:GetInt())) + return obj +end + +e2function void egpobject:initialize(table arguments) + if not this._notInitialized then return end + local egp = this.EGP + local converted = {} + + for k, v in pairs(arguments.s) do + if EGP_ALLOWED_ARGS[k] == arguments.stypes[k] or false then converted[k] = v end + end + + this._notInitialized = nil + this:Initialize(converted) + + local bool, k = EGP:HasObject(egp, this.index) + if bool then table.remove(egp.RenderTable, k) end + + table.insert(egp.RenderTable, this) + EGP:DoAction(egp, self, "SendObject", this) + Update(self, egp) +end + +e2function void egpobject:initialize() + if not this._notInitialized then return end + local egp = this.EGP + + this._notInitialized = nil + this:Initialize({}) + + local bool, k = EGP:HasObject(egp, this.index) + if bool then table.remove(egp.RenderTable, k) end + + table.insert(egp.RenderTable, this) + EGP:DoAction(egp, self, "SendObject", this) + Update(self, egp) +end + +e2function egpobject egpobject:modify(table arguments) + local egp = this.EGP + local converted = {} + + for k, v in pairs(arguments.s) do + if EGP_ALLOWED_ARGS[k] == arguments.stypes[k] or false then converted[k] = v end + end + + if this:EditObject(converted) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) return this end +end + __e2setcost(7) ---------------------------- @@ -138,6 +241,22 @@ end -------------------------------------------------------- __e2setcost(7) +[nodiscard] +e2function number egpobject:egpIndex(index) + if not isValid(this) then return self:throw("Invalid EGP Object", -1) end + if this.index == index then return -1 end + local egp = this.EGP + local ret = 0 + + local bool, k = EGP:HasObject(egp, index) + if bool then table.remove(egp.RenderTable, k) ret = 1 end + + this.index = index + + EGP:DoAction(egp, self, "SendObject", this) + Update(self, egp) + return ret +end ---------------------------- -- Size @@ -149,6 +268,13 @@ e2function void egpobject:egpSize(vector2 size) if this:EditObject({ w = size[1], h = size[2] }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end +e2function void egpobject:egpSize(width, height) + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:EditObject({ w = width, h = height }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + e2function void egpobject:egpSize(number size) if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP @@ -166,6 +292,20 @@ e2function void egpobject:egpPos(vector2 pos) if this:SetPos(pos[1], pos[2]) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end +e2function void egpobject:egpPos(x, y) + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:SetPos(x, y) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + +e2function void egpobject:egpPos(x, y, x2, y2) + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:SetPos(x, y, nil, x2, y2) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + ---------------------------- -- Angle ---------------------------- @@ -173,12 +313,19 @@ e2function void egpobject:egpAngle(number angle) if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end - if this:EditObject({ angle = angle, _angle = angle }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end + if this:Set("angle", angle) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end ------------- -- Position & Angle ------------- +e2function void egpobject:egpPos(x, y, angle) + if not isValid(this) then return self:throw("Invalid EGP Object", nil) end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + if this:SetPos(x, y, angle) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end +end + e2function void egpobject:egpAngle(vector2 worldpos, vector2 axispos, number angle) if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP @@ -198,6 +345,68 @@ e2function void egpobject:egpAngle(vector2 worldpos, vector2 axispos, number ang end end +---------------------------- +-- Polys +---------------------------- + +local maxVertices = EGP.ConVars.MaxVertices + +e2function void egpobject:egpSetVertices(array verts) + if not isValid(this) then return self:throw("Invalid EGP Object") end + if not this.vertices then return end + if #verts < 3 then return end + local max = maxVertices:GetInt() + + local vertices = {} + for _, v in ipairs(verts) do + if istable(v) then + local n = #vertices + if n > max then + break + elseif #v == 2 then + vertices[n + 1] = { x = v[1], y = v[2] } + elseif #v == 4 then + vertices[n + 1] = { x= v[1], y = v[2], u = v[3], v = v[4] } + end + end + end + + if this:Set("vertices", vertices) then + local egp = this.EGP + EGP:InsertQueue(egp, self.player, EGP._SetVertex, "SetVertex", this.index, vertices, true) -- wtf? + Update(self, egp) + end +end + +e2function void egpobject:egpSetVertices(...args) + if not isValid(this) then return self:throw("Invalid EGP Object") end + if not this.vertices then return end + if #args < 3 then return end + local max = maxVertices:GetInt() + + local vertices = {} + for k, v in ipairs(args) do + if istable(v) then + local n = #vertices + if n > max then + break + elseif typeids[k] == "xv2" then + vertices[n + 1] = { x= v[1], y = v[2] } + elseif typeids[k] == "xv4" then + vertices[n + 1] = { x= v[1], y = v[2], u = v[3], v = v[4] } + end + end + end + + if this:Set("vertices", vertices) then + local egp = this.EGP + EGP:InsertQueue(egp, self.player, EGP._SetVertex, "SetVertex", this.index, vertices, true) -- wtf? + Update(self, egp) + end +end + + + ---------------------------- -- Color ---------------------------- @@ -259,6 +468,7 @@ e2function void egpobject:egpFidelity(number fidelity) if this:EditObject({ fidelity = math.Clamp(fidelity, 3, 180) }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end +[nodiscard] e2function number egpobject:egpFidelity() return this.fidelity or -1 end @@ -282,7 +492,7 @@ e2function void egpobject:egpParent(number parentindex) end e2function void wirelink:egpParent(egpobject child, egpobject parent) - if not isValid(child) or not isValid(parent) then return self:throw("Invalid EGP Object", nil) end + if not (isValid(child) or isValid(parent) or child.EGP == this or parent.EGP == this) then return self:throw("Invalid EGP Object", nil) end if not EGP:IsAllowed(self, this) then return end if EGP:SetParent(this, child, parent) then EGP:DoAction(this, self, "SendObject", child) Update(self, this) end end @@ -303,6 +513,7 @@ e2function void egpobject:egpParent(entity parent) end -- Returns the entity a tracker is parented to +[nodiscard] e2function entity egpobject:egpTrackerParent() if not isValid(this) then return self:throw("Invalid EGP Object", nil) end return IsValid(this.parententity) and this.parententity or NULL @@ -322,6 +533,7 @@ e2function void egpobject:egpUnParent() if EGP:UnParent(egp, this) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end +[nodiscard] e2function number egpobject:egpParentIndex() if not isValid(this) then return self:throw("Invalid EGP Object", nil) end return this.parent or nil @@ -351,17 +563,34 @@ e2function void egpobject:egpRemove() Update(self, egp) end +e2function void egpobject:unload() + if not isValid(this) then return end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + + EGP:DoAction(egp, self, "RemoveObject", this.index) + this._notInitialized = true + Update(self, egp) +end + +[nodiscard] +e2function number egpobject:isLoaded() + return isValid(this) and not this._notInitialized and 1 or 0 +end + -------------------------------------------------------- -- Get functions -------------------------------------------------------- __e2setcost(20) +[nodiscard] e2function vector egpobject:egpGlobalPos() if not isValid(this) then return self:throw("Invalid EGP Object", vector_origin) end local _, posang = EGP:GetGlobalPos(this.EGP, this) return Vector(posang.x, posang.y, posang.angle) end +[nodiscard] e2function array egpobject:egpGlobalVertices() if not isValid(this) then return self:throw("Invalid EGP Object", {}) end local hasvertices, data = EGP:GetGlobalPos(this.EGP, this) @@ -384,6 +613,7 @@ e2function array egpobject:egpGlobalVertices() end end +[nodiscard] e2function number wirelink:egpHasObject(egpobject object) return this == object.EGP and 1 or 0 end @@ -391,46 +621,62 @@ end __e2setcost(3) +[nodiscard] e2function vector2 egpobject:egpPos() if not isValid(this) then return self:throw("Invalid EGP Object", { -1, -1 }) end return (this.x and this.y and { this.x, this.y }) or { -1, -1 } end + +[nodiscard] +e2function vector egpobject:egpPosAng() + if not isValid(this) then return self:throw("Invalid EGP Object", Vector(-1, -1, -1)) end + return (this.x and this.y and this.angle and Vector(this.x, this.y, this.angle)) or Vector(-1, -1, -1) +end + +[nodiscard] e2function vector2 egpobject:egpSize() if not isValid(this) then return self:throw("Invalid EGP Object", { -1, -1 }) end return (this.w and this.h and { this.w, this.h }) or { -1, -1 } end +[nodiscard] e2function number egpobject:egpSizeNum() if not isValid(this) then return self:throw("Invalid EGP Object", -1) end return this.size or -1 end +[nodiscard] e2function vector4 egpobject:egpColor4() if not isValid(this) then return self:throw("Invalid EGP Object", { -1, -1, -1, -1 }) end return (this.r and this.g and this.b and this.a and { this.r, this.g, this.b, this.a }) or { -1, -1, -1, -1 } end +[nodiscard] e2function vector egpobject:egpColor() if not isValid(this) then return self:throw("Invalid EGP Object", -1) end return (this.r and this.g and this.b and Vector(this.r, this.g, this.b)) or Vector(-1, -1, -1) end +[nodiscard] e2function number egpobject:egpAlpha() if not isValid(this) then return self:throw("Invalid EGP Object", -1) end return this.a or -1 end +[nodiscard] e2function number egpobject:egpAngle() if not isValid(this) then return self:throw("Invalid EGP Object", -1) end return this.angle or -1 end +[nodiscard] e2function string egpobject:egpMaterial() if not isValid(this) then return self:throw("Invalid EGP Object", "") end return this.material or "" end +[nodiscard] e2function number egpobject:egpRadius() if not isValid(this) then return self:throw("Invalid EGP Object", -1) end return this.radius or -1 @@ -438,6 +684,7 @@ end __e2setcost(10) +[nodiscard] e2function array egpobject:egpVertices() if this.vertices then local ret = {} @@ -459,8 +706,9 @@ end -------------------------------------------------------- __e2setcost(4) +[nodiscard] e2function string egpobject:egpObjectType() - return EGP.Objects.Names_Inverted[this.ID] or "Unknown" + return this.Name or "Unknown" end -------------------------------------------------------- @@ -469,6 +717,7 @@ end __e2setcost(15) +[nodiscard] e2function egpobject wirelink:egpCopy(number index, egpobject from) if not EGP:IsAllowed(self, this) then return end if not isValid(from) then return self:throw("Invalid EGPObject", NULL_EGPOBJECT) end @@ -480,14 +729,28 @@ e2function egpobject wirelink:egpCopy(number index, egpobject from) end end +e2function void egpobject:egpCopy(egpobject from) + if not EGP:IsAllowed(self, this) then return end + if not isValid(from) then return self:throw("Invalid EGPObject") end + if from then + local copy = table.Copy(from) + copy.index = this.index + copy.EGP = this.EGP + local bool, obj = EGP:CreateObject(copy.EGP, from.ID, copy, self.player) + if bool then EGP:DoAction(this, self, "SendObject", obj) Update(self, this) return end + end +end + __e2setcost(10) +[nodiscard] e2function number egpobject:egpObjectContainsPoint(vector2 point) return isValid(this) and this:Contains(point[1], point[2]) and 1 or 0 end __e2setcost(5) +[nodiscard] e2function egpobject wirelink:egpobject(number index) if not EGP:IsAllowed(self, this) then return end local _, _, obj = EGP:HasObject(this, index) @@ -496,51 +759,30 @@ end __e2setcost(2) +[nodiscard] e2function string egpobject:egpObjectType() return isValid(this) and EGP.Objects.Names_Inverted[this.ID] or "Unknown" end __e2setcost(1) +[nodiscard] e2function egpobject noegpobject() return NULL_EGPOBJECT end +[nodiscard] e2function string toString(egpobject egpo) return tostring(egpo) -end +end +[nodiscard] e2function string egpobject:toString() = e2function string toString(egpobject egpo) -------------------------------------------------------- -- Array Index Operators -------------------------------------------------------- --- Table of allowed arguments and their types -local EGP_ALLOWED_ARGS = - { - x = "n", - x2 = "n", - y = "n", - y2 = "n", - z = "n", - w = "n", - h = "n", - r = "n", - g = "n", - b = "n", - a = "n", - size = "n", - angle = "n", - fidelity = "n", - radius = "n", - valign = "n", - halign = "n", - text = "s", - font = "s", - material = "s", - } - registerCallback("postinit", function() local fixDefault = E2Lib.fixDefault for _, v in pairs(wire_expression_types) do diff --git a/lua/wire/client/e2descriptions.lua b/lua/wire/client/e2descriptions.lua index 8b8fae92f4..0b881ba0f2 100644 --- a/lua/wire/client/e2descriptions.lua +++ b/lua/wire/client/e2descriptions.lua @@ -1385,31 +1385,31 @@ E2Helper.Descriptions["bNot(nn)"] = "Performs a binary Not. The second argument E2Helper.Descriptions["egpAlign(xwl:nn)"] = "Changes the horizontal alignment. Works on: text and text layout. Number can be 0, 1 or 2" E2Helper.Descriptions["egpAlign(xwl:nnn)"] = "Changes the horizontal and vertical alignment. Works on: text and text layout. Numbers can be 0, 1 or 2" E2Helper.Descriptions["egpAlpha(xwl:nn)"] = "Changes the alpha (transparency) of an object" -E2Helper.Descriptions["egpAlpha(xwl:n)"] = "Returns the alpha of the object" +E2Helper.Descriptions["egpAlpha"] = "Returns the alpha of the object" E2Helper.Descriptions["egpAngle(xwl:nn)"] = "Changes the angle of the object" -E2Helper.Descriptions["egpAngle(xwl:n)"] = "Returns the angle of the object" +E2Helper.Descriptions["egpAngle"] = "Returns the angle of the object" E2Helper.Descriptions["egpAngle(xwl:nxv2xv2n)"] = "Rotates the object around the first vec2 with the second vec2 as offset at angle N" -E2Helper.Descriptions["egpColor(xwl:n)"] = "Returns the color of the object as 3D vector" +E2Helper.Descriptions["egpColor"] = "Returns the color of the object as 3D vector" E2Helper.Descriptions["egpColor(xwl:nnnnn)"] = "Changes the color and alpha of the object" E2Helper.Descriptions["egpColor(xwl:nxv4)"] = "Changes the color and alpha of the object" E2Helper.Descriptions["egpColor(xwl:nv)"] = "Changes the color of the object" -E2Helper.Descriptions["egpColor4(xwl:n)"] = "Returns the color of the object as 4D vector (including alpha)" -E2Helper.Descriptions["egpFidelity(xwl:n)"] = "Returns the fidelity of the object" +E2Helper.Descriptions["egpColor4"] = "Returns the color of the object as 4D vector (including alpha)" +E2Helper.Descriptions["egpFidelity"] = "Returns the fidelity of the object" E2Helper.Descriptions["egpFidelity(xwl:nn)"] = "Changes the fidelity of the object (the number of vertices the circle will use)" E2Helper.Descriptions["egpFont(xwl:nsn)"] = "Changes the font and size of the text object" -E2Helper.Descriptions["egpFont(xwl:ns)"] = "Changes the font of the text object" -E2Helper.Descriptions["egpMaterial(xwl:n)"] = "Returns the material of the object" +E2Helper.Descriptions["egpFont"] = "Changes the font of the text object" +E2Helper.Descriptions["egpMaterial"] = "Returns the material of the object" E2Helper.Descriptions["egpMaterial(xwl:ns)"] = "Changes the material of the object" E2Helper.Descriptions["egpMaterialFromScreen(xwl:ne)"] = "Sets the material of the object to a current snapshot of the target screen. Note that this only works for players which see both the egp as well the target screen at that time" E2Helper.Descriptions["egpOrder(xwl:nn)"] = "Sets the order at which the object will be rendered" -E2Helper.Descriptions["egpOrder(xwl:n)"] = "Returns the order at which the object is rendered" -E2Helper.Descriptions["egpParent(xwl:n)"] = "Returns the index of the parent object" +E2Helper.Descriptions["egpOrder"] = "Returns the order at which the object is rendered" +E2Helper.Descriptions["egpParent"] = "Returns the index of the parent object" E2Helper.Descriptions["egpParent(xwl:ne)"] = "Parents the 3D tracker object to an entity" E2Helper.Descriptions["egpParent(xwl:nn)"] = "Parents the object to another object. Parented objects' positions are local to their parent" E2Helper.Descriptions["egpParentToCursor(xwl:n)"] = "Parents the object to player's cursor" E2Helper.Descriptions["egpUnParent(xwl:n)"] = "Un-parents the object" E2Helper.Descriptions["egpPos(xwl:n)"] = "Returns the position of the object" -E2Helper.Descriptions["egpPos(xwl:nxv2)"] = "Changes the position of the object" +E2Helper.Descriptions["egpPos"] = "Changes the position of the object" E2Helper.Descriptions["egpPos(xwl:nv)"] = "Changes the world position of the 3D tracker object" E2Helper.Descriptions["egpQueue()"] = "Returns the number of items in your queue" E2Helper.Descriptions["egpQueueClk(e)"] = "Returns 1 if the current execution was caused by the EGP queue system of specified screen" @@ -1420,8 +1420,8 @@ E2Helper.Descriptions["egpQueuePlayer()"] = "Returns the player which ordered th E2Helper.Descriptions["egpQueueScreen()"] = "Returns the screen entity which the queue finished sending items for" E2Helper.Descriptions["egpQueueScreenWirelink()"] = "Returns the screen wirelink which the queue finished sending items for" E2Helper.Descriptions["egpRadius(xwl:nn)"] = "Changes the corner radius of the rounded box object" -E2Helper.Descriptions["egpRadius(xwl:n)"] = "Returns the corcner radius of the rounded box object" -E2Helper.Descriptions["egpRemove(xwl:n)"] = "Removes the object from the screen" +E2Helper.Descriptions["egpRadius"] = "Returns the corcner radius of the rounded box object" +E2Helper.Descriptions["egpRemove"] = "Removes the object from the screen" E2Helper.Descriptions["egpResolution(xwl:xv2xv2)"] = "Sets the scale of the screen such that the top left corner is equal to the first vector and the bottom right corner is equal to the second vector" E2Helper.Descriptions["egpScale(xwl:xv2xv2)"] = "Sets the scale of the screen's X axis to the first vector and Y axis to the second vector" E2Helper.Descriptions["egpScrH(e)"] = "Returns the player's screen resolution height" @@ -1430,20 +1430,19 @@ E2Helper.Descriptions["egpScrSize(e)"] = "Returns the player's screen resolution E2Helper.Descriptions["egpSetText(xwl:ns)"] = "Changes the text of the text object" E2Helper.Descriptions["egpSize(xwl:n)"] = "Returns the size of the object" E2Helper.Descriptions["egpSize(xwl:nn)"] = "Changes the size of the text/line/outline object" -E2Helper.Descriptions["egpSize(xwl:nxv2)"] = "Changes the size of the object" -E2Helper.Descriptions["egpSizeNum(xwl:n)"] = "Returns the size of the text/line/outline object" +E2Helper.Descriptions["egpSize"] = "Changes the width and height of the object" +E2Helper.Descriptions["egpSizeNum"] = "Returns the size of the text/line/outline object" E2Helper.Descriptions["egpToWorld(xwl:xv2)"] = "Converts a 2D vector on the screen or emitter into a 3D vector in the world" -E2Helper.Descriptions["egpTrackerParent(xwl:n)"] = "Returns the parent entity of the 3D tracker object" +E2Helper.Descriptions["egpTrackerParent"] = "Returns the parent entity of the 3D tracker object" E2Helper.Descriptions["egpCanSendUmsg()"] = "Returns 1 if you can send an usermessage at the moment, 0 otherwise" E2Helper.Descriptions["egpClear(xwl:)"] = "Clears the EGP screen" E2Helper.Descriptions["egpClearQueue()"] = "Clears your entire queue" -E2Helper.Descriptions["egpCopy(xwl:nn)"] = "Copies the settings of the second object into the first. If the first object does not exist, it's created" -E2Helper.Descriptions["egpConnectedUsers(xwl:)"] = "Returns an array of players connected to the EGP" +E2Helper.Descriptions["egpCopy"] = "Copies the settings of the second object into the first. If the first object does not exist, it's created" E2Helper.Descriptions["egpCursor(xwl:e)"] = "Returns the specified player's aim position on the screen" E2Helper.Descriptions["egpDrawTopLeft(xwl:n)"] = "Set to 1 to make boxes, outline boxes, rounded boxes, and rounded outline boxes draw from the top left corner instead of from the center" -E2Helper.Descriptions["egpGlobalPos(xwl:n)"] = "Returns the \"global\" (= it takes the parents' positions into consideration) position as a 3D vector. X and Y being the 2D X,Y coordinates, while Z is the angle" -E2Helper.Descriptions["egpGlobalVertices(xwl:n)"] = "Returns an array of 2D vectors with the \"global\" positions of the vertices in the object" +E2Helper.Descriptions["egpGlobalPos"] = "Returns the \"global\" (= it takes the parents' positions into consideration) position as a 3D vector. X and Y being the 2D X,Y coordinates, while Z is the angle" +E2Helper.Descriptions["egpGlobalVertices"] = "Returns an array of 2D vectors with the \"global\" positions of the vertices in the object" E2Helper.Descriptions["egpGlobalFiltering(xwl:n)"] = "Changes the texture filter used to draw all EGP Objects. Works only on EGP Screens. See _TEXFILTER constants (POINT=sharp, ANISOTROPIC=blurry/default)" E2Helper.Descriptions["egpHasObject(xwl:n)"] = "Returns 1 if the object with specified index exists on the screen, 0 if not" E2Helper.Descriptions["egpObjectContainsPoint(xwl:nxv2)"] = "Returns 1 if the object with specified index contains the specified point" @@ -1458,9 +1457,9 @@ E2Helper.Descriptions["egpMaxObjects()"] = "Returns the maximum amount of object E2Helper.Descriptions["egpMaxUmsgPerSecond()"] = "Returns the maximum number of usermessages you can send per second" E2Helper.Descriptions["egpNumObjects(xwl:)"] = "Returns the number of objects on the screen" E2Helper.Descriptions["egpRunOnQueue(xwl:n)"] = "Set to 1 if you want your E2 to be triggered once the queue has finished sending all items in the queue for the screen" -E2Helper.Descriptions["egpVertices(xwl:n)"] = "Returns an array of the vertices of the object" +E2Helper.Descriptions["egpVertices"] = "Returns an array of the vertices of the object" E2Helper.Descriptions["egpObjectIndexes(xwl:)"] = "Returns an array containing all object indexes being used" -E2Helper.Descriptions["egpObjectType(xwl:n)"] = "Returns the type of the object with specified index" +E2Helper.Descriptions["egpObjectType"] = "Returns the type of the object" E2Helper.Descriptions["egpObjectTypes(xwl:)"] = "Returns an array whose keys are bound to object index, and value being the type of particular object" E2Helper.Descriptions["egp3DTracker"] = "Creates a 3D tracker object at specified world position" @@ -1485,60 +1484,50 @@ E2Helper.Descriptions["egpTriangleOutline"] = "Creates a outline triangle with s E2Helper.Descriptions["egpWedge"] = "Creates a wedge object. Wedge objects are like circles, except they have a cake-piece-like mouth which you can change using egpSize" E2Helper.Descriptions["egpWedgeOutline"] = "Creates a outline wedge object. Wedge objects are like circles, except they have a cake-piece-like mouth which you can change using egpSize" +E2Helper.Descriptions["egpCreate(xwl:s)"] = "Creates an object prototype of the specified type. Note that you have to initialize the object before it's sent to the screen." +E2Helper.Descriptions["egpCreate(xwl:sn)"] = "Creates an object prototype of the specified type at the index. Note that you have to initialize the object before it's sent to the screen." +E2Helper.Descriptions["initialize(xeo:)"] = "Initializes an object prototype." +E2Helper.Descriptions["initialize(xeo:t)"] = "Initializes an object prototype with the provided arguments." +E2Helper.Descriptions["modify(xeo:t)"] = "Modifies an object with the provided arguments." + E2Helper.Descriptions["egpAlign(xeo:n)"] = "Changes the horizontal alignment. Works on: text and text layout. Number can be 0, 1 or 2" E2Helper.Descriptions["egpAlign(xeo:nn)"] = "Changes the horizontal and vertical alignment. Works on: text and text layout. Numbers can be 0, 1 or 2" E2Helper.Descriptions["egpAlpha(xeo:n)"] = "Changes the alpha (transparency) of an object" -E2Helper.Descriptions["egpAlpha(xeo:)"] = "Returns the alpha of the object" E2Helper.Descriptions["egpAngle(xeo:n)"] = "Changes the angle of the object" -E2Helper.Descriptions["egpAngle(xeo:)"] = "Returns the angle of the object" E2Helper.Descriptions["egpAngle(xeo:xv2xv2n)"] = "Rotates the object around the first vec2 with the second vec2 as offset at angle N" -E2Helper.Descriptions["egpColor(xeo:)"] = "Returns the color of the object as 3D vector" E2Helper.Descriptions["egpColor(xeo:nnnn)"] = "Changes the color and alpha of the object" E2Helper.Descriptions["egpColor(xeo:xv4)"] = "Changes the color and alpha of the object" E2Helper.Descriptions["egpColor(xeo:v)"] = "Changes the color of the object" -E2Helper.Descriptions["egpColor4(xeo:)"] = "Returns the color of the object as 4D vector (including alpha)" -E2Helper.Descriptions["egpFidelity(xeo:)"] = "Returns the fidelity of the object" E2Helper.Descriptions["egpFidelity(xeo:n)"] = "Changes the fidelity of the object (the number of vertices the circle will use)" E2Helper.Descriptions["egpFont(xeo:sn)"] = "Changes the font and size of the text object" -E2Helper.Descriptions["egpFont(xeo:s)"] = "Changes the font of the text object" -E2Helper.Descriptions["egpMaterial(xeo:)"] = "Returns the material of the object" E2Helper.Descriptions["egpMaterial(xeo:s)"] = "Changes the material of the object" E2Helper.Descriptions["egpMaterialFromScreen(xeo:e)"] = "Sets the material of the object to a current snapshot of the target screen. Note that this only works for players which see both the egp as well the target screen at that time" E2Helper.Descriptions["egpOrder(xeo:n)"] = "Sets the order at which the object will be rendered" -E2Helper.Descriptions["egpOrder(xeo:)"] = "Returns the order at which the object is rendered" -E2Helper.Descriptions["egpParent(xeo:)"] = "Returns the index of the parent object" E2Helper.Descriptions["egpParent(xeo:e)"] = "Parents the 3D tracker object to an entity" E2Helper.Descriptions["egpParent(xeo:n)"] = "Parents the object to another object. Parented objects' positions are local to their parent" E2Helper.Descriptions["egpParent(xeo:xeo)"] = "Parents the object to another object. Parented objects' positions are local to their parent" -E2Helper.Descriptions["egpParent(xeo:xeoxeo)"] = "Parents the object to another object. Parented objects' positions are local to their parent" +E2Helper.Descriptions["egpParent(xwl:xeoxeo)"] = "Parents the object to another object. Parented objects' positions are local to their parent" E2Helper.Descriptions["egpParentToCursor(xeo:)"] = "Parents the object to player's cursor" E2Helper.Descriptions["egpParentIndex(xeo:)"] = "Returns the index of the parent object" E2Helper.Descriptions["egpUnParent(xeo:)"] = "Un-parents the object" E2Helper.Descriptions["egpPos(xeo:)"] = "Returns the position of the object" -E2Helper.Descriptions["egpPos(xeo:xv2)"] = "Changes the position of the object" +E2Helper.Descriptions["egpPosAng(xeo:)"] = "Returns the position (x, y) and angle (z) of the object" +E2Helper.Descriptions["egpPos(xeo:nnnn)"] = "Changes the position of the start and end of a line object, otherwise acts normally." E2Helper.Descriptions["egpPos(xeo:v)"] = "Changes the world position of the 3D tracker object" E2Helper.Descriptions["egpRadius(xeo:n)"] = "Changes the corner radius of the rounded box object" -E2Helper.Descriptions["egpRadius(xeo:)"] = "Returns the corcner radius of the rounded box object" -E2Helper.Descriptions["egpRemove(xeo:)"] = "Removes the object from the screen" -E2Helper.Descriptions["egpRemove(xwl:xeo)"] = "Removes the object from the screen" E2Helper.Descriptions["egpSetText(xeo:s)"] = "Changes the text of the text object" E2Helper.Descriptions["egpSetText(xeo:ssn)"] = "Changes the text, font, and text size of the text object" +E2Helper.Descriptions["egpSetVertices"] = "Sets the vertices of the object. Can use vector2 or vector4 for vertices." E2Helper.Descriptions["egpSize(xeo:)"] = "Returns the size of the object" E2Helper.Descriptions["egpSize(xeo:n)"] = "Changes the size of the text/line/outline object" -E2Helper.Descriptions["egpSize(xeo:xv2)"] = "Changes the size of the object" -E2Helper.Descriptions["egpSizeNum(xeo:)"] = "Returns the size of the text/line/outline object" -E2Helper.Descriptions["egpTrackerParent(xeo:)"] = "Returns the parent entity of the 3D tracker object" +E2Helper.Descriptions["isLoaded(xeo:)"] = "Returns 1 if the object is initialized." +E2Helper.Descriptions["unload(xeo:)"] = "Removes an object from the screen but keeps its data intact. You can still modify an unloaded object. Reload it by calling :initialize() on it." -E2Helper.Descriptions["egpCopy(xwl:nxeo)"] = "Copies the settings of the second object into the first. If the first object does not exist, it's created" E2Helper.Descriptions["egpConnectedUsers(xwl:)"] = "Returns an array of players connected to the EGP" E2Helper.Descriptions["egpCursor(xwl:e)"] = "Returns the specified player's aim position on the screen" -E2Helper.Descriptions["egpGlobalPos(xeo:)"] = "Returns the \"global\" (= it takes the parents' positions into consideration) position as a 3D vector. X and Y being the 2D X,Y coordinates, while Z is the angle" -E2Helper.Descriptions["egpGlobalVertices(xeo:)"] = "Returns an array of 2D vectors with the \"global\" positions of the vertices in the object" E2Helper.Descriptions["egpHasObject(xwl:xeo)"] = "Returns 1 if the object exists on the screen, 0 if not" E2Helper.Descriptions["egpObjectContainsPoint(xeo:xv2)"] = "Returns 1 if the object with specified index contains the specified point" E2Helper.Descriptions["egpFiltering(xeo:n)"] = "Changes the texture filter used to draw the object. Works on objects that draw a material. See _TEXFILTER constants (POINT=sharp, ANISOTROPIC=blurry/default)" -E2Helper.Descriptions["egpVertices(xeo:)"] = "Returns an array of the vertices of the object" -E2Helper.Descriptions["egpObjectType(xeo:)"] = "Returns the type of the object" E2Helper.Descriptions["egpobject(xwl:n)"] = "Returns the EGPObject at the index" E2Helper.Descriptions["noegpobject"] = "Returns a NULL egpobject." E2Helper.Descriptions["toString(xeo:)"] = "Returns a string representation of the EGPObject" From c69ffecfcf5c8ebcdde6c2ee94c376fae6dc7688 Mon Sep 17 00:00:00 2001 From: Denneisk Date: Thu, 7 Sep 2023 01:46:38 -0400 Subject: [PATCH 12/28] Minor bug fix --- lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua | 5 +++-- lua/entities/gmod_wire_expression2/core/egpobjects.lua | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua b/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua index 533ae364a1..05ca792720 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua @@ -304,13 +304,14 @@ if (SERVER) then function EGP:DoAction( Ent, E2, Action, ... ) if (Action == "SendObject") then local Data = {...} - if not Data[1] then return end + local obj = Data[1] + if not obj or obj._notInitialized then return end if (E2 and E2.entity and E2.entity:IsValid()) then E2.prf = E2.prf + 30 end - self:AddQueueObject( Ent, E2.player, SendObjects, Data[1] ) + self:AddQueueObject( Ent, E2.player, SendObjects, obj) elseif (Action == "RemoveObject") then local Data = {...} if not Data[1] then return end diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index ab630718ad..7abac64e93 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -400,7 +400,7 @@ e2function void egpobject:egpSetVertices(...args) if this:Set("vertices", vertices) then local egp = this.EGP - EGP:InsertQueue(egp, self.player, EGP._SetVertex, "SetVertex", this.index, vertices, true) -- wtf? + EGP:InsertQueue(egp, self.player, EGP._SetVertex, "SetVertex", this.index, vertices, true) Update(self, egp) end end From ad5054c04944ad2fe78d16c7f79bfe6496b4d800 Mon Sep 17 00:00:00 2001 From: Denneisk Date: Thu, 7 Sep 2023 04:08:35 -0400 Subject: [PATCH 13/28] Add order methods --- .../gmod_wire_expression2/core/egpobjects.lua | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index 7abac64e93..8c0d06efdf 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -159,11 +159,65 @@ e2function egpobject egpobject:modify(table arguments) if this:EditObject(converted) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) return this end end -__e2setcost(7) +-------------------------------------------------------- +-- Order +-------------------------------------------------------- + +__e2setcost(15) + +e2function void egpobject:egpOrder(order) + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + local bool, k = EGP:HasObject(egp, this.index) + if (bool) then + if EGP:SetOrder(egp, k, order) then + EGP:DoAction(egp, self, "SendObject", this) + Update(self, egp) + end + end +end + +e2function number egpobject:egpOrder() + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + local bool, k = EGP:HasObject(egp, this.index) + return bool and k or -1 +end + +e2function void egpobject:egpOrderAbove(abovethis) + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + local bool, k = EGP:HasObject(egp, this.index) + if bool then + if EGP:HasObject(egp, abovethis) then + if EGP:SetOrder(egp, k, abovethis, 1) then + EGP:DoAction(egp, self, "SendObject", this) + Update(self, egp) + end + end + end +end + +e2function void egpobject:egpOrderBelow(belowthis) + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + local bool, k = EGP:HasObject(egp, this.index) + if bool then + if EGP:HasObject(egp, belowthis) then + if EGP:SetOrder(egp, k, belowthis, -1) then + EGP:DoAction(egp, self, "SendObject", this) + Update(self, egp) + end + end + end +end ---------------------------- -- Set Text ---------------------------- + +__e2setcost(7) + e2function void egpobject:egpSetText(string text) if not isValid(this) then return self:throw("Invalid EGP Object", nil) end local egp = this.EGP From e613183b29fe38fb8993ed15d06c1608dbaa5580 Mon Sep 17 00:00:00 2001 From: Denneisk Date: Thu, 7 Sep 2023 12:15:17 -0400 Subject: [PATCH 14/28] Minor fix for removing objects that don't exist --- lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua b/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua index 05ca792720..ecc51ccdf4 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua @@ -314,7 +314,8 @@ if (SERVER) then self:AddQueueObject( Ent, E2.player, SendObjects, obj) elseif (Action == "RemoveObject") then local Data = {...} - if not Data[1] then return end + local obj = Data[1] + if not obj or obj._notInitialized then return end if (E2 and E2.entity and E2.entity:IsValid()) then E2.prf = E2.prf + 20 @@ -322,7 +323,7 @@ if (SERVER) then for i=1,#Ent.RenderTable do E2.prf = E2.prf + 0.3 - if Ent.RenderTable[i].index == Data[1] then + if Ent.RenderTable[i].index == obj then table.remove( Ent.RenderTable, i ) break end From a32393cb6a112554bfe1c9a5a14a0d73fd6915cb Mon Sep 17 00:00:00 2001 From: Denneisk Date: Sat, 9 Sep 2023 10:17:22 -0400 Subject: [PATCH 15/28] Removed egpCreate, bugfixes - Added auto-generated egp(index, table) constructors, replaces egpCreate - Added xeo:draw/:hide, replaces :initialize/:unload - Moved NULL_EGPOBJECT as a field of EGP - Made EGP:CreateObject() never return nil - Fixed some EGP functions erroneously returning nil - Changed xeo:egpOrderAbove/:egpOrderBelow to use EGP objects instead of index --- .../lib/egplib/objectcontrol.lua | 8 +- .../core/egpfunctions.lua | 148 ++++++++++------- .../gmod_wire_expression2/core/egpobjects.lua | 153 +++++++++--------- lua/wire/client/e2descriptions.lua | 61 ++++--- 4 files changed, 210 insertions(+), 160 deletions(-) diff --git a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua index 0b41f4b826..89deb37854 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua @@ -76,6 +76,10 @@ local M_EGPObject = {__tostring = function(self) return "[EGPObject] ".. self.Na setmetatable(baseObj, M_EGPObject) EGP.Objects.Base = baseObj +local M_NULL_EGPOBJECT = { __tostring = function(self) return "[EGPObject] NULL" end, __eq = function(a, b) return getmetatable(a) == getmetatable(b) end } +local NULL_EGPOBJECT = setmetatable({}, M_NULL_EGPOBJECT) +EGP.NULL_EGPOBJECT = NULL_EGPOBJECT + ---------------------------- -- Get Object ---------------------------- @@ -225,11 +229,11 @@ end ---------------------------- function EGP:CreateObject( Ent, ObjID, Settings ) - if not self:ValidEGP(Ent) then return false end + if not self:ValidEGP(Ent) then return false, NULL_EGPOBJECT end if not self.Objects.Names_Inverted[ObjID] then ErrorNoHalt("Trying to create nonexistant object! Please report this error to Divran at wiremod.com. ObjID: " .. ObjID .. "\n") - return false + return false, NULL_EGPOBJECT end if SERVER then Settings.index = math.Round(math.Clamp(Settings.index or 1, 1, self.ConVars.MaxObjects:GetInt())) end diff --git a/lua/entities/gmod_wire_expression2/core/egpfunctions.lua b/lua/entities/gmod_wire_expression2/core/egpfunctions.lua index 1413424fbb..09a2824ddb 100644 --- a/lua/entities/gmod_wire_expression2/core/egpfunctions.lua +++ b/lua/entities/gmod_wire_expression2/core/egpfunctions.lua @@ -1,3 +1,6 @@ + +local NULL_EGPOBJECT = EGP.NULL_EGPOBJECT + local function Update(self,this) self.data.EGP.UpdatesNeeded[this] = true end @@ -80,7 +83,7 @@ e2function void wirelink:egpOrder( number index, number order ) end e2function number wirelink:egpOrder( number index ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return -1 end local bool, k, v = EGP:HasObject( this, index ) if (bool) then return k @@ -124,31 +127,34 @@ __e2setcost(15) -- Box -------------------------------------------------------- e2function egpobject wirelink:egpBox( number index, vector2 pos, vector2 size ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["Box"], { index = index, w = size[1], h = size[2], x = pos[1], y = pos[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end -------------------------------------------------------- -- BoxOutline -------------------------------------------------------- e2function egpobject wirelink:egpBoxOutline( number index, vector2 pos, vector2 size ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["BoxOutline"], { index = index, w = size[1], h = size[2], x = pos[1], y = pos[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end -------------------------------------------------------- -- RoundedBox -------------------------------------------------------- e2function egpobject wirelink:egpRoundedBox( number index, vector2 pos, vector2 size ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["RoundedBox"], { index = index, w = size[1], h = size[2], x = pos[1], y = pos[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end e2function void wirelink:egpRadius( number index, number radius ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end local bool, k, v = EGP:HasObject( this, index ) if (bool) then if (EGP:EditObject( v, { radius = radius } )) then EGP:DoAction( this, self, "SendObject", v ) Update(self,this) end @@ -159,24 +165,27 @@ end -- RoundedBoxOutline -------------------------------------------------------- e2function egpobject wirelink:egpRoundedBoxOutline( number index, vector2 pos, vector2 size ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["RoundedBoxOutline"], { index = index, w = size[1], h = size[2], x = pos[1], y = pos[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end -------------------------------------------------------- -- Text -------------------------------------------------------- e2function egpobject wirelink:egpText( number index, string text, vector2 pos ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["Text"], { index = index, text = text, x = pos[1], y = pos[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end e2function egpobject wirelink:egpTextLayout( number index, string text, vector2 pos, vector2 size ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["TextLayout"], { index = index, text = text, x = pos[1], y = pos[2], w = size[1], h = size[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end __e2setcost(10) @@ -269,9 +278,9 @@ __e2setcost(20) local function maxvertices() return EGP.ConVars.MaxVertices:GetInt() end e2function egpobject wirelink:egpPoly( number index, ...args ) - if (!EGP:IsAllowed( self, this )) then return end - if (!EGP:ValidEGP( this )) then return self:throw("Invalid wirelink!", nil) end - if #args < 3 then return end -- No less than 3 + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end + if (!EGP:ValidEGP( this )) then return self:throw("Invalid wirelink!", NULL_EGPOBJECT) end + if #args < 3 then return NULL_EGPOBJECT end -- No less than 3 local max = maxvertices() @@ -290,13 +299,14 @@ e2function egpobject wirelink:egpPoly( number index, ...args ) end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["Poly"], { index = index, vertices = vertices }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end e2function egpobject wirelink:egpPoly( number index, array args ) - if (!EGP:IsAllowed( self, this )) then return end - if (!EGP:ValidEGP( this )) then return self:throw("Invalid wirelink!", nil) end - if (#args<3) then return end -- No less than 3 + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end + if (!EGP:ValidEGP( this )) then return self:throw("Invalid wirelink!", NULL_EGPOBJECT) end + if (#args<3) then return NULL_EGPOBJECT end -- No less than 3 local max = maxvertices() @@ -315,7 +325,8 @@ e2function egpobject wirelink:egpPoly( number index, array args ) end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["Poly"], { index = index, vertices = vertices }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end -------------------------------------------------------- @@ -323,9 +334,9 @@ end -------------------------------------------------------- e2function egpobject wirelink:egpPolyOutline( number index, ...args ) - if (!EGP:IsAllowed( self, this )) then return end - if (!EGP:ValidEGP( this )) then return self:throw("Invalid wirelink!", nil) end - if #args < 3 then return end -- No less than 3 + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end + if (!EGP:ValidEGP( this )) then return self:throw("Invalid wirelink!", NULL_EGPOBJECT) end + if #args < 3 then return NULL_EGPOBJECT end -- No less than 3 local max = maxvertices() @@ -344,13 +355,14 @@ e2function egpobject wirelink:egpPolyOutline( number index, ...args ) end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["PolyOutline"], { index = index, vertices = vertices }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end e2function egpobject wirelink:egpPolyOutline( number index, array args ) - if (!EGP:IsAllowed( self, this )) then return end - if (!EGP:ValidEGP( this )) then return self:throw("Invalid wirelink!", nil) end - if (#args<3) then return end -- No less than 3 + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end + if (!EGP:ValidEGP( this )) then return self:throw("Invalid wirelink!", NULL_EGPOBJECT) end + if (#args<3) then return NULL_EGPOBJECT end -- No less than 3 local max = maxvertices() @@ -369,7 +381,8 @@ e2function egpobject wirelink:egpPolyOutline( number index, array args ) end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["PolyOutline"], { index = index, vertices = vertices }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end e2function void wirelink:egpAddVertices( number index, array args ) @@ -408,9 +421,9 @@ end -------------------------------------------------------- e2function egpobject wirelink:egpLineStrip( number index, ...args ) - if (!EGP:IsAllowed( self, this )) then return end - if (!EGP:ValidEGP( this )) then return self:throw("Invalid wirelink!", nil) end - if #args < 2 then return end -- No less than 2 + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end + if (!EGP:ValidEGP( this )) then return self:throw("Invalid wirelink!", NULL_EGPOBJECT) end + if #args < 2 then return NULL_EGPOBJECT end -- No less than 2 local max = maxvertices() @@ -429,13 +442,14 @@ e2function egpobject wirelink:egpLineStrip( number index, ...args ) end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["LineStrip"], { index = index, vertices = vertices }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end e2function egpobject wirelink:egpLineStrip( number index, array args ) - if (!EGP:IsAllowed( self, this )) then return end - if (!EGP:ValidEGP( this )) then return self:throw("Invalid wirelink!", nil) end - if (#args<2) then return end -- No less than 2 + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end + if (!EGP:ValidEGP( this )) then return self:throw("Invalid wirelink!", NULL_EGPOBJECT) end + if (#args<2) then return NULL_EGPOBJECT end -- No less than 2 local max = maxvertices() @@ -454,7 +468,8 @@ e2function egpobject wirelink:egpLineStrip( number index, array args ) end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["LineStrip"], { index = index, vertices = vertices }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end __e2setcost(15) @@ -463,61 +478,67 @@ __e2setcost(15) -- Line -------------------------------------------------------- e2function egpobject wirelink:egpLine( number index, vector2 pos1, vector2 pos2 ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["Line"], { index = index, x = pos1[1], y = pos1[2], x2 = pos2[1], y2 = pos2[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end -------------------------------------------------------- -- Circle -------------------------------------------------------- e2function egpobject wirelink:egpCircle( number index, vector2 pos, vector2 size ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["Circle"], { index = index, x = pos[1], y = pos[2], w = size[1], h = size[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end -------------------------------------------------------- -- Circle Outline -------------------------------------------------------- e2function egpobject wirelink:egpCircleOutline( number index, vector2 pos, vector2 size ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["CircleOutline"], { index = index, x = pos[1], y = pos[2], w = size[1], h = size[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end -------------------------------------------------------- -- Triangle -------------------------------------------------------- e2function egpobject wirelink:egpTriangle( number index, vector2 v1, vector2 v2, vector2 v3 ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end local vertices = { { x = v1[1], y = v1[2] }, { x = v2[1], y = v2[2] }, { x = v3[1], y = v3[2] } } local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["Poly"], { index = index, vertices = vertices }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end -------------------------------------------------------- -- Triangle Outline -------------------------------------------------------- e2function egpobject wirelink:egpTriangleOutline( number index, vector2 v1, vector2 v2, vector2 v3 ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end local vertices = { { x = v1[1], y = v1[2] }, { x = v2[1], y = v2[2] }, { x = v3[1], y = v3[2] } } local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["PolyOutline"], { index = index, vertices = vertices }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end -------------------------------------------------------- -- Wedge -------------------------------------------------------- e2function egpobject wirelink:egpWedge( number index, vector2 pos, vector2 size ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["Wedge"], { index = index, x = pos[1], y = pos[2], w = size[1], h = size[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end --[[ I'm sticking to my policy of not spamming pointless functions. e2function void wirelink:egpWedge( number index, vector2 pos, vector2 size, number angle, number mouthsize ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["Wedge"], { index = index, x = pos[1], y = pos[2], w = size[1], h = size[2], size = mouthsize, angle = angle }, self.player ) if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end end @@ -527,14 +548,15 @@ end -- Wedge Outline -------------------------------------------------------- e2function egpobject wirelink:egpWedgeOutline( number index, vector2 pos, vector2 size ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["WedgeOutline"], { index = index, x = pos[1], y = pos[2], w = size[1], h = size[2] }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end --[[ I'm sticking to my policy of not spamming pointless functions. e2function void wirelink:egpWedgeOutline( number index, vector2 pos, vector2 size, number angle, number mouthsize ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["WedgeOutline"], { index = index, x = pos[1], y = pos[2], w = size[1], h = size[2], size = mouthsize, angle = angle }, self.player ) if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end end @@ -544,13 +566,14 @@ end -- 3DTracker -------------------------------------------------------- e2function egpobject wirelink:egp3DTracker( number index, vector pos ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["3DTracker"], { index = index, target_x = pos[1], target_y = pos[2], target_z = pos[3], directionality = 0 }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end e2function egpobject wirelink:egp3DTracker( number index, vector pos, number directionality ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end if directionality > 0 then directionality = 1 @@ -559,7 +582,8 @@ e2function egpobject wirelink:egp3DTracker( number index, vector pos, number dir end local bool, obj = EGP:CreateObject( this, EGP.Objects.Names["3DTracker"], { index = index, target_x = pos[1], target_y = pos[2], target_z = pos[3], directionality = directionality }, self.player ) - if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end __e2setcost(10) @@ -992,14 +1016,16 @@ end __e2setcost(15) e2function egpobject wirelink:egpCopy( index, fromindex ) - if (!EGP:IsAllowed( self, this )) then return end + if (!EGP:IsAllowed( self, this )) then return NULL_EGPOBJECT end local bool, k, v = EGP:HasObject( this, fromindex ) if (bool) then local copy = table.Copy( v ) copy.index = index local bool2, obj = EGP:CreateObject( this, v.ID, copy, self.player ) - if (bool2) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) return obj end + if (bool2) then EGP:DoAction( this, self, "SendObject", obj ) Update(self,this) end + return obj end + return NULL_EGPOBJECT end __e2setcost(20) @@ -1156,7 +1182,7 @@ e2function void wirelink:egpHudEnable(enable) end e2function array wirelink:egpConnectedUsers() - if not EGP:ValidEGP(this) then return self:throw("Invalid wirelink!", nil) end + if not EGP:ValidEGP(this) then return self:throw("Invalid wirelink!", {}) end if not this.Users then return {} end local sanitised_array, i = {}, 0 diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index 8c0d06efdf..c5a9b39050 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -2,11 +2,13 @@ -- File for EGP Object handling in E2. -- --- Dumb but simple workaround -local M_NULL_EGPOBJECT = { __tostring = function(self) return "[EGPObject] NULL" end, __eq = function(a, b) return getmetatable(a) == getmetatable(b) end } -local NULL_EGPOBJECT = setmetatable({}, M_NULL_EGPOBJECT) +-- Dumb but simple +local NULL_EGPOBJECT = EGP.NULL_EGPOBJECT +local M_NULL_EGPOBJECT = getmetatable(NULL_EGPOBJECT) local M_EGPObject = getmetatable(EGP.Objects.Base) +local maxobjects = EGP.ConVars.MaxObjects + -- Table of allowed arguments and their types local EGP_ALLOWED_ARGS = { @@ -82,72 +84,11 @@ end ---- Functions ---------------------------- --- Creation/modification +-- Table modification ---------------------------- __e2setcost(10) -local maxobjects = EGP.ConVars.MaxObjects --- To be implemented when index LUT is implemented/EGP.HasValue is O(1). The following is therefore not conclusive. ---[[ -e2function egpobject wirelink:egpCreate(string type) - local obj = EGP.Objects[type:lower()] - if not obj then return self:throw(string.format("Invalid object type '%d'!", type), NULL_EGPOBJECT) end - obj = table.Copy(obj) - obj.EGP = this - local index = EGP.NextFreeIndex(this) - if not index then return self:throw(string.format("EGP Object limit reached for EGP [%d].", this:EntIndex()), NULL_EGPOBJECT) end - obj._notInitialized = true - obj.index = index - return obj -end -]] -[nodiscard] -e2function egpobject wirelink:egpCreate(string type, index) - local obj = EGP.Objects[type:lower()] - if not obj then return self:throw(string.format("Invalid object type '%d'!", type), NULL_EGPOBJECT) end - obj = table.Copy(obj) - obj.EGP = this - obj._notInitialized = true - obj.index = math.Round(math.Clamp(index, 1, maxobjects:GetInt())) - return obj -end - -e2function void egpobject:initialize(table arguments) - if not this._notInitialized then return end - local egp = this.EGP - local converted = {} - - for k, v in pairs(arguments.s) do - if EGP_ALLOWED_ARGS[k] == arguments.stypes[k] or false then converted[k] = v end - end - - this._notInitialized = nil - this:Initialize(converted) - - local bool, k = EGP:HasObject(egp, this.index) - if bool then table.remove(egp.RenderTable, k) end - - table.insert(egp.RenderTable, this) - EGP:DoAction(egp, self, "SendObject", this) - Update(self, egp) -end - -e2function void egpobject:initialize() - if not this._notInitialized then return end - local egp = this.EGP - - this._notInitialized = nil - this:Initialize({}) - - local bool, k = EGP:HasObject(egp, this.index) - if bool then table.remove(egp.RenderTable, k) end - - table.insert(egp.RenderTable, this) - EGP:DoAction(egp, self, "SendObject", this) - Update(self, egp) -end - e2function egpobject egpobject:modify(table arguments) local egp = this.EGP local converted = {} @@ -184,13 +125,14 @@ e2function number egpobject:egpOrder() return bool and k or -1 end -e2function void egpobject:egpOrderAbove(abovethis) +e2function void egpobject:egpOrderAbove(egpobject abovethis) local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end + if not (isValid(this) or isValid(abovethis)) then self:throw("Invalid EGP Object") end local bool, k = EGP:HasObject(egp, this.index) if bool then - if EGP:HasObject(egp, abovethis) then - if EGP:SetOrder(egp, k, abovethis, 1) then + if EGP:HasObject(egp, abovethis.index) then + if EGP:SetOrder(egp, k, abovethis.index, 1) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -198,13 +140,14 @@ e2function void egpobject:egpOrderAbove(abovethis) end end -e2function void egpobject:egpOrderBelow(belowthis) +e2function void egpobject:egpOrderBelow(egpobject belowthis) local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end + if not (isValid(this) or isValid(belowthis)) then self:throw("Invalid EGP Object") end local bool, k = EGP:HasObject(egp, this.index) if bool then - if EGP:HasObject(egp, belowthis) then - if EGP:SetOrder(egp, k, belowthis, -1) then + if EGP:HasObject(egp, belowthis.index) then + if EGP:SetOrder(egp, k, belowthis.index, -1) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -617,19 +560,30 @@ e2function void egpobject:egpRemove() Update(self, egp) end -e2function void egpobject:unload() +e2function void egpobject:draw() + if not this._nodraw then return end + local egp = this.EGP + if not EGP:IsAllowed(self, egp) then return end + + if EGP:CreateObject(egp, this.ID, this) then + EGP:DoAction(egp, self, "SendObject", this) + Update(self, egp) + end +end + +e2function void egpobject:hide() if not isValid(this) then return end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end EGP:DoAction(egp, self, "RemoveObject", this.index) - this._notInitialized = true + this._nodraw = true Update(self, egp) end [nodiscard] -e2function number egpobject:isLoaded() - return isValid(this) and not this._notInitialized and 1 or 0 +e2function number egpobject:isVisible() + return isValid(this) and not this._nodraw and 1 or 0 end -------------------------------------------------------- @@ -838,6 +792,7 @@ e2function string egpobject:toString() = e2function string toString(egpobject eg -------------------------------------------------------- registerCallback("postinit", function() + E2Lib.currentextension = "egpobjects" local fixDefault = E2Lib.fixDefault for _, v in pairs(wire_expression_types) do local id = v[1] @@ -892,4 +847,52 @@ registerCallback("postinit", function() return end) end + + local egpCreate = EGP.CreateObject + for name, id in pairs(EGP.Objects.Names) do + -- Indexed table "constructor" + registerFunction("egp" .. name, "xwl:nt", "xeo", function(self, args) + local op1, op2, op3 = args[2], args[3], args[4] + local this, index, args = op1[1](self, op1), op2[1](self, op2), op3[1](self, op3) + if not EGP:IsAllowed(self, this) then return NULL_EGPOBJECT end + + local converted = {} + + for k, v in pairs(args.s) do + if EGP_ALLOWED_ARGS[k] == args.stypes[k] or false then converted[k] = v end + end + + converted.index = index + + local bool, obj = egpCreate(EGP, this, id, converted) + if bool then + EGP:DoAction(this, self, "SendObject", obj) + Update(self, this) + end + return obj + end, 10, { "index", "args" }) + + --[[ + -- Unindexed table constructor + registerFunction("egp" .. name, "xwl:t", "xeo", function(self, args) + local op1, op2 = args[2], args[3] + local this, args = op1[1](self, op1), op2[1](self, op2) + + local converted = {} + + for k, v in pairs(args.s) do + if EGP_ALLOWED_ARGS[k] == args.stypes[k] or false then converted[k] = v end + end + + converted.index = EGP.GetNextIndex(this) + + local bool, obj = egpCreate(this, id, converted) + if bool then + EGP:DoAction(this, self, "SendObject", obj) + Update(self, this) + return obj + end + end, 10, { "this", "args" }, { "nodiscard" }) + ]] + end end) diff --git a/lua/wire/client/e2descriptions.lua b/lua/wire/client/e2descriptions.lua index 0b881ba0f2..fb5152a86d 100644 --- a/lua/wire/client/e2descriptions.lua +++ b/lua/wire/client/e2descriptions.lua @@ -1402,6 +1402,8 @@ E2Helper.Descriptions["egpMaterial"] = "Returns the material of the object" E2Helper.Descriptions["egpMaterial(xwl:ns)"] = "Changes the material of the object" E2Helper.Descriptions["egpMaterialFromScreen(xwl:ne)"] = "Sets the material of the object to a current snapshot of the target screen. Note that this only works for players which see both the egp as well the target screen at that time" E2Helper.Descriptions["egpOrder(xwl:nn)"] = "Sets the order at which the object will be rendered" +E2Helper.Descriptions["egpOrderAbove(xwl:nn)"] = "Makes the object render above the object at the index" +E2Helper.Descriptions["egpOrderBelow(xwl:nn)"] = "Makes the object render below the object at the index" E2Helper.Descriptions["egpOrder"] = "Returns the order at which the object is rendered" E2Helper.Descriptions["egpParent"] = "Returns the index of the parent object" E2Helper.Descriptions["egpParent(xwl:ne)"] = "Parents the 3D tracker object to an entity" @@ -1462,32 +1464,44 @@ E2Helper.Descriptions["egpObjectIndexes(xwl:)"] = "Returns an array containing a E2Helper.Descriptions["egpObjectType"] = "Returns the type of the object" E2Helper.Descriptions["egpObjectTypes(xwl:)"] = "Returns an array whose keys are bound to object index, and value being the type of particular object" -E2Helper.Descriptions["egp3DTracker"] = "Creates a 3D tracker object at specified world position" +E2Helper.Descriptions["egp3DTracker(xwl:nv)"] = "Creates a 3D tracker object at specified world position" E2Helper.Descriptions["egp3DTracker(xwl:nvn)"] = "Creates a 3D tracker object at specified world position that is only visible behind (directionality=-1), in front of (directionality=1) the screen/emitter, or both (directionality=0). HUD is unaffected by directionality." -E2Helper.Descriptions["egpBox"] = "Creates a box. First 2D vector is the position, second is size" -E2Helper.Descriptions["egpBoxOutline"] = "Creates an outline box. First 2D vector is the position, second is size" -E2Helper.Descriptions["egpCircle"] = "Creates a circle. First 2D vector is the position, second is size" -E2Helper.Descriptions["egpCircleOutline"] = "Creates an outline circle. First 2D vector is the position, second is size" -E2Helper.Descriptions["egpLine"] = "Creates a line. First 2D vector is the start position, second is end position" -E2Helper.Descriptions["egpLineStrip"] = "Creates a curve with specified points as 2D/4D vectors (x,y)/(x,y,u,v)" +E2Helper.Descriptions["egpBox(xwl:nxv2xv2)"] = "Creates a box. First 2D vector is the position, second is size" +E2Helper.Descriptions["egpBoxOutline(xwl:nxv2xv2)"] = "Creates an outline box. First 2D vector is the position, second is size" +E2Helper.Descriptions["egpCircle(xwl:nxv2xv2)"] = "Creates a circle. First 2D vector is the position, second is size" +E2Helper.Descriptions["egpCircleOutline(xwl:nxv2xv2)"] = "Creates an outline circle. First 2D vector is the position, second is size" +E2Helper.Descriptions["egpLine(xwl:nxv2xv2)"] = "Creates a line. First 2D vector is the start position, second is end position" +E2Helper.Descriptions["egpLineStrip(xwl:n...)"] = "Creates a curve with specified points as 2D/4D vectors (x,y)/(x,y,u,v)" E2Helper.Descriptions["egpLineStrip(xwl:nr)"] = "Creates a curve with specified points as array of 2D/4D vectors (x,y)/(x,y,u,v)" E2Helper.Descriptions["egpPoly(xwl:nr)"] = "Creates a polygon with specified points as array of 2D/4D vectors (x,y)/(x,y,u,v)" -E2Helper.Descriptions["egpPoly"] = "Creates a polygon with specified points as 2D/4D vectors (x,y)/(x,y,u,v)" +E2Helper.Descriptions["egpPoly(xwl:n...)"] = "Creates a polygon with specified points as 2D/4D vectors (x,y)/(x,y,u,v)" E2Helper.Descriptions["egpPolyOutline(xwl:nr)"] = "Creates a outline polygon with specified points as array of 2D/4D vectors (x,y)/(x,y,u,v)" -E2Helper.Descriptions["egpPolyOutline"] = "Creates a outline polygon with specified points as 2D/4D vectors (x,y)/(x,y,u,v)" -E2Helper.Descriptions["egpRoundedBox"] = "Creates a rounded box. First 2D vector is the position, second is size" -E2Helper.Descriptions["egpRoundedBoxOutline"] = "Creates a rounded outline box. First 2D vector is the position, second is size" -E2Helper.Descriptions["egpText"] = "Creates a text object" -E2Helper.Descriptions["egpTextLayout"] = "Creates a text layout object" -E2Helper.Descriptions["egpTriangle"] = "Creates a triangle with specified vertices" -E2Helper.Descriptions["egpTriangleOutline"] = "Creates a outline triangle with specified vertices" +E2Helper.Descriptions["egpPolyOutline(xwl:n...)"] = "Creates a outline polygon with specified points as 2D/4D vectors (x,y)/(x,y,u,v)" +E2Helper.Descriptions["egpRoundedBox(xwl:nxv2xv2)"] = "Creates a rounded box. First 2D vector is the position, second is size" +E2Helper.Descriptions["egpRoundedBoxOutline(xwl:nxv2xv2)"] = "Creates a rounded outline box. First 2D vector is the position, second is size" +E2Helper.Descriptions["egpText(xwl:nsxv2)"] = "Creates a text object" +E2Helper.Descriptions["egpTextLayout(xwl:nsxv2xv2)"] = "Creates a text layout object" +E2Helper.Descriptions["egpTriangle(xwl:nxv2xv2xv2)"] = "Creates a triangle with specified vertices" +E2Helper.Descriptions["egpTriangleOutline(xwl:nxv2xv2xv2)"] = "Creates a outline triangle with specified vertices" +E2Helper.Descriptions["egpWedge(xwl:nxv2xv2)"] = "Creates a wedge object. Wedge objects are like circles, except they have a cake-piece-like mouth which you can change using egpSize" +E2Helper.Descriptions["egpWedgeOutline(xwl:nxv2xv2)"] = "Creates a outline wedge object. Wedge objects are like circles, except they have a cake-piece-like mouth which you can change using egpSize" + +E2Helper.Descriptions["egp3DTracker"] = "Creates a 3D tracker with the provided arguments" +E2Helper.Descriptions["egpBox"] = "Creates a box with the provided arguments" +E2Helper.Descriptions["egpBoxOutline"] = "Creates an outline box with the provided arguments" +E2Helper.Descriptions["egpCircle"] = "Creates a circle with the provided arguments" +E2Helper.Descriptions["egpCircleOutline"] = "Creates an outline circle with the provided arguments" +E2Helper.Descriptions["egpLine"] = "Creates a line with the provided arguments" +E2Helper.Descriptions["egpLineStrip"] = "Creates a curve with with the provided arguments. Use egpSetVertices to add vertices to it" +E2Helper.Descriptions["egpPoly"] = "Creates a polygon with with the provided arguments. Use egpSetVertices to add vertices to it" +E2Helper.Descriptions["egpPolyOutline"] = "Creates a outline polygon with with the provided arguments. Use egpSetVertices to add vertices to it" +E2Helper.Descriptions["egpRoundedBox"] = "Creates a rounded box with with the provided arguments" +E2Helper.Descriptions["egpRoundedBoxOutline"] = "Creates a rounded outline box with with the provided arguments" +E2Helper.Descriptions["egpText"] = "Creates a text object with with the provided arguments" +E2Helper.Descriptions["egpTextLayout"] = "Creates a text layout object with with the provided arguments" E2Helper.Descriptions["egpWedge"] = "Creates a wedge object. Wedge objects are like circles, except they have a cake-piece-like mouth which you can change using egpSize" E2Helper.Descriptions["egpWedgeOutline"] = "Creates a outline wedge object. Wedge objects are like circles, except they have a cake-piece-like mouth which you can change using egpSize" -E2Helper.Descriptions["egpCreate(xwl:s)"] = "Creates an object prototype of the specified type. Note that you have to initialize the object before it's sent to the screen." -E2Helper.Descriptions["egpCreate(xwl:sn)"] = "Creates an object prototype of the specified type at the index. Note that you have to initialize the object before it's sent to the screen." -E2Helper.Descriptions["initialize(xeo:)"] = "Initializes an object prototype." -E2Helper.Descriptions["initialize(xeo:t)"] = "Initializes an object prototype with the provided arguments." E2Helper.Descriptions["modify(xeo:t)"] = "Modifies an object with the provided arguments." E2Helper.Descriptions["egpAlign(xeo:n)"] = "Changes the horizontal alignment. Works on: text and text layout. Number can be 0, 1 or 2" @@ -1502,7 +1516,9 @@ E2Helper.Descriptions["egpFidelity(xeo:n)"] = "Changes the fidelity of the objec E2Helper.Descriptions["egpFont(xeo:sn)"] = "Changes the font and size of the text object" E2Helper.Descriptions["egpMaterial(xeo:s)"] = "Changes the material of the object" E2Helper.Descriptions["egpMaterialFromScreen(xeo:e)"] = "Sets the material of the object to a current snapshot of the target screen. Note that this only works for players which see both the egp as well the target screen at that time" -E2Helper.Descriptions["egpOrder(xeo:n)"] = "Sets the order at which the object will be rendered" +E2Helper.Descriptions["egpOrder(xeo:n)"] = "Sets the order at which the object will be rendered. This is different from index" +E2Helper.Descriptions["egpOrderAbove(xeo:n)"] = "Makes the object render above the object at the index" +E2Helper.Descriptions["egpOrderBelow(xeo:n)"] = "Makes the object render below the object at the index" E2Helper.Descriptions["egpParent(xeo:e)"] = "Parents the 3D tracker object to an entity" E2Helper.Descriptions["egpParent(xeo:n)"] = "Parents the object to another object. Parented objects' positions are local to their parent" E2Helper.Descriptions["egpParent(xeo:xeo)"] = "Parents the object to another object. Parented objects' positions are local to their parent" @@ -1520,8 +1536,9 @@ E2Helper.Descriptions["egpSetText(xeo:ssn)"] = "Changes the text, font, and text E2Helper.Descriptions["egpSetVertices"] = "Sets the vertices of the object. Can use vector2 or vector4 for vertices." E2Helper.Descriptions["egpSize(xeo:)"] = "Returns the size of the object" E2Helper.Descriptions["egpSize(xeo:n)"] = "Changes the size of the text/line/outline object" -E2Helper.Descriptions["isLoaded(xeo:)"] = "Returns 1 if the object is initialized." -E2Helper.Descriptions["unload(xeo:)"] = "Removes an object from the screen but keeps its data intact. You can still modify an unloaded object. Reload it by calling :initialize() on it." +E2Helper.Descriptions["isVisible(xeo:)"] = "Returns 1 if the object is visible." +E2Helper.Descriptions["hide(xeo:)"] = "Removes an object from the screen but keeps its data intact." +E2Helper.Descriptions["draw(xeo:)"] = "Shows a hidden EGP object." E2Helper.Descriptions["egpConnectedUsers(xwl:)"] = "Returns an array of players connected to the EGP" E2Helper.Descriptions["egpCursor(xwl:e)"] = "Returns the specified player's aim position on the screen" From 04efd55f6db99a7b25f5c1e8a66c84ca01af3eb5 Mon Sep 17 00:00:00 2001 From: Denneisk Date: Sat, 9 Sep 2023 10:22:32 -0400 Subject: [PATCH 16/28] Rename xeo:egpobjectContainsPoint to simply :containsPoint --- lua/entities/gmod_wire_expression2/core/egpobjects.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index c5a9b39050..d77684954a 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -752,7 +752,7 @@ end __e2setcost(10) [nodiscard] -e2function number egpobject:egpObjectContainsPoint(vector2 point) +e2function number egpobject:containsPoint(vector2 point) return isValid(this) and this:Contains(point[1], point[2]) and 1 or 0 end From 30016e153dcc8ce9b92d02792df60062167125f8 Mon Sep 17 00:00:00 2001 From: Denneisk Date: Sat, 9 Sep 2023 10:25:49 -0400 Subject: [PATCH 17/28] forgot e2description --- lua/wire/client/e2descriptions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/wire/client/e2descriptions.lua b/lua/wire/client/e2descriptions.lua index fb5152a86d..f58d594d37 100644 --- a/lua/wire/client/e2descriptions.lua +++ b/lua/wire/client/e2descriptions.lua @@ -1543,7 +1543,7 @@ E2Helper.Descriptions["draw(xeo:)"] = "Shows a hidden EGP object." E2Helper.Descriptions["egpConnectedUsers(xwl:)"] = "Returns an array of players connected to the EGP" E2Helper.Descriptions["egpCursor(xwl:e)"] = "Returns the specified player's aim position on the screen" E2Helper.Descriptions["egpHasObject(xwl:xeo)"] = "Returns 1 if the object exists on the screen, 0 if not" -E2Helper.Descriptions["egpObjectContainsPoint(xeo:xv2)"] = "Returns 1 if the object with specified index contains the specified point" +E2Helper.Descriptions["containsPoint(xeo:xv2)"] = "Returns 1 if the object contains the specified point" E2Helper.Descriptions["egpFiltering(xeo:n)"] = "Changes the texture filter used to draw the object. Works on objects that draw a material. See _TEXFILTER constants (POINT=sharp, ANISOTROPIC=blurry/default)" E2Helper.Descriptions["egpobject(xwl:n)"] = "Returns the EGPObject at the index" E2Helper.Descriptions["noegpobject"] = "Returns a NULL egpobject." From 5603ee99955f2387626390ff04023619810a8845 Mon Sep 17 00:00:00 2001 From: Denneisk Date: Sat, 9 Sep 2023 10:32:46 -0400 Subject: [PATCH 18/28] Fix nodraw --- lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua | 3 +-- lua/entities/gmod_wire_expression2/core/egpobjects.lua | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua b/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua index ecc51ccdf4..d878c47bdd 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua @@ -305,7 +305,7 @@ if (SERVER) then if (Action == "SendObject") then local Data = {...} local obj = Data[1] - if not obj or obj._notInitialized then return end + if not obj or obj._nodraw then return end if (E2 and E2.entity and E2.entity:IsValid()) then E2.prf = E2.prf + 30 @@ -315,7 +315,6 @@ if (SERVER) then elseif (Action == "RemoveObject") then local Data = {...} local obj = Data[1] - if not obj or obj._notInitialized then return end if (E2 and E2.entity and E2.entity:IsValid()) then E2.prf = E2.prf + 20 diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index d77684954a..a080a2508f 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -563,6 +563,7 @@ end e2function void egpobject:draw() if not this._nodraw then return end local egp = this.EGP + this._nodraw = nil if not EGP:IsAllowed(self, egp) then return end if EGP:CreateObject(egp, this.ID, this) then @@ -572,7 +573,7 @@ e2function void egpobject:draw() end e2function void egpobject:hide() - if not isValid(this) then return end + if not isValid(this) or this._nodraw then return end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end From 8f76e6a1962c41d79a710209e4fa72904064bfb1 Mon Sep 17 00:00:00 2001 From: Denneisk Date: Sun, 10 Sep 2023 19:49:09 -0400 Subject: [PATCH 19/28] Fix set on poly-like object, add EGP object inheritance. --- .../lib/egplib/objectcontrol.lua | 22 +++++++++++----- .../gmod_wire_egp/lib/objects/linestrip.lua | 23 +++++++++++++++++ .../gmod_wire_egp/lib/objects/poly.lua | 23 +++++++++++++++++ .../gmod_wire_egp/lib/objects/polyoutline.lua | 25 ++++++++++++++++++- .../gmod_wire_expression2/core/egpobjects.lua | 3 ++- 5 files changed, 88 insertions(+), 8 deletions(-) diff --git a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua index 89deb37854..21dd7fbc8b 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua @@ -116,12 +116,22 @@ function EGP:NewObject( Name ) return setmetatable(self.Objects[lower], M_EGPObject) end -local folder = "entities/gmod_wire_egp/lib/objects/" -local files = file.Find(folder.."*.lua", "LUA") -table.sort( files ) -for _,v in pairs( files ) do - include(folder..v) - if (SERVER) then AddCSLuaFile(folder..v) end +do + local folder = "entities/gmod_wire_egp/lib/objects/" + local files = file.Find(folder.."*.lua", "LUA") + for _, v in ipairs(files) do + AddCSLuaFile(folder .. v) + end + + local pending = {} + for _, v in ipairs(files) do + local path = folder .. v + local ok, thisOrParent = include(path) + if not ok then + if not pending[thisOrParent] then pending[thisOrParent] = {} end + pending[#thisOrParent + 1] = path + end + end end ---------------------------- diff --git a/lua/entities/gmod_wire_egp/lib/objects/linestrip.lua b/lua/entities/gmod_wire_egp/lib/objects/linestrip.lua index d1ac95d4de..81b49e619c 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/linestrip.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/linestrip.lua @@ -83,4 +83,27 @@ function Obj:SetPos(x, y, angle) self.x, self.y, self.angle = x, y, angle if self._x then self._x, self._y, self._angle = x, y, angle end return true +end + +function Obj:Set(key, value) + if key == "vertices" then + self.vertices = value + self.x, self.y = EGP.getCenterFrom(self) + return true + elseif key == "x" then + ret = self:SetPos(value, self.y, self.angle) + return true + elseif key == "y" then + ret = self:SetPos(self.x, value, self.angle) + return true + elseif key == "angle" then + ret = self:SetPos(self.x, self.y, value) + return true + else + if self[key] ~= nil and self[key] ~= value then + self[key] = value + return true + end + end + return false end \ No newline at end of file diff --git a/lua/entities/gmod_wire_egp/lib/objects/poly.lua b/lua/entities/gmod_wire_egp/lib/objects/poly.lua index ee084210d1..67ac9a338e 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/poly.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/poly.lua @@ -128,3 +128,26 @@ function Obj:SetPos(x, y, angle) if self._x then self._x, self._y, self._angle = x, y, angle end return true end + +function Obj:Set(key, value) + if key == "vertices" then + self.vertices = value + self.x, self.y = EGP.getCenterFrom(self) + return true + elseif key == "x" then + ret = self:SetPos(value, self.y, self.angle) + return true + elseif key == "y" then + ret = self:SetPos(self.x, value, self.angle) + return true + elseif key == "angle" then + ret = self:SetPos(self.x, self.y, value) + return true + else + if self[key] ~= nil and self[key] ~= value then + self[key] = value + return true + end + end + return false +end diff --git a/lua/entities/gmod_wire_egp/lib/objects/polyoutline.lua b/lua/entities/gmod_wire_egp/lib/objects/polyoutline.lua index bb3ca99c2f..692fad2750 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/polyoutline.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/polyoutline.lua @@ -1,5 +1,5 @@ -- Author: sk8 (& Divran) -local Obj = EGP:NewObject( "PolyOutline" ) +local Obj = EGP.Inherit(EGP:NewObject("PolyOutline"), EGP.Objects.Poly) Obj.w = nil Obj.h = nil Obj.angle = 0 @@ -81,4 +81,27 @@ function Obj:SetPos(x, y, angle) self.x, self.y, self.angle = x, y, angle if self._x then self._x, self._y, self._angle = x, y, angle end return true +end + +function Obj:Set(key, value) + if key == "vertices" then + self.vertices = value + self.x, self.y = EGP.getCenterFrom(self) + return true + elseif key == "x" then + ret = self:SetPos(value, self.y, self.angle) + return true + elseif key == "y" then + ret = self:SetPos(self.x, value, self.angle) + return true + elseif key == "angle" then + ret = self:SetPos(self.x, self.y, value) + return true + else + if self[key] ~= nil and self[key] ~= value then + self[key] = value + return true + end + end + return false end \ No newline at end of file diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index a080a2508f..5c98d448c3 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -850,7 +850,8 @@ registerCallback("postinit", function() end local egpCreate = EGP.CreateObject - for name, id in pairs(EGP.Objects.Names) do + local workingSet = table.Copy(EGP.Objects.Names) + for name, id in pairs(workingSet) do -- Indexed table "constructor" registerFunction("egp" .. name, "xwl:nt", "xeo", function(self, args) local op1, op2, op3 = args[2], args[3], args[4] From 7de253101c1db5487412df40bcb17207b05c6ecc Mon Sep 17 00:00:00 2001 From: Denneisk Date: Sun, 10 Sep 2023 22:01:05 -0400 Subject: [PATCH 20/28] Rename every xeo function Add xeo:parent(), returns parent object Minor fixes and optimizations, chiefly with function returns Remove xeo:egpIndex(n), indexes should be irrelevant Removed redundant xeo:egpObjectType() that I swore I already removed --- .../gmod_wire_expression2/core/egpobjects.lua | 230 ++++++++---------- 1 file changed, 108 insertions(+), 122 deletions(-) diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index 5c98d448c3..1eb00297d5 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -97,7 +97,8 @@ e2function egpobject egpobject:modify(table arguments) if EGP_ALLOWED_ARGS[k] == arguments.stypes[k] or false then converted[k] = v end end - if this:EditObject(converted) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) return this end + if this:EditObject(converted) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end + return this end -------------------------------------------------------- @@ -106,7 +107,7 @@ end __e2setcost(15) -e2function void egpobject:egpOrder(order) +e2function void egpobject:setOrder(order) local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end local bool, k = EGP:HasObject(egp, this.index) @@ -118,14 +119,14 @@ e2function void egpobject:egpOrder(order) end end -e2function number egpobject:egpOrder() +e2function number egpobject:getOrder() local egp = this.EGP - if not EGP:IsAllowed(self, egp) then return end + if not EGP:IsAllowed(self, egp) then return -1 end local bool, k = EGP:HasObject(egp, this.index) return bool and k or -1 end -e2function void egpobject:egpOrderAbove(egpobject abovethis) +e2function void egpobject:setOrderAbove(egpobject abovethis) local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if not (isValid(this) or isValid(abovethis)) then self:throw("Invalid EGP Object") end @@ -140,7 +141,7 @@ e2function void egpobject:egpOrderAbove(egpobject abovethis) end end -e2function void egpobject:egpOrderBelow(egpobject belowthis) +e2function void egpobject:setOrderBelow(egpobject belowthis) local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if not (isValid(this) or isValid(belowthis)) then self:throw("Invalid EGP Object") end @@ -161,15 +162,15 @@ end __e2setcost(7) -e2function void egpobject:egpSetText(string text) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setText(string text) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:Set("text", text) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end -e2function void egpobject:egpSetText(string text, string font, number size) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setText(string text, string font, number size) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:EditObject({ text = text, font = font, size = size }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -178,15 +179,15 @@ end ---------------------------- -- Alignment ---------------------------- -e2function void egpobject:egpAlign(number halign) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setAlign(number halign) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:Set("halign", math.Clamp(halign, 0, 2)) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end -e2function void egpobject:egpAlign(number halign, number valign) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setAlign(number halign, number valign) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:EditObject({ valign = math.Clamp(valign, 0, 2), halign = math.Clamp(halign, 0, 2) }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -195,8 +196,8 @@ end ---------------------------- -- Filtering ---------------------------- -e2function void egpobject:egpFiltering(number filtering) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setFiltering(number filtering) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:Set("filtering", math.Clamp(filtering, 0, 3)) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -205,19 +206,19 @@ end ---------------------------- -- Font ---------------------------- -e2function void egpobject:egpFont(string font) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setFont(string font) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end - if #font > 30 then return self:throw("Font string is too long!", nil) end + if #font > 30 then return self:throw("Font string is too long!") end if this:Set("font", font) then EGP:DoAction(egp, self, "SendObject", obj) Update(self, this) end end -e2function void egpobject:egpFont(string font, number size) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setFont(string font, number size) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end - if #font > 30 then return self:throw("Font string is too long!", nil) end + if #font > 30 then return self:throw("Font string is too long!") end if this:EditObject({ font = font, size = size }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end @@ -226,8 +227,8 @@ end -------------------------------------------------------- __e2setcost(10) -e2function void egpobject:egpPos(vector pos) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setPos(vector pos) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:EditObject({ target_x = pos[1], target_y = pos[2], target_z = pos[3] }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -238,42 +239,26 @@ end -------------------------------------------------------- __e2setcost(7) -[nodiscard] -e2function number egpobject:egpIndex(index) - if not isValid(this) then return self:throw("Invalid EGP Object", -1) end - if this.index == index then return -1 end - local egp = this.EGP - local ret = 0 - - local bool, k = EGP:HasObject(egp, index) - if bool then table.remove(egp.RenderTable, k) ret = 1 end - - this.index = index - - EGP:DoAction(egp, self, "SendObject", this) - Update(self, egp) - return ret -end ---------------------------- -- Size ---------------------------- -e2function void egpobject:egpSize(vector2 size) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setSize(vector2 size) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:EditObject({ w = size[1], h = size[2] }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end -e2function void egpobject:egpSize(width, height) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setSize(width, height) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:EditObject({ w = width, h = height }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end -e2function void egpobject:egpSize(number size) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setSize(number size) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:Set("size", size) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -282,22 +267,22 @@ end ---------------------------- -- Position ---------------------------- -e2function void egpobject:egpPos(vector2 pos) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setPos(vector2 pos) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:SetPos(pos[1], pos[2]) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end -e2function void egpobject:egpPos(x, y) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setPos(x, y) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:SetPos(x, y) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end -e2function void egpobject:egpPos(x, y, x2, y2) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setPos(x, y, x2, y2) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:SetPos(x, y, nil, x2, y2) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -306,8 +291,8 @@ end ---------------------------- -- Angle ---------------------------- -e2function void egpobject:egpAngle(number angle) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setAngle(number angle) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:Set("angle", angle) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -316,15 +301,15 @@ end ------------- -- Position & Angle ------------- -e2function void egpobject:egpPos(x, y, angle) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setPos(x, y, angle) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:SetPos(x, y, angle) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end -e2function void egpobject:egpAngle(vector2 worldpos, vector2 axispos, number angle) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:rotateAroundAxis(vector2 worldpos, vector2 axispos, number angle) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this.x and this.y then @@ -335,10 +320,7 @@ e2function void egpobject:egpAngle(vector2 worldpos, vector2 axispos, number ang angle = -ang.yaw - local t = { x = x, _x = x, y = y, _y = y } - if this.angle then t.angle, t._angle = angle, angle end - - if this:EditObject(t) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end + if this:SetPos(x, y, angle) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end end @@ -348,7 +330,7 @@ end local maxVertices = EGP.ConVars.MaxVertices -e2function void egpobject:egpSetVertices(array verts) +e2function void egpobject:setVertices(array verts) if not isValid(this) then return self:throw("Invalid EGP Object") end if not this.vertices then return end if #verts < 3 then return end @@ -375,7 +357,7 @@ e2function void egpobject:egpSetVertices(array verts) end end -e2function void egpobject:egpSetVertices(...args) +e2function void egpobject:setVertices(...args) if not isValid(this) then return self:throw("Invalid EGP Object") end if not this.vertices then return end if #args < 3 then return end @@ -407,29 +389,29 @@ end ---------------------------- -- Color ---------------------------- -e2function void egpobject:egpColor(vector4 color) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setColor(vector4 color) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:EditObject({ r = color[1], g = color[2], b = color[3], a = color[4] }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end -e2function void egpobject:egpColor(vector color) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setColor(vector color) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:EditObject({ r = color[1], g = color[2], b = color[3] }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end -e2function void egpobject:egpColor(r, g, b, a) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setColor(r, g, b, a) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:EditObject({ r = r, g = g, b = b, a = a }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end -e2function void egpobject:egpAlpha(number a) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setAlpha(number a) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:Set("a", a) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end @@ -438,16 +420,16 @@ end ---------------------------- -- Material ---------------------------- -e2function void egpobject:egpMaterial(string material) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setMaterial(string material) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end material = WireLib.IsValidMaterial(material) if this:Set("material", material) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end -e2function void egpobject:egpMaterialFromScreen(entity gpu) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setMaterialFromScreen(entity gpu) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if gpu and gpu:IsValid() then @@ -458,45 +440,46 @@ end ---------------------------- -- Fidelity (number of corners for circles and wedges) ---------------------------- -e2function void egpobject:egpFidelity(number fidelity) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:setFidelity(number fidelity) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if this:EditObject({ fidelity = math.Clamp(fidelity, 3, 180) }) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end [nodiscard] -e2function number egpobject:egpFidelity() +e2function number egpobject:getFidelity() return this.fidelity or -1 end ---------------------------- -- Parenting ---------------------------- -e2function void egpobject:egpParent(egpobject parent) - if not isValid(this) or not isValid(parent) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:parentTo(egpobject parent) + if not isValid(this) or not isValid(parent) then return self:throw("Invalid EGP Object") end local egp = this.EGP if egp ~= parent.EGP then return self:throw("Invalid EGP Object", nil) end if not EGP:IsAllowed(self, egp) then return end if EGP:SetParent(egp, this, parent) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end -e2function void egpobject:egpParent(number parentindex) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:parentTo(number parentindex) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if EGP:SetParent(egp, this, parentindex) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end e2function void wirelink:egpParent(egpobject child, egpobject parent) - if not (isValid(child) or isValid(parent) or child.EGP == this or parent.EGP == this) then return self:throw("Invalid EGP Object", nil) end if not EGP:IsAllowed(self, this) then return end + if not EGP:ValidEGP(this) then return self:throw("Invalid wirelink!") end + if not (isValid(child) or isValid(parent) or child.EGP == this or parent.EGP == this) then return self:throw("Invalid EGP Object", nil) end if EGP:SetParent(this, child, parent) then EGP:DoAction(this, self, "SendObject", child) Update(self, this) end end -- Entity parenting (only for 3Dtracker - does nothing for any other object) -e2function void egpobject:egpParent(entity parent) - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:trackerParent(entity parent) + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not parent or not parent:IsValid() then return end if not EGP:IsAllowed(self, egp) then return end @@ -511,29 +494,36 @@ end -- Returns the entity a tracker is parented to [nodiscard] -e2function entity egpobject:egpTrackerParent() - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function entity egpobject:trackerParent() + if not isValid(this) then return self:throw("Invalid EGP Object", NULL) end return IsValid(this.parententity) and this.parententity or NULL end -e2function void egpobject:egpParentToCursor() - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:parentToCursor() + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if EGP:SetParent(egp, this, -1) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end -e2function void egpobject:egpUnParent() - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end +e2function void egpobject:unparent() + if not isValid(this) then return self:throw("Invalid EGP Object") end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end if EGP:UnParent(egp, this) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end end [nodiscard] -e2function number egpobject:egpParentIndex() - if not isValid(this) then return self:throw("Invalid EGP Object", nil) end - return this.parent or nil +e2function number egpobject:parentIndex() + if not isValid(this) then return self:throw("Invalid EGP Object", 0) end + return this.parent or 0 +end + +[nodiscard] +e2function egpobject egpobject:parent() + if not isValid(this) then return self:throw("Invalid EGP Object", NULL_EGPOBJECT) end + local _, _, v = EGP:HasObject(this.EGP, this.parent) + return v or NULL_EGPOBJECT end -------------------------------------------------------- @@ -541,6 +531,7 @@ end -------------------------------------------------------- e2function void wirelink:egpRemove(egpobject obj) if not EGP:IsAllowed(self, this) then return end + if not EGP:ValidEGP(this) then return end if isValid(obj) then EGP:DoAction(this, self, "RemoveObject", obj.index) table.Empty(obj) @@ -549,7 +540,7 @@ e2function void wirelink:egpRemove(egpobject obj) end end -e2function void egpobject:egpRemove() +e2function void egpobject:remove() if not isValid(this) then return end local egp = this.EGP if not EGP:IsAllowed(self, egp) then return end @@ -593,14 +584,14 @@ end __e2setcost(20) [nodiscard] -e2function vector egpobject:egpGlobalPos() - if not isValid(this) then return self:throw("Invalid EGP Object", vector_origin) end +e2function vector egpobject:globalPos() + if not isValid(this) then return self:throw("Invalid EGP Object", Vector(0, 0, 0)) end local _, posang = EGP:GetGlobalPos(this.EGP, this) return Vector(posang.x, posang.y, posang.angle) end [nodiscard] -e2function array egpobject:egpGlobalVertices() +e2function array egpobject:globalVertices() if not isValid(this) then return self:throw("Invalid EGP Object", {}) end local hasvertices, data = EGP:GetGlobalPos(this.EGP, this) if hasvertices then @@ -631,62 +622,62 @@ end __e2setcost(3) [nodiscard] -e2function vector2 egpobject:egpPos() +e2function vector2 egpobject:getPos() if not isValid(this) then return self:throw("Invalid EGP Object", { -1, -1 }) end return (this.x and this.y and { this.x, this.y }) or { -1, -1 } end [nodiscard] -e2function vector egpobject:egpPosAng() +e2function vector egpobject:getPosAng() if not isValid(this) then return self:throw("Invalid EGP Object", Vector(-1, -1, -1)) end return (this.x and this.y and this.angle and Vector(this.x, this.y, this.angle)) or Vector(-1, -1, -1) end [nodiscard] -e2function vector2 egpobject:egpSize() +e2function vector2 egpobject:getSize() if not isValid(this) then return self:throw("Invalid EGP Object", { -1, -1 }) end return (this.w and this.h and { this.w, this.h }) or { -1, -1 } end [nodiscard] -e2function number egpobject:egpSizeNum() +e2function number egpobject:getSizeNum() if not isValid(this) then return self:throw("Invalid EGP Object", -1) end return this.size or -1 end [nodiscard] -e2function vector4 egpobject:egpColor4() +e2function vector4 egpobject:getColor4() if not isValid(this) then return self:throw("Invalid EGP Object", { -1, -1, -1, -1 }) end return (this.r and this.g and this.b and this.a and { this.r, this.g, this.b, this.a }) or { -1, -1, -1, -1 } end [nodiscard] -e2function vector egpobject:egpColor() - if not isValid(this) then return self:throw("Invalid EGP Object", -1) end +e2function vector egpobject:getColor() + if not isValid(this) then return self:throw("Invalid EGP Object", Vector(-1, -1, -1)) end return (this.r and this.g and this.b and Vector(this.r, this.g, this.b)) or Vector(-1, -1, -1) end [nodiscard] -e2function number egpobject:egpAlpha() +e2function number egpobject:getAlpha() if not isValid(this) then return self:throw("Invalid EGP Object", -1) end return this.a or -1 end [nodiscard] -e2function number egpobject:egpAngle() +e2function number egpobject:getAngle() if not isValid(this) then return self:throw("Invalid EGP Object", -1) end return this.angle or -1 end [nodiscard] -e2function string egpobject:egpMaterial() +e2function string egpobject:getMaterial() if not isValid(this) then return self:throw("Invalid EGP Object", "") end return this.material or "" end [nodiscard] -e2function number egpobject:egpRadius() +e2function number egpobject:getRadius() if not isValid(this) then return self:throw("Invalid EGP Object", -1) end return this.radius or -1 end @@ -694,7 +685,7 @@ end __e2setcost(10) [nodiscard] -e2function array egpobject:egpVertices() +e2function array egpobject:getVertices() if this.vertices then local ret = {} for k, v in ipairs(this.vertices) do @@ -716,7 +707,7 @@ end __e2setcost(4) [nodiscard] -e2function string egpobject:egpObjectType() +e2function string egpobject:getObjectType() return this.Name or "Unknown" end @@ -728,7 +719,8 @@ __e2setcost(15) [nodiscard] e2function egpobject wirelink:egpCopy(number index, egpobject from) - if not EGP:IsAllowed(self, this) then return end + if not EGP:IsAllowed(self, this) then return NULL_EGPOBJECT end + if not EGP:ValidEGP(this) then return self:throw("Invalid wirelink!", NULL_EGPOBJECT) end if not isValid(from) then return self:throw("Invalid EGPObject", NULL_EGPOBJECT) end if from then local copy = table.Copy(from) @@ -738,7 +730,7 @@ e2function egpobject wirelink:egpCopy(number index, egpobject from) end end -e2function void egpobject:egpCopy(egpobject from) +e2function void egpobject:copyFrom(egpobject from) if not EGP:IsAllowed(self, this) then return end if not isValid(from) then return self:throw("Invalid EGPObject") end if from then @@ -761,18 +753,12 @@ __e2setcost(5) [nodiscard] e2function egpobject wirelink:egpobject(number index) - if not EGP:IsAllowed(self, this) then return end + if not EGP:IsAllowed(self, this) then return NULL_EGPOBJECT end + if not EGP:ValidEGP(this) then return self:throw("Invalid wirelink!", NULL_EGPOBJECT) end local _, _, obj = EGP:HasObject(this, index) return obj or NULL_EGPOBJECT end -__e2setcost(2) - -[nodiscard] -e2function string egpobject:egpObjectType() - return isValid(this) and EGP.Objects.Names_Inverted[this.ID] or "Unknown" -end - __e2setcost(1) [nodiscard] From 5be1685ed895bb3c951bec43a38f9a83d2eb9371 Mon Sep 17 00:00:00 2001 From: Denneisk Date: Mon, 11 Sep 2023 01:03:10 -0400 Subject: [PATCH 21/28] Add EGP object inheritance. Reduces LOC. +Other miscellaneous fixes to make this work. --- .../lib/egplib/objectcontrol.lua | 69 +++++++----- .../gmod_wire_egp/lib/egplib/parenting.lua | 4 +- .../lib/egplib/usefulfunctions.lua | 20 ++-- .../gmod_wire_egp/lib/objects/3dtracker.lua | 7 +- .../gmod_wire_egp/lib/objects/box.lua | 29 +++-- .../gmod_wire_egp/lib/objects/boxoutline.lua | 26 ++--- .../gmod_wire_egp/lib/objects/circle.lua | 27 +++-- .../lib/objects/circleoutline.lua | 26 ++--- .../gmod_wire_egp/lib/objects/line.lua | 30 +++--- .../gmod_wire_egp/lib/objects/linestrip.lua | 102 +----------------- .../gmod_wire_egp/lib/objects/poly.lua | 43 +++----- .../gmod_wire_egp/lib/objects/polyoutline.lua | 100 +++-------------- .../gmod_wire_egp/lib/objects/roundedbox.lua | 19 ++-- .../lib/objects/roundedboxoutline.lua | 28 +++-- .../gmod_wire_egp/lib/objects/text.lua | 31 +++--- .../gmod_wire_egp/lib/objects/textlayout.lua | 34 ++---- 16 files changed, 219 insertions(+), 376 deletions(-) diff --git a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua index 21dd7fbc8b..d7704309ca 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua @@ -3,9 +3,10 @@ -------------------------------------------------------- local EGP = EGP -EGP.Objects = {} -EGP.Objects.Names = {} -EGP.Objects.Names_Inverted = {} +local egpObjects = {} +egpObjects.Names = {} +egpObjects.Names_Inverted = {} +EGP.Objects = egpObjects -- This object is not used. It's only a base local baseObj = {} @@ -13,27 +14,28 @@ baseObj.ID = 0 baseObj.x = 0 baseObj.y = 0 baseObj.angle = 0 -baseObj.w = 0 -baseObj.h = 0 baseObj.r = 255 baseObj.g = 255 baseObj.b = 255 baseObj.a = 255 baseObj.filtering = TEXFILTER.ANISOTROPIC -baseObj.material = "" -if CLIENT then baseObj.material = false end baseObj.parent = 0 -baseObj.EGP = NULL -- EGP entity parent +if SERVER then + baseObj.material = "" + baseObj.EGP = NULL -- EGP entity parent +else + baseObj.material = false +end function baseObj:Transmit() - EGP:SendPosSize( self ) + EGP.SendPosAng(self) EGP:SendColor( self ) - EGP:SendMaterial( self ) + EGP:SendMaterial(self) net.WriteUInt(math.Clamp(self.filtering,0,3), 2) net.WriteInt( self.parent, 16 ) end function baseObj:Receive() local tbl = {} - EGP:ReceivePosSize( tbl ) + EGP.ReceivePosAng(tbl) EGP:ReceiveColor( tbl, self ) EGP:ReceiveMaterial( tbl ) tbl.filtering = net.ReadUInt(2) @@ -41,7 +43,7 @@ function baseObj:Receive() return tbl end function baseObj:DataStreamInfo() - return { x = self.x, y = self.y, w = self.w, h = self.h, r = self.r, g = self.g, b = self.b, a = self.a, material = self.material, filtering = self.filtering, parent = self.parent } + return { x = self.x, y = self.y, angle = self.angle, w = self.w, h = self.h, r = self.r, g = self.g, b = self.b, a = self.a, material = self.material, filtering = self.filtering, parent = self.parent } end function baseObj:Contains(x, y) return false @@ -95,20 +97,21 @@ end -- Load all objects ---------------------------- -function EGP:NewObject( Name ) - local lower = Name:lower() -- Makes my life easier +function EGP:NewObject(name, super) + local lower = name:lower() -- Makes my life easier + if not super then super = baseObj end if self.Objects[lower] then return self.Objects[lower] end -- Create table self.Objects[lower] = {} -- Set info - self.Objects[lower].Name = Name - table.Inherit(self.Objects[lower], self.Objects.Base) + self.Objects[lower].Name = name + table.Inherit(self.Objects[lower], super) -- Create lookup table local ID = table.Count(self.Objects) self.Objects[lower].ID = ID - self.Objects.Names[Name] = ID + self.Objects.Names[name] = ID -- Inverted lookup table self.Objects.Names_Inverted[ID] = lower @@ -116,20 +119,30 @@ function EGP:NewObject( Name ) return setmetatable(self.Objects[lower], M_EGPObject) end -do - local folder = "entities/gmod_wire_egp/lib/objects/" - local files = file.Find(folder.."*.lua", "LUA") - for _, v in ipairs(files) do - AddCSLuaFile(folder .. v) +local folder = "entities/gmod_wire_egp/lib/objects/" + +function EGP.ObjectInherit(to, from) + local super = egpObjects[from:lower()] + if super then + return EGP:NewObject(to, super) + else + local path = folder .. from .. ".lua" + if file.Exists(path, "LUA") then + super = include(path) + AddCSLuaFile(path) + return EGP:NewObject(to, super) + else + ErrorNoHalt(string.format("EGP couldn't find object '%s' to inherit from (to object '%s').\n", from, to)) + end end +end - local pending = {} +do + local files = file.Find(folder.."*.lua", "LUA") for _, v in ipairs(files) do - local path = folder .. v - local ok, thisOrParent = include(path) - if not ok then - if not pending[thisOrParent] then pending[thisOrParent] = {} end - pending[#thisOrParent + 1] = path + if not egpObjects[v:sub(1, #v - 4):lower()] then -- Remove the extension and check if the object already exists. + include(folder .. v) + AddCSLuaFile(folder .. v) end end end diff --git a/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua b/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua index 12ae7d71a4..0b7766fa35 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua @@ -18,7 +18,7 @@ EGP.ParentingFuncs.addUV = addUV local function makeArray( v, fakepos ) local ret = {} if isstring(v.verticesindex) then - if (not fakepos) then + if fakepos then if (not v["_"..v.verticesindex]) then EGP:AddParentIndexes( v ) end for k,v in ipairs( v["_"..v.verticesindex] ) do ret[#ret+1] = v.x @@ -31,7 +31,7 @@ local function makeArray( v, fakepos ) end end else - if (not fakepos) then + if fakepos then for k,v2 in ipairs( v.verticesindex ) do ret[#ret+1] = v["_"..v2[1]] ret[#ret+1] = v["_"..v2[2]] diff --git a/lua/entities/gmod_wire_egp/lib/egplib/usefulfunctions.lua b/lua/entities/gmod_wire_egp/lib/egplib/usefulfunctions.lua index 8107e4e34f..979b98b2d3 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/usefulfunctions.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/usefulfunctions.lua @@ -190,11 +190,15 @@ end ----------------------- -- Other ----------------------- -function EGP:SendPosSize( obj ) - net.WriteInt( obj.w, 16 ) - net.WriteInt( obj.h, 16 ) +function EGP.SendPosAng(obj) net.WriteInt( obj.x, 16 ) net.WriteInt( obj.y, 16 ) + net.WriteInt(obj.angle * 64, 16) +end + +function EGP.SendSize(obj) + net.WriteInt(obj.w, 16) + net.WriteInt(obj.h, 16) end function EGP:SendColor( obj ) @@ -204,11 +208,15 @@ function EGP:SendColor( obj ) if (obj.a) then net.WriteUInt( math.Clamp( obj.a, 0, 255 ) , 8) end end -function EGP:ReceivePosSize( tbl ) -- Used with SendPosSize - tbl.w = net.ReadInt(16) - tbl.h = net.ReadInt(16) +function EGP.ReceivePosAng(tbl) tbl.x = net.ReadInt(16) tbl.y = net.ReadInt(16) + tbl.angle = net.ReadInt(16) / 64 +end + +function EGP.ReceiveSize(tbl) + tbl.w = net.ReadInt(16) + tbl.h = net.ReadInt(16) end function EGP:ReceiveColor( tbl, obj ) -- Used with SendColor diff --git a/lua/entities/gmod_wire_egp/lib/objects/3dtracker.lua b/lua/entities/gmod_wire_egp/lib/objects/3dtracker.lua index 2ebd9e5f60..1b1e981077 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/3dtracker.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/3dtracker.lua @@ -1,8 +1,6 @@ -- Author: Divran local Obj = EGP:NewObject( "3DTracker" ) Obj.material = nil -Obj.w = nil -Obj.h = nil Obj.target_x = 0 Obj.target_y = 0 Obj.target_z = 0 @@ -12,7 +10,6 @@ Obj.b = nil Obj.a = nil Obj.parententity = NULL Obj.NeedsConstantUpdate = true -Obj.angle = 0 Obj.directionality = 0 function Obj:Draw(egp) @@ -90,7 +87,7 @@ function Obj:Transmit() net.WriteFloat( self.target_y ) net.WriteFloat( self.target_z ) net.WriteEntity( self.parententity ) - net.WriteInt((self.angle%360)*64, 16) + net.WriteInt(self.angle * 64, 16) net.WriteInt( self.directionality, 2 ) end @@ -109,3 +106,5 @@ end function Obj:DataStreamInfo() return { target_x = self.target_x, target_y = self.target_y, target_z = self.target_z, parententity = self.parententity, directionality = self.directionality } end + +return Obj \ No newline at end of file diff --git a/lua/entities/gmod_wire_egp/lib/objects/box.lua b/lua/entities/gmod_wire_egp/lib/objects/box.lua index 2bed122116..d4a7815e3d 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/box.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/box.lua @@ -1,29 +1,36 @@ -- Author: Divran local Obj = EGP:NewObject( "Box" ) -Obj.angle = 0 Obj.CanTopLeft = true +Obj.w = 0 +Obj.h = 0 + +local base = Obj.BaseClass + Obj.Draw = function( self ) if (self.a>0) then surface.SetDrawColor( self.r, self.g, self.b, self.a ) surface.DrawTexturedRectRotated( self.x, self.y, self.w, self.h, self.angle ) end end + Obj.Transmit = function( self ) - net.WriteInt((self.angle%360)*20, 16) - self.BaseClass.Transmit( self ) + EGP.SendSize(self) + base.Transmit(self) end + Obj.Receive = function( self ) - local tbl = {} - tbl.angle = net.ReadInt(16)/20 - table.Merge( tbl, self.BaseClass.Receive( self ) ) + tbl = {} + EGP.ReceiveSize(tbl) + table.Merge(tbl, base.Receive(self)) return tbl end -Obj.DataStreamInfo = function( self ) - local tbl = {} - table.Merge( tbl, self.BaseClass.DataStreamInfo( self ) ) - table.Merge( tbl, { angle = self.angle } ) + +function Obj:DataStreamInfo() + local tbl = { w = self.w, h = self.h } + table.Merge(tbl, base.DataStreamInfo(self)) return tbl end + function Obj:Contains(x, y) x, y = EGP.WorldToLocal(self, x, y) @@ -33,3 +40,5 @@ function Obj:Contains(x, y) return -w <= x and x <= w and -h <= y and y <= h end + +return Obj \ No newline at end of file diff --git a/lua/entities/gmod_wire_egp/lib/objects/boxoutline.lua b/lua/entities/gmod_wire_egp/lib/objects/boxoutline.lua index 2eac0a8d66..cee45e7c2b 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/boxoutline.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/boxoutline.lua @@ -1,8 +1,9 @@ -- Author: Divran -local Obj = EGP:NewObject( "BoxOutline" ) +local Obj = EGP.ObjectInherit("BoxOutline", "Box") Obj.size = 1 -Obj.angle = 0 -Obj.CanTopLeft = true + +local base = Obj.BaseClass + local function rotate( x, y, a ) local a = a * math.pi / 180 local _x = math.cos(a) * x - math.sin(a) * y @@ -49,20 +50,19 @@ end Obj.Transmit = function( self ) net.WriteInt( self.size, 16 ) - net.WriteInt( (self.angle%360)*20, 16 ) - self.BaseClass.Transmit( self ) + base.Transmit(self) end + Obj.Receive = function( self ) - local tbl = {} - tbl.size = net.ReadInt(16) - tbl.angle = net.ReadInt(16)/20 - table.Merge( tbl, self.BaseClass.Receive( self ) ) + local tbl = { size = net.ReadInt(16) } + table.Merge(tbl, base.Receive(self)) return tbl end + Obj.DataStreamInfo = function( self ) - local tbl = {} - tbl.size = self.size - tbl.angle = self.angle - table.Merge( tbl, self.BaseClass.DataStreamInfo( self ) ) + local tbl = { size = self.size } + table.Merge(tbl, base.DataStreamInfo(self)) return tbl end + +return Obj diff --git a/lua/entities/gmod_wire_egp/lib/objects/circle.lua b/lua/entities/gmod_wire_egp/lib/objects/circle.lua index eafc98153e..5227605c7c 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/circle.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/circle.lua @@ -1,7 +1,10 @@ -- Author: Divran -local Obj = EGP:NewObject( "Circle" ) +local Obj = EGP.ObjectInherit("Circle", "Box") Obj.angle = 0 Obj.fidelity = 180 + +local base = Obj.BaseClass + local cos, sin, rad, floor = math.cos, math.sin, math.rad, math.floor Obj.Draw = function( self ) if (self.a>0 and self.w > 0 and self.h > 0) then @@ -30,27 +33,31 @@ Obj.Draw = function( self ) surface.DrawPoly( self.vert_cache.verts ) end end -Obj.Transmit = function( self ) - net.WriteInt( (self.angle%360)*20, 16 ) - net.WriteUInt( self.fidelity, 8 ) - self.BaseClass.Transmit( self ) + +Obj.Transmit = function(self) + if not self then self = this end + net.WriteUInt(self.fidelity, 8) + base.Transmit(self) end + Obj.Receive = function( self ) local tbl = {} - tbl.angle = net.ReadInt(16)/20 tbl.fidelity = net.ReadUInt(8) - table.Merge( tbl, self.BaseClass.Receive( self ) ) + table.Merge(tbl, base.Receive(self)) return tbl end + Obj.DataStreamInfo = function( self ) - local tbl = {} - table.Merge( tbl, self.BaseClass.DataStreamInfo( self ) ) - table.Merge( tbl, { angle = self.angle, fidelity = self.fidelity } ) + local tbl = { fidelity = self.fidelity } + table.Merge(tbl, base.DataStreamInfo(self)) return tbl end + function Obj:Contains(x, y) -- Just do this directly since angle doesn't affect circles local _, realpos = EGP:GetGlobalPos(self.EGP, self) x, y = (x - realpos.x) / self.w, (y - realpos.y) / self.h return x * x + y * y <= 1 end + +return Obj \ No newline at end of file diff --git a/lua/entities/gmod_wire_egp/lib/objects/circleoutline.lua b/lua/entities/gmod_wire_egp/lib/objects/circleoutline.lua index c0620b760b..1e0e70f7b8 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/circleoutline.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/circleoutline.lua @@ -1,8 +1,9 @@ -- Author: Divran -local Obj = EGP:NewObject( "CircleOutline" ) -Obj.angle = 0 +local Obj = EGP.ObjectInherit("CircleOutline", "Circle") Obj.size = 1 -Obj.fidelity = 180 + +local base = Obj.BaseClass + local cos, sin, rad = math.cos, math.sin, math.rad Obj.Draw = function( self ) if (self.a>0 and self.w > 0 and self.h > 0) then @@ -28,23 +29,24 @@ Obj.Draw = function( self ) EGP:DrawPath(self.vert_cache.verts, self.size, true) end end + Obj.Transmit = function( self ) - net.WriteInt( (self.angle%360)*20, 16 ) - net.WriteInt( self.size, 16 ) - net.WriteUInt(self.fidelity, 8) - self.BaseClass.Transmit( self ) + net.WriteInt(self.size, 16) + base.Transmit(self) end + Obj.Receive = function( self ) local tbl = {} - tbl.angle = net.ReadInt(16)/20 tbl.size = net.ReadInt(16) - tbl.fidelity = net.ReadUInt(8) - table.Merge( tbl, self.BaseClass.Receive( self ) ) + table.Merge(tbl, base.Receive( self)) return tbl end + Obj.DataStreamInfo = function( self ) local tbl = {} - table.Merge( tbl, self.BaseClass.DataStreamInfo( self ) ) - table.Merge( tbl, { angle = self.angle, size = self.size, fidelity = self.fidelity } ) + tbl.size = self.size + table.Merge(tbl, base.DataStreamInfo(self)) return tbl end + +return Obj \ No newline at end of file diff --git a/lua/entities/gmod_wire_egp/lib/objects/line.lua b/lua/entities/gmod_wire_egp/lib/objects/line.lua index 5751104bb3..397a905da2 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/line.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/line.lua @@ -1,12 +1,12 @@ -- Author: Divran local Obj = EGP:NewObject( "Line" ) -Obj.w = nil -Obj.h = nil -Obj.angle = 0 Obj.x2 = 0 Obj.y2 = 0 Obj.size = 1 Obj.verticesindex = { { "x", "y" }, { "x2", "y2" } } + +local base = Obj.BaseClass + Obj.Draw = function( self ) if (self.a>0) then surface.SetDrawColor( self.r, self.g, self.b, self.a ) @@ -14,25 +14,21 @@ Obj.Draw = function( self ) end end Obj.Transmit = function( self ) - net.WriteInt( self.x, 16 ) - net.WriteInt( self.y, 16 ) + EGP.SendPosAng(self) net.WriteInt( self.x2, 16 ) net.WriteInt( self.y2, 16 ) net.WriteInt( self.size, 16 ) net.WriteInt( self.parent, 16 ) - net.WriteInt(self.angle, 10) EGP:SendMaterial( self ) EGP:SendColor( self ) end Obj.Receive = function( self ) local tbl = {} - tbl.x = net.ReadInt(16) - tbl.y = net.ReadInt(16) + EGP.ReceivePosAng(tbl) tbl.x2 = net.ReadInt(16) tbl.y2 = net.ReadInt(16) tbl.size = net.ReadInt(16) tbl.parent = net.ReadInt(16) - tbl.angle = net.ReadInt(10) EGP:ReceiveMaterial( tbl ) EGP:ReceiveColor( tbl, self ) return tbl @@ -65,10 +61,20 @@ function Obj:SetPos(x, y, angle, x2, y2) local sx, sx2, sy, sy2, sa = self.x, self.x2, self.y, self.y2, self.angle if not angle then angle = sa end if sx == x and sy == y and sa == angle and sx2 == x2 and sy2 == y2 then return false end - local vec = LocalToWorld(Vector(sx2 - sx, sy2 - sy, 0), angle_zero, Vector(x, y, 0), Angle(0, sa - angle, 0)) + local vec + if not (x2 or y2) then + x2 = x2 or sx2 + y2 = y2 or sy2 + vec = LocalToWorld(Vector(sx2 - sx, sy2 - sy, 0), angle_zero, Vector(x, y, 0), Angle(0, sa - angle, 0)) + self.x2, self.y2 = vec.x, vec.y + else + self.x2, self.y2 = x2, y2 + end self.x, self.y, self.angle = x, y, angle - self.x2, self.y2 = vec.x, vec.y + if self._x then self._x, self._y, self._angle, self._x2, self._y2 = x, y, angle, x2, y2 end return true -end \ No newline at end of file +end + +return Obj \ No newline at end of file diff --git a/lua/entities/gmod_wire_egp/lib/objects/linestrip.lua b/lua/entities/gmod_wire_egp/lib/objects/linestrip.lua index 81b49e619c..02102fd448 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/linestrip.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/linestrip.lua @@ -1,11 +1,6 @@ -- Author: sk8 (& Divran) -local Obj = EGP:NewObject( "LineStrip" ) -Obj.w = nil -Obj.h = nil -Obj.angle = 0 -Obj.vertices = {} -Obj.verticesindex = "vertices" -Obj.size = 1 +local Obj = EGP.ObjectInherit("LineStrip", "PolyOutline") + Obj.Draw = function( self ) local n = #self.vertices if (self.a>0 and n>0 and self.size>0) then @@ -14,96 +9,5 @@ Obj.Draw = function( self ) EGP:DrawPath(self.vertices, self.size, false) end end -Obj.Transmit = function( self, Ent, ply ) - net.WriteUInt( #self.vertices, 16 ) - for i=1,#self.vertices do - net.WriteInt( self.vertices[i].x, 16 ) - net.WriteInt( self.vertices[i].y, 16 ) - end - net.WriteInt(self.angle, 10) - net.WriteInt(self.parent, 16) - net.WriteInt(self.size, 16) - EGP:SendMaterial( self ) - EGP:SendColor( self ) -end -Obj.Receive = function( self ) - local tbl = {} - tbl.vertices = {} - for i=1,net.ReadUInt(16) do - tbl.vertices[ i ] = { x = net.ReadInt(16), y = net.ReadInt(16) } - end - tbl.angle = net.ReadInt(10) - tbl.parent = net.ReadInt(16) - tbl.size = net.ReadInt(16) - EGP:ReceiveMaterial( tbl ) - EGP:ReceiveColor( tbl, self ) - return tbl -end -Obj.DataStreamInfo = function( self ) - return { vertices = self.vertices, material = self.material, r = self.r, g = self.g, b = self.b, a = self.a, parent = self.parent, angle = self.angle } -end - -function Obj:Initialize(args) - self:EditObject(args) - self.x, self.y = EGP.getCenterFrom(self) -end -function Obj:EditObject(args) - local ret = false - if args.vertices then - self.vertices = args.vertices - self.x, self.y = EGP.getCenterFrom(self) - args.vertices = nil - end - if args.x or args.y or args.angle then - ret = self:SetPos(args.x or self.x, args.y or self.y, args.angle or self.angle) - args.x = nil - args.y = nil - args.angle = nil - if args._x then args._x = nil args._y = nil args._angle = nil end - end - for k, v in pairs(args) do - if self[k] ~= nil and self[k] ~= v then - self[k] = v - ret = true - end - end - return ret -end - -function Obj:SetPos(x, y, angle) - local sx, sy, sa = self.x, self.y, self.angle - if not angle then angle = sa end - if sx == x and sy == y and sa == angle then return false end - for i, v in ipairs(self.vertices) do - local vec = LocalToWorld(Vector(v.x - sx, v.y - sy, 0), angle_zero, Vector(x, y, 0), Angle(0, sa - angle, 0)) - v.x = vec.x - v.y = vec.y - end - self.x, self.y, self.angle = x, y, angle - if self._x then self._x, self._y, self._angle = x, y, angle end - return true -end - -function Obj:Set(key, value) - if key == "vertices" then - self.vertices = value - self.x, self.y = EGP.getCenterFrom(self) - return true - elseif key == "x" then - ret = self:SetPos(value, self.y, self.angle) - return true - elseif key == "y" then - ret = self:SetPos(self.x, value, self.angle) - return true - elseif key == "angle" then - ret = self:SetPos(self.x, self.y, value) - return true - else - if self[key] ~= nil and self[key] ~= value then - self[key] = value - return true - end - end - return false -end \ No newline at end of file +return Obj \ No newline at end of file diff --git a/lua/entities/gmod_wire_egp/lib/objects/poly.lua b/lua/entities/gmod_wire_egp/lib/objects/poly.lua index 67ac9a338e..fe6c4aa890 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/poly.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/poly.lua @@ -1,12 +1,11 @@ -- Author: Divran -local Obj = EGP:NewObject( "Poly" ) -Obj.w = nil -Obj.h = nil -Obj.angle = 0 +local Obj = EGP:NewObject("Poly") Obj.vertices = {} Obj.verticesindex = "vertices" Obj.HasUV = true +local base = Obj.BaseClass + -- Returns whether c is to the left of the line from a to b. local function counterclockwise( a, b, c ) local area = (a.x - c.x) * (b.y - c.y) - (b.x - c.x) * (a.y - c.y) @@ -22,7 +21,7 @@ Obj.Draw = function( self ) end end Obj.Transmit = function( self, Ent, ply ) - if (#self.vertices <= 28) then + if (#self.vertices <= 255) then net.WriteUInt( #self.vertices, 8 ) for i=1,#self.vertices do net.WriteInt( self.vertices[i].x, 16 ) @@ -34,14 +33,7 @@ Obj.Transmit = function( self, Ent, ply ) net.WriteUInt( 0, 8 ) EGP:InsertQueue( Ent, ply, EGP._SetVertex, "SetVertex", self.index, self.vertices ) end - net.WriteUInt(math.Clamp(self.filtering,0,3), 2) - net.WriteInt( self.parent, 16 ) - net.WriteInt(self.angle % 360, 10) - net.WriteInt(self.x, 16) - net.WriteInt(self.y, 16) - EGP:SendMaterial( self ) - EGP:SendColor( self ) - + base.Transmit(self) end Obj.Receive = function( self ) @@ -50,22 +42,11 @@ Obj.Receive = function( self ) for i = 1, net.ReadUInt(8) do tbl.vertices[ i ] = { x = net.ReadInt(16), y = net.ReadInt(16), u = net.ReadFloat(), v = net.ReadFloat() } end - tbl.filtering = net.ReadUInt(2) - tbl.parent = net.ReadInt(16) - tbl.angle = net.ReadInt(10) - tbl.x = net.ReadInt(16) - tbl.y = net.ReadInt(16) - EGP:ReceiveMaterial( tbl ) - EGP:ReceiveColor( tbl, self ) + table.Merge(tbl, base.Receive(self)) return tbl end Obj.DataStreamInfo = function( self ) - return { vertices = self.vertices, material = self.material, r = self.r, g = self.g, b = self.b, a = self.a, filtering = self.filtering, parent = self.parent, angle = self.angle } -end - -function Obj:Initialize(args) - self:EditObject(args) - self.x, self.y = EGP.getCenterFrom(self) + return { vertices = self.vertices, material = self.material, r = self.r, g = self.g, b = self.b, a = self.a, filtering = self.filtering, parent = self.parent, x = self.x, y = self.y, angle = self.angle } end function Obj:Contains(x, y) @@ -98,13 +79,14 @@ function Obj:EditObject(args) self.vertices = args.vertices self.x, self.y = EGP.getCenterFrom(self) args.vertices = nil + ret = true end if args.x or args.y or args.angle then ret = self:SetPos(args.x or self.x, args.y or self.y, args.angle or self.angle) args.x = nil args.y = nil args.angle = nil - if args._x then args._x, args._y, args._angle = nil, nil, nil end + if self._x then args._x, args._y, args._angle = nil, nil, nil end end for k, v in pairs(args) do if self[k] ~= nil and self[k] ~= v then @@ -115,6 +97,8 @@ function Obj:EditObject(args) return ret end +Obj.Initialize = Obj.EditObject + function Obj:SetPos(x, y, angle) local sx, sy, sa = self.x, self.y, self.angle if not angle then angle = sa end @@ -124,7 +108,7 @@ function Obj:SetPos(x, y, angle) v.x = vec.x v.y = vec.y end - self.x, self.y, self.angle = x, y, angle + self.x, self.y, self.angle = x, y, angle % 360 if self._x then self._x, self._y, self._angle = x, y, angle end return true end @@ -133,6 +117,7 @@ function Obj:Set(key, value) if key == "vertices" then self.vertices = value self.x, self.y = EGP.getCenterFrom(self) + self.angle = 0 return true elseif key == "x" then ret = self:SetPos(value, self.y, self.angle) @@ -151,3 +136,5 @@ function Obj:Set(key, value) end return false end + +return Obj \ No newline at end of file diff --git a/lua/entities/gmod_wire_egp/lib/objects/polyoutline.lua b/lua/entities/gmod_wire_egp/lib/objects/polyoutline.lua index 692fad2750..d59d7622f0 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/polyoutline.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/polyoutline.lua @@ -1,11 +1,9 @@ -- Author: sk8 (& Divran) -local Obj = EGP.Inherit(EGP:NewObject("PolyOutline"), EGP.Objects.Poly) -Obj.w = nil -Obj.h = nil -Obj.angle = 0 -Obj.vertices = {} -Obj.verticesindex = "vertices" +local Obj = EGP.ObjectInherit("PolyOutline", "Poly") Obj.size = 1 +Obj.HasUV = nil + +local base = Obj.BaseClass Obj.Draw = function( self ) local n = #self.vertices @@ -14,94 +12,22 @@ Obj.Draw = function( self ) EGP:DrawPath(self.vertices, self.size, true) end end + Obj.Transmit = function( self, Ent, ply ) - net.WriteUInt( #self.vertices, 16 ) - for i=1,#self.vertices do - net.WriteInt( self.vertices[i].x, 16 ) - net.WriteInt( self.vertices[i].y, 16 ) - end - net.WriteInt(self.parent, 16) net.WriteInt(self.size, 16) - EGP:SendMaterial( self ) - EGP:SendColor( self ) + base.Transmit(self) end + Obj.Receive = function( self ) - local tbl = {} - tbl.vertices = {} - for i=1,net.ReadUInt(16) do - tbl.vertices[ i ] = { x = net.ReadInt(16), y = net.ReadInt(16) } - end - tbl.parent = net.ReadInt(16) - tbl.size = net.ReadInt(16) - EGP:ReceiveMaterial( tbl ) - EGP:ReceiveColor( tbl, self ) + local tbl = { size = net.ReadInt(16) } + table.Merge(tbl, base.Receive(self)) return tbl end -Obj.DataStreamInfo = function( self ) - return { vertices = self.vertices, material = self.material, r = self.r, g = self.g, b = self.b, a = self.a, parent = self.parent } -end - -function Obj:Initialize(args) - self:EditObject(args) - self.x, self.y = EGP.getCenterFrom(self) -end -function Obj:EditObject(args) - local ret = false - if args.vertices then - self.vertices = args.vertices - self.x, self.y = EGP.getCenterFrom(self) - args.vertices = nil - end - if args.x or args.y or args.angle then - ret = self:SetPos(args.x or self.x, args.y or self.y, args.angle or self.angle) - args.x = nil - args.y = nil - args.angle = nil - if args._x then args._x, args._y, args._angle = nil, nil, nil end - end - for k, v in pairs(args) do - if self[k] ~= nil and self[k] ~= v then - self[k] = v - ret = true - end - end - return ret +Obj.DataStreamInfo = function( self ) + return table.Merge({ size = self.size }, base.DataStreamInfo(self)) end -function Obj:SetPos(x, y, angle) - local sx, sy, sa = self.x, self.y, self.angle - if not angle then angle = sa end - if sx == x and sy == y and sa == angle then return false end - for i, v in ipairs(self.vertices) do - local vec = LocalToWorld(Vector(v.x - sx, v.y - sy, 0), angle_zero, Vector(x, y, 0), Angle(0, sa - angle, 0)) - v.x = vec.x - v.y = vec.y - end - self.x, self.y, self.angle = x, y, angle - if self._x then self._x, self._y, self._angle = x, y, angle end - return true -end +Obj.Contains = EGP.Objects.Base.Contains -function Obj:Set(key, value) - if key == "vertices" then - self.vertices = value - self.x, self.y = EGP.getCenterFrom(self) - return true - elseif key == "x" then - ret = self:SetPos(value, self.y, self.angle) - return true - elseif key == "y" then - ret = self:SetPos(self.x, value, self.angle) - return true - elseif key == "angle" then - ret = self:SetPos(self.x, self.y, value) - return true - else - if self[key] ~= nil and self[key] ~= value then - self[key] = value - return true - end - end - return false -end \ No newline at end of file +return Obj \ No newline at end of file diff --git a/lua/entities/gmod_wire_egp/lib/objects/roundedbox.lua b/lua/entities/gmod_wire_egp/lib/objects/roundedbox.lua index ab50f5584a..e16fb93a18 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/roundedbox.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/roundedbox.lua @@ -1,9 +1,10 @@ -- Author: sk8 (& Divran) -local Obj = EGP:NewObject( "RoundedBox" ) -Obj.angle = 0 +local Obj = EGP.ObjectInherit("RoundedBox", "Box") Obj.radius = 16 -Obj.CanTopLeft = true Obj.fidelity = 36 + +local base = Obj.BaseClass + Obj.Draw = function( self ) if EGP:CacheNeedsUpdate(self, {"x", "y", "w", "h", "angle", "fidelity", "radius"}) then local xs,ys , sx,sy = self.x,self.y , self.w, self.h @@ -33,23 +34,21 @@ Obj.Draw = function( self ) surface.DrawPoly(self.vert_cache.verts) end Obj.Transmit = function( self ) - net.WriteInt((self.angle%360)*20, 16) net.WriteInt(self.radius, 16) net.WriteUInt(self.fidelity, 8) - self.BaseClass.Transmit( self ) + base.Transmit(self) end Obj.Receive = function( self ) local tbl = {} - tbl.angle = net.ReadInt(16)/20 tbl.radius = net.ReadInt(16) tbl.fidelity = net.ReadUInt(8) - table.Merge( tbl, self.BaseClass.Receive( self ) ) + table.Merge(tbl, base.Receive(self)) return tbl end Obj.DataStreamInfo = function( self ) local tbl = {} - table.Merge( tbl, self.BaseClass.DataStreamInfo( self ) ) - table.Merge( tbl, { angle = self.angle, radius = self.radius, fidelity = self.fidelity } ) + table.Merge( tbl, base.DataStreamInfo( self ) ) + table.Merge( tbl, { radius = self.radius, fidelity = self.fidelity } ) return tbl end function Obj:Contains(x, y) @@ -66,3 +65,5 @@ function Obj:Contains(x, y) x, y = x / h, y / h return x * x + y * y <= 1 end + +return Obj \ No newline at end of file diff --git a/lua/entities/gmod_wire_egp/lib/objects/roundedboxoutline.lua b/lua/entities/gmod_wire_egp/lib/objects/roundedboxoutline.lua index 5919657569..02a218ec3f 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/roundedboxoutline.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/roundedboxoutline.lua @@ -1,10 +1,9 @@ -- Author: sk8 (& Divran) -local Obj = EGP:NewObject( "RoundedBoxOutline" ) -Obj.angle = 0 -Obj.radius = 16 +local Obj = EGP.ObjectInherit("RoundedBoxOutline", "RoundedBox") Obj.size = 1 -Obj.CanTopLeft = true -Obj.fidelity = 36 + +local base = Obj.BaseClass + Obj.Draw = function( self ) if EGP:CacheNeedsUpdate(self, {"x", "y", "w", "h", "angle", "fidelity", "radius"}) then local xs,ys , sx,sy = self.x,self.y , self.w, self.h @@ -29,24 +28,21 @@ Obj.Draw = function( self ) EGP:DrawPath(self.vert_cache.verts, self.size, true) end Obj.Transmit = function( self ) - net.WriteInt((self.angle%360)*20, 16) - net.WriteInt(self.radius, 16) net.WriteInt(self.size, 16) - net.WriteUInt(self.fidelity, 8) - self.BaseClass.Transmit( self ) + base.Transmit(self) end Obj.Receive = function( self ) local tbl = {} - tbl.angle = net.ReadInt(16)/20 - tbl.radius = net.ReadInt(16) tbl.size = net.ReadInt(16) - tbl.fidelity = net.ReadUInt(8) - table.Merge( tbl, self.BaseClass.Receive( self ) ) + table.Merge(tbl, base.Receive(self)) return tbl end Obj.DataStreamInfo = function( self ) - local tbl = {} - table.Merge( tbl, self.BaseClass.DataStreamInfo( self ) ) - table.Merge( tbl, { angle = self.angle, radius = self.radius, fidelity = self.fidelity } ) + local tbl = { size = self.size } + table.Merge(tbl, base.DataStreamInfo(self)) return tbl end + +Obj.Contains = nil + +return Obj \ No newline at end of file diff --git a/lua/entities/gmod_wire_egp/lib/objects/text.lua b/lua/entities/gmod_wire_egp/lib/objects/text.lua index 5a7d1ff34b..213293a58b 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/text.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/text.lua @@ -1,13 +1,10 @@ -- Author: Divran local Obj = EGP:NewObject( "Text" ) -Obj.h = nil -Obj.w = nil Obj.text = "" Obj.font = "WireGPU_ConsoleFont" Obj.size = 18 Obj.valign = 0 Obj.halign = 0 -Obj.angle = 0 local surface_SetTextPos local surface_DrawText @@ -98,30 +95,36 @@ function Obj:Draw(ent, drawMat) end end Obj.Transmit = function( self, Ent, ply ) - net.WriteInt( self.x, 16 ) - net.WriteInt( self.y, 16 ) - EGP:InsertQueue( Ent, ply, EGP._SetText, "SetText", self.index, self.text ) + EGP.SendPosAng(self) + local len = #self.text + if len <= 1024 then + net.WriteUInt(len, 11) + net.WriteData(self.text, len) + else + net.WriteUInt(0, 11) + EGP:InsertQueue(Ent, ply, EGP._SetText, "SetText", self.index, self.text) + end net.WriteString(self.font) - net.WriteUInt(math.Clamp(self.size,0,256), 8) + net.WriteUInt(math.Clamp(self.size, 0, 255), 8) net.WriteUInt(math.Clamp(self.valign,0,2), 2) net.WriteUInt(math.Clamp(self.halign,0,2), 2) - net.WriteInt( self.parent, 16 ) - EGP:SendColor( self ) - net.WriteInt((self.angle%360)*20, 16) + net.WriteInt(self.parent, 16) + EGP:SendColor(self) end Obj.Receive = function( self ) local tbl = {} - tbl.x = net.ReadInt(16) - tbl.y = net.ReadInt(16) + EGP.ReceivePosAng(tbl) + local len = net.ReadUInt(11) + local text = net.ReadData(len) + tbl.text = #text > 0 and text or nil tbl.font = net.ReadString() tbl.size = net.ReadUInt(8) tbl.valign = net.ReadUInt(2) tbl.halign = net.ReadUInt(2) tbl.parent = net.ReadInt(16) EGP:ReceiveColor( tbl, self ) - tbl.angle = net.ReadInt(16)/20 return tbl end Obj.DataStreamInfo = function( self ) - return { x = self.x, y = self.y, valign = self.valign, halign = self.halign, size = self.size, r = self.r, g = self.g, b = self.b, a = self.a, text = self.text, font = self.font, parent = self.parent, angle = self.angle } + return { x = self.x, y = self.y, angle = self.angle, valign = self.valign, halign = self.halign, size = self.size, r = self.r, g = self.g, b = self.b, a = self.a, text = self.text, font = self.font, parent = self.parent } end diff --git a/lua/entities/gmod_wire_egp/lib/objects/textlayout.lua b/lua/entities/gmod_wire_egp/lib/objects/textlayout.lua index d9d183a586..1d0b0656ae 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/textlayout.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/textlayout.lua @@ -1,13 +1,9 @@ -- Author: Divran -local Obj = EGP:NewObject( "TextLayout" ) +local Obj = EGP.ObjectInherit("TextLayout", "Text") Obj.h = 512 Obj.w = 512 -Obj.text = "" -Obj.font = "WireGPU_ConsoleFont" -Obj.size = 18 -Obj.valign = 0 -Obj.halign = 0 -Obj.angle = 0 + +local base = Obj.BaseClass local cam_PushModelMatrix local cam_PopModelMatrix @@ -93,28 +89,14 @@ function Obj:Draw(ent, drawMat) end end Obj.Transmit = function( self, Ent, ply ) - EGP:SendPosSize( self ) - EGP:InsertQueue( Ent, ply, EGP._SetText, "SetText", self.index, self.text ) - net.WriteString(self.font) - net.WriteUInt(math.Clamp(self.size,0,256), 8) - net.WriteUInt(math.Clamp(self.valign,0,2), 2) - net.WriteUInt(math.Clamp(self.halign,0,2), 2) - net.WriteInt( self.parent, 16 ) - EGP:SendColor( self ) - net.WriteInt((self.angle%360)*20, 16) + EGP.SendSize(self) + base.Transmit(self) end Obj.Receive = function( self ) local tbl = {} - EGP:ReceivePosSize( tbl ) - tbl.font = net.ReadString(8) - tbl.size = net.ReadUInt(8) - tbl.valign = net.ReadUInt(2) - tbl.halign = net.ReadUInt(2) - tbl.parent = net.ReadInt(16) - EGP:ReceiveColor( tbl, self ) - tbl.angle = net.ReadInt(16)/20 - return tbl + EGP.ReceiveSize(tbl) + return table.Merge(tbl, base.Receive(self)) end Obj.DataStreamInfo = function( self ) - return { x = self.x, y = self.y, w = self.w, h = self.h, valign = self.valign, halign = self.halign, size = self.size, r = self.r, g = self.g, b = self.b, a = self.a, text = self.text, font = self.font, parent = self.parent, angle = self.angle } + return table.Merge({ w = self.w, h = self.h}, base.DataStreamInfo(self)) end From 2546baf82a28d7310bf1fbe42bfe03a8821db7c7 Mon Sep 17 00:00:00 2001 From: Denneisk Date: Mon, 11 Sep 2023 03:49:25 -0400 Subject: [PATCH 22/28] E2Descriptions. Fix getMaterial returning entity. --- .../gmod_wire_expression2/core/egpobjects.lua | 2 +- lua/wire/client/e2descriptions.lua | 87 ++++++++++++------- 2 files changed, 56 insertions(+), 33 deletions(-) diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index 1eb00297d5..418e4cf387 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -673,7 +673,7 @@ end [nodiscard] e2function string egpobject:getMaterial() if not isValid(this) then return self:throw("Invalid EGP Object", "") end - return this.material or "" + return tostring(this.material) or "" end [nodiscard] diff --git a/lua/wire/client/e2descriptions.lua b/lua/wire/client/e2descriptions.lua index f58d594d37..e8d4df62b3 100644 --- a/lua/wire/client/e2descriptions.lua +++ b/lua/wire/client/e2descriptions.lua @@ -1504,47 +1504,70 @@ E2Helper.Descriptions["egpWedgeOutline"] = "Creates a outline wedge object. Wedg E2Helper.Descriptions["modify(xeo:t)"] = "Modifies an object with the provided arguments." -E2Helper.Descriptions["egpAlign(xeo:n)"] = "Changes the horizontal alignment. Works on: text and text layout. Number can be 0, 1 or 2" -E2Helper.Descriptions["egpAlign(xeo:nn)"] = "Changes the horizontal and vertical alignment. Works on: text and text layout. Numbers can be 0, 1 or 2" -E2Helper.Descriptions["egpAlpha(xeo:n)"] = "Changes the alpha (transparency) of an object" -E2Helper.Descriptions["egpAngle(xeo:n)"] = "Changes the angle of the object" -E2Helper.Descriptions["egpAngle(xeo:xv2xv2n)"] = "Rotates the object around the first vec2 with the second vec2 as offset at angle N" -E2Helper.Descriptions["egpColor(xeo:nnnn)"] = "Changes the color and alpha of the object" -E2Helper.Descriptions["egpColor(xeo:xv4)"] = "Changes the color and alpha of the object" -E2Helper.Descriptions["egpColor(xeo:v)"] = "Changes the color of the object" -E2Helper.Descriptions["egpFidelity(xeo:n)"] = "Changes the fidelity of the object (the number of vertices the circle will use)" -E2Helper.Descriptions["egpFont(xeo:sn)"] = "Changes the font and size of the text object" -E2Helper.Descriptions["egpMaterial(xeo:s)"] = "Changes the material of the object" -E2Helper.Descriptions["egpMaterialFromScreen(xeo:e)"] = "Sets the material of the object to a current snapshot of the target screen. Note that this only works for players which see both the egp as well the target screen at that time" -E2Helper.Descriptions["egpOrder(xeo:n)"] = "Sets the order at which the object will be rendered. This is different from index" -E2Helper.Descriptions["egpOrderAbove(xeo:n)"] = "Makes the object render above the object at the index" -E2Helper.Descriptions["egpOrderBelow(xeo:n)"] = "Makes the object render below the object at the index" -E2Helper.Descriptions["egpParent(xeo:e)"] = "Parents the 3D tracker object to an entity" -E2Helper.Descriptions["egpParent(xeo:n)"] = "Parents the object to another object. Parented objects' positions are local to their parent" -E2Helper.Descriptions["egpParent(xeo:xeo)"] = "Parents the object to another object. Parented objects' positions are local to their parent" +E2Helper.Descriptions["copyFrom(xeo:xeo)"] = "Copies the settings of the second object into the first. If the first object does not exist, it's created" +E2Helper.Descriptions["getAlpha(xeo:)"] = "Returns the alpha of the object" +E2Helper.Descriptions["getAngle(xeo:)"] = "Returns the angle of the object" +E2Helper.Descriptions["getColor(xeo:)"] = "Returns the color of the object as a vector" +E2Helper.Descriptions["getColor4(xeo:)"] = "Returns the color of the object as a vector4" +E2Helper.Descriptions["getFidelity(xeo:)"] = "Returns the fidelity of the object" +E2Helper.Descriptions["getMaterial(xeo:)"] = "Returns the material of the object. Note this does not return anything when using a GPU material" +E2Helper.Descriptions["getObjectType(xeo:)"] = "Returns the type of the object" +E2Helper.Descriptions["getOrder(xeo:)"] = "Returns the order at which the object is rendered" +E2Helper.Descriptions["getRadius(xeo:)"] = "Returns the radius of the object" +E2Helper.Descriptions["getSize(xeo:)"] = "Returns the size of the object" +E2Helper.Descriptions["getSizeNum(xeo:)"] = "Returns the size of the text/line/outline object" +E2Helper.Descriptions["getVertices(xeo:)"] = "Returns an array of the vertices of the object" +E2Helper.Descriptions["globalPos(xeo:)"] = "Returns the \"global\" (= it takes the parents' positions into consideration) position as a 3D vector. X and Y being the 2D X,Y coordinates, while Z is the angle" +E2Helper.Descriptions["globalVertices(xeo:)"] = "Returns an array of 2D vectors with the \"global\" positions of the vertices in the object" +E2Helper.Descriptions["setAlign(xeo:n)"] = "Changes the horizontal alignment. Works on: text and text layout. Number can be 0, 1 or 2" +E2Helper.Descriptions["setAlign(xeo:nn)"] = "Changes the horizontal and vertical alignment. Works on: text and text layout. Numbers can be 0, 1 or 2" +E2Helper.Descriptions["setAlpha(xeo:n)"] = "Changes the alpha (transparency) of an object" +E2Helper.Descriptions["setAngle(xeo:n)"] = "Changes the angle of the object" +E2Helper.Descriptions["rotateAroundAxis(xeo:xv2xv2n)"] = "Rotates the object around the first vec2 with the second vec2 as offset at angle N" +E2Helper.Descriptions["setColor(xeo:nnnn)"] = "Changes the color and alpha of the object" +E2Helper.Descriptions["setColor(xeo:xv4)"] = "Changes the color and alpha of the object" +E2Helper.Descriptions["setColor(xeo:v)"] = "Changes the color of the object" +E2Helper.Descriptions["setFidelity(xeo:n)"] = "Changes the fidelity of the object (the number of vertices the circle will use)" +E2Helper.Descriptions["setFont(xeo:s)"] = "Changes the font of the text object" +E2Helper.Descriptions["setFont(xeo:sn)"] = "Changes the font and size of the text object" +E2Helper.Descriptions["setMaterial(xeo:s)"] = "Changes the material of the object" +E2Helper.Descriptions["setMaterialFromScreen(xeo:e)"] = "Sets the material of the object to a current snapshot of the target screen. Note that this only works for players which see both the egp as well the target screen at that time" +E2Helper.Descriptions["setOrder(xeo:n)"] = "Sets the order at which the object will be rendered. This is different from index" +E2Helper.Descriptions["setOrderAbove(xeo:xeo)"] = "Makes the object render above the object" +E2Helper.Descriptions["setOrderBelow(xeo:xeo)"] = "Makes the object render below the object" +E2Helper.Descriptions["parent(xeo:)"] = "Returns the parent object" +E2Helper.Descriptions["parentTo(xeo:n)"] = "Parents the object to another object. Parented objects' positions are local to their parent" +E2Helper.Descriptions["parentTo(xeo:xeo)"] = "Parents the object to another object. Parented objects' positions are local to their parent" E2Helper.Descriptions["egpParent(xwl:xeoxeo)"] = "Parents the object to another object. Parented objects' positions are local to their parent" -E2Helper.Descriptions["egpParentToCursor(xeo:)"] = "Parents the object to player's cursor" -E2Helper.Descriptions["egpParentIndex(xeo:)"] = "Returns the index of the parent object" -E2Helper.Descriptions["egpUnParent(xeo:)"] = "Un-parents the object" -E2Helper.Descriptions["egpPos(xeo:)"] = "Returns the position of the object" -E2Helper.Descriptions["egpPosAng(xeo:)"] = "Returns the position (x, y) and angle (z) of the object" -E2Helper.Descriptions["egpPos(xeo:nnnn)"] = "Changes the position of the start and end of a line object, otherwise acts normally." -E2Helper.Descriptions["egpPos(xeo:v)"] = "Changes the world position of the 3D tracker object" -E2Helper.Descriptions["egpRadius(xeo:n)"] = "Changes the corner radius of the rounded box object" -E2Helper.Descriptions["egpSetText(xeo:s)"] = "Changes the text of the text object" -E2Helper.Descriptions["egpSetText(xeo:ssn)"] = "Changes the text, font, and text size of the text object" -E2Helper.Descriptions["egpSetVertices"] = "Sets the vertices of the object. Can use vector2 or vector4 for vertices." -E2Helper.Descriptions["egpSize(xeo:)"] = "Returns the size of the object" -E2Helper.Descriptions["egpSize(xeo:n)"] = "Changes the size of the text/line/outline object" +E2Helper.Descriptions["parentToCursor(xeo:)"] = "Parents the object to player's cursor" +E2Helper.Descriptions["parentIndex(xeo:)"] = "Returns the index of the parent object" +E2Helper.Descriptions["remove(xeo:)"] = "Removes the object from the screen" +E2Helper.Descriptions["unparent(xeo:)"] = "Un-parents the object" +E2Helper.Descriptions["getPos(xeo:)"] = "Returns the position of the object" +E2Helper.Descriptions["getPosAng(xeo:)"] = "Returns the position (x, y) and angle (z) of the object" +E2Helper.Descriptions["setPos(xeo:nnnn)"] = "Changes the position of the start and end of a line object, otherwise acts normally." +E2Helper.Descriptions["setPos(xeo:v)"] = "Changes the world position of the 3D tracker object" +E2Helper.Descriptions["setPos(xeo:xv2)"] = "Changes the position of the object" +E2Helper.Descriptions["setPos(xeo:nn)"] = "Changes the position of the object" +E2Helper.Descriptions["setPos(xeo:nnn)"] = "Changes the position and angle of the object" +E2Helper.Descriptions["setRadius(xeo:n)"] = "Changes the corner radius of the rounded box object" +E2Helper.Descriptions["setText(xeo:s)"] = "Changes the text of the text object" +E2Helper.Descriptions["setText(xeo:ssn)"] = "Changes the text, font, and text size of the text object" +E2Helper.Descriptions["setVertices"] = "Sets the vertices of the object. Can use vector2 or vector4 for vertices." +E2Helper.Descriptions["setSize(xeo:n)"] = "Changes the size of the text/line/outline object" +E2Helper.Descriptions["setSize(xeo:nn)"] = "Changes the width and height of an object" +E2Helper.Descriptions["setSize(xeo:xv2)"] = "Changes the width and height of an object" E2Helper.Descriptions["isVisible(xeo:)"] = "Returns 1 if the object is visible." E2Helper.Descriptions["hide(xeo:)"] = "Removes an object from the screen but keeps its data intact." E2Helper.Descriptions["draw(xeo:)"] = "Shows a hidden EGP object." +E2Helper.Descriptions["trackerParent(xeo:)"] = "Returns the parent entity of the 3D tracker object." +E2Helper.Descriptions["trackerParent(xeo:e)"] = "Parents the 3D tracker object to an entity" E2Helper.Descriptions["egpConnectedUsers(xwl:)"] = "Returns an array of players connected to the EGP" E2Helper.Descriptions["egpCursor(xwl:e)"] = "Returns the specified player's aim position on the screen" E2Helper.Descriptions["egpHasObject(xwl:xeo)"] = "Returns 1 if the object exists on the screen, 0 if not" E2Helper.Descriptions["containsPoint(xeo:xv2)"] = "Returns 1 if the object contains the specified point" -E2Helper.Descriptions["egpFiltering(xeo:n)"] = "Changes the texture filter used to draw the object. Works on objects that draw a material. See _TEXFILTER constants (POINT=sharp, ANISOTROPIC=blurry/default)" +E2Helper.Descriptions["setFiltering(xeo:n)"] = "Changes the texture filter used to draw the object. Works on objects that draw a material. See _TEXFILTER constants (POINT=sharp, ANISOTROPIC=blurry/default)" E2Helper.Descriptions["egpobject(xwl:n)"] = "Returns the EGPObject at the index" E2Helper.Descriptions["noegpobject"] = "Returns a NULL egpobject." E2Helper.Descriptions["toString(xeo:)"] = "Returns a string representation of the EGPObject" From 6744d996fe4c1e79f34364efdfcf6986e4f3766b Mon Sep 17 00:00:00 2001 From: Denneisk <20892685+Denneisk@users.noreply.github.com> Date: Wed, 20 Sep 2023 21:23:06 -0400 Subject: [PATCH 23/28] Minor code reduction --- lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua | 6 +++--- lua/entities/gmod_wire_egp/lib/objects/line.lua | 5 +---- .../gmod_wire_egp/lib/objects/roundedboxoutline.lua | 1 + lua/entities/gmod_wire_egp/lib/objects/text.lua | 1 + 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua index d7704309ca..0869ca2f47 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua @@ -30,7 +30,7 @@ function baseObj:Transmit() EGP.SendPosAng(self) EGP:SendColor( self ) EGP:SendMaterial(self) - net.WriteUInt(math.Clamp(self.filtering,0,3), 2) + if self.filtering then net.WriteUInt(math.Clamp(self.filtering,0,3), 2) end net.WriteInt( self.parent, 16 ) end function baseObj:Receive() @@ -38,12 +38,12 @@ function baseObj:Receive() EGP.ReceivePosAng(tbl) EGP:ReceiveColor( tbl, self ) EGP:ReceiveMaterial( tbl ) - tbl.filtering = net.ReadUInt(2) + if self.filtering then tbl.filtering = net.ReadUInt(2) end tbl.parent = net.ReadInt(16) return tbl end function baseObj:DataStreamInfo() - return { x = self.x, y = self.y, angle = self.angle, w = self.w, h = self.h, r = self.r, g = self.g, b = self.b, a = self.a, material = self.material, filtering = self.filtering, parent = self.parent } + return { x = self.x, y = self.y, angle = self.angle, w = self.w, h = self.h, r = self.r, g = self.g, b = self.b, a = self.a, material = self.material, parent = self.parent } end function baseObj:Contains(x, y) return false diff --git a/lua/entities/gmod_wire_egp/lib/objects/line.lua b/lua/entities/gmod_wire_egp/lib/objects/line.lua index be96e1fcd3..365c9320c7 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/line.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/line.lua @@ -1,13 +1,12 @@ -- Author: Divran local Obj = EGP:NewObject( "Line" ) +Obj.material = nil Obj.filtering = nil Obj.x2 = 0 Obj.y2 = 0 Obj.size = 1 Obj.verticesindex = { { "x", "y" }, { "x2", "y2" } } -local base = Obj.BaseClass - Obj.Draw = function( self ) if (self.a>0) then surface.SetDrawColor( self.r, self.g, self.b, self.a ) @@ -20,7 +19,6 @@ Obj.Transmit = function( self ) net.WriteInt( self.y2, 16 ) net.WriteInt( self.size, 16 ) net.WriteInt( self.parent, 16 ) - EGP:SendMaterial( self ) EGP:SendColor( self ) end Obj.Receive = function( self ) @@ -30,7 +28,6 @@ Obj.Receive = function( self ) tbl.y2 = net.ReadInt(16) tbl.size = net.ReadInt(16) tbl.parent = net.ReadInt(16) - EGP:ReceiveMaterial( tbl ) EGP:ReceiveColor( tbl, self ) return tbl end diff --git a/lua/entities/gmod_wire_egp/lib/objects/roundedboxoutline.lua b/lua/entities/gmod_wire_egp/lib/objects/roundedboxoutline.lua index 02a218ec3f..aafa6e3a2b 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/roundedboxoutline.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/roundedboxoutline.lua @@ -1,6 +1,7 @@ -- Author: sk8 (& Divran) local Obj = EGP.ObjectInherit("RoundedBoxOutline", "RoundedBox") Obj.size = 1 +Obj.filtering = nil local base = Obj.BaseClass diff --git a/lua/entities/gmod_wire_egp/lib/objects/text.lua b/lua/entities/gmod_wire_egp/lib/objects/text.lua index 213293a58b..155a26131f 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/text.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/text.lua @@ -1,5 +1,6 @@ -- Author: Divran local Obj = EGP:NewObject( "Text" ) +Obj.material = nil Obj.text = "" Obj.font = "WireGPU_ConsoleFont" Obj.size = 18 From cf471a5d2bf0e4b9064d9419596cde7dd65608b1 Mon Sep 17 00:00:00 2001 From: Denneisk <20892685+Denneisk@users.noreply.github.com> Date: Mon, 2 Oct 2023 14:31:54 -0400 Subject: [PATCH 24/28] Update to compiler rewrite --- .../gmod_wire_expression2/core/egpobjects.lua | 25 ++++++------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index 418e4cf387..109f86522d 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -77,10 +77,6 @@ e2function number operator==(egpobject lhs, egpobject rhs) return (lhs == rhs) and 1 or 0 end -e2function number operator!=(egpobject lhs, egpobject rhs) - return (lhs ~= rhs) and 1 or 0 -end - ---- Functions ---------------------------- @@ -789,7 +785,7 @@ registerCallback("postinit", function() __e2setcost(5) -- Getter - registerOperator("idx", id .. "=xeos", id, function(self, args) + registerOperator("indexget", "xeos" .. id, id, function(self, args) local op1, op2 = args[2], args[3] local this, index = op1[1](self, op1), op2[1](self, op2) local indexType = EGP_ALLOWED_ARGS[index] @@ -805,10 +801,7 @@ registerCallback("postinit", function() end) -- Setter - registerOperator("idx", id .. "=xeos" .. id, id, function(self, args) - local op1, op2, op3, scope = args[2], args[3], args[4], args[5] - local this, index, value = op1[1](self, op1), op2[1](self, op2), op3[1](self, op3) - + registerOperator("indexset", "xeos" .. id, id, function(self, this, index, value) if not EGP_ALLOWED_ARGS[index] then return fixDefault(default) end if not isValid(this) then return self:throw("Tried to acces invalid EGP Object", nil) end @@ -819,9 +812,7 @@ registerCallback("postinit", function() end) -- Implicitly typed setter - registerOperator("idx", "xeos" .. id, id, function(self, args) - local op1, op2, op3, scope = args[2], args[3], args[4], args[5] - local this, index, value = op1[1](self, op1), op2[1](self, op2), op3[1](self, op3) + registerOperator("indexset", "xeos", id, function(self, this, index, value) local indexType = EGP_ALLOWED_ARGS[index] if not indexType then return end @@ -840,8 +831,7 @@ registerCallback("postinit", function() for name, id in pairs(workingSet) do -- Indexed table "constructor" registerFunction("egp" .. name, "xwl:nt", "xeo", function(self, args) - local op1, op2, op3 = args[2], args[3], args[4] - local this, index, args = op1[1](self, op1), op2[1](self, op2), op3[1](self, op3) + local this, index, args = args[1], args[2], args[3] if not EGP:IsAllowed(self, this) then return NULL_EGPOBJECT end local converted = {} @@ -858,13 +848,12 @@ registerCallback("postinit", function() Update(self, this) end return obj - end, 10, { "index", "args" }) + end, 10, { "index", "args" }, { legacy = false }) --[[ -- Unindexed table constructor registerFunction("egp" .. name, "xwl:t", "xeo", function(self, args) - local op1, op2 = args[2], args[3] - local this, args = op1[1](self, op1), op2[1](self, op2) + local this, index, args = args[1], args[2], args[3] local converted = {} @@ -880,7 +869,7 @@ registerCallback("postinit", function() Update(self, this) return obj end - end, 10, { "this", "args" }, { "nodiscard" }) + end, 10, { "this", "args" }, { nodiscard = true, legacy = false }) ]] end end) From 53e68c2631fa2a54e315b0a4b10045271e54583c Mon Sep 17 00:00:00 2001 From: Denneisk <20892685+Denneisk@users.noreply.github.com> Date: Sun, 22 Oct 2023 09:17:41 -0400 Subject: [PATCH 25/28] Minor update --- lua/entities/gmod_wire_expression2/core/egpobjects.lua | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index 109f86522d..1ac1e2f2b4 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -44,14 +44,10 @@ end ---- Type defintion -registerType("egpobject", "xeo", nil, +registerType("egpobject", "xeo", NULL_EGPOBJECT, + nil, nil, nil, - function(retval) - if retval == nil then return end - if not istable(retval) then error("Return value is neither nil nor a table, but a " .. type(retval) .. "!", 0) end - if not getmetatable(retval) == M_EGPObject then error("Return value is not an egpobject!", 0) end - end, function(v) return not istable(v) or getmetatable(v) ~= M_EGPObject end From 47f8b9e98e97e02334ff4c0877ba27b7f10df1cc Mon Sep 17 00:00:00 2001 From: Denneisk <20892685+Denneisk@users.noreply.github.com> Date: Thu, 26 Oct 2023 11:30:27 -0400 Subject: [PATCH 26/28] Lint and minor optimize drawing for RoundedBox Simplify drawing for RoundedBoxOutline Lints --- .../gmod_wire_egp/lib/objects/roundedbox.lua | 47 ++++++++++--------- .../lib/objects/roundedboxoutline.lua | 21 +-------- .../gmod_wire_expression2/core/egpobjects.lua | 2 - 3 files changed, 28 insertions(+), 42 deletions(-) diff --git a/lua/entities/gmod_wire_egp/lib/objects/roundedbox.lua b/lua/entities/gmod_wire_egp/lib/objects/roundedbox.lua index e16fb93a18..9f666b88d7 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/roundedbox.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/roundedbox.lua @@ -4,31 +4,36 @@ Obj.radius = 16 Obj.fidelity = 36 local base = Obj.BaseClass +local max, min, sin, cos, rad = math.max, math.min, math.sin, math.cos, math.rad -Obj.Draw = function( self ) - if EGP:CacheNeedsUpdate(self, {"x", "y", "w", "h", "angle", "fidelity", "radius"}) then - local xs,ys , sx,sy = self.x,self.y , self.w, self.h - local polys = {} - local source = { {x=-1,y=-1} , {x=1,y=-1} , {x=1,y=1} , {x=-1,y=1} } - local radius = math.max(0,math.min((math.min(sx,sy)/2), self.radius )) - local div,angle = 360/self.fidelity, -self.angle - for x=1,4 do - for i=0,(self.fidelity+1)/4 do - local srx,sry = source[x].x,source[x].y - local scx,scy = srx*(sx-(radius*2))/2 , sry*(sy-(radius*2))/2 - scx,scy = scx*math.cos(math.rad(angle)) - scy*math.sin(math.rad(angle)), - scx*math.sin(math.rad(angle)) + scy*math.cos(math.rad(angle)) - local a,r = math.rad(div*i+(x*90)), radius - local dir = {x=math.sin(-(a+math.rad(angle))),y=math.cos(-(a+math.rad(angle)))} - local dirUV = {x=math.sin(-a),y=math.cos(-a)} - local ru,rv = (radius/sx),(radius/sy) - local u,v = 0.5 + (dirUV.x*ru) + (srx/2)*(1-(ru*2)), - 0.5 + (dirUV.y*rv) + (sry/2)*(1-(rv*2)) - polys[#polys+1] = {x=xs+scx+(dir.x*r), y=ys+scy+(dir.y*r) , u=u,v=v} +function Obj:Calculate() + if EGP:CacheNeedsUpdate(self, {"x", "y", "w", "h", "angle", "fidelity", "radius"}) then + local xs,ys , sx,sy = self.x,self.y , self.w, self.h + local polys = {} + local source = { {x=-1,y=-1} , {x=1,y=-1} , {x=1,y=1} , {x=-1,y=1} } + local radius = max(0, min(min(sx, sy) / 2, self.radius)) + local div, angle = 360/self.fidelity, rad(-self.angle) + for x=1,4 do + for i = 0, (self.fidelity + 1) / 4 do + local srx,sry = source[x].x,source[x].y + local scx,scy = srx*(sx-(radius*2))/2 , sry*(sy-(radius*2))/2 + scx,scy = scx * cos(angle) - scy * sin(angle), + scx * sin(angle) + scy * cos(angle) + local a, r = rad(div*i+(x*90)), radius + local dir = {x = sin(-(a + angle)),y = cos(-(a + angle))} + local dirUV = {x = sin(-a),y = cos(-a)} + local ru,rv = (radius/sx), (radius/sy) + local u,v = 0.5 + (dirUV.x*ru) + (srx/2)*(1-(ru*2)), + 0.5 + (dirUV.y*rv) + (sry/2)*(1-(rv*2)) + polys[#polys+1] = {x=xs+scx+(dir.x*r), y=ys+scy+(dir.y*r) , u=u,v=v} end end self.vert_cache.verts = polys end +end + +Obj.Draw = function( self ) + self:Calculate() surface.SetDrawColor(self.r,self.g,self.b,self.a) surface.DrawPoly(self.vert_cache.verts) @@ -57,7 +62,7 @@ function Obj:Contains(x, y) local w, h = self.w / 2, self.h / 2 if self.EGP.TopLeft then x, y = x - w, y - h end - local r = math.min(math.min(w, h), self.radius) + local r = min(min(w, h), self.radius) x, y = math.abs(x), math.abs(y) if x > w or y > h then return false end x, y = x - w + r, y - h + r diff --git a/lua/entities/gmod_wire_egp/lib/objects/roundedboxoutline.lua b/lua/entities/gmod_wire_egp/lib/objects/roundedboxoutline.lua index aafa6e3a2b..e73eda9bba 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/roundedboxoutline.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/roundedboxoutline.lua @@ -6,25 +6,8 @@ Obj.filtering = nil local base = Obj.BaseClass Obj.Draw = function( self ) - if EGP:CacheNeedsUpdate(self, {"x", "y", "w", "h", "angle", "fidelity", "radius"}) then - local xs,ys , sx,sy = self.x,self.y , self.w, self.h - local polys = {} - local source = { {x=-1,y=-1} , {x=1,y=-1} , {x=1,y=1} , {x=-1,y=1} } - local radius = math.max(0,math.min((math.min(sx,sy)/2), self.radius )) - local div,angle = 360/self.fidelity, -self.angle - for x=1,4 do - for i=0,(self.fidelity+1)/4 do - local srx,sry = source[x].x,source[x].y - local scx,scy = srx*(sx-(radius*2))/2 , sry*(sy-(radius*2))/2 - scx,scy = scx*math.cos(math.rad(angle)) - scy*math.sin(math.rad(angle)), - scx*math.sin(math.rad(angle)) + scy*math.cos(math.rad(angle)) - local a,r = math.rad(div*i+(x*90)), radius - local dir = {x=math.sin(-(a+math.rad(angle))),y=math.cos(-(a+math.rad(angle)))} - polys[#polys+1] = {x=xs+scx+(dir.x*r), y=ys+scy+(dir.y*r)} - end - end - self.vert_cache.verts = polys - end + self:Calculate() + surface.SetDrawColor(self.r,self.g,self.b,self.a) EGP:DrawPath(self.vert_cache.verts, self.size, true) end diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index 1ac1e2f2b4..38052cf13c 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -7,8 +7,6 @@ local NULL_EGPOBJECT = EGP.NULL_EGPOBJECT local M_NULL_EGPOBJECT = getmetatable(NULL_EGPOBJECT) local M_EGPObject = getmetatable(EGP.Objects.Base) -local maxobjects = EGP.ConVars.MaxObjects - -- Table of allowed arguments and their types local EGP_ALLOWED_ARGS = { From fd3900b558e7fa457abfc362e3272fedfa2f4de3 Mon Sep 17 00:00:00 2001 From: Denneisk <20892685+Denneisk@users.noreply.github.com> Date: Fri, 27 Oct 2023 01:25:58 -0400 Subject: [PATCH 27/28] Fix problems with polys Massively simplify global pos getting Split getting global vertices into different function Fixed bad egpo indexget Harden EGPObjects against bad inputs Change some small syntax things --- .../lib/egplib/objectcontrol.lua | 9 +- .../gmod_wire_egp/lib/egplib/parenting.lua | 131 +++++++----------- .../gmod_wire_egp/lib/egplib/queuesystem.lua | 4 +- .../lib/egplib/transmitreceive.lua | 8 +- .../lib/egplib/usefulfunctions.lua | 19 ++- .../gmod_wire_egp/lib/objects/poly.lua | 51 ++++--- lua/entities/gmod_wire_egp_emitter.lua | 6 +- lua/entities/gmod_wire_egp_hud/huddraw.lua | 4 +- .../core/egpfunctions.lua | 7 +- .../gmod_wire_expression2/core/egpobjects.lua | 13 +- 10 files changed, 126 insertions(+), 126 deletions(-) diff --git a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua index 0869ca2f47..886d68cd79 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua @@ -50,6 +50,10 @@ function baseObj:Contains(x, y) end function baseObj:EditObject(args) local ret = false + if args.x or args.y or args.angle then + self:SetPos(args.x or self.x, args.y or self.y, args.angle or self.angle) + args.x, args.y, args.angle = nil, nil, nil + end for k, v in pairs(args) do if self[k] ~= nil and self[k] ~= v then self[k] = v @@ -63,7 +67,10 @@ function baseObj:SetPos(x, y, angle) local ret = false if self.x ~= x then self.x, ret = x, true end if self.y ~= y then self.y, ret = y, true end - if angle and self.angle ~= angle then self.angle, ret = angle, true end + if angle then + angle = angle % 360 + if self.angle ~= angle then self.angle, ret = angle, true end + end return ret end function baseObj:Set(member, value) diff --git a/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua b/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua index 5afc88403f..1f6a623a53 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/parenting.lua @@ -18,7 +18,7 @@ EGP.ParentingFuncs.addUV = addUV local function makeArray( v, fakepos ) local ret = {} if isstring(v.verticesindex) then - if fakepos then + if not fakepos then if (not v["_"..v.verticesindex]) then EGP:AddParentIndexes( v ) end for k,v in ipairs( v["_"..v.verticesindex] ) do ret[#ret+1] = v.x @@ -90,7 +90,8 @@ end EGP.getCenterFrom = getCenterFrom -- (returns true if obj has vertices, false if not, followed by the new position data) -function EGP:GetGlobalPos( Ent, index ) +local function GetGlobalPos(self, Ent, index) + if self ~= EGP then Ent, index = self, Ent end local bool, obj if istable(index) then obj = index @@ -99,84 +100,58 @@ function EGP:GetGlobalPos( Ent, index ) bool, _, obj = self:HasObject(Ent, index) end if bool then - if obj.verticesindex then -- Object has vertices - if obj.parent and obj.parent ~= 0 then -- Object is parented - local data, ret - if obj.parent == -1 then -- object is parented to the cursor - local xy = { 0, 0 } - if CLIENT then - xy = self:EGPCursor(Ent, LocalPlayer()) - end - local x, y = xy[1], xy[2] - local r = makeArray(obj) - for i = 1, #r, 2 do - local x_ = r[i] - local y_ = r[i + 1] - local vec = LocalToWorld(Vector(x_, y_, 0), Angle(0, obj._angle or 0, 0), Vector(x, y, 0), angle_zero) - r[i] = vec.x - r[i + 1] = vec.y - end - - if isstring(obj.verticesindex) then - local temp = makeTable( obj, r ) - addUV( obj, temp ) - ret = { [obj.verticesindex] = temp } - else ret = makeTable(obj, r) end - local vec, ang = LocalToWorld(Vector(obj._x, obj._y, 0), Angle(0, obj._angle or 0, 0), Vector(x, y, 0), Angle(0, -data.angle or 0, 0)) - ret.x, ret.y, ret.angle = vec.x, vec.y, -ang.y - return true, ret - else - local _, _, prnt = self:HasObject(Ent, obj.parent) - local _, data = self:GetGlobalPos(Ent, prnt) - local x, y, ang = data.x, data.y, data.angle or 0 - local objang = obj._angle or 0 - local temp = makeArray( obj ) - for i = 1, #temp, 2 do - local x_ = temp[i] - local y_ = temp[i + 1] - local vec = LocalToWorld(Vector(x_, y_, 0), Angle(0, objang, 0), Vector(x, y, 0), Angle(0, -ang, 0)) - temp[i] = vec.x - temp[i + 1] = vec.y - end - - if isstring(obj.verticesindex) then ret = { [obj.verticesindex] = makeTable(obj, temp) } else ret = makeTable(obj, temp) end - local vec, ang = LocalToWorld(Vector(obj._x, obj._y, 0), Angle(0, objang, 0), Vector(x, y, 0), Angle(0, -ang, 0)) - ret.x, ret.y, ret.angle = vec.x, vec.y, -ang.y - return true, ret + if obj.parent and obj.parent ~= 0 then -- Object is parented + if obj.parent == -1 then -- Object is parented to the cursor + local x, y = 0, 0 + if CLIENT then + xy = EGP:EGPCursor( Ent, LocalPlayer() ) + x, y = xy[1], xy[2] end - if isstring(obj.verticesindex) then ret = { [obj.verticesindex] = makeTable(obj, makeArray(obj)) } else ret = makeTable(obj, makeArray(obj)) end - local vec, ang = LocalToWorld(Vector(obj._x, obj._y, 0), Angle(0, obj._angle or 0, 0), Vector(data.x, data.y, 0), Angle(0, -data.angle, 0)) - ret.x, ret.y, ret.angle = vec.x, vec.y, -ang.y - return true, ret - end - local ret = {} - if isstring(obj.verticesindex) then ret = { [obj.verticesindex] = makeTable(obj, makeArray(obj, true)) } else ret = makeTable(obj, makeArray(obj, true)) end - ret.x, ret.y, ret.angle = obj.x, obj.y, obj.angle - return true, ret - else -- Object does not have vertices - if obj.parent and obj.parent ~= 0 then -- Object is parented - if obj.parent == -1 then -- Object is parented to the cursor - local xy = { 0, 0 } - if (CLIENT) then - xy = self:EGPCursor( Ent, LocalPlayer() ) - end - local x, y = xy[1], xy[2] - local vec, ang = LocalToWorld( Vector( obj._x, obj._y, 0 ), Angle( 0, obj._angle or 0, 0 ), Vector( x, y, 0 ), angle_zero ) - return false, { x = vec.x, y = vec.y, angle = -ang.y } - else - local _, _, prnt = self:HasObject(Ent, obj.parent) - local _, data = self:GetGlobalPos(Ent, prnt) - local vec, ang = LocalToWorld( Vector( obj._x, obj._y, 0 ), Angle( 0, obj._angle or 0, 0 ), Vector( data.x, data.y, 0 ), Angle( 0, -(data.angle or 0), 0 ) ) - return false, { x = vec.x, y = vec.y, angle = -ang.y } - end + local vec, ang = LocalToWorld(Vector(obj._x, obj._y, 0), Angle(0, obj._angle or 0, 0), Vector(x, y, 0), angle_zero) + return obj.verticesindex ~= nil, { x = vec.x, y = vec.y, angle = -ang.y } + else + local _, data = GetGlobalPos(Ent, select(3, EGP:HasObject(Ent, obj.parent))) + local vec, ang = LocalToWorld(Vector(obj._x, obj._y, 0), Angle(0, -obj._angle or 0, 0), Vector(data.x, data.y, 0), Angle(0, -data.angle or 0, 0)) + return obj.verticesindex ~= nil, { x = vec.x, y = vec.y, angle = -ang.y } end - return false, { x = obj.x, y = obj.y, angle = obj.angle or 0 } end + return obj.verticesindex ~= nil, { x = obj.x, y = obj.y, angle = obj.angle or 0 } end - return false, {x=0,y=0,angle=0} + return false, { x = 0, y = 0, angle = 0 } +end +EGP.GetGlobalPos = GetGlobalPos + + +local function getGlobalVertices(ent, obj) + if obj.verticesindex then + local _, globalpos = GetGlobalPos(ent, obj) + local gx, gy, gang = globalpos.x, globalpos.y, globalpos.angle + + local r = makeArray(obj, obj.parent ~= NULL_EGPOBJECT) + local globalvec, globalang = Vector(gx, gy, 0), Angle(0, -gang, 0) + local objang = obj._angle or obj.angle or 0 + for i = 1, #r, 2 do + local x_ = r[i] + local y_ = r[i + 1] + local vec = LocalToWorld(Vector(x_, y_, 0), Angle(0, objang, 0), globalvec, globalang) + r[i] = vec.x + r[i + 1] = vec.y + end + + local ret + if isstring(obj.verticesindex) then + local temp = makeTable(obj, r) + addUV(obj, temp) + ret = { [obj.verticesindex] = temp } + else + ret = makeTable(obj, r) + end + return ret + end end +EGP.GetGlobalVertices = getGlobalVertices -------------------------------------------------------- -- Parenting functions @@ -245,7 +220,7 @@ function EGP:SetParent( Ent, index, parentindex ) bool, parentindex = parentindex ~= nil, parentindex.index end if (bool) then - self:AddParentIndexes( v ) + EGP:AddParentIndexes( v ) if (SERVER) then parentindex = math.Clamp(parentindex,1,self.ConVars.MaxObjects:GetInt()) end @@ -256,7 +231,7 @@ function EGP:SetParent( Ent, index, parentindex ) -- If the user is trying to create a circle of parents, causing an infinite loop if (not CheckParents( Ent, v, parentindex, {} )) then return false end - if (self:EditObject( v, { parent = parentindex } )) then return true, v end + if v:Set("parent", parentindex) then return true, v end end end end @@ -290,13 +265,13 @@ function EGP:UnParent( Ent, index ) index = v.index end if (bool) then - local hasVertices, data = self:GetGlobalPos( Ent, index ) - self:RemoveParentIndexes( v, hasVertices ) + local hasVertices, data = EGP:GetGlobalPos( Ent, index ) + EGP:RemoveParentIndexes( v, hasVertices ) if (not v.parent or v.parent == 0) then return false end data.parent = 0 - if (self:EditObject( v, data, Ent:GetPlayer() )) then return true, v end + if v:EditObject(data) then return true, v end end end diff --git a/lua/entities/gmod_wire_egp/lib/egplib/queuesystem.lua b/lua/entities/gmod_wire_egp/lib/egplib/queuesystem.lua index bf82455fa9..215e2f1f4d 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/queuesystem.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/queuesystem.lua @@ -22,13 +22,13 @@ function EGP:AddQueueObject( Ent, ply, Function, Object ) found = true if (v.OnRemove) then v:OnRemove() end local Obj = self:GetObjectByID( Object.ID ) - self:EditObject( Obj, Object:DataStreamInfo() ) + Obj:EditObject(Object:DataStreamInfo()) Obj.index = v.index if (Obj.OnCreate) then Obj:OnCreate() end LastItem.Args[1][k] = Obj else -- Edit found = true - self:EditObject( v, Object:DataStreamInfo() ) + v:EditObject(Object:DataStreamInfo()) end break diff --git a/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua b/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua index 4afa360ed3..2f29799a52 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua @@ -262,8 +262,12 @@ if (SERVER) then else net.WriteUInt(v.ID, 8) -- Else send the ID of the object + local original = v + if (Ent.Scaling or Ent.TopLeft) then v = table.Copy(v) -- Make a copy of the table so it doesn't overwrite the serverside object + -- Todo: Make transmit only used for server join/leave/"newframes"/etc, not every time it updates + if original.VerticesUpdate then original.VerticesUpdate = false end end -- Scale the positions and size @@ -273,7 +277,7 @@ if (SERVER) then -- Move the object to draw from the top left if (Ent.TopLeft) then - EGP:MoveTopLeft( Ent, v ) + EGP.MoveTopLeft( Ent, v ) end if v.ChangeOrder then -- We want to change the order of this object, send the index to where we wish to move it @@ -620,7 +624,7 @@ if (SERVER) then -- Move the object to draw from the top left if (v.TopLeft) then - EGP:MoveTopLeft( v, obj ) + EGP.MoveTopLeft( v, obj ) end DataToSend[#DataToSend+1] = { ID = obj.ID, index = obj.index, Settings = obj:DataStreamInfo() } diff --git a/lua/entities/gmod_wire_egp/lib/egplib/usefulfunctions.lua b/lua/entities/gmod_wire_egp/lib/egplib/usefulfunctions.lua index 52a3ea2a5c..7636c1b6bb 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/usefulfunctions.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/usefulfunctions.lua @@ -59,8 +59,7 @@ function EGP:ScaleObject( ent, v ) end local settings = makeTable(v, r) addUV(v, settings) - if isstring(v.verticesindex) then settings = { [v.verticesindex] = settings } end - self:EditObject( v, settings ) + if isstring(v.verticesindex) then v.vertices = settings else v:EditObject(settings) end else if (v.x) then v.x = (v.x - xMin) * xMul @@ -81,8 +80,8 @@ end -- Draw from top left -------------------------------------------------------- -function EGP:MoveTopLeft(ent, obj) - if not self:ValidEGP(ent) then return end +function EGP.MoveTopLeft(ent, obj) + if not EGP:ValidEGP(ent) then return end local t = nil if obj.CanTopLeft and obj.x and obj.y and obj.w and obj.h then @@ -91,14 +90,14 @@ function EGP:MoveTopLeft(ent, obj) if obj.angle then t.angle = -ang.yaw end end if obj.IsParented then - local bool, _, parent = self:HasObject(ent, obj.parent) + local bool, _, parent = EGP:HasObject(ent, obj.parent) if bool and parent.CanTopLeft and parent.w and parent.h then if not t then t = { x = obj.x, y = obj.y, angle = obj.angle } end t.x = t.x - parent.w / 2 t.y = t.y - parent.h / 2 + + if t.angle then t.angle = t.angle end end - if not t then t = { angle = obj.angle } end - if t.angle then t.angle = -t.angle end end if t then @@ -488,9 +487,9 @@ function EGP.Draw(ent) for _, obj in ipairs(rt) do if obj.parent == -1 or obj.NeedsConstantUpdate then ent.NeedsUpdate = true end if obj.parent ~= 0 then - if not obj.IsParented then EGP:SetParent(ent, obj.index, obj.parent) end - local _, data = EGP:GetGlobalPos(ent, obj.index) - EGP:EditObject(obj, data) + if not obj.IsParented then EGP:SetParent(ent, obj, obj.parent) end + local _, data = EGP.GetGlobalPos(ent, obj) + obj:SetPos(data.x, data.y, data.angle) elseif obj.IsParented then EGP:UnParent(ent, obj) end diff --git a/lua/entities/gmod_wire_egp/lib/objects/poly.lua b/lua/entities/gmod_wire_egp/lib/objects/poly.lua index fe6c4aa890..222dfd99a7 100644 --- a/lua/entities/gmod_wire_egp/lib/objects/poly.lua +++ b/lua/entities/gmod_wire_egp/lib/objects/poly.lua @@ -3,6 +3,7 @@ local Obj = EGP:NewObject("Poly") Obj.vertices = {} Obj.verticesindex = "vertices" Obj.HasUV = true +if SERVER then Obj.VerticesUpdate = true end local base = Obj.BaseClass @@ -21,32 +22,38 @@ Obj.Draw = function( self ) end end Obj.Transmit = function( self, Ent, ply ) - if (#self.vertices <= 255) then - net.WriteUInt( #self.vertices, 8 ) - for i=1,#self.vertices do - net.WriteInt( self.vertices[i].x, 16 ) - net.WriteInt( self.vertices[i].y, 16 ) - net.WriteFloat( self.vertices[i].u or 0 ) - net.WriteFloat( self.vertices[i].v or 0 ) + net.WriteBool(self.VerticesUpdate) + if self.VerticesUpdate then + if (#self.vertices <= 255) then + net.WriteUInt( #self.vertices, 8 ) + for i=1,#self.vertices do + net.WriteInt( self.vertices[i].x, 16 ) + net.WriteInt( self.vertices[i].y, 16 ) + net.WriteFloat( self.vertices[i].u or 0 ) + net.WriteFloat( self.vertices[i].v or 0 ) + end + self.VerticesUpdate = false + else + net.WriteUInt( 0, 8 ) + EGP:InsertQueue( Ent, ply, EGP._SetVertex, "SetVertex", self.index, self.vertices ) end - else - net.WriteUInt( 0, 8 ) - EGP:InsertQueue( Ent, ply, EGP._SetVertex, "SetVertex", self.index, self.vertices ) end base.Transmit(self) end Obj.Receive = function( self ) local tbl = {} - tbl.vertices = {} - for i = 1, net.ReadUInt(8) do - tbl.vertices[ i ] = { x = net.ReadInt(16), y = net.ReadInt(16), u = net.ReadFloat(), v = net.ReadFloat() } + if net.ReadBool() then + tbl.vertices = {} + for i = 1, net.ReadUInt(8) do + tbl.vertices[ i ] = { x = net.ReadInt(16), y = net.ReadInt(16), u = net.ReadFloat(), v = net.ReadFloat() } + end end table.Merge(tbl, base.Receive(self)) return tbl end Obj.DataStreamInfo = function( self ) - return { vertices = self.vertices, material = self.material, r = self.r, g = self.g, b = self.b, a = self.a, filtering = self.filtering, parent = self.parent, x = self.x, y = self.y, angle = self.angle } + return { material = self.material, r = self.r, g = self.g, b = self.b, a = self.a, filtering = self.filtering, parent = self.parent, x = self.x, y = self.y, angle = self.angle } end function Obj:Contains(x, y) @@ -77,8 +84,14 @@ function Obj:EditObject(args) local ret = false if args.vertices then self.vertices = args.vertices - self.x, self.y = EGP.getCenterFrom(self) + if self.IsParented then + self._x, self._y = EGP.getCenterFrom(self) + else + self.x, self.y = EGP.getCenterFrom(self) + end args.vertices = nil + self.angle = 0 + if SERVER then self.VerticesUpdate = true end ret = true end if args.x or args.y or args.angle then @@ -101,14 +114,17 @@ Obj.Initialize = Obj.EditObject function Obj:SetPos(x, y, angle) local sx, sy, sa = self.x, self.y, self.angle - if not angle then angle = sa end + if not x then x = sx end + if not y then y = sy end + if not angle then angle = sa else angle = angle % 360 end if sx == x and sy == y and sa == angle then return false end + for i, v in ipairs(self.vertices) do local vec = LocalToWorld(Vector(v.x - sx, v.y - sy, 0), angle_zero, Vector(x, y, 0), Angle(0, sa - angle, 0)) v.x = vec.x v.y = vec.y end - self.x, self.y, self.angle = x, y, angle % 360 + self.x, self.y, self.angle = x, y, angle if self._x then self._x, self._y, self._angle = x, y, angle end return true end @@ -118,6 +134,7 @@ function Obj:Set(key, value) self.vertices = value self.x, self.y = EGP.getCenterFrom(self) self.angle = 0 + if SERVER then self.VerticesUpdate = true end return true elseif key == "x" then ret = self:SetPos(value, self.y, self.angle) diff --git a/lua/entities/gmod_wire_egp_emitter.lua b/lua/entities/gmod_wire_egp_emitter.lua index a6e803f509..f0257a0196 100644 --- a/lua/entities/gmod_wire_egp_emitter.lua +++ b/lua/entities/gmod_wire_egp_emitter.lua @@ -93,9 +93,9 @@ if CLIENT then for _, obj in ipairs(rt) do if obj.parent == -1 or obj.NeedsConstantUpdate then self.NeedsUpdate = true end if obj.parent ~= 0 then - if not obj.IsParented then EGP:SetParent(self, obj.index, obj.parent) end - local _, data = EGP:GetGlobalPos(self, obj.index) - EGP:EditObject(obj, data) + if not obj.IsParented then EGP:SetParent(self, obj, obj.parent) end + local _, data = EGP.GetGlobalPos(self, obj) + obj:SetPos(data.x, data.y, data.angle) elseif obj.IsParented then EGP:UnParent(self, obj) end diff --git a/lua/entities/gmod_wire_egp_hud/huddraw.lua b/lua/entities/gmod_wire_egp_hud/huddraw.lua index 00abae75db..7c30c7b2b5 100644 --- a/lua/entities/gmod_wire_egp_hud/huddraw.lua +++ b/lua/entities/gmod_wire_egp_hud/huddraw.lua @@ -39,8 +39,8 @@ if CLIENT then r[i+1] = (r[i+1]- yMin) * yMul end local settings = {} - if isstring(v.verticesindex) then settings = { [v.verticesindex] = makeTable( v, r ) } else settings = makeTable( v, r ) end - EGP:EditObject(v, settings) + if isstring(v.verticesindex) then settings = { [v.verticesindex] = makeTable( v, r ) } else v.vertices = makeTable(v, r) end + v:EditObject(settings) else if v.x then v.x = (v.x - xMin) * xMul diff --git a/lua/entities/gmod_wire_expression2/core/egpfunctions.lua b/lua/entities/gmod_wire_expression2/core/egpfunctions.lua index d927afcada..b01bf3272e 100644 --- a/lua/entities/gmod_wire_expression2/core/egpfunctions.lua +++ b/lua/entities/gmod_wire_expression2/core/egpfunctions.lua @@ -842,9 +842,10 @@ e2function vector wirelink:egpGlobalPos( number index ) end e2function array wirelink:egpGlobalVertices( number index ) - local hasvertices, data = EGP:GetGlobalPos( this, index ) - if (hasvertices) then - if (data.vertices) then + local hasobject, _, object = EGP:HasObject(this, index) + if hasobject and object.verticesindex then + local data = EGP:GetGlobalVertices(object) + if data.vertices then local ret = {} for i=1,#data.vertices do local v = data.vertices[i] diff --git a/lua/entities/gmod_wire_expression2/core/egpobjects.lua b/lua/entities/gmod_wire_expression2/core/egpobjects.lua index 38052cf13c..58560a4b78 100644 --- a/lua/entities/gmod_wire_expression2/core/egpobjects.lua +++ b/lua/entities/gmod_wire_expression2/core/egpobjects.lua @@ -87,7 +87,7 @@ e2function egpobject egpobject:modify(table arguments) if EGP_ALLOWED_ARGS[k] == arguments.stypes[k] or false then converted[k] = v end end - if this:EditObject(converted) then EGP:DoAction(egp, self, "SendObject", this) Update(self, egp) end + if this:EditObject(converted) then EGP:DoAction(egp, self, "Update", this) Update(self, egp) end return this end @@ -583,8 +583,8 @@ end [nodiscard] e2function array egpobject:globalVertices() if not isValid(this) then return self:throw("Invalid EGP Object", {}) end - local hasvertices, data = EGP:GetGlobalPos(this.EGP, this) - if hasvertices then + if this.verticesindex then + local data = EGP:GetGlobalVertices(this.EGP, this) if data.vertices then local ret = {} for i = 1, #data.vertices do @@ -598,9 +598,8 @@ e2function array egpobject:globalVertices() elseif data.x and data.y and data.x2 and data.y2 then return { {data.x, data.y}, {data.x2, data.y2} } end - else - return {} end + return {} end [nodiscard] @@ -779,9 +778,7 @@ registerCallback("postinit", function() __e2setcost(5) -- Getter - registerOperator("indexget", "xeos" .. id, id, function(self, args) - local op1, op2 = args[2], args[3] - local this, index = op1[1](self, op1), op2[1](self, op2) + registerOperator("indexget", "xeos" .. id, id, function(self, this, index) local indexType = EGP_ALLOWED_ARGS[index] if not indexType then return fixDefault(default) end From 40e67a87aa824c7dfb054985fe9f537715f3a210 Mon Sep 17 00:00:00 2001 From: Denneisk <20892685+Denneisk@users.noreply.github.com> Date: Fri, 27 Oct 2023 01:47:09 -0400 Subject: [PATCH 28/28] Fix oversight + minor change of local scope --- lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua | 6 +++--- lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua | 3 +-- lua/entities/gmod_wire_expression2/core/egpfunctions.lua | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua index 886d68cd79..8778b38f07 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/objectcontrol.lua @@ -51,7 +51,7 @@ end function baseObj:EditObject(args) local ret = false if args.x or args.y or args.angle then - self:SetPos(args.x or self.x, args.y or self.y, args.angle or self.angle) + ret = self:SetPos(args.x or self.x, args.y or self.y, args.angle or self.angle) args.x, args.y, args.angle = nil, nil, nil end for k, v in pairs(args) do @@ -65,8 +65,8 @@ end baseObj.Initialize = baseObj.EditObject function baseObj:SetPos(x, y, angle) local ret = false - if self.x ~= x then self.x, ret = x, true end - if self.y ~= y then self.y, ret = y, true end + if x and self.x ~= x then self.x, ret = x, true end + if y and self.y ~= y then self.y, ret = y, true end if angle then angle = angle % 360 if self.angle ~= angle then self.angle, ret = angle, true end diff --git a/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua b/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua index 2f29799a52..05812e7579 100644 --- a/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua +++ b/lua/entities/gmod_wire_egp/lib/egplib/transmitreceive.lua @@ -262,9 +262,8 @@ if (SERVER) then else net.WriteUInt(v.ID, 8) -- Else send the ID of the object - local original = v - if (Ent.Scaling or Ent.TopLeft) then + local original = v v = table.Copy(v) -- Make a copy of the table so it doesn't overwrite the serverside object -- Todo: Make transmit only used for server join/leave/"newframes"/etc, not every time it updates if original.VerticesUpdate then original.VerticesUpdate = false end diff --git a/lua/entities/gmod_wire_expression2/core/egpfunctions.lua b/lua/entities/gmod_wire_expression2/core/egpfunctions.lua index b01bf3272e..fb20d11951 100644 --- a/lua/entities/gmod_wire_expression2/core/egpfunctions.lua +++ b/lua/entities/gmod_wire_expression2/core/egpfunctions.lua @@ -638,7 +638,7 @@ e2function void wirelink:egpAngle( number index, number angle ) if (!EGP:IsAllowed( self, this )) then return end local bool, k, v = EGP:HasObject( this, index ) if (bool) then - if v:EditObject( { angle = angle, _angle = angle }) then EGP:DoAction( this, self, "SendObject", v ) Update(self,this) end + if v:SetPos(nil, nil, angle) then EGP:DoAction( this, self, "SendObject", v ) Update(self,this) end end end