
TOOL.Category		= "Poser"
TOOL.Name			= "#Face Poser"
TOOL.Command		= nil
TOOL.ConfigName		= nil

local EYE_END = 11
local gLastFacePoseEntity = NULL
TOOL.FaceTimer = 0

/*---------------------------------------------------------
---------------------------------------------------------*/
function TOOL:FacePoserEntity()
	return self:GetWeapon():GetNetworkedEntity( 1 )
end

/*---------------------------------------------------------
---------------------------------------------------------*/
function TOOL:SetFacePoserEntity( ent )
	return self:GetWeapon():SetNetworkedEntity( 1, ent )
end

/*---------------------------------------------------------
---------------------------------------------------------*/
function TOOL:Think()

	// If we're on the client just make sure the context menu is up to date
	if (CLIENT) then
	
		if ( self:FacePoserEntity() == gLastFacePoseEntity ) then return end
		gLastFacePoseEntity = self:FacePoserEntity();
		self:UpdateFaceControlPanel();
	
	return end
	
	// On the server we continually set the flex weights
	
	if (self.FaceTimer > CurTime() ) then return end
	if (self:FacePoserEntity() == NULL) then return end
	
	local ent = self:FacePoserEntity()
	
	local FlexNum = ent:GetFlexNum() - 1
	if (FlexNum <= 0) then return end
	
	for i=0, FlexNum do
	
		local num = self:GetClientNumber( "flex"..i )
		ent:SetFlexWeight( i, num )
		
	end
	
	local num = self:GetClientNumber( "scale" )
	ent:SetFlexScale( num )
	
end



	/*---------------------------------------------------------
		Alt fire sucks the facepose from the model's face
	---------------------------------------------------------*/
	function TOOL:RightClick( trace )
	
		if ( SERVER ) then
			self:SetFacePoserEntity( trace.Entity )
		end
	
		if ( trace.Entity == NULL ) then return end
		if ( trace.Entity:GetFlexNum() == 0 ) then return end
		
		local ent = trace.Entity
		local FlexNum = ent:GetFlexNum()
		
		if ( SERVER ) then
				
			// This stops it applying the current sliders to the newly selected face.. 
			// it should probably be linked to the ping somehow.. but 1 second seems pretty safe
			self.FaceTimer = CurTime() + 1	
			
			// In multiplayer the rest is only done on the client to save bandwidth.
			// We can't do that in single player because these functions don't get called on the client
			if ( !SinglePlayer() ) then return end		
			
		end
		
		for i=0, FlexNum-1 do
		
			local Weight = '0.0'
			
			if (i <= FlexNum - EYE_END) then
				Weight = ent:GetFlexWeight( i )
			end
			
			self:GetOwner():ConCommand( "faceposer_flex"..i.." " .. Weight )
			
		end
		
		self:GetOwner():ConCommand( "faceposer_scale "..ent:GetFlexScale() )
			
	end
	
if ( SERVER ) then

	/*---------------------------------------------------------
		Just select as the current object
		- Current settings will get applied
	---------------------------------------------------------*/
	function TOOL:LeftClick( trace )
	
		if ( trace.Entity == NULL ) then return end
		if ( trace.Entity:GetFlexNum() == 0 ) then return end
		
		self.FaceTimer = 0;
		self:SetFacePoserEntity( trace.Entity )
		
	end
	
	function CC_Face_Randomize( pl, command, arguments )
	
		for i=0, 64 do
			local num = math.Rand( 0, 1 )
			pl:ConCommand( "faceposer_flex"..i.." " .. string.format( "%.3f", num ) )
		end

	end
	
	concommand.Add( "faceposer_randomize", CC_Face_Randomize )
	
end

if ( CLIENT ) then

	for i=0,64 do
		TOOL.ClientConVar[ "flex"..i ] = "0.5"
	end
	
	TOOL.ClientConVar[ "scale" ] = "1.0"
	
	/*---------------------------------------------------------
		Updates the spawn menu panel
	---------------------------------------------------------*/
	function TOOL:UpdateFaceControlPanel( index )
	
		local ent = self:FacePoserEntity()
		if (ent == NULL) then return end
		
		local FlexNum = ent:GetFlexNum()

		// We've selected a new entity - rebuild the controls list
		local CPanel = GetControlPanel( "faceposer" )
		if ( !CPanel ) then Msg("Couldn't find faceposer panel!\n") return end
		
		CPanel:ClearControls()
		CPanel:AddHeader()
		CPanel:AddDefaultControls()
		

		local params = {}
			params.Label = "#FacePoser_scale"
			params.Type = "Float"
			params.Min = "-1"
			params.Max = "20"
			params.Command = "faceposer_scale"
			
			CPanel:AddControl( "Slider", params )
			
		local params = {}
			params.Text = "#FacePoser_randomize"
			params.Command = "faceposer_randomize"
			
			CPanel:AddControl( "Button", params )
		
		for i=0, FlexNum-EYE_END do
				
			local params = {}
			params.Label = "#" .. ent:GetFlexName( i ) // # so we can language them up - is it worth $10 yet?
			params.Type = "Float"
			params.Min, params.Max = ent:GetFlexBounds( i )
			params.Command = "faceposer_flex"..i
			
			CPanel:AddControl( "Slider", params )
			
		end
	
	end
	
	
	
	local FacePoser	= surface.GetTextureID( "gui/faceposer_indicator" )
	
	/*---------------------------------------------------------
	   Draw a box indicating the face we have selected
	---------------------------------------------------------*/
	function TOOL:DrawHUD()

		local selected = self:FacePoserEntity()
		
		if ( selected == NULL ) then return end
		if ( selected:IsWorld() ) then return end
		
		local vEyePos = selected:EyePos()
		
		local eyeattachment = selected:LookupAttachment( "eyes" )
		if (eyeattachment == 0) then return end
		
		local attachment = selected:GetAttachment( eyeattachment )
		local scrpos = attachment.Pos:ToScreen()
		if (!scrpos.visible) then return end
		
		// Work out the side distance to give a rough headsize box..
		local player_eyes = LocalPlayer():EyeAngles()
		local side = (attachment.Pos + player_eyes:Right() * 20):ToScreen()
		local size = math.abs( side.x - scrpos.x )
		
		surface.SetDrawColor( 255, 255, 255, 255 )
		surface.SetTexture( FacePoser )
		surface.DrawTexturedRect( scrpos.x-size, scrpos.y-size, size*2, size*2 )

	end
	
end
