Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add flexes and eye posing to E2 #2810

Merged
merged 5 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions lua/entities/gmod_wire_expression2/core/bone.lua
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ end
--- Returns an array containing all of <this>'s bones. This array's first element has the index 0!
e2function array entity:bones()
if not IsValid(this) then return { } end
return GetBones(this)
return table.Copy(GetBones(this))
thegrb93 marked this conversation as resolved.
Show resolved Hide resolved
Vurv78 marked this conversation as resolved.
Show resolved Hide resolved
end

--- Returns <this>'s number of bones.
Expand Down Expand Up @@ -291,6 +291,20 @@ e2function vector bone:inertia()
return this:GetInertia()
end

__e2setcost(5)

e2function number bone:getJiggle()
local ent, index = isValidBone(this)
if not ent then return self:throw("Invalid bone!", 0) end
return ent:GetManipulateBoneJiggle(index) or 0
end

e2function vector bone:getScale()
local ent, index = isValidBone(this)
if not ent then return self:throw("Invalid bone!", Vector(0, 0, 0)) end
return ent:GetManipulateBoneScale(index)
end

--[[************************************************************************]]--
__e2setcost(30)

Expand Down Expand Up @@ -418,7 +432,3 @@ e2function string toString(bone b)
end

WireLib.registerDebuggerFormat("BONE", e2_tostring_bone)

--[[************************************************************************]]--

-- TODO: constraints
5 changes: 5 additions & 0 deletions lua/entities/gmod_wire_expression2/core/custom/cl_prop.lua
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,8 @@ E2Helper.Descriptions["setPos(b:v)"] = "Sets the position of a bone."
E2Helper.Descriptions["setAng(b:a)"] = "Set the rotation of a bone."
E2Helper.Descriptions["ragdollSetPos(e:v)"] = "Sets the position of a ragdoll while preserving pose."
E2Helper.Descriptions["ragdollSetAng(e:a)"] = "Set the rotation of a ragdoll while preserving pose."
E2Helper.Descriptions["setEyeTarget"] = "For NPCs, sets the eye target to the world position. For ragdolls, sets the eye target to the local eye position"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you verified these work in the E2Helper? I know there's some hacky workaround allowing this, but I thought it was only when the function had no parameters.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they work. I didn't know it was a hack. Admittedly I just find it easier (less typing) so I prefer using it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how ignoring the signature and only providing the name of a function wouldn't be a hack

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it's a good hack in my book because it lets me type less.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's it supposed to be? setEyeTarget(e:)? Is it okay without the args?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently so, I haven't checked myself. I thought that only worked for no parameter functions. Either way that behavior shouldn't be relied on, the signature should be setEyeTarget(e:v).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just a way for setting the description of multiple functions of the same name. It's not like someone's going to rewrite how E2Descriptions are handled anytime soon.

Copy link
Contributor

@Vurv78 Vurv78 Nov 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has nothing to do with rewriting the e2helper, that behavior just shouldn't be relied on since it may conflict with any other addon adding a function with that name. I guess it'd be somewhat fine here since the name isn't too generic but I wouldn't want to set a precedent of relying on this.

Also you don't even need it for the usecase you gave, most of these functions don't have overloads.

E2Helper.Descriptions["setEyeTargetLocal"] = "Sets the eye target to the local eye position"
E2Helper.Descriptions["setEyeTargetWorld"] = "Sets the eye target to the world position"
E2Helper.Descriptions["setFlexScale"] = "Sets the flex scale of the entity"
E2Helper.Descriptions["setFlexWeight"] = "Sets the flex weight of the flex"
76 changes: 76 additions & 0 deletions lua/entities/gmod_wire_expression2/core/custom/prop.lua
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,7 @@ e2function void entity:propStatic( number static )
end
end

-- Bones --
--------------------------------------------------------------------------------

e2function void bone:boneManipulate(vector pos, angle rot, isFrozen, gravity, collision)
Expand Down Expand Up @@ -577,6 +578,25 @@ e2function void bone:setAngVelocityInstant(vector velocity)
ent:PhysWake()
end

--[[
__e2setcost(5000)
-- Apparently these functions are expensive

e2function void bone:setJiggle(weight)
local ent, index = boneVerify(self, this)
if not ValidAction(self, ent, "heavybone") then return end
weight = math.Clamp(weight, 0, 255)
ent:ManipulateBoneJiggle(index, weight)
end

e2function void bone:setScale(vector scale)
local ent, index = boneVerify(self, this)
if ent:GetPhysicsObjectCount() <= 1 then return self:throw("Entity is not a ragdoll!") end
if not ValidAction(self, ent, "heavybone") then return end
ent:ManipulateBoneScale(index, scale)
end
]]

__e2setcost(5000)

-- This code was leveraged from Garry's Mod. Perhaps it would be a bit cleaner with a slight rewrite.
Expand Down Expand Up @@ -828,6 +848,62 @@ e2function number propCanCreate()
return 0
end

-- Flexes --
--------------------------------------------------------------------------------

-- Setters

__e2setcost(10)

e2function void entity:setEyeTarget(vector pos)
if not ValidAction(self, this, "eyetarget") then return end
this:SetEyeTarget(pos)
end

e2function void entity:setFlexWeight(number flex, number weight)
if not ValidAction(self, this, "flexweight" .. flex) then return end
this:SetFlexWeight(flex, weight)
end

__e2setcost(30)

e2function void entity:setEyeTargetLocal(vector pos)
if not ValidAction(self, this, "eyetarget") then return end
if not this:IsRagdoll() then
local attachment = this:GetAttachment(this:LookupAttachment("eyes"))
if attachment then
pos = LocalToWorld(pos, angle_zero, attachment.Pos, attachment.Ang)
end
end
this:SetEyeTarget(pos)
end

e2function void entity:setEyeTargetWorld(vector pos)
if not ValidAction(self, this, "eyetarget") then return end
if this:IsRagdoll() then
local attachment = this:GetAttachment(this:LookupAttachment("eyes"))
if attachment then
pos = WorldToLocal(pos, angle_zero, attachment.Pos, attachment.Ang)
end
end
this:SetEyeTarget(pos)
end

__e2setcost(20)

e2function void entity:setFlexWeight(string flex, number weight)
flex = this:GetFlexIDByName(flex)
if flex then
if not ValidAction(self, this, "flexweight" .. flex) then return end
this:SetFlexWeight(flex, weight)
end
end

e2function void entity:setFlexScale(number scale)
if not ValidAction(self, this, "flexscale") then return end
this:SetFlexScale(scale)
end

registerCallback("construct",
function(self)
self.data.propSpawnEffect = true
Expand Down
69 changes: 69 additions & 0 deletions lua/entities/gmod_wire_expression2/core/entity.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,75 @@ e2function void entity:noCollideAll(number state)
this:SetCollisionGroup(state == 0 and COLLISION_GROUP_NONE or COLLISION_GROUP_WORLD)
end

--[[******************************************************************************]]
-- Flexes

__e2setcost(5)

e2function array entity:getFlexBounds(number flex)
if not IsValid(this) then return self:throw("Invalid entity!", {}) end
return { this:GetFlexBounds(flex) }
end

e2function number entity:getFlexCount()
if not IsValid(this) then return self:throw("Invalid entity!", 0) end
return this:GetFlexNum()
end

e2function number entity:getFlexID(string flex)
if not IsValid(this) then return self:throw("Invalid entity!", 0) end
return this:GetFlexIDByName(flex) or -1
end

e2function number entity:getFlexScale()
if not IsValid(this) then return self:throw("Invalid entity!", 0) end
return this:GetFlexScale()
end

e2function string entity:getFlexName(number id)
if not IsValid(this) then return self:throw("Invalid entity!", "") end
return this:GetFlexName(id) or ""
end

e2function number entity:getFlexWeight(number flex)
if not IsValid(this) then return self:throw("Invalid entity!", 0) end
return this:GetFlexWeight(flex)
end

e2function number entity:hasFlexes()
if not IsValid(this) then return self:throw("Invalid entity!", 0) end
return this:HasFlexManipulator() and 1 or 0
end

__e2setcost(15)

e2function array entity:getFlexBounds(string flex)
if not IsValid(this) then return self:throw("Invalid entity!", {}) end
flex = this:GetFlexIDByName(flex)
return flex and { this:GetFlexBounds(flex) } or {}
end

e2function number entity:getFlexWeight(string flex)
if not IsValid(this) then return self:throw("Invalid entity!", 0) end
flex = this:GetFlexIDByName(flex)
return flex and this:GetFlexWeight(flex) or 0
end

__e2setcost(50)

e2function array entity:getFlexes()
if not IsValid(this) then return self:throw("Invalid entity!", 0) end
local ret = {}
for i = 0, this:GetFlexNum() - 1 do
ret[i] = this:GetFlexName(i)
end
self.prf = self.prf + (#ret + 1) * 5
return ret
end

--[[******************************************************************************]]
-- End e2functions

hook.Add("OnEntityCreated", "E2_entityCreated", function(ent)
if not IsValid(ent) then return end -- Engine is precaching a model or bad addon

Expand Down
12 changes: 12 additions & 0 deletions lua/wire/client/e2descriptions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,16 @@ E2Helper.Descriptions["attachmentPos(e:s)"] = "Same as E:attachmentPos(E:lookupA
E2Helper.Descriptions["attachmentAng(e:s)"] = "Same as E:attachmentAng(E:lookupAttachment(attachmentName))"
E2Helper.Descriptions["attachments(e:)"] = "Returns array of attachment names of the entity"

-- Flexes
E2Helper.Descriptions["getFlexBounds"] = "Gets the upper and lower bounds of the flex if it exists"
E2Helper.Descriptions["getFlexCount"] = "Gets the number of flexes on the entity"
E2Helper.Descriptions["getFlexID"] = "Gets the flex ID of the given name or -1 if it doesn't exist"
E2Helper.Descriptions["getFlexName"] = "Gets the name of the flex"
E2Helper.Descriptions["getFlexScale"] = "Gets the flex scale of the entity"
E2Helper.Descriptions["getFlexWeight"] = "Gets the weight of the flex"
E2Helper.Descriptions["getFlexes"] = "Gets a 0-indexed array of all flexes and their names"
E2Helper.Descriptions["hasFlexes"] = "Returns 1 if the entity has flexes"

-- Vector
E2Helper.Descriptions["vec2(n)"] = "Makes a 2D vector"
E2Helper.Descriptions["vec2(nn)"] = "Makes a 2D vector"
Expand Down Expand Up @@ -702,6 +712,8 @@ E2Helper.Descriptions["boneCount(e:)"] = "Returns Es number of bones"
E2Helper.Descriptions["nobone()"] = "Returns an invalid bone"
E2Helper.Descriptions["aimBone(e:)"] = "Returns the bone the player is currently aiming at"
E2Helper.Descriptions["entity(b:)"] = "Returns the entity B belongs to"
E2Helper.Descriptions["getJiggle(b:)"] = "Returns the jiggle amount of the bone"
E2Helper.Descriptions["getScale(b:)"] = "Returns the visual scale of the bone"
E2Helper.Descriptions["index(b:)"] = "Returns Bs index in the entity it belongs to. Returns -1 if the bone is invalid or an error occured"
E2Helper.Descriptions["pos(b:)"] = "Returns Bs position"
E2Helper.Descriptions["forward(b:)"] = "Returns a vector describing Bs forward direction"
Expand Down