Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions spriter/definitions/SpatialInfo.hx
Original file line number Diff line number Diff line change
Expand Up @@ -61,24 +61,35 @@ class SpatialInfo implements ISpriterPooled
return this;
}

/**
* Convenient method to set both x and y in one line.
* @param x
* @param y
* @return
*/
public function setPos(x:Float = 0, y:Float = 0):SpatialInfo
{
this.x = x;
this.y = y;
return this;
}

/**
* Convenient method to set both scaleX and scaleY.
* @param scale
* @return
*/
public function setScale(scale:Float):SpatialInfo
{
this.scaleX = scale;
this.scaleY = scale;
return this;
}
/**
*
* Get SpatialInfo modified by parent.
* @param parentInfo
* @param out if null, this method will override this SpatialInfo
* @return
* @return SpatialInfo modified with parent values. Use out if specified.
*/
public function unmapFromParent(parentInfo:SpatialInfo, out:SpatialInfo = null):SpatialInfo
{
Expand Down Expand Up @@ -115,10 +126,18 @@ class SpatialInfo implements ISpriterPooled
return out;
}

/**
* Create a new SpatialInfo with values from this.
* @return new SpatialInfo
*/
inline public function copy():SpatialInfo
{
return new SpatialInfo(x, y, angle, scaleX, scaleY, a, spin);
}
/**
* Copy SpatialInfo from other values
* @param out spatialInfo to copy
*/
public function clone(out:SpatialInfo):Void
{
out.init(x, y, angle, scaleX, scaleY, a, spin);//initializing the out object with the values of this object
Expand Down
38 changes: 33 additions & 5 deletions spriter/definitions/SpriterAnimation.hx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class SpriterAnimation
public var soundlines:Array<Metaline<SoundlineKey>>;
#end

var _triggerTime:Int;



public function new(xml:Access)
Expand Down Expand Up @@ -121,10 +123,13 @@ class SpriterAnimation
}
#end
}

_triggerTime = -1;
}
/**
*
* @param newTime Use a time between [0,length]
* @param newTime Use a time between [0,length[
* @param elapsedTime elapsed time
* @param library library to compute and draw the final graphics
* @param root IScml to use some features
* @param currentEntity to use some features
Expand Down Expand Up @@ -231,6 +236,8 @@ class SpriterAnimation
objectKeys[k].paint();
}*/

var triggerResult = false;

//following lines not in scml references yet
#if !SPRITER_NO_TAG
if (taglines != null)
Expand All @@ -239,6 +246,7 @@ class SpriterAnimation
{
if (isTriggered(tag.time, mainKey.time, newTime, elapsedTime))
{
triggerResult = true;
spriter.clearTag();
for (i in 0...tag.t.length)
{
Expand All @@ -258,6 +266,7 @@ class SpriterAnimation
{
if (isTriggered(keyVar.time, mainKey.time, newTime, elapsedTime))
{
triggerResult = true;
spriter.updateVar(_var.id, keyVar.value);
}
}
Expand All @@ -273,6 +282,7 @@ class SpriterAnimation
{
if (isTriggered(soundKey.time, mainKey.time, newTime, elapsedTime))
{
triggerResult = true;
spriter.dispatchSound(soundKey.folder, soundKey.file);
}
}
Expand All @@ -288,24 +298,42 @@ class SpriterAnimation
{
if (isTriggered(eventKey.time, mainKey.time, newTime, elapsedTime))
{
triggerResult = true;
spriter.dispatchEvent(event.name);
}
}
}
}
#end

//we store the trigger time only when everything has been tested (if not we'll only trigger first event...)
if(triggerResult)
_triggerTime = mainKey.time;
else if (_triggerTime != mainKey.time)
_triggerTime = -1;//we reset if we changed the mainkey because it'll allow to trigger when play back and forth

//clean up
spatialInfo = null;
}

function isTriggered(triggerTime:Int, keyTime:Int, newTime:Int, elapsedTime:Int):Bool
/**
* Check if an event, variable or sound is triggered.
* By checking if triggerTime and keyTime have same value;
* And then if triggerTime has been reached for the first time (in the current loop)
* @param triggerTime
* @param keyTime
* @param newTime
* @param elapsedTime
* @return Bool
*/
function isTriggered(eventTime:Int, keyTime:Int, newTime:Int, elapsedTime:Int):Bool
{
if (triggerTime == keyTime)
if (eventTime == keyTime)
{
if (newTime - elapsedTime < keyTime)
if (newTime - elapsedTime <= keyTime && _triggerTime != keyTime)
{
return true;
}else if (triggerTime == 0 && newTime == elapsedTime) { //allow to trigger the first frame
}else if (eventTime == 0 && newTime == elapsedTime) { //allow to trigger the first frame
return true;
}else {
return false;
Expand Down
155 changes: 130 additions & 25 deletions spriter/engine/Spriter.hx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import spriter.definitions.SpriterEntity;
import spriter.definitions.SpriterFile;
import spriter.definitions.SpriterFolder;
import spriter.library.AbstractLibrary;
import spriter.util.MathUtils;
import spriter.util.SpriterUtil;
import spriter.vars.Variable;
import spriter.util.MathUtils;
#if SPRITER_CUSTOM_MAP
import spriter.definitions.CustomCharMap;
#end
Expand All @@ -28,13 +28,26 @@ class Spriter
public var library:AbstractLibrary;
public var spriterName:String;
/**
* Time elapsed since beginning of current animation
* Time in ms that can be used to jump to a specific time.
* Beware of specifities that make it difficult to read:
* - time elapsed since beginning of current animation.
* - Resetted when starting new animation or on reflection.
* - Starting at animation length when animating backward and then become negative.
* @see also progress property that should be more convenient
*/
public var time:Int = 0;
/**
* Time in the range of [0,currentAnimation.length[ in ms
* Calculated from time and playbackSpeed
*/
public var timeMS:Int = 0;
public var normalizedTime(default, null):Int = 0;

/**
* Time in the range of [0,currentAnimation.length]
* Time progression in the range of [0,1] in ms that can be used to jump to a specific progression
*/
public var normalizedTime:Int = 0;
public var progress(get, set):Float;
//used to update progress without calling setter that modifies time and normalized Time
var _progress:Float;

/**
* Manipulate positions (x,y), scale, alpha and rotation through this object.
Expand Down Expand Up @@ -126,37 +139,43 @@ class Spriter

public function advanceTime(elapsedMS:Int):Void
{
var speedElapsed = Std.int(elapsedMS * playbackSpeed);
var changedSign = false;
if (!paused)
{
timeMS += Std.int(elapsedMS * playbackSpeed);
var prevValue = time;
time += speedElapsed;
changedSign = !SpriterUtil.sameSign(prevValue, time);

if (currentAnimation.loopType == LOOPING)
{
normalizedTime += Std.int(elapsedMS * playbackSpeed);
if (normalizedTime >= currentAnimation.length)//forward
{
normalizedTime -= currentAnimation.length;
++loop;
}else if (normalizedTime <= 0)//backward
{
normalizedTime += currentAnimation.length;
++loop;
}
if(time >= 0)
{
normalizedTime = time % currentAnimation.length;
}else{
normalizedTime = ((currentAnimation.length + (time % currentAnimation.length)) % currentAnimation.length);
}

loop = Std.int(time / currentAnimation.length);

}else{//no looping
normalizedTime = Std.int(Math.max(0, Math.min(timeMS, currentAnimation.length)));
}else{
//no looping
normalizedTime = Std.int(Math.max(0, Math.min(time, currentAnimation.length)));
}

}
_progress = normalizedTime / currentAnimation.length;
//even if paused we need to draw it
currentAnimation.setCurrentTime(normalizedTime, Std.int(MathUtils.fabs(elapsedMS * playbackSpeed)), library, this, currentEntity, info);
currentAnimation.setCurrentTime(normalizedTime, MathUtils.abs(speedElapsed), library, this, currentEntity, info);
//callback
if (currentAnimation.loopType == LOOPING)
{
if (loop > lastLoop) {
if (loop != lastLoop || changedSign) {
lastLoop = loop;
dispatchComplete();
}
}else {//no looping
}else {
//no looping
var when:Int = playbackSpeed > 0 ? currentAnimation.length : 0;
if (normalizedTime == when) {
if (!onCompleteOnce && !hasReflect) onCompleteOnce = true;//force to avoid dispatching every frame when it's done
Expand Down Expand Up @@ -351,7 +370,7 @@ class Spriter

/**
* Play a stack of animations whatever the entity.
* @param name of the entity
* @param name of the entities
* @param anims names of the animations in order
* @param endAnimCallback function callback, return (s:Spriter, entity:String, anim:String)
* @param removeCallback remove function callback after dispatch
Expand All @@ -377,16 +396,97 @@ class Spriter
}
}

/**
* Reset time to start time or end time depending of playback direction.
*/
public function resetTime():Void
{
if (playbackSpeed > 0)
{
loop = lastLoop = normalizedTime = timeMS = 0;
}else{
loop = lastLoop = 0;
normalizedTime = timeMS = currentAnimation.length;
progress = 0;
}else{
loop = 0;
lastLoop = 0;
progress = 1;
}
}

/**
* Set time progression
* @param p progress of the animation. Value must be [0,1].
*/
function set_progress(p:Float):Float
{
if (p < 0)
p = 0;
else if (p > 1)
p = 1;
_progress = p;
time = normalizedTime = Std.int(p * currentAnimation.length);
return _progress;
}
function get_progress():Float
{
return _progress;
}

public function getNextKeyTime():Int
{
var nextTime = 0;

var len:Int = currentAnimation.mainlineKeys.length;
for (m in 0...len)
{
if(currentAnimation.mainlineKeys[m].time > time)
{
nextTime = currentAnimation.mainlineKeys[m].time;
break;
}

}

return nextTime;
}

public function getPrevKeyTime():Int
{
var i = currentAnimation.mainlineKeys.length - 1;

var prevTime = currentAnimation.mainlineKeys[i].time;
while(i >= 0) {
if(currentAnimation.mainlineKeys[i].time < time)
{
prevTime = currentAnimation.mainlineKeys[i].time;
break;
}
i--;
}
return prevTime;
}

/**
* Set the current time to the next frame time
*/
public function nextFrame():Void
{
var t = getNextKeyTime();
progress = t / currentAnimation.length;
}
/**
* Set the current time to the previous frame time
*/
public function prevFrame():Void
{
var t = getPrevKeyTime();
progress = t / currentAnimation.length;
}

/**
* Reverse the playback speed and reset the time to start or end time depending if playing forward or backward
* @param value
* @return
*/
public function reverse(value:Bool = true):Spriter
{
if (value)
Expand All @@ -400,6 +500,11 @@ class Spriter
resetTime();
return this;
}
/**
* Set to true to animate forward and then backward
* @param value
* @return
*/
public function reflect(value:Bool = true):Spriter
{
if (value)
Expand Down
Loading