

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



		local bonecount = ent:GetBoneCount()

		if ( !bonecount || bonecount <= 1 ) then return false end

		return ents.FindByClassAndParent( "widget_bones", ent ) == nil

		

	end,



	Action = function( self, ent )

	

		self:MsgStart()

			net.WriteEntity( ent )

		self:MsgEnd()

		

	end,



	Receive = function( self, length, player )



		local ent = net.ReadEntity()

		if ( !IsValid( ent ) ) then return end

		if ( !self:Filter( ent, player ) ) 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, ply )



			-- 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 ) 



		return ents.FindByClassAndParent( "widget_bones", ent ) != nil



	end,



	Action = function( self, ent )



		self:MsgStart()

			net.WriteEntity( ent )

		self:MsgEnd()

		

	end,



	Receive = function( self, length, player )



		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 || bone <= 0 ) then return end

		local pos, ang = ent:GetBonePosition( bone )



		return v, 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",

	

	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 || bone <= 0 ) then return end

		local pbone = ent:GetBoneParent(bone)

		if ( !pbone || pbone <= 0 ) then return end

		local pos, ang = ent:GetBonePosition( pbone )

		

		v = v + (pos-v)*0.5;



		return v, ang

	

	end

}

scripted_ents.Register( widget_bonemanip_scale, "widget_bonemanip_scale" )

