mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
237 lines
6.2 KiB
Lua
237 lines
6.2 KiB
Lua
--[[
|
|
| This file was obtained through the combined efforts
|
|
| of Madbluntz & Plymouth Antiquarian Society.
|
|
|
|
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
|
| Maloy, DrPepper10 @ RIP, Atle!
|
|
|
|
|
| Visit for more: https://plymouth.thetwilightzone.ru/
|
|
--]]
|
|
|
|
|
|
AddCSLuaFile()
|
|
|
|
properties.Add( "bone_manipulate", {
|
|
MenuLabel = "#edit_bones",
|
|
Order = 500,
|
|
MenuIcon = "icon16/vector.png",
|
|
|
|
Filter = function( self, ent, ply )
|
|
|
|
if ( !gamemode.Call( "CanProperty", ply, "bonemanipulate", ent ) ) then return false end
|
|
if ( IsValid( ent.AttachedEntity ) ) then ent = ent.AttachedEntity end -- If our ent has an attached entity, we want to use and modify its bones instead
|
|
|
|
local bonecount = ent:GetBoneCount()
|
|
if ( bonecount <= 1 ) then return false end
|
|
|
|
return ents.FindByClassAndParent( "widget_bones", ent ) == nil
|
|
|
|
end,
|
|
|
|
Action = function( self, ent )
|
|
|
|
if ( IsValid( ent.AttachedEntity ) ) then ent = ent.AttachedEntity end
|
|
|
|
self:MsgStart()
|
|
net.WriteEntity( ent )
|
|
self:MsgEnd()
|
|
|
|
end,
|
|
|
|
Receive = function( self, length, ply )
|
|
|
|
local ent = net.ReadEntity()
|
|
if ( !IsValid( ent ) ) then return end
|
|
if ( !properties.CanBeTargeted( ent, ply ) ) then return end
|
|
if ( !self:Filter( ent, ply ) ) then return end
|
|
|
|
ent.widget = ents.Create( "widget_bones" )
|
|
ent.widget:Setup( ent )
|
|
ent.widget:Spawn()
|
|
ent.widget.LastBonePress = 0
|
|
ent.widget.BonePressCount = 0
|
|
|
|
-- What happens when we click on a bone?
|
|
ent.widget.OnBoneClick = function( w, boneid, pl )
|
|
|
|
-- If we have an old axis, remove it
|
|
if ( IsValid( w.axis ) ) then w.axis:Remove() end
|
|
|
|
-- We clicked on the same bone
|
|
if ( w.LastBonePress == boneid ) then
|
|
w.BonePressCount = w.BonePressCount + 1
|
|
if ( w.BonePressCount >= 3 ) then w.BonePressCount = 0 end
|
|
-- We clicked on a new bone!
|
|
else
|
|
w.BonePressCount = 0
|
|
w.LastBonePress = boneid
|
|
end
|
|
|
|
local EntityCycle = { "widget_bonemanip_move", "widget_bonemanip_rotate", "widget_bonemanip_scale" }
|
|
|
|
w.axis = ents.Create( EntityCycle[ w.BonePressCount + 1 ] )
|
|
w.axis:Setup( ent, boneid, w.BonePressCount == 1 )
|
|
w.axis:Spawn()
|
|
w.axis:SetPriority( 0.5 )
|
|
w:DeleteOnRemove( w.axis )
|
|
|
|
end
|
|
end
|
|
|
|
} )
|
|
|
|
properties.Add( "bone_manipulate_end", {
|
|
MenuLabel = "#stop_editing_bones",
|
|
Order = 500,
|
|
MenuIcon = "icon16/vector_delete.png",
|
|
|
|
Filter = function( self, ent )
|
|
|
|
if ( IsValid( ent.AttachedEntity ) ) then ent = ent.AttachedEntity end -- If our ent has an attached entity, we want to use and modify its bones instead
|
|
|
|
return ents.FindByClassAndParent( "widget_bones", ent ) != nil
|
|
|
|
end,
|
|
|
|
Action = function( self, ent )
|
|
|
|
if ( IsValid( ent.AttachedEntity ) ) then ent = ent.AttachedEntity end
|
|
|
|
self:MsgStart()
|
|
net.WriteEntity( ent )
|
|
self:MsgEnd()
|
|
|
|
end,
|
|
|
|
Receive = function( self, length, ply )
|
|
|
|
local ent = net.ReadEntity()
|
|
if ( !IsValid( ent ) ) then return end
|
|
if ( !IsValid( ent.widget ) ) then return end
|
|
|
|
ent.widget:Remove()
|
|
|
|
end
|
|
} )
|
|
|
|
local widget_bonemanip_move = {
|
|
Base = "widget_axis",
|
|
|
|
OnArrowDragged = function( self, num, dist, pl, mv )
|
|
|
|
-- Prediction doesn't work properly yet.. because of the confusion with the bone moving, and the parenting, Agh.
|
|
if ( CLIENT ) then return end
|
|
|
|
local ent = self:GetParent()
|
|
if ( !IsValid( ent ) ) then return end
|
|
|
|
local bone = self:GetParentAttachment()
|
|
if ( bone <= 0 ) then return end
|
|
|
|
local v = Vector( 0, 0, 0 )
|
|
|
|
if ( num == 1 ) then v.x = dist end
|
|
if ( num == 2 ) then v.y = dist end
|
|
if ( num == 3 ) then v.z = dist end
|
|
|
|
ent:ManipulateBonePosition( bone, ent:GetManipulateBonePosition( bone ) + v )
|
|
|
|
end,
|
|
|
|
--
|
|
-- Although we use the position from our bone, we want to use the angles from the
|
|
-- parent bone - because that's the direction our bone goes
|
|
--
|
|
CalcAbsolutePosition = function( self, v, a )
|
|
|
|
local ent = self:GetParent()
|
|
if ( !IsValid( ent ) ) then return end
|
|
|
|
local bone = ent:GetBoneParent( self:GetParentAttachment() )
|
|
if ( bone <= 0 ) then return end
|
|
|
|
local _, ang = ent:GetBonePosition( bone )
|
|
local pos, _ = ent:GetBonePosition( self:GetParentAttachment() )
|
|
return pos, ang
|
|
|
|
end
|
|
}
|
|
|
|
scripted_ents.Register( widget_bonemanip_move, "widget_bonemanip_move" )
|
|
|
|
local widget_bonemanip_rotate = {
|
|
Base = "widget_axis",
|
|
|
|
OnArrowDragged = function( self, num, dist, pl, mv )
|
|
|
|
-- Prediction doesn't work properly yet.. because of the confusion with the bone moving, and the parenting, Agh.
|
|
if ( CLIENT ) then return end
|
|
|
|
local ent = self:GetParent()
|
|
if ( !IsValid( ent ) ) then return end
|
|
|
|
local bone = self:GetParentAttachment()
|
|
if ( bone <= 0 ) then return end
|
|
|
|
local v = Angle( 0, 0, 0 )
|
|
|
|
if ( num == 2 ) then v.x = dist end
|
|
if ( num == 3 ) then v.y = dist end
|
|
if ( num == 1 ) then v.z = dist end
|
|
|
|
ent:ManipulateBoneAngles( bone, ent:GetManipulateBoneAngles( bone ) + v )
|
|
|
|
end
|
|
}
|
|
scripted_ents.Register( widget_bonemanip_rotate, "widget_bonemanip_rotate" )
|
|
|
|
local widget_bonemanip_scale = {
|
|
Base = "widget_axis",
|
|
IsScaleArrow = true,
|
|
|
|
OnArrowDragged = function( self, num, dist, pl, mv )
|
|
|
|
-- Prediction doesn't work properly yet.. because of the confusion with the bone moving, and the parenting, Agh.
|
|
if ( CLIENT ) then return end
|
|
|
|
local ent = self:GetParent()
|
|
if ( !IsValid( ent ) ) then return end
|
|
|
|
local bone = self:GetParentAttachment()
|
|
if ( bone <= 0 ) then return end
|
|
|
|
local v = Vector( 0, 0, 0 )
|
|
|
|
if ( num == 1 ) then v.x = dist end
|
|
if ( num == 2 ) then v.y = dist end
|
|
if ( num == 3 ) then v.z = dist end
|
|
|
|
ent:ManipulateBoneScale( bone, ent:GetManipulateBoneScale( bone ) + v * 0.1 )
|
|
ent:ManipulateBoneScale( ent:GetBoneParent( bone ), ent:GetManipulateBoneScale( ent:GetBoneParent( bone ) ) + v )
|
|
|
|
end,
|
|
|
|
--
|
|
-- Although we use the position from our bone, we want to use the angles from the
|
|
-- parent bone - because that's the direction our bone goes
|
|
--
|
|
CalcAbsolutePosition = function( self, v, a )
|
|
|
|
local ent = self:GetParent()
|
|
if ( !IsValid( ent ) ) then return end
|
|
|
|
local bone = self:GetParentAttachment()
|
|
if ( bone <= 0 ) then return end
|
|
|
|
local pbone = ent:GetBoneParent( bone )
|
|
if ( pbone <= 0 ) then return end
|
|
|
|
local pos, ang = ent:GetBonePosition( bone )
|
|
local pos2, _ = ent:GetBonePosition( pbone )
|
|
|
|
return pos + ( pos2 - pos ) * 0.5, ang
|
|
|
|
end
|
|
}
|
|
scripted_ents.Register( widget_bonemanip_scale, "widget_bonemanip_scale" )
|