:NAME camera_animation

:GLOBAL c_node*	head_node
:GLOBAL c_node*	elbow_node
:GLOBAL c_node*	base_node

:PARAM s_function1d time_to_crease_angle

:VAR boolean target_aquired
:VAR float32 target_aquired_time

-- --------------- globals ---------------

k_crease_angle= -1	-- in radians


-- --------------- initialization ---------------

function global_initialize(g)
	g.head_node= nil
	g.elbow_node= nil
	g.base_node= nil
end

function param_initialize(p)

end

function var_initialize(v)
	v.target_aquired= false
	v.target_aquired_time= 0
end


-- --------------- component ---------------

function attach(object)

	local definition= object.definition
	local model= definition.model
	
	if (model) then
		local skeleton= model.skeleton
		if (skeleton) then
			global.head_node= skeleton.node_get_by_name("head");
			global.elbow_node= skeleton.node_get_by_name("elbow");
			global.base_node= skeleton.node_get_by_name("base");
			
			-- set it to base position
			local head_state= object.node_state_from_node(global.head_node)
			local elbow_state= object.node_state_from_node(global.elbow_node)
			local base_state= object.node_state_from_node(global.base_node)
			
			base_state.rotation_set(k_crease_angle)
			elbow_state.rotation_set(-2*k_crease_angle)
			head_state.rotation_set(k_crease_angle)
			
			object.mark_all_nodes_dirty()
		
		end
	end
end

function update(object)

	local aim= object.aim_get()
	if (aim) then
		if (global.head_node) then
			
			local target_angle= aim.angle
			local object_angle= object.transform.rotation
			local angle_delta= target_angle - object_angle
			
			
			-- first determine crease angle
			
			local perception= object.perception_get()
			local target= perception.target_cache
			local crease_angle= 0
			local time= world_state_get().time.time
			if (target and target.is_visible()) then
				if (not var.target_aquired) then
					var.target_aquired= true
					var.target_aquired_time= time
				end
			else
				if (var.target_aquired) then
					if ((time - var.target_aquired_time) > param.time_to_crease_angle.input_range_max) then
						var.target_aquired= false
					end
				end
			end
			
			if (var.target_aquired) then
				crease_angle= param.time_to_crease_angle.evaluate(time - var.target_aquired_time)
			else
				crease_angle= param.time_to_crease_angle.evaluate(0)
			end
			
			-- then modify joints
						
			if (angle_delta > math.pi) then
				angle_delta = angle_delta - 2*(math.pi)			
			elseif (angle_delta < -math.pi) then
				angle_delta = angle_delta + 2*(math.pi)
			end
			
			-- split angle delta betwen the base and the head
			
			local base_state= object.node_state_from_node(global.base_node)
			if (base_state) then
				local base_rotation= angle_delta * 0.33
				base_state.rotation_set(crease_angle + base_rotation)
				angle_delta = angle_delta - base_rotation						
			end
			
			local elbow_state= object.node_state_from_node(global.elbow_node)
			if (elbow_state) then
				elbow_state.rotation_set(-2*crease_angle)
			end

			local head_state= object.node_state_from_node(global.head_node)
			if (head_state) then
				head_state.rotation_set(crease_angle + angle_delta)
			end
			
			object.mark_all_nodes_dirty()			
		end
	end
end

component_register(attach, update, nil, nil)
