mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 05:43:46 +03:00
Upload
This commit is contained in:
236
lua/autorun/properties/bone_manipulate.lua
Normal file
236
lua/autorun/properties/bone_manipulate.lua
Normal file
@@ -0,0 +1,236 @@
|
||||
--[[
|
||||
| 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" )
|
||||
Reference in New Issue
Block a user