mirror of
https://github.com/Winded/RagdollMover.git
synced 2025-03-04 03:13:36 -05:00
Basic use for Prop ragdoll tool now works as was intended, using secondary fire will make it select all constrained entities that player aimed at, which would allow to set a custom skeleton for prop ragdoll through drag and drop feature. Pressing reload on entities with Prop Ragdoll data will dissolve the prop ragdoll. Removing one of the entities that make up a prop ragdoll will dissolve it too. Constrained entities tab in ragdoll mover will now ignore props that are parented to something. IK Chains creator tool now supports saving prop ragdoll IKs
This commit is contained in:
parent
1263e56dea
commit
630d23955d
@ -115,7 +115,7 @@ local function rgmGetConstrainedEntities(parent)
|
||||
local count = 1
|
||||
|
||||
for _, ent in pairs(conents) do
|
||||
if not IsValid(ent) or ent:IsWorld() or ent:IsConstraint() or not util.IsValidModel(ent:GetModel()) then continue end
|
||||
if not IsValid(ent) or ent:IsWorld() or ent:IsConstraint() or not util.IsValidModel(ent:GetModel()) or IsValid(ent:GetParent()) then continue end
|
||||
if ent:GetPhysicsObjectCount() > 0 then
|
||||
children[count] = ent
|
||||
count = count + 1
|
||||
|
@ -121,6 +121,8 @@ net.Receive("rgmikRequestSave", function(len, pl)
|
||||
local ent = tool.SelectedSaveEnt
|
||||
if not ent or not ent.rgmIKChains then rgmSendNotif(6, pl) return end
|
||||
|
||||
local ispropragdoll = ent.rgmPRidtoent and true or false
|
||||
|
||||
local num = 0
|
||||
local iks = {}
|
||||
|
||||
@ -131,29 +133,51 @@ net.Receive("rgmikRequestSave", function(len, pl)
|
||||
|
||||
net.Start("rgmikSave")
|
||||
|
||||
net.WriteBool(ispropragdoll)
|
||||
|
||||
net.WriteEntity(ent)
|
||||
net.WriteUInt(num,4)
|
||||
|
||||
for i = 1, num do
|
||||
net.WriteUInt(iks[i].type, 4)
|
||||
net.WriteUInt(ent:TranslatePhysBoneToBone(iks[i].hip), 10)
|
||||
net.WriteUInt(ent:TranslatePhysBoneToBone(iks[i].knee), 10)
|
||||
net.WriteUInt(ent:TranslatePhysBoneToBone(iks[i].foot), 10)
|
||||
if not ispropragdoll then
|
||||
for i = 1, num do
|
||||
net.WriteUInt(iks[i].type, 4)
|
||||
net.WriteUInt(ent:TranslatePhysBoneToBone(iks[i].hip), 10)
|
||||
net.WriteUInt(ent:TranslatePhysBoneToBone(iks[i].knee), 10)
|
||||
net.WriteUInt(ent:TranslatePhysBoneToBone(iks[i].foot), 10)
|
||||
end
|
||||
else
|
||||
for i = 1, num do
|
||||
net.WriteUInt(iks[i].type, 4)
|
||||
net.WriteUInt(iks[i].hip, 13)
|
||||
net.WriteUInt(iks[i].knee, 13)
|
||||
net.WriteUInt(iks[i].foot, 13)
|
||||
end
|
||||
end
|
||||
|
||||
net.Send(pl)
|
||||
end)
|
||||
|
||||
net.Receive("rgmikLoad", function(len, pl)
|
||||
local ispropragdoll = net.ReadBool()
|
||||
local num = net.ReadUInt(4)
|
||||
local iktable = {}
|
||||
|
||||
for i = 1, num do
|
||||
iktable[i] = {}
|
||||
iktable[i].type = net.ReadUInt(4)
|
||||
iktable[i].hip = net.ReadUInt(10)
|
||||
iktable[i].knee = net.ReadUInt(10)
|
||||
iktable[i].foot = net.ReadUInt(10)
|
||||
if not ispropragdoll then
|
||||
for i = 1, num do
|
||||
iktable[i] = {}
|
||||
iktable[i].type = net.ReadUInt(4)
|
||||
iktable[i].hip = net.ReadUInt(10)
|
||||
iktable[i].knee = net.ReadUInt(10)
|
||||
iktable[i].foot = net.ReadUInt(10)
|
||||
end
|
||||
else
|
||||
for i = 1, num do
|
||||
iktable[i] = {}
|
||||
iktable[i].type = net.ReadUInt(4)
|
||||
iktable[i].hip = net.ReadUInt(13)
|
||||
iktable[i].knee = net.ReadUInt(13)
|
||||
iktable[i].foot = net.ReadUInt(13)
|
||||
end
|
||||
end
|
||||
|
||||
local tool = pl:GetTool("ragmover_ikchains")
|
||||
@ -162,11 +186,23 @@ net.Receive("rgmikLoad", function(len, pl)
|
||||
local ent = tool.SelectedSaveEnt
|
||||
if not ent then return end
|
||||
|
||||
ent.rgmIKChains = {}
|
||||
if not ispropragdoll then
|
||||
ent.rgmIKChains = {}
|
||||
|
||||
for k, ik in ipairs(iktable) do
|
||||
if ik.hip == 1023 or ik.knee == 1023 or ik.foot == 1023 then continue end
|
||||
table.insert(ent.rgmIKChains, {hip = rgm.BoneToPhysBone(ent, ik.hip), knee = rgm.BoneToPhysBone(ent, ik.knee), foot = rgm.BoneToPhysBone(ent, ik.foot), type = ik.type})
|
||||
for k, ik in ipairs(iktable) do
|
||||
if ik.hip == 1023 or ik.knee == 1023 or ik.foot == 1023 then continue end
|
||||
table.insert(ent.rgmIKChains, {hip = rgm.BoneToPhysBone(ent, ik.hip), knee = rgm.BoneToPhysBone(ent, ik.knee), foot = rgm.BoneToPhysBone(ent, ik.foot), type = ik.type})
|
||||
end
|
||||
else
|
||||
if not ent.rgmPRidtoent or not ent:GetClass() == "prop_physics" then return end
|
||||
|
||||
for id, ent in pairs(ent.rgmPRidtoent) do
|
||||
ent.rgmIKChains = {}
|
||||
|
||||
for k, ik in ipairs(iktable) do
|
||||
table.insert(ent.rgmIKChains, {hip = ik.hip, knee = ik.knee, foot = ik.foot, type = ik.type})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
rgmSendNotif(7, pl)
|
||||
@ -269,7 +305,7 @@ end
|
||||
function TOOL:RightClick(tr)
|
||||
local ent = tr.Entity
|
||||
|
||||
if ent:GetClass() == "prop_ragdoll" then
|
||||
if ent:GetClass() == "prop_ragdoll" or (ent:GetClass() == "prop_physics" and ent.rgmPRidtoent) then
|
||||
if SERVER then
|
||||
if self.SelectedSaveEnt == ent then return false end
|
||||
rgmSendEnt(ent, self:GetOwner())
|
||||
@ -365,12 +401,22 @@ local function ChainSaver(cpanel)
|
||||
local iktable = util.JSONToTable(json)
|
||||
|
||||
net.Start("rgmikLoad")
|
||||
net.WriteBool(iktable.ispropragdoll)
|
||||
net.WriteUInt(#iktable, 4)
|
||||
for k, ik in ipairs(iktable) do
|
||||
net.WriteUInt(ik.type, 4)
|
||||
net.WriteUInt(SelectedEnt:LookupBone(ik.hip) or 1023, 10)
|
||||
net.WriteUInt(SelectedEnt:LookupBone(ik.knee) or 1023, 10)
|
||||
net.WriteUInt(SelectedEnt:LookupBone(ik.foot) or 1023, 10)
|
||||
if not iktable.ispropragdoll then
|
||||
for k, ik in ipairs(iktable) do
|
||||
net.WriteUInt(ik.type, 4)
|
||||
net.WriteUInt(SelectedEnt:LookupBone(ik.hip) or 1023, 10)
|
||||
net.WriteUInt(SelectedEnt:LookupBone(ik.knee) or 1023, 10)
|
||||
net.WriteUInt(SelectedEnt:LookupBone(ik.foot) or 1023, 10)
|
||||
end
|
||||
else
|
||||
for k, ik in ipairs(iktable) do
|
||||
net.WriteUInt(ik.type, 4)
|
||||
net.WriteUInt(ik.hip, 13)
|
||||
net.WriteUInt(ik.knee, 13)
|
||||
net.WriteUInt(ik.foot, 13)
|
||||
end
|
||||
end
|
||||
net.SendToServer()
|
||||
end
|
||||
@ -589,14 +635,27 @@ end)
|
||||
|
||||
net.Receive("rgmikSave", function(len)
|
||||
local iktable = {}
|
||||
local ispropragdoll = net.ReadBool()
|
||||
local ent = net.ReadEntity()
|
||||
local count = net.ReadUInt(4)
|
||||
|
||||
for i = 1, net.ReadUInt(4) do
|
||||
iktable[i] = {}
|
||||
iktable[i].type = net.ReadUInt(4)
|
||||
iktable[i].hip = ent:GetBoneName(net.ReadUInt(10))
|
||||
iktable[i].knee = ent:GetBoneName(net.ReadUInt(10))
|
||||
iktable[i].foot = ent:GetBoneName(net.ReadUInt(10))
|
||||
if not ispropragdoll then
|
||||
for i = 1, count do
|
||||
iktable[i] = {}
|
||||
iktable[i].type = net.ReadUInt(4)
|
||||
iktable[i].hip = ent:GetBoneName(net.ReadUInt(10))
|
||||
iktable[i].knee = ent:GetBoneName(net.ReadUInt(10))
|
||||
iktable[i].foot = ent:GetBoneName(net.ReadUInt(10))
|
||||
end
|
||||
else
|
||||
iktable.ispropragdoll = true
|
||||
for i = 1, count do
|
||||
iktable[i] = {}
|
||||
iktable[i].type = net.ReadUInt(4)
|
||||
iktable[i].hip = net.ReadUInt(13)
|
||||
iktable[i].knee = net.ReadUInt(13)
|
||||
iktable[i].foot = net.ReadUInt(13)
|
||||
end
|
||||
end
|
||||
|
||||
local json = util.TableToJSON(iktable, true)
|
||||
|
@ -3,7 +3,21 @@ TOOL.Category = "Poser"
|
||||
TOOL.Command = nil
|
||||
TOOL.ConfigName = ""
|
||||
|
||||
CVMaxPRBones = CreateConVar("sv_ragdollmover_max_prop_ragdoll_bones", 32, FCVAR_ARCHIVE + FCVAR_NOTIFY, "Maximum amount of bones that can be used in single Prop Ragdoll", 0, 4096)
|
||||
|
||||
local function ClearPropRagdoll(ent)
|
||||
ent.rgmPRidtoent = nil
|
||||
ent.rgmPRenttoid = nil
|
||||
ent.rgmPRparent = nil
|
||||
duplicator.ClearEntityModifier(ent, "Ragdoll Mover Prop Ragdoll")
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
|
||||
util.AddNetworkString("rgmprSendConEnts")
|
||||
util.AddNetworkString("rgmprApplySkeleton")
|
||||
|
||||
|
||||
duplicator.RegisterEntityModifier("Ragdoll Mover Prop Ragdoll", function(pl, ent, data)
|
||||
|
||||
ent.rgmPRenttoid = table.Copy(data.enttoid)
|
||||
@ -31,6 +45,7 @@ if SERVER then
|
||||
local newdata = {}
|
||||
newdata.enttoid = {}
|
||||
for e, id in pairs(ent.rgmPRenttoid) do
|
||||
if type(e) ~= "Entity" or not IsValid(e) then continue end
|
||||
newdata.enttoid[e:EntIndex()] = id
|
||||
end
|
||||
newdata.idtoent = table.Copy(ent.rgmPRidtoent)
|
||||
@ -39,94 +54,579 @@ if SERVER then
|
||||
duplicator.ClearEntityModifier(ent, "Ragdoll Mover Prop Ragdoll")
|
||||
duplicator.StoreEntityModifier(ent, "Ragdoll Mover Prop Ragdoll", newdata)
|
||||
|
||||
for id, e in pairs(ent.rgmPRidtoent) do
|
||||
for e, id in pairs(ent.rgmPRenttoid) do
|
||||
if type(e) ~= "Entity" or (type(e) == "Entity" and not IsValid(e)) then -- if some of those entities don't exist, then we gotta dissolve the "ragdoll"
|
||||
ent.rgmPRidtoent = nil
|
||||
ent.rgmPRenttoid = nil
|
||||
ent.rgmPRparent = nil
|
||||
duplicator.ClearEntityModifier(ent, "Ragdoll Mover Prop Ragdoll")
|
||||
ClearPropRagdoll(ent)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("EntityRemoved", "rgmPropRagdollEntRemoved", function(ent)
|
||||
if ent.rgmPRidtoent then
|
||||
for id, ent in pairs(ent.rgmPRidtoent) do
|
||||
if not IsValid(ent) then continue end
|
||||
ClearPropRagdoll(ent)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
net.Receive("rgmprApplySkeleton", function(len, pl)
|
||||
local count = net.ReadUInt(13)
|
||||
local ents = {}
|
||||
local fail = false
|
||||
|
||||
for i = 0, count - 1 do
|
||||
ents[i] = {}
|
||||
ents[i].ent = net.ReadEntity()
|
||||
ents[i].id = net.ReadUInt(13)
|
||||
local parent = net.ReadUInt(13)
|
||||
ents[i].parent = parent ~= 4100 and parent or nil
|
||||
if not IsValid(ents[i].ent) or not ents[i].ent:GetClass() == "prop_physics" then
|
||||
fail = true
|
||||
end
|
||||
end
|
||||
|
||||
if fail or count > CVMaxPRBones:GetInt() then return end
|
||||
|
||||
for id, data in pairs(ents) do
|
||||
local ent = data.ent
|
||||
|
||||
if ent.rgmPRidtoent then
|
||||
for id, ent in pairs(ent.rgmPRidtoent) do
|
||||
ClearPropRagdoll(ent)
|
||||
end
|
||||
end
|
||||
|
||||
ent.rgmPRidtoent = {}
|
||||
ent.rgmPRenttoid = {}
|
||||
ent.rgmPRparent = data.parent
|
||||
for id, moredata in pairs(ents) do
|
||||
ent.rgmPRidtoent[moredata.id] = moredata.ent
|
||||
ent.rgmPRenttoid[moredata.ent] = moredata.id
|
||||
end
|
||||
|
||||
local data = {}
|
||||
data.idtoent = table.Copy(ent.rgmPRidtoent)
|
||||
data.enttoid = {}
|
||||
for ent, id in pairs(ent.rgmPRenttoid) do
|
||||
data.enttoid[ent:EntIndex()] = id
|
||||
end
|
||||
data.parent = ent.rgmPRparent
|
||||
|
||||
duplicator.StoreEntityModifier(ent, "Ragdoll Mover Prop Ragdoll", data)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function TOOL:LeftClick(tr)
|
||||
local stage = self:GetStage()
|
||||
local ent = tr.Entity
|
||||
|
||||
if ent:GetClass() ~= "prop_physics" then return false end
|
||||
return false
|
||||
end
|
||||
|
||||
if stage == 0 then
|
||||
ent.rgmPRidtoent = {}
|
||||
ent.rgmPRenttoid = {}
|
||||
ent.rgmPRidtoent[0] = ent
|
||||
ent.rgmPRenttoid[ent] = 0
|
||||
function TOOL:RightClick(tr)
|
||||
if SERVER then
|
||||
local ent = tr.Entity
|
||||
local doweusethis = false
|
||||
local conents = {}
|
||||
local count = 0
|
||||
|
||||
self.idtoent = ent.rgmPRidtoent
|
||||
self.enttoid = ent.rgmPRenttoid
|
||||
print("One")
|
||||
self:SetStage(1)
|
||||
return true
|
||||
elseif stage == 1 then
|
||||
if self.enttoid[ent] then return false end
|
||||
self.idtoent[1] = ent
|
||||
self.enttoid[ent] = 1
|
||||
|
||||
ent.rgmPRidtoent = self.idtoent
|
||||
ent.rgmPRenttoid = self.enttoid
|
||||
ent.rgmPRparent = 0
|
||||
print("Two")
|
||||
self:SetStage(2)
|
||||
return true
|
||||
|
||||
elseif stage == 2 then
|
||||
if self.enttoid[ent] then return false end
|
||||
self.idtoent[2] = ent
|
||||
self.enttoid[ent] = 2
|
||||
|
||||
ent.rgmPRidtoent = self.idtoent
|
||||
ent.rgmPRenttoid = self.enttoid
|
||||
ent.rgmPRparent = 1
|
||||
print("Three")
|
||||
self:SetStage(3)
|
||||
return true
|
||||
|
||||
else
|
||||
if self.enttoid[ent] then return false end
|
||||
self.idtoent[3] = ent
|
||||
self.enttoid[ent] = 3
|
||||
|
||||
ent.rgmPRidtoent = self.idtoent
|
||||
ent.rgmPRenttoid = self.enttoid
|
||||
ent.rgmPRparent = 2
|
||||
print("Four")
|
||||
self:SetStage(0)
|
||||
|
||||
if SERVER then
|
||||
for id, ent in pairs(ent.rgmPRidtoent) do
|
||||
local data = {}
|
||||
data.idtoent = table.Copy(ent.rgmPRidtoent)
|
||||
data.enttoid = {}
|
||||
for e, id in pairs(ent.rgmPRenttoid) do
|
||||
data.enttoid[e:EntIndex()] = id
|
||||
if IsValid(ent) and ent:GetClass("prop_physics") then
|
||||
doweusethis = true
|
||||
local ents = constraint.GetAllConstrainedEntities(ent)
|
||||
for ent, _ in pairs(ents) do
|
||||
if ent:GetClass() == "prop_physics" and not IsValid(ent:GetParent()) then
|
||||
conents[ent] = true
|
||||
end
|
||||
data.parent = ent.rgmPRparent
|
||||
duplicator.StoreEntityModifier(ent, "Ragdoll Mover Prop Ragdoll", data)
|
||||
end
|
||||
for ent, _ in pairs(conents) do
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
self.idtoent = nil
|
||||
self.enttoid = nil
|
||||
|
||||
return true
|
||||
net.Start("rgmprSendConEnts")
|
||||
net.WriteBool(doweusethis)
|
||||
if doweusethis then
|
||||
net.WriteUInt(count, 13)
|
||||
for ent, _ in pairs(conents) do
|
||||
net.WriteEntity(ent)
|
||||
end
|
||||
end
|
||||
net.Send(self:GetOwner())
|
||||
end
|
||||
|
||||
return false
|
||||
return true
|
||||
end
|
||||
|
||||
function TOOL:Reload(tr)
|
||||
local ent = tr.Entity
|
||||
if not IsValid(ent) or not ent.rgmPRidtoent then return false end
|
||||
|
||||
if SERVER then
|
||||
for id, ent in pairs(ent.rgmPRidtoent) do
|
||||
ClearPropRagdoll(ent)
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
if CLIENT then
|
||||
|
||||
local PRUI
|
||||
local HoveredEnt
|
||||
|
||||
local function RGMCallApplySkeleton()
|
||||
if not PRUI or not PRUI.PRTree or not PRUI.PRTree.Nodes then return end
|
||||
if not next(PRUI.PRTree.Nodes) then return end
|
||||
local tree = PRUI.PRTree
|
||||
|
||||
net.Start("rgmprApplySkeleton")
|
||||
net.WriteUInt(tree.Bones, 13)
|
||||
for id, node in pairs(tree.Nodes) do
|
||||
net.WriteEntity(node.ent)
|
||||
net.WriteUInt(node.id, 13)
|
||||
net.WriteUInt(node.parent or 4100,13)
|
||||
end
|
||||
net.SendToServer()
|
||||
end
|
||||
|
||||
local function DeleteNodeRecursive(node)
|
||||
if IsValid(node) then
|
||||
node:SetParent(nil)
|
||||
node:Remove()
|
||||
for _, child in ipairs(node:GetChildNodes()) do
|
||||
DeleteNodeRecursive(child)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function FindSelfRecursive(nodestart, nodefind)
|
||||
if nodestart == nodefind then return true end
|
||||
|
||||
for _, node in ipairs(nodestart:GetChildNodes()) do
|
||||
if node == nodefind then return true end
|
||||
if FindSelfRecursive(node, nodefind) then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function TreeUpdateHBar()
|
||||
local width = 0
|
||||
|
||||
for id, node in pairs(PRUI.PRTree.Nodes) do
|
||||
local labelsize = node.Label:GetTextSize()
|
||||
local curwidth = labelsize + (node.depth * 17)
|
||||
if curwidth > width then
|
||||
width = curwidth
|
||||
end
|
||||
end
|
||||
|
||||
PRUI.PRTree:UpdateWidth(width + 8 + 32 + 16)
|
||||
end
|
||||
|
||||
local function AddHBar(self) -- There is no horizontal scrollbars in gmod, so I guess we'll override vertical one from GMod
|
||||
self.HBar = vgui.Create("DVScrollBar")
|
||||
|
||||
self.HBar.btnUp.Paint = function(panel, w, h) derma.SkinHook("Paint", "ButtonLeft", panel, w, h) end
|
||||
self.HBar.btnDown.Paint = function(panel, w, h) derma.SkinHook("Paint", "ButtonRight", panel, w, h) end
|
||||
|
||||
self.PanelWidth = 100
|
||||
self.LastWidth = 1
|
||||
|
||||
self.HBar.SetScroll = function(self, scrll)
|
||||
if (not self.Enabled) then self.Scroll = 0 return end
|
||||
|
||||
self.Scroll = math.Clamp( scrll, 0, self.CanvasSize )
|
||||
|
||||
self:InvalidateLayout()
|
||||
|
||||
local func = self:GetParent().OnHScroll
|
||||
if func then
|
||||
func(self:GetParent(), self:GetOffset())
|
||||
end
|
||||
end
|
||||
|
||||
self.HBar.OnMousePressed = function(self)
|
||||
local x, y = self:CursorPos()
|
||||
|
||||
local PageSize = self.BarSize
|
||||
|
||||
if (x > self.btnGrip.x) then
|
||||
self:SetScroll(self:GetScroll() + PageSize)
|
||||
else
|
||||
self:SetScroll(self:GetScroll() - PageSize)
|
||||
end
|
||||
end
|
||||
|
||||
self.HBar.OnCursorMoved = function(self, x, y)
|
||||
if (not self.Enabled) then return end
|
||||
if (not self.Dragging) then return end
|
||||
|
||||
local x, y = self:ScreenToLocal(gui.MouseX(), 0)
|
||||
|
||||
x = x - self.btnUp:GetWide()
|
||||
x = x - self.HoldPos
|
||||
|
||||
local BtnHeight = self:GetTall()
|
||||
if (self:GetHideButtons()) then BtnHeight = 0 end
|
||||
|
||||
local TrackSize = self:GetWide() - BtnHeight * 2 - self.btnGrip:GetWide()
|
||||
|
||||
x = x / TrackSize
|
||||
|
||||
self:SetScroll(x * self.CanvasSize)
|
||||
end
|
||||
|
||||
self.HBar.Grip = function(self)
|
||||
if (!self.Enabled) then return end
|
||||
if (self.BarSize == 0) then return end
|
||||
|
||||
self:MouseCapture(true)
|
||||
self.Dragging = true
|
||||
|
||||
local x, y = self.btnGrip:ScreenToLocal(gui.MouseX(), 0)
|
||||
self.HoldPos = x
|
||||
|
||||
self.btnGrip.Depressed = true
|
||||
end
|
||||
|
||||
self.HBar.PerformLayout = function(self)
|
||||
local Tall = self:GetTall()
|
||||
local BtnHeight = Tall
|
||||
if (self:GetHideButtons()) then BtnHeight = 0 end
|
||||
local Scroll = self:GetScroll() / self.CanvasSize
|
||||
local BarSize = math.max(self:BarScale() * (self:GetWide() - (BtnHeight * 2)), 10)
|
||||
local Track = self:GetWide() - (BtnHeight * 2) - BarSize
|
||||
Track = Track + 1
|
||||
|
||||
Scroll = Scroll * Track
|
||||
|
||||
self.btnGrip:SetPos(BtnHeight + Scroll, 0)
|
||||
self.btnGrip:SetSize(BarSize, Tall)
|
||||
|
||||
if (BtnHeight > 0) then
|
||||
self.btnUp:SetPos(0, 0)
|
||||
self.btnUp:SetSize(BtnHeight, Tall)
|
||||
|
||||
self.btnDown:SetPos(self:GetWide() - BtnHeight, 0)
|
||||
self.btnDown:SetSize(BtnHeight, Tall)
|
||||
|
||||
self.btnUp:SetVisible( true )
|
||||
self.btnDown:SetVisible( true )
|
||||
else
|
||||
self.btnUp:SetVisible( false )
|
||||
self.btnDown:SetVisible( false )
|
||||
self.btnDown:SetSize(BtnHeight, Tall)
|
||||
self.btnUp:SetSize(BtnHeight, Tall)
|
||||
end
|
||||
end
|
||||
|
||||
self.OnVScroll = function(self, iOffset)
|
||||
local x = self.pnlCanvas:GetPos()
|
||||
self.pnlCanvas:SetPos(x, iOffset)
|
||||
end
|
||||
|
||||
self.OnHScroll = function(self, iOffset)
|
||||
local _, y = self.pnlCanvas:GetPos()
|
||||
self.pnlCanvas:SetPos(iOffset, y)
|
||||
end
|
||||
|
||||
self.PerformLayoutInternal = function(self)
|
||||
local HTall, VTall = self:GetTall(), self.pnlCanvas:GetTall()
|
||||
local HWide, VWide = self:GetWide(), self.PanelWidth
|
||||
local XPos, YPos = 0, 0
|
||||
|
||||
self:Rebuild()
|
||||
|
||||
self.VBar:SetUp(self:GetTall(), self.pnlCanvas:GetTall())
|
||||
self.HBar:SetUp(self:GetWide(), self.pnlCanvas:GetWide())
|
||||
YPos = self.VBar:GetOffset()
|
||||
XPos = self.HBar:GetOffset()
|
||||
|
||||
if (self.VBar.Enabled) then VWide = VWide - self.VBar:GetWide() end
|
||||
if (self.HBar.Enabled) then HTall = HTall - self.HBar:GetTall() end
|
||||
|
||||
self.pnlCanvas:SetPos(XPos, YPos)
|
||||
self.pnlCanvas:SetSize(VWide, HTall)
|
||||
|
||||
self:Rebuild()
|
||||
|
||||
if (HWide ~= self.LastWidth) then
|
||||
self.HBar:SetScroll(self.HBar:GetScroll())
|
||||
end
|
||||
|
||||
if (VTall ~= self.pnlCanvas:GetTall()) then
|
||||
self.VBar:SetScroll(self.VBar:GetScroll())
|
||||
end
|
||||
|
||||
self.LastWidth = HWide
|
||||
end
|
||||
|
||||
self.PerformLayout = function(self)
|
||||
self:PerformLayoutInternal()
|
||||
end
|
||||
|
||||
self.UpdateWidth = function(self, newwidth)
|
||||
self.PanelWidth = newwidth
|
||||
self:InvalidateLayout()
|
||||
end
|
||||
end
|
||||
|
||||
local function CCol(cpanel,text, notexpanded)
|
||||
local cat = vgui.Create("DCollapsibleCategory",cpanel)
|
||||
cat:SetExpanded(1)
|
||||
cat:SetLabel(text)
|
||||
cpanel:AddItem(cat)
|
||||
local col = vgui.Create("DPanelList")
|
||||
col:SetAutoSize(true)
|
||||
col:SetSpacing(5)
|
||||
col:EnableHorizontal(false)
|
||||
col:EnableVerticalScrollbar(true)
|
||||
col.Paint = function()
|
||||
surface.DrawRect(0, 0, 500, 500)
|
||||
end
|
||||
cat:SetContents(col)
|
||||
cat:SetExpanded(not notexpanded)
|
||||
return col, cat
|
||||
end
|
||||
local function AddPRNode(parent, node)
|
||||
HoveredEnt = nil
|
||||
|
||||
if node.used then return end
|
||||
if not PRUI then return end
|
||||
local bones = PRUI.PRTree.Bones
|
||||
|
||||
if bones + 1 > CVMaxPRBones:GetInt() then return end
|
||||
local id = 0
|
||||
while PRUI.PRTree.Nodes[id] do
|
||||
id = id + 1
|
||||
end
|
||||
|
||||
PRUI.PRTree.Nodes[id] = parent:AddNode(id .. " [" .. node.text .. "]", "icon16/brick.png")
|
||||
PRUI.PRTree.Nodes[id].ent = node.ent
|
||||
PRUI.PRTree.Nodes[id].id = id
|
||||
PRUI.PRTree.Nodes[id].parent = parent.id or nil
|
||||
PRUI.PRTree.Nodes[id].depth = parent.depth and parent.depth + 1 or 1
|
||||
PRUI.PRTree.Nodes[id]:Droppable("rgmPRMove")
|
||||
|
||||
PRUI.PRTree.Nodes[id].DoRightClick = function()
|
||||
local deletemenu = DermaMenu(false, PRUI.PRTree)
|
||||
|
||||
local deletebutt = deletemenu:AddOption("Remove from list", function()
|
||||
local parent = PRUI.PRTree.Nodes[id]:GetParent()
|
||||
parent:SetVisible(false)
|
||||
DeleteNodeRecursive(PRUI.PRTree.Nodes[id])
|
||||
if next(parent:GetChildren()) then
|
||||
parent:SetVisible(true)
|
||||
else
|
||||
parent:GetParent().ChildNodes = nil
|
||||
end
|
||||
end)
|
||||
deletebutt:SetIcon("icon16/cross.png")
|
||||
|
||||
deletemenu:Open()
|
||||
return true
|
||||
end
|
||||
|
||||
PRUI.PRTree.Nodes[id]:Receiver("rgmprNew", function(self, received, dropped)
|
||||
PRUI.PRTree:SetSelectedItem(PRUI.PRTree.Nodes[id])
|
||||
if not dropped then return end
|
||||
|
||||
for k, v in ipairs(received) do
|
||||
AddPRNode(PRUI.PRTree.Nodes[id], v)
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
PRUI.PRTree.Nodes[id]:Receiver("rgmPRMove", function(self, received, dropped)
|
||||
PRUI.PRTree:SetSelectedItem(PRUI.PRTree.Nodes[id])
|
||||
if not dropped then return end
|
||||
|
||||
for k, v in ipairs(received) do
|
||||
if FindSelfRecursive(v, self) then continue end
|
||||
local parent = v:GetParent()
|
||||
parent:SetVisible(false)
|
||||
self:InsertNode(v)
|
||||
v.parent = id
|
||||
v.depth = self.depth + 1
|
||||
if next(parent:GetChildren()) then
|
||||
parent:SetVisible(true)
|
||||
else
|
||||
parent:GetParent().ChildNodes = nil
|
||||
end
|
||||
|
||||
TreeUpdateHBar()
|
||||
end
|
||||
end)
|
||||
|
||||
PRUI.PRTree.Nodes[id].OnRemove = function()
|
||||
if not PRUI.PRTree.Nodes[id] then return end
|
||||
node.used = false
|
||||
node:SetIcon("icon16/brick.png")
|
||||
PRUI.PRTree.Bones = PRUI.PRTree.Bones - 1
|
||||
PRUI.PRTree.Nodes[id] = nil
|
||||
end
|
||||
|
||||
node.used = true
|
||||
node:SetIcon("icon16/delete.png")
|
||||
|
||||
if IsValid(PRUI.PRTree.Nodes[id]:GetParent()) then
|
||||
PRUI.PRTree.Nodes[id]:GetParent():SetVisible(true)
|
||||
end
|
||||
|
||||
PRUI.PRTree.Bones = bones + 1
|
||||
|
||||
TreeUpdateHBar()
|
||||
|
||||
end
|
||||
|
||||
local function PropRagdollCreator(cpanel)
|
||||
|
||||
local helptext = vgui.Create("DLabel", cpanel)
|
||||
helptext:SetWrap(true)
|
||||
helptext:SetAutoStretchVertical(true)
|
||||
helptext:SetDark(true)
|
||||
helptext:SetText("Drag nodes from Constrained Entities tab into Prop Ragdoll tab to create skeleton for your prop ragdoll and then apply it. This tool can not read Prop Ragdoll skeleton data from existing Prop Ragdolls")
|
||||
cpanel:AddItem(helptext)
|
||||
|
||||
local PropRagdollUI = {}
|
||||
local constrainedents = CCol(cpanel, "Constrained Entities")
|
||||
|
||||
PropRagdollUI.EntTree = vgui.Create("DTree", constrainedents)
|
||||
PropRagdollUI.EntTree:SetTall(300)
|
||||
constrainedents:AddItem(PropRagdollUI.EntTree)
|
||||
|
||||
local creatorpanel = CCol(cpanel, "Prop Ragdoll")
|
||||
|
||||
PropRagdollUI.PRTree = vgui.Create("DTree", creatorpanel)
|
||||
PropRagdollUI.PRTree:SetTall(300)
|
||||
PropRagdollUI.PRTree.Bones = 0
|
||||
PropRagdollUI.PRTree:Receiver("rgmprNew", function(self, received, dropped)
|
||||
if not dropped then return end
|
||||
|
||||
for k, v in ipairs(received) do
|
||||
AddPRNode(PropRagdollUI.PRTree, v)
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
PropRagdollUI.PRTree:Receiver("rgmPRMove", function(self, received, dropped)
|
||||
if not dropped then return end
|
||||
|
||||
for k, v in ipairs(received) do
|
||||
local parent = v:GetParent()
|
||||
parent:SetVisible(false)
|
||||
self:Root():InsertNode(v)
|
||||
v.parent = nil
|
||||
if next(parent:GetChildren()) then
|
||||
parent:SetVisible(true)
|
||||
else
|
||||
parent:GetParent().ChildNodes = nil
|
||||
end
|
||||
|
||||
TreeUpdateHBar()
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
AddHBar(PropRagdollUI.PRTree)
|
||||
creatorpanel:AddItem(PropRagdollUI.PRTree)
|
||||
creatorpanel:AddItem(PropRagdollUI.PRTree.HBar)
|
||||
|
||||
local applybutt = vgui.Create("DButton", creatorpanel)
|
||||
applybutt:SetText("Apply Skeleton")
|
||||
|
||||
applybutt.DoClick = RGMCallApplySkeleton
|
||||
|
||||
creatorpanel:AddItem(applybutt)
|
||||
|
||||
return PropRagdollUI
|
||||
|
||||
end
|
||||
|
||||
local function GetModelName(ent)
|
||||
local name = ent:GetModel()
|
||||
local splitname = string.Split(name, "/")
|
||||
return splitname[#splitname]
|
||||
end
|
||||
|
||||
local function UpdateConstrainedEnts(ents)
|
||||
if not PRUI then return end
|
||||
PRUI.EntTree:Clear()
|
||||
PRUI.PRTree:Clear()
|
||||
PRUI.EntNodes = {}
|
||||
PRUI.PRTree.Bones = 0
|
||||
PRUI.PRTree.Nodes = {}
|
||||
|
||||
if not next(ents) then return end
|
||||
for _, ent in ipairs(ents) do
|
||||
local text = GetModelName(ent)
|
||||
PRUI.EntNodes[ent] = PRUI.EntTree:AddNode(text, "icon16/brick.png")
|
||||
PRUI.EntNodes[ent]:Droppable("rgmprNew")
|
||||
PRUI.EntNodes[ent].ent = ent
|
||||
PRUI.EntNodes[ent].text = text
|
||||
PRUI.EntNodes[ent].used = false
|
||||
|
||||
PRUI.EntNodes[ent].Label.OnCursorEntered = function()
|
||||
if PRUI.EntNodes[ent].used then return end
|
||||
HoveredEnt = ent
|
||||
end
|
||||
|
||||
PRUI.EntNodes[ent].Label.OnCursorExited = function()
|
||||
HoveredEnt = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function TOOL.BuildCPanel(CPanel)
|
||||
|
||||
PRUI = PropRagdollCreator(CPanel)
|
||||
|
||||
end
|
||||
|
||||
local COLOR_RGMGREEN = Color(0,200,0,255)
|
||||
|
||||
function TOOL:DrawHUD()
|
||||
|
||||
if PRUI and PRUI.PRTree and PRUI.PRTree.Nodes then
|
||||
for id, node in pairs(PRUI.PRTree.Nodes) do
|
||||
local ent = node.ent
|
||||
local pos = ent:GetPos():ToScreen()
|
||||
local textpos = { x = pos.x+5, y = pos.y-5 }
|
||||
surface.DrawCircle(pos.x, pos.y, 3.5, COLOR_RGMGREEN)
|
||||
draw.SimpleText(node.id,"Default",textpos.x,textpos.y,COLOR_RGMGREEN,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM)
|
||||
|
||||
if not node.parent then continue end
|
||||
local parent = PRUI.PRTree.Nodes[node.parent].ent
|
||||
local parentpos = parent:GetPos():ToScreen()
|
||||
surface.SetDrawColor(255, 255, 255)
|
||||
surface.DrawLine(pos.x, pos.y, parentpos.x, parentpos.y)
|
||||
end
|
||||
end
|
||||
|
||||
if IsValid(HoveredEnt) then
|
||||
rgm.DrawEntName(HoveredEnt)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
net.Receive("rgmprSendConEnts", function(len, pl)
|
||||
|
||||
local validents = net.ReadBool()
|
||||
local ents = {}
|
||||
|
||||
if validents then
|
||||
local count = net.ReadUInt(13)
|
||||
for i = 1, count do
|
||||
ents[i] = net.ReadEntity()
|
||||
end
|
||||
end
|
||||
|
||||
UpdateConstrainedEnts(ents)
|
||||
end)
|
||||
|
||||
end
|
||||
|
@ -149,5 +149,6 @@ tool.ragmover_ikchains.upperarm=Upperarm
|
||||
tool.ragmover_ikchains.knee=Knee
|
||||
tool.ragmover_ikchains.elbow=Elbow
|
||||
|
||||
|
||||
tool.ragmover_propragdoll.name=Ragdoll Mover - Prop Ragdoll
|
||||
tool.ragmover_propragdoll.name2=Rag Mover - Prop Ragdoll
|
||||
|
Loading…
Reference in New Issue
Block a user