API Docs for:
Show:

File: ../src/components/poser.js

///@INFO: UNCOMMON
/**
* Transitions between different poses
* @class Poser
* @namespace LS.Components
* @constructor
* @param {String} object to configure from
*/


function Poser(o)
{
	this.enabled = true;

	this.only_internal_nodes = true;
	this.base_nodes = []; //uids and original transform of the nodes affected by the poser
	this.poses = {};

	if(o)
		this.configure(o);
}

/*
Poser.prototype.configure = function(o)
{
	
}
*/

Poser.icon = "mini-icon-clock.png";

Poser.prototype.onAddedToScene = function( scene )
{
	//LEvent.bind(scene,"update",this.onUpdate, this);
}

Poser.prototype.onRemovedFromScene = function(scene)
{
	//LEvent.unbind(scene,"update",this.onUpdate, this);
}

/*
Poser.prototype.onUpdate = function(e, dt)
{
	this.applyPose();

	var scene = this._root.scene;
	if(!scene)
		scene.requestFrame();
}
*/

Poser.prototype.addBaseNode = function( node )
{
	var node_data = null;
	var uid = node.uid;

	//check if it is already in this.base_nodes
	for(var i = 0; i < this.base_nodes.length; ++i)
	{
		var v = this.base_nodes[i];
		if( v.node_uid != uid )
			continue;
		node_data = v;
		break;
	}

	//add new base node
	if(!node_data)
	{
		node_data = { 
			node_uid: uid, 
			data: Array(10)
		};
		this.base_nodes.push( node_data );
	}
	
	if(node.transform)
		node_data.data = node.transform.data;
}

Poser.prototype.removeBaseNode = function( node )
{
	if(!node)
		return;

	if(node.constructor === String)
		node = this._root.scene.getNode( node );

	if(!node)
	{
		console.warn("Node not found");
		return;
	}

	//check if it is already in this.base_nodes
	for(var i = 0; i < this.base_nodes.length; ++i)
	{
		var v = this.base_nodes[i];
		if( v.node_uid != node.uid )
			continue;

		this.base_nodes.splice(i,1);
		this.purgePoses();
		break;
	}
}

Poser.prototype.setChildrenAsBaseNodes = function( include_root )
{
	this.base_nodes.length = 0;
	if(include_root)
		this.addBaseNode( this._root );
	var descendants = this._root.getDescendants();
	for(var i = 0; i < descendants.length; ++i)
		this.addBaseNode( descendants[i] );
}

Poser.prototype.addPose = function( name )
{
	var pose = {
		name: name,
		nodes: []
	};
	this.poses[ name ] = pose;
	this.updatePose( name );
}

Poser.prototype.removePose = function( name )
{
	delete this.poses[ name ];
}

//call to update the value of a pose using the current nodes transform
Poser.prototype.updatePose = function( name )
{
	if(!this._root || !this._root.scene) //could happen
		return;

	var pose = this.poses[ name ];
	if(!pose)
		return null;

	var scene = this._root.scene;
	pose.nodes.length = 0;

	for(var i = 0; i < this.base_nodes.length; ++i)
	{
		var base_node_info = this.base_nodes[i];
		var node = scene.getNode( base_node_info.node_uid );
		if(!node)
		{
			console.warn("addPose error, node not found in scene");
			continue; 
		}

		var pose_info = {
			node_uid: node.uid,
			data: toArray( node.transform.data )
		};

		pose.nodes.push( pose_info );
	}

	this.poses[ name ] = pose;
	return pose;
}

//call to apply one pose to the nodes
Poser.prototype.applyPose = function( name, weight )
{
	if(!name || !this._root || !this._root.scene)
		return;

	if(weight === undefined)
		weight = 1;
	if(weight <= 0)
		return;

	var pose = this.poses[ name ];
	if(!pose)
		return null;

	var scene = this._root.scene;
	if(!scene)
		return;

	for(var i = 0; i < pose.nodes.length; ++i)
	{
		var info = pose.nodes[i];
		var node = scene.getNode( info.node_uid );
		if(!node || !node.transform)
			continue; //maybe the node was removed from the scene

		//overwrite
		if(weight >= 1)		
		{
			node.transform.data = info.data;
			continue;
		}

		var a = node.transform;
		var b = info.data;

		//interpolate
		vec3.lerp( a._position, a._position, b, weight ); //position
		vec3.lerp( a._scaling, a._scaling, b.subarray(7,10), weight ); //scale
		quat.slerp( a._rotation, a._rotation, b.subarray(3,7), weight ); //rotation
		node.transform._must_update = true;
	}

	this.poses[ name ] = pose;
	return pose;
}

//remove nodes from poses if they are not used
Poser.prototype.purgePoses = function()
{
	//mark which nodes in the pose exist in the scene
	var valid_nodes = {};
	var scene = this._root.scene;
	if(!scene)
		return;

	for(var i = 0; i < this.base_nodes.length; ++i)
	{
		var info = this.base_nodes[i];
		var node = scene.getNode( info.node_uid );
		if(node)
			valid_nodes[ node.uid ] = true;
	}

	//now check all the poses, if they use a node that doesnt exist in the scene, remove it from the pose
	for(var i in this.poses)
	{
		var pose = this.poses[i];
		var pose_nodes = pose.nodes;

		for( var j = 0; j < pose_nodes.length; ++j )
		{
			var uid = pose_nodes[j].node_uid;
			if(valid_nodes[uid])
				continue;
			pose_nodes.splice(j,1);
			j--;
		}
	}
}



LS.registerComponent( Poser );