r3-legacy/src/game-lib-system-animation.js

278 lines
11 KiB
JavaScript
Raw Normal View History

2017-09-05 05:22:52 +02:00
/**
* System takes care of updating all the entities (based on their component data)
* @param apiSystem GameLib.API.System
* @constructor
*/
GameLib.System.Animation = function(
apiSystem
) {
GameLib.System.call(
this,
apiSystem
);
};
GameLib.System.Animation.prototype = Object.create(GameLib.System.prototype);
GameLib.System.Animation.prototype.constructor = GameLib.System.Animation;
GameLib.System.Animation.prototype.start = function() {
GameLib.System.prototype.start.call(this);
this.animationEntities = GameLib.EntityManager.Instance.findEntities([GameLib.D3.Animation]);
2017-09-14 10:50:09 +02:00
this.animationEntities.map(
function(animationEntity) {
/**
* Get all meshes and all animation components
*/
var meshComponents = animationEntity.getComponents(GameLib.D3.Mesh);
var animationComponents = animationEntity.getComponents(GameLib.D3.Animation);
2017-09-14 10:50:09 +02:00
animationComponents.map(function(animation){
2017-09-05 05:22:52 +02:00
meshComponents.map(function(mesh){
2017-09-14 10:50:09 +02:00
if (animation.rotationSpeed) {
2017-09-14 10:50:09 +02:00
/**
* Back up the current property descriptor
*/
mesh.animationObject = {
backupAngleDescriptor : Object.getOwnPropertyDescriptor(mesh.quaternion, 'angle'),
targetAngle : mesh.quaternion.angle,
angleIncrement : true,
intermediateAngle : mesh.quaternion.angle,
subscription : null
};
2017-09-14 10:50:09 +02:00
var getIntermediateAngle = function() {
return mesh.animationObject.intermediateAngle;
};
2017-09-14 10:50:09 +02:00
var animateRotation = function(value) {
2017-09-14 10:50:09 +02:00
mesh.animationObject.intermediateAngle = value;
var done = false;
if (mesh.animationObject.angleIncrement) {
/**
* We are rotating upwards
*/
if (value >= mesh.animationObject.targetAngle) {
/**
* We need to stop
*/
done = true;
}
} else {
/**
* We are rotating downwards
*/
if (value <= mesh.animationObject.targetAngle) {
/**
* We need to stop
*/
done = true;
}
2017-09-14 10:50:09 +02:00
}
if (done) {
2017-09-14 10:50:09 +02:00
/**
* Stop subscribing to before render events
*/
mesh.animationObject.subscription.remove();
2017-09-14 10:50:09 +02:00
/**
*
* @type {null}
*/
mesh.animationObject.subscription = null;
2017-09-14 10:50:09 +02:00
/**
* Start checking again for animation requests
*/
Object.defineProperty(
mesh.quaternion,
'angle',
{
'get' : getIntermediateAngle,
'set' : animationCheck,
'configurable' : true
}
);
/**
* Set our target angle value
*/
mesh.animationObject.intermediateAngle = mesh.animationObject.targetAngle;
/**
* Update our actual angle
*/
mesh.quaternion.angle = mesh.animationObject.targetAngle;
/**
* Update our instance
*/
mesh.updateInstance();
/**
* Now we say that our intermediate angle is zero, because we will apply our rotation
* and this will prevent us from re-registering a new 'animationRender' event
*/
mesh.animationObject.intermediateAngle = 0;
/**
* Apply our position, rotation and scale to the mesh
*/
mesh.applyPositionRotationScale();
}
};
var animationCheck = function(value) {
/**
* Check if we have work to do
*/
if (mesh.animationObject.intermediateAngle === value) {
/**
* Nothing to do
*/
return;
} else if (mesh.animationObject.intermediateAngle > value) {
/**
* We will rotate towards by decrementing
*/
mesh.animationObject.angleIncrement = false;
} else {
/**
* We will rotate towards by incrementing
*/
mesh.animationObject.angleIncrement = true;
}
/**
* We say what our target angle is - when we reach our target angle, we want
* to stop our animation
*/
mesh.animationObject.targetAngle = value;
/**
* Now override the setter again
*/
Object.defineProperty(
mesh.quaternion,
'angle',
{
'get' : getIntermediateAngle,
'set' : animateRotation,
'configurable' : true
}
);
/**
* Now we subscribe to 'before render' events, and slowly increment the value
* @type {{fn, remove}}
*/
mesh.animationObject.subscription = GameLib.Event.Subscribe(
GameLib.Event.BEFORE_RENDER,
function(data) {
var increment = Math.abs(animation.rotationSpeed);
if (mesh.angleIncrement) {
increment *= -1;
}
mesh.quaternion.angle = (data.delta * increment) + mesh.animationObject.intermediateAngle;
var backup = mesh.updateRotationFromAxisAngle;
mesh.updateRotationFromAxisAngle = true;
mesh.updateInstance();
mesh.updateRotationFromAxisAngle = backup;
}
);
};
/**
* Override the property descriptor - to slowly increment the angle, but report back its
* target angle as its actual angle.
*/
Object.defineProperty(
mesh.quaternion,
'angle',
{
'get' : getIntermediateAngle,
'set' : animationCheck,
'configurable' : true
}
);
}
});
});
}
);
};
2017-09-05 05:22:52 +02:00
/**
* Stop Animation System
*/
2017-09-05 05:22:52 +02:00
GameLib.System.Animation.prototype.stop = function() {
GameLib.System.prototype.stop.call(this);
this.animationEntities = GameLib.EntityManager.Instance.findEntities([GameLib.D3.Animation]);
this.animationEntities.map(
function(animationEntity) {
/**
* Get all meshes and all animation components
*/
var meshComponents = animationEntity.getComponents(GameLib.D3.Mesh);
var animationComponents = animationEntity.getComponents(GameLib.D3.Animation);
animationComponents.map(
function (animation) {
meshComponents.map(
function (mesh) {
if (animation.rotationSpeed) {
if (mesh.animationObject) {
if (mesh.animationObject.backupAngleDescriptor) {
Object.defineProperty(
mesh.quaternion,
'angle',
mesh.animationObject.backupAngleDescriptor
)
}
if (mesh.animationObject.targetAngle) {
mesh.quaternion.angle = mesh.animationObject.targetAngle;
}
if (mesh.animationObject.subscription) {
mesh.animationObject.subscription.remove();
}
delete mesh.animationObject;
}
}
}
)
}
)
}
);
2017-09-05 05:22:52 +02:00
};