mirror of
https://github.com/Heretek-AI/GDevelop.git
synced 2026-07-23 02:25:52 -04:00
1055 lines
28 KiB
JavaScript
1055 lines
28 KiB
JavaScript
/**
|
|
* @memberof gdjs
|
|
* @class TweenRuntimeBehavior
|
|
* @param {gdjs.RuntimeScene} runtimeScene The runtime scene the behavior belongs to.
|
|
* @param {Object} behaviorData The data to initialize the behavior
|
|
* @param {gdjs.RuntimeObject} owner The runtime object the behavior belongs to.
|
|
*/
|
|
gdjs.TweenRuntimeBehavior = function(runtimeScene, behaviorData, owner) {
|
|
gdjs.RuntimeBehavior.call(this, runtimeScene, behaviorData, owner);
|
|
|
|
/** @type Object.<string, gdjs.TweenRuntimeBehavior.TweenInstance > */
|
|
this._tweens = {};
|
|
this._runtimeScene = runtimeScene;
|
|
this._isActive = true;
|
|
};
|
|
|
|
gdjs.TweenRuntimeBehavior.prototype = Object.create(
|
|
gdjs.RuntimeBehavior.prototype
|
|
);
|
|
|
|
gdjs.registerBehavior('Tween::TweenBehavior', gdjs.TweenRuntimeBehavior);
|
|
|
|
gdjs.TweenRuntimeBehavior.easings = [
|
|
'linear',
|
|
'easeInQuad',
|
|
'easeOutQuad',
|
|
'easeInOutQuad',
|
|
'easeInCubic',
|
|
'easeOutCubic',
|
|
'easeInOutCubic',
|
|
'easeInQuart',
|
|
'easeOutQuart',
|
|
'easeInOutQuart',
|
|
'easeInQuint',
|
|
'easeOutQuint',
|
|
'easeInOutQuint',
|
|
'easeInSine',
|
|
'easeOutSine',
|
|
'easeInOutSine',
|
|
'easeInExpo',
|
|
'easeOutExpo',
|
|
'easeInOutExpo',
|
|
'easeInCirc',
|
|
'easeOutCirc',
|
|
'easeInOutCirc',
|
|
'easeOutBounce',
|
|
'easeInBack',
|
|
'easeOutBack',
|
|
'easeInOutBack',
|
|
'elastic',
|
|
'swingFromTo',
|
|
'swingFrom',
|
|
'swingTo',
|
|
'bounce',
|
|
'bouncePast',
|
|
'easeFromTo',
|
|
'easeFrom',
|
|
'easeTo',
|
|
];
|
|
|
|
/**
|
|
* A tween being played in a behavior.
|
|
* @param {shifty.Tweenable} instance The Shifty tween that is played
|
|
* @param {boolean} hasFinished
|
|
* @param {number} startTime The time at which the tween starts
|
|
* @param {number} totalDuration The time of the whole tween
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.TweenInstance = function(
|
|
instance,
|
|
hasFinished,
|
|
startTime,
|
|
totalDuration
|
|
) {
|
|
this.instance = instance;
|
|
this.hasFinished = hasFinished;
|
|
this.startTime = startTime;
|
|
this.totalDuration = totalDuration;
|
|
this.resumeOnActivate = false;
|
|
};
|
|
|
|
gdjs.TweenRuntimeBehavior.prototype._addTween = function(
|
|
identifier,
|
|
instance,
|
|
startTime,
|
|
totalDuration
|
|
) {
|
|
this._tweens[identifier] = new gdjs.TweenRuntimeBehavior.TweenInstance(
|
|
instance,
|
|
false,
|
|
startTime,
|
|
totalDuration
|
|
);
|
|
};
|
|
|
|
gdjs.TweenRuntimeBehavior.prototype._getTween = function(identifier) {
|
|
return this._tweens[identifier];
|
|
};
|
|
|
|
gdjs.TweenRuntimeBehavior.prototype._tweenExists = function(identifier) {
|
|
return !!this._tweens[identifier];
|
|
};
|
|
|
|
gdjs.TweenRuntimeBehavior.prototype._tweenIsPlaying = function(identifier) {
|
|
return this._tweens[identifier].instance.isPlaying();
|
|
};
|
|
|
|
gdjs.TweenRuntimeBehavior.prototype._pauseTween = function(identifier) {
|
|
var tween = this._tweens[identifier];
|
|
|
|
// Pause the tween, and remove it from the scene of living tweens
|
|
// (the invariant is that scene only contains tweens being played).
|
|
tween.instance.pause();
|
|
if (this._runtimeScene.shiftyJsScene) {
|
|
this._runtimeScene.shiftyJsScene.remove(tween.instance);
|
|
}
|
|
};
|
|
|
|
gdjs.TweenRuntimeBehavior.prototype._resumeTween = function(identifier) {
|
|
var tween = this._tweens[identifier];
|
|
|
|
// Resume the tween, and add it back to the scene of living tweens
|
|
// (the invariant is that scene only contains tweens being played).
|
|
tween.instance.resume().catch(function() {
|
|
// Do nothing if the Promise is rejected. Rejection is used
|
|
// by Shifty.js to signal that the tween was not finished.
|
|
// We catch it to avoid an uncaught promise error, and to
|
|
// ensure that the content of the "then" is always applied:
|
|
});
|
|
if (this._runtimeScene.shiftyJsScene) {
|
|
this._runtimeScene.shiftyJsScene.add(tween.instance);
|
|
}
|
|
};
|
|
|
|
gdjs.TweenRuntimeBehavior.prototype._stopTween = function(
|
|
identifier,
|
|
jumpToDest
|
|
) {
|
|
return this._tweens[identifier].instance.stop(jumpToDest);
|
|
};
|
|
|
|
gdjs.TweenRuntimeBehavior.prototype._setTweenFinished = function(
|
|
identifier,
|
|
hasFinished
|
|
) {
|
|
this._tweens[identifier].hasFinished = hasFinished;
|
|
};
|
|
|
|
gdjs.TweenRuntimeBehavior.prototype._tweenHasFinished = function(identifier) {
|
|
return this._tweens[identifier].hasFinished;
|
|
};
|
|
|
|
gdjs.TweenRuntimeBehavior.prototype._removeObjectFromScene = function(
|
|
identifier
|
|
) {
|
|
this._removeTween(identifier);
|
|
return this.owner.deleteFromScene(this._runtimeScene);
|
|
};
|
|
|
|
gdjs.TweenRuntimeBehavior.prototype._removeTween = function(identifier) {
|
|
if (!this._tweens[identifier]) return;
|
|
|
|
this._tweens[identifier].instance.stop();
|
|
gdjs.TweenRuntimeBehavior.removeFromScene(
|
|
this._runtimeScene,
|
|
this._tweens[identifier].instance
|
|
);
|
|
delete this._tweens[identifier];
|
|
};
|
|
|
|
gdjs.TweenRuntimeBehavior.prototype._setupTweenEnding = function(
|
|
identifier,
|
|
destroyObjectWhenFinished
|
|
) {
|
|
var that = this;
|
|
if (destroyObjectWhenFinished) {
|
|
this._tweens[identifier].instance
|
|
.tween()
|
|
.catch(function() {
|
|
// Do nothing if the Promise is rejected. Rejection is used
|
|
// by Shifty.js to signal that the tween was not finished.
|
|
// We catch it to avoid an uncaught promise error, and to
|
|
// ensure that the content of the "then" is always applied:
|
|
})
|
|
.then(function() {
|
|
that._removeObjectFromScene(identifier);
|
|
})
|
|
.catch(function() {
|
|
// Do nothing if the Promise is rejected. Rejection is used
|
|
// by Shifty.js to signal that the tween was not finished.
|
|
// We catch it to avoid an uncaught promise error, and to
|
|
// ensure that the content of the "then" is always applied:
|
|
});
|
|
} else {
|
|
this._tweens[identifier].instance
|
|
.tween()
|
|
.catch(function() {
|
|
// Do nothing if the Promise is rejected. Rejection is used
|
|
// by Shifty.js to signal that the tween was not finished.
|
|
// We catch it to avoid an uncaught promise error, and to
|
|
// ensure that the content of the "then" is always applied:
|
|
})
|
|
.then(function() {
|
|
if (that._tweens[identifier]) {
|
|
that._tweens[identifier].hasFinished = true;
|
|
}
|
|
})
|
|
.catch(function() {
|
|
// Do nothing if the Promise is rejected. Rejection is used
|
|
// by Shifty.js to signal that the tween was not finished.
|
|
// We catch it to avoid an uncaught promise error, and to
|
|
// ensure that the content of the "then" is always applied:
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Add an object variable tween.
|
|
* @param {string} identifier Unique id to idenfify the tween
|
|
* @param {gdjs.Variable} variable The object variable to store the tweened value
|
|
* @param {number} fromValue Start value
|
|
* @param {number} toVaue End value
|
|
* @param {string} easingValue Type of easing
|
|
* @param {number} durationValue Duration in milliseconds
|
|
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.addVariableTween = function(
|
|
identifier,
|
|
variable,
|
|
fromValue,
|
|
toValue,
|
|
easingValue,
|
|
durationValue,
|
|
destroyObjectWhenFinished
|
|
) {
|
|
if (!this._isActive) return;
|
|
if (!!gdjs.TweenRuntimeBehavior.easings[easingValue]) return;
|
|
|
|
if (this._tweenExists(identifier)) {
|
|
this.removeTween(identifier);
|
|
}
|
|
|
|
var newTweenable = gdjs.TweenRuntimeBehavior.makeNewTweenable(
|
|
this._runtimeScene
|
|
);
|
|
|
|
newTweenable.setConfig({
|
|
from: {
|
|
value: fromValue,
|
|
},
|
|
to: {
|
|
value: toValue,
|
|
},
|
|
duration: durationValue,
|
|
easing: easingValue,
|
|
step: function step(state) {
|
|
variable.setNumber(state.value);
|
|
},
|
|
});
|
|
|
|
this._addTween(
|
|
identifier,
|
|
newTweenable,
|
|
this._runtimeScene.getTimeManager().getTimeFromStart(),
|
|
durationValue
|
|
);
|
|
|
|
this._setupTweenEnding(identifier, destroyObjectWhenFinished);
|
|
};
|
|
|
|
/**
|
|
* Add an object position tween.
|
|
* @param {string} identifier Unique id to idenfify the tween
|
|
* @param {number} toX The target X position
|
|
* @param {number} toY The target Y position
|
|
* @param {string} easingValue Type of easing
|
|
* @param {number} durationValue Duration in milliseconds
|
|
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.addObjectPositionTween = function(
|
|
identifier,
|
|
toX,
|
|
toY,
|
|
easingValue,
|
|
durationValue,
|
|
destroyObjectWhenFinished
|
|
) {
|
|
var that = this;
|
|
if (!this._isActive) return;
|
|
if (!!gdjs.TweenRuntimeBehavior.easings[easingValue]) return;
|
|
|
|
if (this._tweenExists(identifier)) {
|
|
this.removeTween(identifier);
|
|
}
|
|
|
|
var newTweenable = gdjs.TweenRuntimeBehavior.makeNewTweenable(
|
|
this._runtimeScene
|
|
);
|
|
newTweenable.setConfig({
|
|
from: {
|
|
x: this.owner.getX(),
|
|
y: this.owner.getY(),
|
|
},
|
|
to: {
|
|
x: toX,
|
|
y: toY,
|
|
},
|
|
duration: durationValue,
|
|
easing: easingValue,
|
|
step: function step(state) {
|
|
that.owner.setX(state.x);
|
|
that.owner.setY(state.y);
|
|
},
|
|
});
|
|
|
|
this._addTween(
|
|
identifier,
|
|
newTweenable,
|
|
this._runtimeScene.getTimeManager().getTimeFromStart(),
|
|
durationValue
|
|
);
|
|
|
|
this._setupTweenEnding(identifier, destroyObjectWhenFinished);
|
|
};
|
|
|
|
/**
|
|
* Add an object X position tween.
|
|
* @param {string} identifier Unique id to idenfify the tween
|
|
* @param {number} toX The target X position
|
|
* @param {string} easingValue Type of easing
|
|
* @param {number} durationValue Duration in milliseconds
|
|
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.addObjectPositionXTween = function(
|
|
identifier,
|
|
toX,
|
|
easingValue,
|
|
durationValue,
|
|
destroyObjectWhenFinished
|
|
) {
|
|
var that = this;
|
|
if (!this._isActive) return;
|
|
if (!!gdjs.TweenRuntimeBehavior.easings[easingValue]) return;
|
|
|
|
if (this._tweenExists(identifier)) {
|
|
this.removeTween(identifier);
|
|
}
|
|
|
|
var newTweenable = gdjs.TweenRuntimeBehavior.makeNewTweenable(
|
|
this._runtimeScene
|
|
);
|
|
newTweenable.setConfig({
|
|
from: {
|
|
x: this.owner.getX(),
|
|
},
|
|
to: {
|
|
x: toX,
|
|
},
|
|
duration: durationValue,
|
|
easing: easingValue,
|
|
step: function step(state) {
|
|
that.owner.setX(state.x);
|
|
},
|
|
});
|
|
|
|
this._addTween(
|
|
identifier,
|
|
newTweenable,
|
|
this._runtimeScene.getTimeManager().getTimeFromStart(),
|
|
durationValue
|
|
);
|
|
|
|
this._setupTweenEnding(identifier, destroyObjectWhenFinished);
|
|
};
|
|
|
|
/**
|
|
* Add an object Y position tween.
|
|
* @param {string} identifier Unique id to idenfify the tween
|
|
* @param {number} toY The target Y position
|
|
* @param {string} easingValue Type of easing
|
|
* @param {number} durationValue Duration in milliseconds
|
|
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.addObjectPositionYTween = function(
|
|
identifier,
|
|
toY,
|
|
easingValue,
|
|
durationValue,
|
|
destroyObjectWhenFinished
|
|
) {
|
|
var that = this;
|
|
if (!this._isActive) return;
|
|
if (!!gdjs.TweenRuntimeBehavior.easings[easingValue]) return;
|
|
|
|
if (this._tweenExists(identifier)) {
|
|
this.removeTween(identifier);
|
|
}
|
|
|
|
var newTweenable = gdjs.TweenRuntimeBehavior.makeNewTweenable(
|
|
this._runtimeScene
|
|
);
|
|
newTweenable.setConfig({
|
|
from: {
|
|
y: this.owner.getY(),
|
|
},
|
|
to: {
|
|
y: toY,
|
|
},
|
|
duration: durationValue,
|
|
easing: easingValue,
|
|
step: function step(state) {
|
|
that.owner.setY(state.y);
|
|
},
|
|
});
|
|
|
|
this._addTween(
|
|
identifier,
|
|
newTweenable,
|
|
this._runtimeScene.getTimeManager().getTimeFromStart(),
|
|
durationValue
|
|
);
|
|
|
|
this._setupTweenEnding(identifier, destroyObjectWhenFinished);
|
|
};
|
|
|
|
/**
|
|
* Add an object angle tween.
|
|
* @param {string} identifier Unique id to idenfify the tween
|
|
* @param {number} toAngle The target angle
|
|
* @param {string} easingValue Type of easing
|
|
* @param {number} durationValue Duration in milliseconds
|
|
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.addObjectAngleTween = function(
|
|
identifier,
|
|
toAngle,
|
|
easingValue,
|
|
durationValue,
|
|
destroyObjectWhenFinished
|
|
) {
|
|
var that = this;
|
|
if (!this._isActive) return;
|
|
if (!!gdjs.TweenRuntimeBehavior.easings[easingValue]) return;
|
|
|
|
if (this._tweenExists(identifier)) {
|
|
this.removeTween(identifier);
|
|
}
|
|
|
|
var newTweenable = gdjs.TweenRuntimeBehavior.makeNewTweenable(
|
|
this._runtimeScene
|
|
);
|
|
newTweenable.setConfig({
|
|
from: {
|
|
angle: this.owner.getAngle(),
|
|
},
|
|
to: {
|
|
angle: toAngle,
|
|
},
|
|
duration: durationValue,
|
|
easing: easingValue,
|
|
step: function step(state) {
|
|
that.owner.setAngle(state.angle);
|
|
},
|
|
});
|
|
|
|
this._addTween(
|
|
identifier,
|
|
newTweenable,
|
|
this._runtimeScene.getTimeManager().getTimeFromStart(),
|
|
durationValue
|
|
);
|
|
|
|
this._setupTweenEnding(identifier, destroyObjectWhenFinished);
|
|
};
|
|
|
|
/**
|
|
* Add an object scale tween.
|
|
* @param {string} identifier Unique id to idenfify the tween
|
|
* @param {number} toScaleX The target X-scale
|
|
* @param {number} toScaleY The target Y-scale
|
|
* @param {string} easingValue Type of easing
|
|
* @param {number} durationValue Duration in milliseconds
|
|
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.addObjectScaleTween = function(
|
|
identifier,
|
|
toScaleX,
|
|
toScaleY,
|
|
easingValue,
|
|
durationValue,
|
|
destroyObjectWhenFinished
|
|
) {
|
|
var that = this;
|
|
if (!this._isActive) return;
|
|
if (!this.owner.setScaleX || !this.owner.setScaleY) return;
|
|
|
|
if (!!gdjs.TweenRuntimeBehavior.easings[easingValue]) return;
|
|
|
|
if (this._tweenExists(identifier)) {
|
|
this.removeTween(identifier);
|
|
}
|
|
|
|
if (toScaleX < 0) toScaleX = 0;
|
|
if (toScaleY < 0) toScaleY = 0;
|
|
|
|
var newTweenable = gdjs.TweenRuntimeBehavior.makeNewTweenable(
|
|
this._runtimeScene
|
|
);
|
|
newTweenable.setConfig({
|
|
from: {
|
|
scaleX: this.owner.getScaleX(),
|
|
scaleY: this.owner.getScaleY(),
|
|
},
|
|
to: {
|
|
scaleX: toScaleX,
|
|
scaleY: toScaleY,
|
|
},
|
|
duration: durationValue,
|
|
easing: easingValue,
|
|
step: function step(state) {
|
|
that.owner.setScaleX(state.scaleX);
|
|
that.owner.setScaleY(state.scaleY);
|
|
},
|
|
});
|
|
|
|
this._addTween(
|
|
identifier,
|
|
newTweenable,
|
|
this._runtimeScene.getTimeManager().getTimeFromStart(),
|
|
durationValue
|
|
);
|
|
|
|
this._setupTweenEnding(identifier, destroyObjectWhenFinished);
|
|
};
|
|
|
|
/**
|
|
* Add an object X-scale tween.
|
|
* @param {string} identifier Unique id to idenfify the tween
|
|
* @param {number} toScaleX The target X-scale
|
|
* @param {string} easingValue Type of easing
|
|
* @param {number} durationValue Duration in milliseconds
|
|
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.addObjectScaleXTween = function(
|
|
identifier,
|
|
toScaleX,
|
|
easingValue,
|
|
durationValue,
|
|
destroyObjectWhenFinished
|
|
) {
|
|
var that = this;
|
|
if (!this._isActive) return;
|
|
if (!this.owner.setScaleX) return;
|
|
|
|
if (!!gdjs.TweenRuntimeBehavior.easings[easingValue]) return;
|
|
|
|
if (this._tweenExists(identifier)) {
|
|
this.removeTween(identifier);
|
|
}
|
|
|
|
var newTweenable = gdjs.TweenRuntimeBehavior.makeNewTweenable(
|
|
this._runtimeScene
|
|
);
|
|
newTweenable.setConfig({
|
|
from: {
|
|
scaleX: this.owner.getScaleX(),
|
|
},
|
|
to: {
|
|
scaleX: toScaleX,
|
|
},
|
|
duration: durationValue,
|
|
easing: easingValue,
|
|
step: function step(state) {
|
|
that.owner.setScaleX(state.scaleX);
|
|
},
|
|
});
|
|
|
|
this._addTween(
|
|
identifier,
|
|
newTweenable,
|
|
this._runtimeScene.getTimeManager().getTimeFromStart(),
|
|
durationValue
|
|
);
|
|
|
|
this._setupTweenEnding(identifier, destroyObjectWhenFinished);
|
|
};
|
|
|
|
/**
|
|
* Add an object scale y tween.
|
|
* @param {string} identifier Unique id to idenfify the tween
|
|
* @param {number} toScaleY The target Y-scale
|
|
* @param {string} easingValue Type of easing
|
|
* @param {number} durationValue Duration in milliseconds
|
|
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.addObjectScaleYTween = function(
|
|
identifier,
|
|
toScaleY,
|
|
easingValue,
|
|
durationValue,
|
|
destroyObjectWhenFinished
|
|
) {
|
|
var that = this;
|
|
if (!this._isActive) return;
|
|
if (!this.owner.setScaleY) return;
|
|
|
|
if (!!gdjs.TweenRuntimeBehavior.easings[easingValue]) return;
|
|
|
|
if (this._tweenExists(identifier)) {
|
|
this.removeTween(identifier);
|
|
}
|
|
|
|
var newTweenable = gdjs.TweenRuntimeBehavior.makeNewTweenable(
|
|
this._runtimeScene
|
|
);
|
|
newTweenable.setConfig({
|
|
from: {
|
|
scaleY: this.owner.getScaleY(),
|
|
},
|
|
to: {
|
|
scaleY: toScaleY,
|
|
},
|
|
duration: durationValue,
|
|
easing: easingValue,
|
|
step: function step(state) {
|
|
that.owner.setScaleY(state.scaleY);
|
|
},
|
|
});
|
|
|
|
this._addTween(
|
|
identifier,
|
|
newTweenable,
|
|
this._runtimeScene.getTimeManager().getTimeFromStart(),
|
|
durationValue
|
|
);
|
|
|
|
this._setupTweenEnding(identifier, destroyObjectWhenFinished);
|
|
};
|
|
|
|
/**
|
|
* Add an object opacity tween.
|
|
* @param {string} identifier Unique id to idenfify the tween
|
|
* @param {number} toOpacity The target opacity
|
|
* @param {string} easingValue Type of easing
|
|
* @param {number} durationValue Duration in milliseconds
|
|
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.addObjectOpacityTween = function(
|
|
identifier,
|
|
toOpacity,
|
|
easingValue,
|
|
durationValue,
|
|
destroyObjectWhenFinished
|
|
) {
|
|
var that = this;
|
|
if (!this._isActive) return;
|
|
if (!this.owner.getOpacity || !this.owner.setOpacity) return;
|
|
|
|
if (!!gdjs.TweenRuntimeBehavior.easings[easingValue]) return;
|
|
|
|
if (this._tweenExists(identifier)) {
|
|
this.removeTween(identifier);
|
|
}
|
|
|
|
var newTweenable = gdjs.TweenRuntimeBehavior.makeNewTweenable(
|
|
this._runtimeScene
|
|
);
|
|
newTweenable.setConfig({
|
|
from: {
|
|
opacity: this.owner.getOpacity(),
|
|
},
|
|
to: {
|
|
opacity: toOpacity,
|
|
},
|
|
duration: durationValue,
|
|
easing: easingValue,
|
|
step: function step(state) {
|
|
that.owner.setOpacity(state.opacity);
|
|
},
|
|
});
|
|
|
|
this._addTween(
|
|
identifier,
|
|
newTweenable,
|
|
this._runtimeScene.getTimeManager().getTimeFromStart(),
|
|
durationValue
|
|
);
|
|
|
|
this._setupTweenEnding(identifier, destroyObjectWhenFinished);
|
|
};
|
|
|
|
/**
|
|
* Add an object color tween.
|
|
* @param {string} identifier Unique id to idenfify the tween
|
|
* @param {string} toColor The target color
|
|
* @param {string} easingValue Type of easing
|
|
* @param {number} durationValue Duration in milliseconds
|
|
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.addObjectColorTween = function(
|
|
identifier,
|
|
toColor,
|
|
easingValue,
|
|
durationValue,
|
|
destroyObjectWhenFinished
|
|
) {
|
|
var that = this;
|
|
if (!this._isActive) return;
|
|
if (!this.owner.getColor || !this.owner.setColor) return;
|
|
if (
|
|
!toColor.match(
|
|
'^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]);){2}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$'
|
|
)
|
|
)
|
|
return;
|
|
|
|
if (!!gdjs.TweenRuntimeBehavior.easings[easingValue]) return;
|
|
|
|
if (this._tweenExists(identifier)) {
|
|
this.removeTween(identifier);
|
|
}
|
|
|
|
var fromColor = this.owner.getColor().split(';');
|
|
var toColor = toColor.split(';');
|
|
if (toColor.length !== 3) return;
|
|
|
|
var newTweenable = gdjs.TweenRuntimeBehavior.makeNewTweenable(
|
|
this._runtimeScene
|
|
);
|
|
newTweenable.setConfig({
|
|
from: {
|
|
red: fromColor[0],
|
|
green: fromColor[1],
|
|
blue: fromColor[2],
|
|
},
|
|
to: {
|
|
red: toColor[0],
|
|
green: toColor[1],
|
|
blue: toColor[2],
|
|
},
|
|
duration: durationValue,
|
|
easing: easingValue,
|
|
step: function step(state) {
|
|
that.owner.setColor(
|
|
Math.floor(state.red) +
|
|
';' +
|
|
Math.floor(state.green) +
|
|
';' +
|
|
Math.floor(state.blue)
|
|
);
|
|
},
|
|
});
|
|
|
|
this._addTween(
|
|
identifier,
|
|
newTweenable,
|
|
this._runtimeScene.getTimeManager().getTimeFromStart(),
|
|
durationValue
|
|
);
|
|
|
|
this._setupTweenEnding(identifier, destroyObjectWhenFinished);
|
|
};
|
|
|
|
/**
|
|
* Add a text object character size tween.
|
|
* @param {string} identifier Unique id to idenfify the tween
|
|
* @param {number} toSize The target character size
|
|
* @param {string} easingValue Type of easing
|
|
* @param {number} durationValue Duration in milliseconds
|
|
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.addTextObjectCharacterSizeTween = function(
|
|
identifier,
|
|
toSize,
|
|
easingValue,
|
|
durationValue,
|
|
destroyObjectWhenFinished
|
|
) {
|
|
var that = this;
|
|
if (!this._isActive) return;
|
|
if (!this.owner.setCharacterSize) return;
|
|
|
|
if (!!gdjs.TweenRuntimeBehavior.easings[easingValue]) return;
|
|
|
|
if (this._tweenExists(identifier)) {
|
|
this.removeTween(identifier);
|
|
}
|
|
|
|
var newTweenable = gdjs.TweenRuntimeBehavior.makeNewTweenable(
|
|
this._runtimeScene
|
|
);
|
|
newTweenable.setConfig({
|
|
from: {
|
|
size: this.owner.getCharacterSize(),
|
|
},
|
|
to: {
|
|
size: toSize,
|
|
},
|
|
duration: durationValue,
|
|
easing: easingValue,
|
|
step: function step(state) {
|
|
that.owner.setCharacterSize(state.size);
|
|
},
|
|
});
|
|
|
|
this._addTween(
|
|
identifier,
|
|
newTweenable,
|
|
this._runtimeScene.getTimeManager().getTimeFromStart(),
|
|
durationValue
|
|
);
|
|
|
|
this._setupTweenEnding(identifier, destroyObjectWhenFinished);
|
|
};
|
|
|
|
/**
|
|
* Tween is playing.
|
|
* @param {string} identifier Unique id to idenfify the tween
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.isPlaying = function(identifier) {
|
|
if (this._tweenExists(identifier) && this._tweenIsPlaying(identifier)) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Tween exists.
|
|
* @param {string} identifier Unique id to idenfify the tween
|
|
* @returns {boolean} The tween exists
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.exists = function(identifier) {
|
|
return this._tweenExists(identifier);
|
|
};
|
|
|
|
/**
|
|
* Tween has finished.
|
|
* @param {string} identifier Unique id to idenfify the tween
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.hasFinished = function(identifier) {
|
|
if (this._tweenExists(identifier)) {
|
|
return this._tweenHasFinished(identifier);
|
|
} else {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Pause a tween.
|
|
* @param {string} identifier Unique id to idenfify the tween
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.pauseTween = function(identifier) {
|
|
if (!this._isActive) return;
|
|
|
|
if (this._tweenExists(identifier) && this._tweenIsPlaying(identifier)) {
|
|
this._pauseTween(identifier);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Stop a tween.
|
|
* @param {string} identifier Unique id to idenfify the tween
|
|
* @param {boolean} jumpToDest Move to destination
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.stopTween = function(
|
|
identifier,
|
|
jumpToDest
|
|
) {
|
|
if (!this._isActive) return;
|
|
|
|
if (this._tweenExists(identifier) && this._tweenIsPlaying(identifier)) {
|
|
this._stopTween(identifier, jumpToDest);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Resume a tween.
|
|
* @param {string} identifier Unique id to idenfify the tween
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.resumeTween = function(identifier) {
|
|
if (!this._isActive) return;
|
|
|
|
if (this._tweenExists(identifier) && !this._tweenIsPlaying(identifier)) {
|
|
this._resumeTween(identifier);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Remove a tween.
|
|
* @param {string} identifierFirst Unique id to idenfify the tween
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.removeTween = function(identifier) {
|
|
this._removeTween(identifier);
|
|
};
|
|
|
|
/**
|
|
* Get tween progress.
|
|
* @param {string} identifier Unique id to idenfify the tween
|
|
* @returns {boolean} Progress of playing tween animation (between 0.0 and 1.0)
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.prototype.getProgress = function(identifier) {
|
|
var tween = this._getTween(identifier);
|
|
if (tween) {
|
|
var currentTime = this._runtimeScene.getTimeManager().getTimeFromStart();
|
|
if (currentTime >= tween.startTime + tween.totalDuration) return 1;
|
|
|
|
return (currentTime - tween.startTime) / tween.totalDuration;
|
|
} else {
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
gdjs.TweenRuntimeBehavior.prototype.onDeActivate = function() {
|
|
if (!this._isActive) return;
|
|
|
|
for (var key in this._tweens) {
|
|
if (this._tweens.hasOwnProperty(key)) {
|
|
var tween = this._tweens[key];
|
|
|
|
if (tween.instance.isPlaying()) {
|
|
tween.resumeOnActivate = true;
|
|
this._pauseTween(key);
|
|
}
|
|
}
|
|
}
|
|
this._isActive = false;
|
|
};
|
|
|
|
gdjs.TweenRuntimeBehavior.prototype.onActivate = function() {
|
|
if (this._isActive) return;
|
|
|
|
for (var key in this._tweens) {
|
|
if (this._tweens.hasOwnProperty(key)) {
|
|
var tween = this._tweens[key];
|
|
|
|
if (tween.resumeOnActivate) {
|
|
tween.resumeOnActivate = false;
|
|
this._resumeTween(key);
|
|
}
|
|
}
|
|
}
|
|
this._isActive = true;
|
|
};
|
|
|
|
/**
|
|
* Static function to create a Tweenable associated to a scene.
|
|
* Don't create manually shifty.Tweenable, otherwise they won't be
|
|
* associated to a scene (and will play even when scene is paused).
|
|
*
|
|
* @param {gdjs.RuntimeScene} runtimeScene
|
|
* @returns {shifty.Tweenable} The new tweenable
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.makeNewTweenable = function(runtimeScene) {
|
|
if (!runtimeScene.shiftyJsScene) {
|
|
runtimeScene.shiftyJsScene = new shifty.Scene();
|
|
}
|
|
|
|
var tweenable = new shifty.Tweenable();
|
|
runtimeScene.shiftyJsScene.add(tweenable);
|
|
return tweenable;
|
|
};
|
|
|
|
/**
|
|
* Static function to remove a Tweenable from a scene.
|
|
*
|
|
* @param {gdjs.RuntimeScene} runtimeScene
|
|
* @param {shifty.Tweenable} tweenable
|
|
*/
|
|
gdjs.TweenRuntimeBehavior.removeFromScene = function(runtimeScene, tweenable) {
|
|
if (!runtimeScene.shiftyJsScene) return;
|
|
|
|
runtimeScene.shiftyJsScene.remove(tweenable);
|
|
};
|
|
|
|
// Callbacks called to pause/resume Shifty scene when a gdjs.RuntimeScene
|
|
// is paused/resumed
|
|
|
|
/**
|
|
* Stop and "destroy" all the tweens when a scene is unloaded.
|
|
* @private
|
|
*/
|
|
gdjs.registerRuntimeSceneUnloadedCallback(function(runtimeScene) {
|
|
if (!runtimeScene.shiftyJsScene) return;
|
|
|
|
// Stop and explictly remove all tweenables to be sure to drop
|
|
// all references to the tweenables of the scene.
|
|
runtimeScene.shiftyJsScene.stop(false);
|
|
runtimeScene.shiftyJsScene.tweenables.forEach(
|
|
runtimeScene.shiftyJsScene.remove.bind(runtimeScene.shiftyJsScene)
|
|
);
|
|
});
|
|
|
|
/**
|
|
* When a scene is paused, pause all the tweens of this scene.
|
|
* @private
|
|
*/
|
|
gdjs.registerRuntimeScenePausedCallback(function(runtimeScene) {
|
|
if (!runtimeScene.shiftyJsScene) return;
|
|
|
|
runtimeScene.shiftyJsScene.pause();
|
|
});
|
|
|
|
/**
|
|
* When a scene is paused, resume all the tweens of this scene.
|
|
* @private
|
|
*/
|
|
gdjs.registerRuntimeSceneResumedCallback(function(runtimeScene) {
|
|
if (!runtimeScene.shiftyJsScene) return;
|
|
|
|
// It is important to set immediately the current Shifty time back to the
|
|
// time of the scene, as the call `resume` will process the tweens.
|
|
// (If not done, tweens will be resumed with the time of the previous
|
|
// scene, that could create weird result/make tweens act as if not paused).
|
|
gdjs.TweenRuntimeBehavior._currentTweenTime = runtimeScene
|
|
.getTimeManager()
|
|
.getTimeFromStart();
|
|
runtimeScene.shiftyJsScene.resume();
|
|
|
|
// Note that per the invariant of shiftyJsScene, shiftyJsScene will only
|
|
// contains tweenables that should be playing (so calling resume is safe).
|
|
});
|
|
|
|
// Handle Shifty.js updates (the time and the "tick" of tweens
|
|
// is controlled by the behavior)
|
|
gdjs.TweenRuntimeBehavior._tweensProcessed = false;
|
|
gdjs.TweenRuntimeBehavior._currentTweenTime = 0;
|
|
|
|
gdjs.TweenRuntimeBehavior.prototype.doStepPreEvents = function(runtimeScene) {
|
|
// Process tweens (once per frame).
|
|
if (!gdjs.TweenRuntimeBehavior._tweensProcessed) {
|
|
gdjs.TweenRuntimeBehavior._currentTweenTime = runtimeScene
|
|
.getTimeManager()
|
|
.getTimeFromStart();
|
|
shifty.processTweens();
|
|
gdjs.TweenRuntimeBehavior._tweensProcessed = true;
|
|
}
|
|
};
|
|
|
|
gdjs.TweenRuntimeBehavior.prototype.doStepPostEvents = function(runtimeScene) {
|
|
gdjs.TweenRuntimeBehavior._tweensProcessed = false;
|
|
};
|
|
|
|
// Set up Shifty.js so that the processing ("tick"/updates) is handled
|
|
// by the behavior (once per frame):
|
|
shifty.Tweenable.setScheduleFunction(function() {
|
|
/* Do nothing, we'll call processTweens manually. */
|
|
});
|
|
|
|
// Set up Shifty.js so that the time is handled by the behavior.
|
|
// It will be set to be the time of the current scene, and should be updated
|
|
// before any tween processing (processTweens, resume).
|
|
shifty.Tweenable.now = function() {
|
|
return gdjs.TweenRuntimeBehavior._currentTweenTime;
|
|
};
|