Merge pull request #58 from penolakushari/adv_select_options

Advanced Selection manipulation options
This commit is contained in:
penolakushari 2024-11-04 18:04:02 +03:00 committed by GitHub
commit eefbda5c3b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 502 additions and 210 deletions

View File

@ -1,6 +1,10 @@
hook.Add("InitPostEntity", "rgmClientSetup", function()
if ConVarExists("ragdollmover_lockselected") then -- i should use some lua variable instead of console variable so it would reset properly
RunConsoleCommand("ragdollmover_lockselected", 0)
end
if ConVarExists("ragdollmover_rotatebutton") then
local BindRot = GetConVar("ragdollmover_rotatebutton"):GetInt()

View File

@ -1048,6 +1048,9 @@ local RGM_CIRCLE = {
{ x = -4, y = 0 }
}
local LockGo = Material("icon16/lock_go.png", "alphatest")
local Lock = Material("icon16/lock.png", "alphatest")
local midw, midh = ScrW()/2, ScrH()/2
local divide540 = RGM_Constants.FLOAT_1DIVIDE540 -- aggressive microoptimizations
@ -1114,13 +1117,14 @@ function AdvBoneSelectRender(ent, bonenodes)
if nodesExist and (not bonenodes[ent][i]) or false then continue end
local pos = ent:GetBonePosition(i)
pos = pos:ToScreen()
local x, y = pos.x, pos.y
local dist = math.abs((mx - pos.x)^2 + (my - pos.y)^2)
local dist = math.abs((mx - x)^2 + (my - y)^2)
local circ = table.Copy(RGM_CIRCLE)
for k, v in ipairs(circ) do
v.x = v.x + pos.x
v.y = v.y + pos.y
v.x = v.x + x
v.y = v.y + y
end
if dist < 576 then -- 24 pixels
@ -1136,6 +1140,16 @@ function AdvBoneSelectRender(ent, bonenodes)
draw.NoTexture()
surface.DrawPoly(circ)
if bonenodes[ent][i].bonelock then
surface.SetMaterial(LockGo)
surface.SetDrawColor(COLOR_WHITE:Unpack())
surface.DrawTexturedRect(x - 12, y - 12, 24, 24)
elseif bonenodes[ent][i].poslock or bonenodes[ent][i].anglock then
surface.SetMaterial(Lock)
surface.SetDrawColor(COLOR_WHITE:Unpack())
surface.DrawTexturedRect(x - 12, y - 12, 24, 24)
end
end
-- We use the average length of all bone names to ensure some names don't overlap each other
@ -1199,27 +1213,118 @@ end
local SelectedBone = nil
function AdvBoneSelectRadialRender(ent, bones, bonenodes)
local Colors = {
Color(255, 140, 105), -- Orange, for Resets
Color(100, 255, 255), -- Cyan (Blue is too dark), for Zeroing scale
Color(100, 255, 0), -- Green, for Locks
Color(255, 255, 255) -- White, for whatever
}
local FeaturesNPhys = {
{ 1, (language.GetPhrase("tool.ragdollmover.resetmenu") .. " " .. language.GetPhrase("tool.ragdollmover.reset")), 1 }, -- 1
{ 5, (language.GetPhrase("tool.ragdollmover.resetmenu") .. " " .. language.GetPhrase("tool.ragdollmover.resetchildren")), 1 }, -- 5
{ 2, (language.GetPhrase("tool.ragdollmover.resetmenu") .. " " .. language.GetPhrase("tool.ragdollmover.resetpos")), 1 }, -- 2
{ 6, (language.GetPhrase("tool.ragdollmover.resetmenu") .. " " .. language.GetPhrase("tool.ragdollmover.resetposchildren")), 1 }, -- 6
{ 3, (language.GetPhrase("tool.ragdollmover.resetmenu") .. " " .. language.GetPhrase("tool.ragdollmover.resetrot")), 1 }, -- 3
{ 7, (language.GetPhrase("tool.ragdollmover.resetmenu") .. " " .. language.GetPhrase("tool.ragdollmover.resetrotchildren")), 1 }, -- 7
{ 4, (language.GetPhrase("tool.ragdollmover.resetmenu") .. " " .. language.GetPhrase("tool.ragdollmover.resetscale")), 1 }, -- 4
{ 8, (language.GetPhrase("tool.ragdollmover.resetmenu") .. " " .. language.GetPhrase("tool.ragdollmover.resetscalechildren")), 1 }, -- 8
{ 9, (language.GetPhrase("tool.ragdollmover.scalezero") .. " " .. language.GetPhrase("tool.ragdollmover.bone")), 2 }, -- 9
{ 10, (language.GetPhrase("tool.ragdollmover.scalezero") .. " " .. language.GetPhrase("tool.ragdollmover.bonechildren")), 2 }, -- 10
{ 15, { "#tool.ragdollmover.unlockscale", "#tool.ragdollmover.lockscale" }, 3 }, --15
{ 17, "#tool.ragdollmover.putgizmopos", 4 }, -- 17
{ 18, "#tool.ragdollmover.resetoffset", 4 } -- 18
}
local FeaturesPhys = {
{ 1, (language.GetPhrase("tool.ragdollmover.resetmenu") .. " " .. language.GetPhrase("tool.ragdollmover.reset")), 1 }, -- 1
{ 5, (language.GetPhrase("tool.ragdollmover.resetmenu") .. " " .. language.GetPhrase("tool.ragdollmover.resetchildren")), 1 }, -- 5
{ 6, (language.GetPhrase("tool.ragdollmover.resetmenu") .. " " .. language.GetPhrase("tool.ragdollmover.resetposchildren")), 1 }, -- 6
{ 7, (language.GetPhrase("tool.ragdollmover.resetmenu") .. " " .. language.GetPhrase("tool.ragdollmover.resetrotchildren")), 1 }, -- 7
{ 8, (language.GetPhrase("tool.ragdollmover.resetmenu") .. " " .. language.GetPhrase("tool.ragdollmover.resetscalechildren")), 1 }, -- 8
{ 9, (language.GetPhrase("tool.ragdollmover.scalezero") .. " " .. language.GetPhrase("tool.ragdollmover.bone")), 2 }, -- 9
{ 10, (language.GetPhrase("tool.ragdollmover.scalezero") .. " " .. language.GetPhrase("tool.ragdollmover.bonechildren")), 2 }, -- 10
{ 19, { "#tool.ragdollmover.unlockall", "#tool.ragdollmover.lockall" }, 3 }, -- 19
{ 12, { "#tool.ragdollmover.unlockpos", "#tool.ragdollmover.lockpos" }, 3 }, -- 12
{ 13, { "#tool.ragdollmover.unlockang", "#tool.ragdollmover.lockang" }, 3}, -- 13
{ 15, { "#tool.ragdollmover.unlockscale", "#tool.ragdollmover.lockscale" }, 3 }, --15
{ 14, "#tool.ragdollmover.lockbone", 3 }, -- 14
{ 11, "#tool.ragdollmover.unlockbone", 3 }, -- 11
{ 16, "#tool.ragdollmover.freezebone", 4 }, -- 16
{ 17, "#tool.ragdollmover.putgizmopos", 4 }, -- 17
{ 18, "#tool.ragdollmover.resetoffset", 4 } -- 18
}
function AdvBoneSelectRadialRender(ent, bones, bonenodes, isresetmode)
local mx, my = input.GetCursorPos()
local count = #bones
local angborder = (360 / count) / 2
local modifier = divide540 * midh
for k, bone in ipairs(bones) do
local name = ent:GetBoneName(bone)
local thisang = (360 / count * (k - 1))
local thisrad = thisang / 180 * math.pi
local uix, uiy = (math.sin(thisrad) * 250 * modifier), (math.cos(thisrad) * -250 * modifier)
local color = COLOR_WHITE
if bonenodes and bonenodes[ent] and bonenodes[ent][bone] and bonenodes[ent][bone].Type then
color = BONETYPE_COLORS[bonenodes[ent][bone].Type]
if not isresetmode then
local count = #bones
local angborder = (360 / count) / 2
for k, bone in ipairs(bones) do
local name = ent:GetBoneName(bone)
local thisang = (360 / count * (k - 1))
local thisrad = thisang / 180 * math.pi
local uix, uiy = (math.sin(thisrad) * 250 * modifier), (math.cos(thisrad) * -250 * modifier)
local color = COLOR_WHITE
if bonenodes and bonenodes[ent] and bonenodes[ent][bone] and bonenodes[ent][bone].Type then
color = BONETYPE_COLORS[bonenodes[ent][bone].Type]
end
uix, uiy = uix + midw, uiy + midh
local selangle = 360 - (math.deg(math.atan2(mx - midw, my - midh)) + 180) -- took this one from overhauled radial menu, which took some of the inspiration from wiremod
local diff = math.abs((thisang - selangle + 180) % 360 - 180)
local isselected = diff < angborder and true or false
local pos = ent:GetBonePosition(bone)
pos = pos:ToScreen()
local circ = table.Copy(RGM_CIRCLE)
for k, v in ipairs(circ) do
v.x = v.x + pos.x
v.y = v.y + pos.y
end
if isselected then
surface.SetDrawColor(COLOR_BRIGHT_YELLOW:Unpack())
color = COLOR_BRIGHT_YELLOW
SelectedBone = bone
else
if bonenodes and bonenodes[ent] and bonenodes[ent][bone] and bonenodes[ent][bone].Type then
surface.SetDrawColor(BONETYPE_COLORS[bonenodes[ent][bone].Type]:Unpack())
else
surface.SetDrawColor(COLOR_RGMGREEN:Unpack())
end
end
draw.NoTexture()
surface.DrawPoly(circ)
local ytextoffset = -14
if uiy > (midh + 30) then ytextoffset = RGMFontSize + 14 end
local xtextoffset = 0
if uix > (midw + 5) then
xtextoffset = 20
elseif uix < (midw - 5) then
xtextoffset = -20
else
ytextoffset = ytextoffset*1.5
end
surface.DrawCircle(uix, uiy, 3.5, color)
draw.SimpleTextOutlined(name, "RagdollMoverFont", uix + xtextoffset, uiy + ytextoffset, color, TEXT_ALIGN_CENTER, TEXT_ALIGN_BOTTOM, OUTLINE_WIDTH, COLOR_RGMBLACK)
end
uix, uiy = uix + midw, uiy + midh
local selangle = 360 - (math.deg(math.atan2(mx - midw, my - midh)) + 180) -- took this one from overhauled radial menu, which took some of the inspiration from wiremod
local diff = math.abs((thisang - selangle + 180) % 360 - 180)
local isselected = diff < angborder and true or false
else
local bone = bones[1]
local btype = 2
if bonenodes and bonenodes[ent] and bonenodes[ent][bone] and bonenodes[ent][bone].Type then
btype = bonenodes[ent][bone].Type
end
local pos = ent:GetBonePosition(bone)
pos = pos:ToScreen()
@ -1230,35 +1335,77 @@ function AdvBoneSelectRadialRender(ent, bones, bonenodes)
v.y = v.y + pos.y
end
if isselected then
surface.SetDrawColor(COLOR_BRIGHT_YELLOW:Unpack())
color = COLOR_BRIGHT_YELLOW
SelectedBone = bone
else
if bonenodes and bonenodes[ent] and bonenodes[ent][bone] and bonenodes[ent][bone].Type then
surface.SetDrawColor(BONETYPE_COLORS[bonenodes[ent][bone].Type]:Unpack())
else
surface.SetDrawColor(COLOR_RGMGREEN:Unpack())
end
end
surface.SetDrawColor(COLOR_WHITE:Unpack())
draw.NoTexture()
surface.DrawPoly(circ)
local ytextoffset = -14
if uiy > (midh + 30) then ytextoffset = RGMFontSize + 14 end
local xtextoffset = 0
if uix > (midw + 5) then
xtextoffset = 20
elseif uix < (midw - 5) then
xtextoffset = -20
else
ytextoffset = ytextoffset*1.5
local boneoptions = btype == 1 and FeaturesPhys or FeaturesNPhys
local count = #boneoptions
if btype == 1 then
if not bonenodes[ent][bone].bonelock then
count = count - 1
else
count = count - 2
end
end
local angborder = (360 / count) / 2
local k = 1
local skipped = 0
for i, option in pairs(boneoptions) do
local id = option[1]
if ( id == 11 and not bonenodes[ent][bone].bonelock ) or ( (id == 12 or id == 13) and bonenodes[ent][bone].bonelock ) then continue end
local name = option[2]
if not isstring(option) then
if id == 12 then
name = bonenodes[ent][bone].poslock and name[1] or name[2]
elseif id == 13 then
name = bonenodes[ent][bone].anglock and name[1] or name[2]
elseif id == 15 then
name = bonenodes[ent][bone].scllock and name[1] or name[2]
elseif id == 19 then
name = ( bonenodes[ent][bone].poslock and bonenodes[ent][bone].anglock ) and name[1] or name[2]
end
end
local thisang = (360 / count * (k - 1))
local thisrad = thisang / 180 * math.pi
local uix, uiy = (math.sin(thisrad) * 250 * modifier), (math.cos(thisrad) * -250 * modifier)
local color = Colors[option[3]]
uix, uiy = uix + midw, uiy + midh
local selangle = 360 - (math.deg(math.atan2(mx - midw, my - midh)) + 180) -- took this one from overhauled radial menu, which took some of the inspiration from wiremod
local diff = math.abs((thisang - selangle + 180) % 360 - 180)
local isselected = diff < angborder and true or false
if isselected then
color = COLOR_BRIGHT_YELLOW
SelectedBone = id
end
local ytextoffset = -14
if uiy > (midh + 30) then ytextoffset = RGMFontSize + 14 end
local xtextoffset = 0
if uix > (midw + 5) then
xtextoffset = 20
elseif uix < (midw - 5) then
xtextoffset = -20
else
ytextoffset = ytextoffset*1.5
end
surface.DrawCircle(uix, uiy, 3.5, color)
draw.SimpleTextOutlined(name, "RagdollMoverFont", uix + xtextoffset, uiy + ytextoffset, color, TEXT_ALIGN_CENTER, TEXT_ALIGN_BOTTOM, OUTLINE_WIDTH, COLOR_RGMBLACK)
k = k + 1
end
surface.DrawCircle(uix, uiy, 3.5, color)
draw.SimpleTextOutlined(name, "RagdollMoverFont", uix + xtextoffset, uiy + ytextoffset, color, TEXT_ALIGN_CENTER, TEXT_ALIGN_BOTTOM, OUTLINE_WIDTH, COLOR_RGMBLACK)
end
end
@ -1296,6 +1443,8 @@ local SkeletonData = {}
local function DrawRecursiveBones(ent, bone, bonenodes)
local mainpos = ent:GetBonePosition(bone)
mainpos = mainpos:ToScreen()
local nodecache = bonenodes[ent]
local nodeexist = nodecache and true or false
for _, boneid in ipairs(ent:GetChildBones(bone)) do
SkeletonData[boneid] = bone
@ -1306,8 +1455,8 @@ local function DrawRecursiveBones(ent, bone, bonenodes)
surface.DrawLine(mainpos.x, mainpos.y, pos.x, pos.y)
DrawRecursiveBones(ent, boneid, bonenodes)
local color
if bonenodes then
color = BONETYPE_COLORS[bonenodes[ent][boneid].Type]
if nodeexist and nodecache[boneid] then
color = BONETYPE_COLORS[nodecache[boneid].Type]
else
color = COLOR_RGMGREEN
end

View File

@ -127,7 +127,7 @@ numpad.Register("rgmAxisChangeStateRot", function(pl)
if not RAGDOLLMOVER[pl] then RAGDOLLMOVER[pl] = {} end
if not rgmMode[pl] then rgmMode[pl] = 1 end
if not pl:GetTool() then return end
if not pl:GetTool() or RAGDOLLMOVER[pl].Moving then return end
if pl:GetTool().Mode ~= "ragdollmover" or pl:GetActiveWeapon():GetClass() ~= "gmod_tool" then return end
if RotKey[pl] == ScaleKey[pl] then
rgmMode[pl] = rgmMode[pl] + 1
@ -147,7 +147,7 @@ end)
numpad.Register("rgmAxisChangeStateScale", function(pl)
if not RAGDOLLMOVER[pl] then RAGDOLLMOVER[pl] = {} end
if not pl:GetTool() then return end
if not pl:GetTool() or RAGDOLLMOVER[pl].Moving then return end
if pl:GetTool().Mode ~= "ragdollmover" or pl:GetActiveWeapon():GetClass() ~= "gmod_tool" then return end
if RotKey[pl] == ScaleKey[pl] then return end
RAGDOLLMOVER[pl].Scale = not RAGDOLLMOVER[pl].Scale

View File

@ -763,24 +763,32 @@ local NETFUNC = {
end
local plTable = RAGDOLLMOVER[pl]
if mode == 1 then
if mode == 0 then
if not plTable.rgmPosLocks[ent][boneid] then
plTable.rgmPosLocks[ent][boneid] = ent:GetPhysicsObjectNum(physbone)
else
plTable.rgmPosLocks[ent][boneid] = nil
end
elseif mode == 2 then
elseif mode == 1 then
if not plTable.rgmAngLocks[ent][boneid] then
plTable.rgmAngLocks[ent][boneid] = ent:GetPhysicsObjectNum(physbone)
else
plTable.rgmAngLocks[ent][boneid] = nil
end
elseif mode == 3 then
elseif mode == 2 then
if not plTable.rgmScaleLocks[ent][bone] then
plTable.rgmScaleLocks[ent][bone] = true
else
plTable.rgmScaleLocks[ent][bone] = false
end
elseif mode == 3 then
if not plTable.rgmPosLocks[ent][boneid] or not plTable.rgmAngLocks[ent][boneid] then
plTable.rgmPosLocks[ent][boneid] = ent:GetPhysicsObjectNum(physbone)
plTable.rgmAngLocks[ent][boneid] = ent:GetPhysicsObjectNum(physbone)
else
plTable.rgmPosLocks[ent][boneid] = nil
plTable.rgmAngLocks[ent][boneid] = nil
end
end
local poslock, anglock, scllock = IsValid(plTable.rgmPosLocks[ent][boneid]), IsValid(plTable.rgmAngLocks[ent][boneid]), plTable.rgmScaleLocks[ent][bone]
@ -2446,6 +2454,7 @@ if CLIENT then
TOOL.Information = {
{ name = "left_advselect", op = 2 },
{ name = "right_advselect", op = 2 },
{ name = "info_advselect", op = 2 },
{ name = "left_gizmomode", op = 1 },
{ name = "right_gizmomode", op = 1 },
@ -3185,6 +3194,7 @@ local Col4
local LockMode, LockTo = false, { id = nil, ent = nil }
local IsPropRagdoll, TreeEntities = false, {}
local ScaleLocks = {}
local ResetMode = false
cvars.AddChangeCallback("ragdollmover_ik_hand_L", function(convar, old, new)
if not IsValid(EnableIKButt) then return end
@ -3226,6 +3236,203 @@ cvars.AddChangeCallback("ragdollmover_ik_leg_R", function(convar, old, new)
end
end)
local NodeFunctions = {
function(ent, id) -- 1 nodeReset
net.Start("RAGDOLLMOVER")
net.WriteUInt(17, 5)
net.WriteEntity(ent)
net.WriteUInt(id, 10)
net.WriteBool(false)
net.SendToServer()
end,
function(ent, id) -- 2 nodeResetPos
net.Start("RAGDOLLMOVER")
net.WriteUInt(18, 5)
net.WriteEntity(ent)
net.WriteBool(false)
net.WriteUInt(id, 10) -- with SFM studiomdl, it seems like upper limit for bones is 256. Used 10 bits in case if there was 512 https://developer.valvesoftware.com/wiki/Skeleton
net.SendToServer()
end,
function(ent, id) -- 3 nodeResetRot
net.Start("RAGDOLLMOVER")
net.WriteUInt(19, 5)
net.WriteEntity(ent)
net.WriteBool(false)
net.WriteUInt(id, 10)
net.SendToServer()
end,
function(ent, id) -- 4 nodeResetScale
net.Start("RAGDOLLMOVER")
net.WriteUInt(20, 5)
net.WriteEntity(ent)
net.WriteBool(false)
net.WriteUInt(id, 10)
net.SendToServer()
end,
function(ent, id) -- 5 nodeResetCh
net.Start("RAGDOLLMOVER")
net.WriteUInt(17, 5)
net.WriteEntity(ent)
net.WriteUInt(id, 10)
net.WriteBool(true)
net.SendToServer()
end,
function(ent, id) -- 6 nodeResetPosCh
net.Start("RAGDOLLMOVER")
net.WriteUInt(18, 5)
net.WriteEntity(ent)
net.WriteBool(true)
net.WriteUInt(id, 10)
net.SendToServer()
end,
function(ent, id) -- 7 nodeResetAngCh
net.Start("RAGDOLLMOVER")
net.WriteUInt(19, 5)
net.WriteEntity(ent)
net.WriteBool(true)
net.WriteUInt(id, 10)
net.SendToServer()
end,
function(ent, id) -- 8 nodeResetScaleCh
net.Start("RAGDOLLMOVER")
net.WriteUInt(20, 5)
net.WriteEntity(ent)
net.WriteBool(true)
net.WriteUInt(id, 10)
net.SendToServer()
end,
function(ent, id) -- 9 nodeScaleZero
net.Start("RAGDOLLMOVER")
net.WriteUInt(21, 5)
net.WriteEntity(ent)
net.WriteBool(false)
net.WriteUInt(id, 10)
net.SendToServer()
end,
function(ent, id) -- 10 nodeScaleZeroCh
net.Start("RAGDOLLMOVER")
net.WriteUInt(21, 5)
net.WriteEntity(ent)
net.WriteBool(true)
net.WriteUInt(id, 10)
net.SendToServer()
end,
function(ent, id) -- 11 nodeUnlock
net.Start("RAGDOLLMOVER")
net.WriteUInt(8, 5)
net.WriteEntity(ent)
net.WriteUInt(id, 10)
net.SendToServer()
end,
function(ent, id) -- 12 nodePosLock
net.Start("RAGDOLLMOVER")
net.WriteUInt(5, 5)
net.WriteEntity(ent)
net.WriteUInt(0, 2)
net.WriteUInt(id, 10)
net.SendToServer()
end,
function(ent, id) -- 13 nodeRotLock
net.Start("RAGDOLLMOVER")
net.WriteUInt(5, 5)
net.WriteEntity(ent)
net.WriteUInt(1, 2)
net.WriteUInt(id, 10)
net.SendToServer()
end,
function(ent, id) -- 14 nodeLockToBone
if LockMode == 1 then
if nodes[LockTo.ent][LockTo.id].poslock or nodes[LockTo.ent][LockTo.id].anglock then
nodes[LockTo.ent][LockTo.id]:SetIcon("icon16/lock.png")
nodes[LockTo.ent][LockTo.id].Label:SetToolTip("#tool.ragdollmover.lockedbone")
elseif nodes[LockTo.ent][LockTo.id].scllock then
nodes[LockTo.ent][LockTo.id]:SetIcon("icon16/lightbulb.png")
nodes[LockTo.ent][LockTo.id].Label:SetToolTip("#tool.ragdollmover.lockedscale")
else
nodes[LockTo.ent][LockTo.id]:SetIcon(BoneTypeSort[nodes[LockTo.ent][LockTo.id].Type].Icon)
nodes[LockTo.ent][LockTo.id].Label:SetToolTip(BoneTypeSort[nodes[LockTo.ent][LockTo.id].Type].ToolTip)
end
elseif LockMode == 2 then
conentnodes[LockTo.id]:SetIcon("icon16/brick_link.png")
conentnodes[LockTo.id].Label:SetToolTip(false)
end
LockMode = 1
LockTo = { id = id, ent = ent }
surface.PlaySound("buttons/button9.wav")
nodes[ent][id]:SetIcon("icon16/brick_add.png")
nodes[ent][id].Label:SetToolTip("#tool.ragdollmover.bonetolock")
ResetMode = false
net.Start("RAGDOLLMOVER")
net.WriteUInt(14, 5)
net.WriteUInt(2, 2)
net.SendToServer()
gui.EnableScreenClicker(false)
end,
function(ent, id) -- 15 nodeScaleLock
net.Start("RAGDOLLMOVER")
net.WriteUInt(5, 5)
net.WriteEntity(ent)
net.WriteUInt(2, 2)
net.WriteUInt(id, 10)
net.SendToServer()
end,
function(ent, id) -- 16 nodeFreezeBone
net.Start("RAGDOLLMOVER")
net.WriteUInt(6, 5)
net.WriteEntity(ent)
net.WriteUInt(id, 10)
net.SendToServer()
end,
function(ent, id) -- 17 nodePutGizmo
local pos = ent:GetBonePosition(id)
if pos == ent:GetPos() then
local matrix = ent:GetBoneMatrix(id)
pos = matrix:GetTranslation()
end
net.Start("RAGDOLLMOVER")
net.WriteUInt(15, 5)
net.WriteVector(pos)
net.SendToServer()
end,
function() -- 18 nodeResetGizmo
RGMResetGizmo()
end,
function(ent, id) -- 19 nodeAllPhysLock
net.Start("RAGDOLLMOVER")
net.WriteUInt(5, 5)
net.WriteEntity(ent)
net.WriteUInt(3, 2)
net.WriteUInt(id, 10)
net.SendToServer()
end
}
local function SetBoneNodes(bonepanel, sortedbones)
nodes = {}
@ -3301,6 +3508,8 @@ local function SetBoneNodes(bonepanel, sortedbones)
LockMode = false
LockTo = { id = nil, ent = nil }
ResetMode = false
net.Start("RAGDOLLMOVER")
net.WriteUInt(14, 5)
net.WriteUInt(0, 2)
@ -3317,89 +3526,49 @@ local function SetBoneNodes(bonepanel, sortedbones)
local option = resetmenu:AddOption("#tool.ragdollmover.reset", function()
if not IsValid(ent) then return end
net.Start("RAGDOLLMOVER")
net.WriteUInt(17, 5)
net.WriteEntity(ent)
net.WriteUInt(v.id, 10)
net.WriteBool(false)
net.SendToServer()
NodeFunctions[1](ent, v.id)
end)
option:SetIcon("icon16/connect.png")
option = resetmenu:AddOption("#tool.ragdollmover.resetpos", function()
if not IsValid(ent) then return end
net.Start("RAGDOLLMOVER")
net.WriteUInt(18, 5)
net.WriteEntity(ent)
net.WriteBool(false)
net.WriteUInt(v.id, 10) -- with SFM studiomdl, it seems like upper limit for bones is 256. Used 10 bits in case if there was 512 https://developer.valvesoftware.com/wiki/Skeleton
net.SendToServer()
NodeFunctions[2](ent, v.id)
end)
option:SetIcon("icon16/connect.png")
option = resetmenu:AddOption("#tool.ragdollmover.resetrot", function()
if not IsValid(ent) then return end
net.Start("RAGDOLLMOVER")
net.WriteUInt(19, 5)
net.WriteEntity(ent)
net.WriteBool(false)
net.WriteUInt(v.id, 10)
net.SendToServer()
NodeFunctions[3](ent, v.id)
end)
option:SetIcon("icon16/connect.png")
option = resetmenu:AddOption("#tool.ragdollmover.resetscale", function()
if not IsValid(ent) then return end
net.Start("RAGDOLLMOVER")
net.WriteUInt(20, 5)
net.WriteEntity(ent)
net.WriteBool(false)
net.WriteUInt(v.id, 10)
net.SendToServer()
NodeFunctions[4](ent, v.id)
end)
option:SetIcon("icon16/connect.png")
option = resetmenu:AddOption("#tool.ragdollmover.resetchildren", function()
if not IsValid(ent) then return end
net.Start("RAGDOLLMOVER")
net.WriteUInt(17, 5)
net.WriteEntity(ent)
net.WriteUInt(v.id, 10)
net.WriteBool(true)
net.SendToServer()
NodeFunctions[5](ent, v.id)
end)
option:SetIcon("icon16/bricks.png")
option = resetmenu:AddOption("#tool.ragdollmover.resetposchildren", function()
if not IsValid(ent) then return end
net.Start("RAGDOLLMOVER")
net.WriteUInt(18, 5)
net.WriteEntity(ent)
net.WriteBool(true)
net.WriteUInt(v.id, 10)
net.SendToServer()
NodeFunctions[6](ent, v.id)
end)
option:SetIcon("icon16/bricks.png")
option = resetmenu:AddOption("#tool.ragdollmover.resetrotchildren", function()
if not IsValid(ent) then return end
net.Start("RAGDOLLMOVER")
net.WriteUInt(19, 5)
net.WriteEntity(ent)
net.WriteBool(true)
net.WriteUInt(v.id, 10)
net.SendToServer()
NodeFunctions[7](ent, v.id)
end)
option:SetIcon("icon16/bricks.png")
option = resetmenu:AddOption("#tool.ragdollmover.resetscalechildren", function()
if not IsValid(ent) then return end
net.Start("RAGDOLLMOVER")
net.WriteUInt(20, 5)
net.WriteEntity(ent)
net.WriteBool(true)
net.WriteUInt(v.id, 10)
net.SendToServer()
NodeFunctions[8](ent, v.id)
end)
option:SetIcon("icon16/bricks.png")
@ -3407,23 +3576,13 @@ local function SetBoneNodes(bonepanel, sortedbones)
option = scalezeromenu:AddOption("#tool.ragdollmover.bone", function()
if not IsValid(ent) then return end
net.Start("RAGDOLLMOVER")
net.WriteUInt(21, 5)
net.WriteEntity(ent)
net.WriteBool(false)
net.WriteUInt(v.id, 10)
net.SendToServer()
NodeFunctions[9](ent, v.id)
end)
option:SetIcon("icon16/connect.png")
option = scalezeromenu:AddOption("#tool.ragdollmover.bonechildren", function()
if not IsValid(ent) then return end
net.Start("RAGDOLLMOVER")
net.WriteUInt(21, 5)
net.WriteEntity(ent)
net.WriteBool(true)
net.WriteUInt(v.id, 10)
net.SendToServer()
NodeFunctions[10](ent, v.id)
end)
option:SetIcon("icon16/bricks.png")
@ -3433,70 +3592,34 @@ local function SetBoneNodes(bonepanel, sortedbones)
option = bonemenu:AddOption("#tool.ragdollmover.unlockbone", function()
if not IsValid(ent) then return end
net.Start("RAGDOLLMOVER")
net.WriteUInt(8, 5)
net.WriteEntity(ent)
net.WriteUInt(v.id, 10)
net.SendToServer()
NodeFunctions[11](ent, v.id)
end)
bonemenu:AddSpacer()
elseif nodes[ent][v.id].Type == BONE_PHYSICAL and IsValid(ent) and ( ent:GetClass() == "prop_ragdoll" or IsPropRagdoll ) then
option = bonemenu:AddOption(( nodes[ent][v.id].poslock and nodes[ent][v.id].anglock ) and "#tool.ragdollmover.unlockall" or "#tool.ragdollmover.lockall", function()
if not IsValid(ent) then return end
NodeFunctions[19](ent, v.id)
end)
option:SetIcon(( nodes[ent][v.id].poslock and nodes[ent][v.id].anglock ) and "icon16/lock.png" or "icon16/brick.png")
option = bonemenu:AddOption(nodes[ent][v.id].poslock and "#tool.ragdollmover.unlockpos" or "#tool.ragdollmover.lockpos", function()
if not IsValid(ent) then return end
net.Start("RAGDOLLMOVER")
net.WriteUInt(5, 5)
net.WriteEntity(ent)
net.WriteUInt(1, 2)
net.WriteUInt(v.id, 10)
net.SendToServer()
NodeFunctions[12](ent, v.id)
end)
option:SetIcon(nodes[ent][v.id].poslock and "icon16/lock.png" or "icon16/brick.png")
option = bonemenu:AddOption(nodes[ent][v.id].anglock and "#tool.ragdollmover.unlockang" or "#tool.ragdollmover.lockang", function()
if not IsValid(ent) then return end
net.Start("RAGDOLLMOVER")
net.WriteUInt(5, 5)
net.WriteEntity(ent)
net.WriteUInt(2, 2)
net.WriteUInt(v.id, 10)
net.SendToServer()
NodeFunctions[13](ent, v.id)
end)
option:SetIcon(nodes[ent][v.id].anglock and "icon16/lock.png" or "icon16/brick.png")
option = bonemenu:AddOption("#tool.ragdollmover.lockbone", function()
if not IsValid(ent) then return end
if LockMode == 1 then
if nodes[LockTo.ent][LockTo.id].poslock or nodes[LockTo.ent][LockTo.id].anglock then
nodes[LockTo.ent][LockTo.id]:SetIcon("icon16/lock.png")
nodes[LockTo.ent][LockTo.id].Label:SetToolTip("#tool.ragdollmover.lockedbone")
elseif nodes[LockTo.ent][LockTo.id].scllock then
nodes[LockTo.ent][LockTo.id]:SetIcon("icon16/lightbulb.png")
nodes[LockTo.ent][LockTo.id].Label:SetToolTip("#tool.ragdollmover.lockedscale")
else
nodes[LockTo.ent][LockTo.id]:SetIcon(BoneTypeSort[nodes[LockTo.ent][LockTo.id].Type].Icon)
nodes[LockTo.ent][LockTo.id].Label:SetToolTip(BoneTypeSort[nodes[LockTo.ent][LockTo.id].Type].ToolTip)
end
elseif LockMode == 2 then
conentnodes[LockTo.id]:SetIcon("icon16/brick_link.png")
conentnodes[LockTo.id].Label:SetToolTip(false)
end
LockMode = 1
LockTo = { id = v.id, ent = ent }
surface.PlaySound("buttons/button9.wav")
nodes[ent][v.id]:SetIcon("icon16/brick_add.png")
nodes[ent][v.id].Label:SetToolTip("#tool.ragdollmover.bonetolock")
net.Start("RAGDOLLMOVER")
net.WriteUInt(14, 5)
net.WriteUInt(2, 2)
net.SendToServer()
gui.EnableScreenClicker(false)
NodeFunctions[14](ent, v.id)
end)
option:SetIcon("icon16/lock.png")
@ -3505,42 +3628,21 @@ local function SetBoneNodes(bonepanel, sortedbones)
option = bonemenu:AddOption(nodes[ent][v.id].scllock and "#tool.ragdollmover.unlockscale" or "#tool.ragdollmover.lockscale", function()
if not IsValid(ent) then return end
net.Start("RAGDOLLMOVER")
net.WriteUInt(5, 5)
net.WriteEntity(ent)
net.WriteUInt(3, 2)
net.WriteUInt(v.id, 10)
net.SendToServer()
NodeFunctions[15](ent, v.id)
end)
option:SetIcon(nodes[ent][v.id].scllock and "icon16/lightbulb.png" or "icon16/connect.png")
if nodes[ent][v.id].Type == BONE_PHYSICAL and IsValid(ent) and ( ent:GetClass() == "prop_ragdoll" or IsPropRagdoll ) then
option = bonemenu:AddOption("#tool.ragdollmover.freezebone", function()
if not IsValid(ent) then return end
net.Start("RAGDOLLMOVER")
net.WriteUInt(6, 5)
net.WriteEntity(ent)
net.WriteUInt(v.id, 10)
net.SendToServer()
NodeFunctions[16](ent, v.id)
end)
option:SetIcon("icon16/transmit_blue.png")
end
bonemenu:AddOption("#tool.ragdollmover.putgizmopos", function()
if not IsValid(ent) then return end
local bone = v.id
local pos = ent:GetBonePosition(bone)
if pos == ent:GetPos() then
local matrix = ent:GetBoneMatrix(bone)
pos = matrix:GetTranslation()
end
net.Start("RAGDOLLMOVER")
net.WriteUInt(15, 5)
net.WriteVector(pos)
net.SendToServer()
NodeFunctions[17](ent, v.id)
end)
local x = bonepanel:LocalToScreen(5, 0)
@ -3882,6 +3984,8 @@ local function RGMBuildConstrainedEnts(parent, children, entpanel)
conentnodes[ent]:SetIcon("icon16/brick_edit.png")
conentnodes[ent].Label:SetToolTip("#tool.ragdollmover.entlock")
ResetMode = false
net.Start("RAGDOLLMOVER")
net.WriteUInt(14, 5)
net.WriteUInt(2, 2)
@ -4467,17 +4571,30 @@ function TOOL:Think()
if plTable then
local op = self:GetOperation()
local nowpressed = input.IsMouseDown(MOUSE_LEFT)
local nowpressed = input.IsMouseDown(MOUSE_LEFT) or input.IsMouseDown(MOUSE_RIGHT)
local isright = input.IsMouseDown(MOUSE_RIGHT)
if nowpressed and not LastPressed and op == 2 then -- left click is a predicted function, so leftclick wouldn't work in singleplayer since i need data from client
local ent = plTable.Entity
if IsValid(ent) then
if self:GetStage() ~= 1 then
local selbones = rgm.AdvBoneSelectPick(ent, nodes)
if next(selbones) then
if #selbones == 1 then
if LockMode == false then
if LockMode == false and isright then
ResetMode = true
net.Start("RAGDOLLMOVER")
net.WriteUInt(14, 5)
net.WriteUInt(3, 2)
net.SendToServer()
plTable.SelectedBones = selbones
gui.EnableScreenClicker(true)
elseif LockMode == false then
net.Start("RAGDOLLMOVER")
net.WriteUInt(4, 5)
net.WriteEntity(ent)
@ -4520,12 +4637,14 @@ function TOOL:Think()
LockTo = { id = nil, ent = nil }
end
timer.Simple(0.1, function()
net.Start("RAGDOLLMOVER")
net.WriteUInt(14, 5)
net.WriteUInt(0, 2)
net.SendToServer()
end)
if not ResetMode then
timer.Simple(0.1, function()
net.Start("RAGDOLLMOVER")
net.WriteUInt(14, 5)
net.WriteUInt(0, 2)
net.SendToServer()
end)
end
else
plTable.SelectedBones = selbones
@ -4537,8 +4656,19 @@ function TOOL:Think()
gui.EnableScreenClicker(true)
end
end
else
if LockMode == false then
local doreset = true
if ResetMode then
ResetMode = false
local funid = rgm.AdvBoneSelectRadialPick()
NodeFunctions[funid](ent, plTable.SelectedBones[1])
if funid == 14 then doreset = false end
elseif LockMode == false and isright then
ResetMode = true
plTable.SelectedBones = { rgm.AdvBoneSelectRadialPick() }
elseif LockMode == false then
net.Start("RAGDOLLMOVER")
net.WriteUInt(4, 5)
net.WriteEntity(ent)
@ -4581,14 +4711,16 @@ function TOOL:Think()
LockTo = { id = nil, ent = nil }
end
timer.Simple(0.1, function()
net.Start("RAGDOLLMOVER")
net.WriteUInt(14, 5)
net.WriteUInt(0, 2)
net.SendToServer()
end)
if not ResetMode and doreset then
timer.Simple(0.1, function()
net.Start("RAGDOLLMOVER")
net.WriteUInt(14, 5)
net.WriteUInt(0, 2)
net.SendToServer()
end)
gui.EnableScreenClicker(false)
gui.EnableScreenClicker(false)
end
end
end
end
@ -4605,6 +4737,7 @@ hook.Add("KeyPress", "rgmSwitchSelectionMode", function(pl, key)
if key == IN_WALK then
if op ~= 2 and IsValid(RAGDOLLMOVER[pl].Entity) then opset = 2 end
ResetMode = false
net.Start("RAGDOLLMOVER")
net.WriteUInt(14, 5)
@ -4695,7 +4828,7 @@ function TOOL:DrawHUD()
if self:GetStage() == 0 then
rgm.AdvBoneSelectRender(ent, nodes)
else
rgm.AdvBoneSelectRadialRender(ent, plTable.SelectedBones, nodes)
rgm.AdvBoneSelectRadialRender(ent, plTable.SelectedBones, nodes, ResetMode)
end
elseif IsValid(tr.Entity) and EntityFilter(tr.Entity, self) and (not bone or aimedbone ~= bone or tr.Entity ~= ent) and not moving then
rgm.DrawBoneConnections(tr.Entity, aimedbone)

View File

@ -12,6 +12,7 @@ tool.ragdollmover.right_gizmomode=Set offset to coordinate center of the object
tool.ragdollmover.reload_gizmomode=Cancel set offset mode
tool.ragdollmover.left_advselect=Select any bone on the ragdoll!
tool.ragdollmover.right_advselect=Access additional bone features
tool.ragdollmover.info_advselect=Cancel selection mode by pressing walk key
tool.ragdollmover.gizmopanel=Gizmo
@ -27,7 +28,7 @@ tool.ragdollmover.gizmorelativerotate=Rotate relative to gizmo
tool.ragdollmover.xoffset=X Offset
tool.ragdollmover.yoffset=Y Offset
tool.ragdollmover.zoffset=Z Offset
tool.ragdollmover.resetoffset=Reset offset
tool.ragdollmover.resetoffset=Reset Gizmo offset
tool.ragdollmover.setoffset=Set offset with toolgun
tool.ragdollmover.ikpanel=IK Chains
@ -89,13 +90,15 @@ tool.ragdollmover.scalezero=Scale to Zero
tool.ragdollmover.bone=Bone
tool.ragdollmover.bonechildren=Bone + Children
tool.ragdollmover.lockall=Lock Pos/Rot
tool.ragdollmover.unlockall=Unlock Pos/Rot
tool.ragdollmover.lockpos=Lock Position
tool.ragdollmover.unlockpos=Unlock Position
tool.ragdollmover.lockang=Lock Rotation
tool.ragdollmover.unlockang=Unlock Rotation
tool.ragdollmover.lockscale=Lock Scale
tool.ragdollmover.unlockscale=Unlock Scale
tool.ragdollmover.lockbone=Lock to this Bone
tool.ragdollmover.lockbone=Lock Other Bone to this Bone
tool.ragdollmover.unlockbone=Unlock this Bone
tool.ragdollmover.freezebone=Freeze/Unfreeze this Bone

View File

@ -12,6 +12,7 @@ tool.ragdollmover.right_gizmomode=Задать сдвиг гизмо в коор
tool.ragdollmover.reload_gizmomode=Отменить режим задания сдвига гизмо
tool.ragdollmover.left_advselect=Выберите любую кость на регдолле!
tool.ragdollmover.left_advselect=Открыть меню доп. возможностей для кости
tool.ragdollmover.info_advselect=Отмените режим выбора нажатием на кнопку ходьбы
tool.ragdollmover.gizmopanel=Гизмо
@ -27,7 +28,7 @@ tool.ragdollmover.gizmorelativerotate=Вращение относительно
tool.ragdollmover.xoffset=Смещение по X
tool.ragdollmover.yoffset=Смещение по Y
tool.ragdollmover.zoffset=Смещение по Z
tool.ragdollmover.resetoffset=Сбросить смещение
tool.ragdollmover.resetoffset=Сбросить смещение Гизмо
tool.ragdollmover.setoffset=Установить смещение при помощи тулгана
tool.ragdollmover.ikpanel=Инверсивная кинематика
@ -77,25 +78,27 @@ tool.ragdollmover.physmovetip=Манипулирование нефизичес
tool.ragdollmover.scalerelativemove=Относительное масштабирование дочерних костей
tool.ragdollmover.resetmenu=Сброс
tool.ragdollmover.resetpos=Сброс позиции
tool.ragdollmover.resetrot=Сброс вращения
tool.ragdollmover.resetscale=Сброс масштабирования
tool.ragdollmover.reset=Сброс всего
tool.ragdollmover.resetposchildren=+Сброс позиции потомка
tool.ragdollmover.resetrotchildren=+Сброс вращения потомка
tool.ragdollmover.resetscalechildren=+Сброс масштабирования потомка
tool.ragdollmover.resetchildren=+Сброс потомка
tool.ragdollmover.resetpos=Позиции
tool.ragdollmover.resetrot=Вращения
tool.ragdollmover.resetscale=Масштабирования
tool.ragdollmover.reset=Всего
tool.ragdollmover.resetposchildren=+Позиций потомков
tool.ragdollmover.resetrotchildren=+Вращения потомков
tool.ragdollmover.resetscalechildren=+Масштабирования потомков
tool.ragdollmover.resetchildren=+Потомков
tool.ragdollmover.scalezero=Установить нулевой размер
tool.ragdollmover.bone=Кость
tool.ragdollmover.bonechildren=Кость + Потомок
tool.ragdollmover.bone=Кости
tool.ragdollmover.bonechildren=Кости + Потомков
tool.ragdollmover.lockall=Заблокировать позицию и поворот
tool.ragdollmover.unlockall=Разблокировать позицию и поворот
tool.ragdollmover.lockpos=Заблокировать позицию
tool.ragdollmover.unlockpos=Разблокировать позицию
tool.ragdollmover.lockang=Заблокировать поворот
tool.ragdollmover.unlockang=Разблокировать поворот
tool.ragdollmover.lockscale=Заблокировать масштабирование
tool.ragdollmover.unlockscale=Разблокировать масштабирование
tool.ragdollmover.lockbone=Привязать к этой кости
tool.ragdollmover.lockbone=Привязать другую кость к этой кости
tool.ragdollmover.unlockbone=Разблокировать кость
tool.ragdollmover.freezebone=Заморозить/разморозить кость