-
Notifications
You must be signed in to change notification settings - Fork 118
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Framelabels #208
Open
mikedotalmond
wants to merge
4
commits into
aduros:master
Choose a base branch
from
mikedotalmond:framelabels
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Framelabels #208
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
29d45f2
Flump frame-label support for MovieSprite
c4240b9
fix incorrect parameters committed last time!
d679458
Revert "Flump frame-label support for MovieSprite"
mikedotalmond e505430
An updated version of frameLabels support for MovieSprite/MovieSymbol
mikedotalmond File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,8 +7,10 @@ package flambe.swf; | |
import flambe.animation.AnimatedFloat; | ||
import flambe.display.Sprite; | ||
import flambe.math.FMath; | ||
|
||
import flambe.swf.MovieSymbol; | ||
import flambe.util.Signal0; | ||
import flambe.util.Signal1.Signal1; | ||
|
||
using flambe.util.Arrays; | ||
using flambe.util.BitSets; | ||
|
@@ -31,29 +33,40 @@ class MovieSprite extends Sprite | |
* that. | ||
*/ | ||
public var speed (default, null) :AnimatedFloat; | ||
|
||
/** get/set the current frame (playhead position) **/ | ||
public var frame(get, set):Float; | ||
|
||
/* The total number of frames in this MovieSprite */ | ||
public var totalFrames(get_totalFrames, never):Int; | ||
|
||
/** Whether this movie is currently paused. */ | ||
public var paused (get, set) :Bool; | ||
|
||
/** Emitted when this movie loops back to the beginning. */ | ||
public var looped (get, null) :Signal0; | ||
|
||
|
||
/** Emitted when the playhead passes a label keyframe on the 'labels' layer. */ | ||
public var labelPassed(default, null):Signal1<String>; | ||
|
||
public function new (symbol :MovieSymbol) | ||
{ | ||
super(); | ||
this.symbol = symbol; | ||
|
||
speed = new AnimatedFloat(1); | ||
|
||
|
||
speed = new AnimatedFloat(1); | ||
labelPassed = new Signal1<String>(); | ||
|
||
_animators = Arrays.create(symbol.layers.length); | ||
for (ii in 0..._animators.length) { | ||
var layer = symbol.layers[ii]; | ||
_animators[ii] = new LayerAnimator(layer); | ||
_animators[ii] = new LayerAnimator(layer); | ||
} | ||
|
||
_frame = 0; | ||
_frame = -1; | ||
_position = 0; | ||
goto(1); | ||
_lastLabelFrame = -1; | ||
goto(0); | ||
} | ||
|
||
/** | ||
|
@@ -74,16 +87,26 @@ class MovieSprite extends Sprite | |
} | ||
return null; | ||
} | ||
|
||
override public function onAdded () | ||
|
||
|
||
/** | ||
* Get the frame index for a frame-label keyframe | ||
* @param name | ||
* @return The frame index, or -1 if no label exists for the given name | ||
*/ | ||
public inline function findLabel(name:String):Float { | ||
return symbol.findLabel(name); | ||
} | ||
|
||
override public function onAdded () | ||
{ | ||
super.onAdded(); | ||
|
||
for (animator in _animators) { | ||
owner.addChild(animator.content); | ||
} | ||
} | ||
|
||
override public function onRemoved () | ||
{ | ||
super.onRemoved(); | ||
|
@@ -97,17 +120,16 @@ class MovieSprite extends Sprite | |
|
||
override public function onUpdate (dt :Float) | ||
{ | ||
super.onUpdate(dt); | ||
super.onUpdate(dt); | ||
|
||
speed.update(dt); | ||
|
||
switch (_flags & (Sprite.MOVIESPRITE_PAUSED | Sprite.MOVIESPRITE_SKIP_NEXT)) { | ||
case 0: | ||
// Neither paused nor skipping set, advance time | ||
_position += speed._*dt; | ||
_position += speed._ * dt; | ||
if (_position > symbol.duration) { | ||
_position = _position % symbol.duration; | ||
|
||
if (_looped != null) { | ||
_looped.emit(); | ||
} | ||
|
@@ -117,47 +139,43 @@ class MovieSprite extends Sprite | |
_flags = _flags.remove(Sprite.MOVIESPRITE_SKIP_NEXT); | ||
} | ||
|
||
var newFrame = _position*symbol.frameRate; | ||
var newFrame = _position * symbol.frameRate; | ||
goto(newFrame); | ||
} | ||
|
||
private function goto (newFrame :Float) | ||
{ | ||
if (_frame == newFrame) { | ||
return; // No change | ||
} | ||
|
||
var wrapped = newFrame < _frame; | ||
if (wrapped) { | ||
for (animator in _animators) { | ||
animator.needsKeyframeUpdate = true; | ||
animator.keyframeIdx = 0; | ||
} | ||
} | ||
for (animator in _animators) { | ||
animator.composeFrame(newFrame); | ||
} | ||
|
||
|
||
for (animator in _animators) { | ||
animator.composeFrame(newFrame, wrapped); | ||
if (animator.labelChanged) labelPassed.emit(animator.currentLabel); | ||
} | ||
|
||
_frame = newFrame; | ||
} | ||
|
||
inline private function get_position () :Float | ||
{ | ||
return _position; | ||
} | ||
|
||
{ | ||
return _position; | ||
} | ||
private function set_position (position :Float) :Float | ||
{ | ||
return _position = FMath.clamp(position, 0, symbol.duration); | ||
} | ||
{ | ||
return _position = FMath.clamp(position, 0, symbol.duration); | ||
} | ||
|
||
inline private function get_paused () :Bool | ||
{ | ||
return _flags.contains(Sprite.MOVIESPRITE_PAUSED); | ||
} | ||
{ | ||
return _flags.contains(Sprite.MOVIESPRITE_PAUSED); | ||
} | ||
|
||
private function set_paused (paused :Bool) | ||
{ | ||
{ | ||
_flags = _flags.set(Sprite.MOVIESPRITE_PAUSED, paused); | ||
return paused; | ||
} | ||
|
@@ -169,7 +187,17 @@ class MovieSprite extends Sprite | |
} | ||
return _looped; | ||
} | ||
|
||
|
||
|
||
inline function get_frame():Float return _frame; | ||
inline function set_frame(value:Float):Float { | ||
_position = value / symbol.frameRate; | ||
goto(value); | ||
return _frame; | ||
} | ||
|
||
inline function get_totalFrames():Int return Math.ceil(symbol.duration / symbol.frameRate); | ||
|
||
/** | ||
* Internal method to set the position to 0 and skip the next update. This is required to modify | ||
* the playback position of child movies during an update step, so that after the update | ||
|
@@ -178,34 +206,42 @@ class MovieSprite extends Sprite | |
@:allow(flambe) function rewind () | ||
{ | ||
_position = 0; | ||
_lastLabelFrame = -1; | ||
_flags = _flags.add(Sprite.MOVIESPRITE_SKIP_NEXT); | ||
} | ||
|
||
private var _animators :Array<LayerAnimator>; | ||
|
||
private var _position :Float; | ||
private var _position :Float; | ||
private var _frame :Float; | ||
|
||
private var _looped :Signal0 = null; | ||
|
||
private var _looped :Signal0 = null; | ||
|
||
// frame labels... | ||
var _framesToLabels:Map<Int,String>; | ||
var _labelsToFrames:Map<String,Int>; | ||
var _lastLabelFrame:Int = -1; | ||
var _frameLabels:Array<String>; | ||
} | ||
|
||
private class LayerAnimator | ||
{ | ||
public var content (default, null) :Entity; | ||
|
||
public var needsKeyframeUpdate :Bool = false; | ||
public var content(default, null):Entity; | ||
|
||
public var currentLabel(default, null):String = null; | ||
public var labelChanged(default, null):Bool = false; | ||
|
||
public var needsKeyframeUpdate:Bool = false; | ||
public var keyframeIdx :Int = 0; | ||
|
||
public var layer :MovieLayer; | ||
|
||
public var layer:MovieLayer; | ||
public function new (layer :MovieLayer) | ||
{ | ||
this.layer = layer; | ||
|
||
content = new Entity(); | ||
if (layer.empty) { | ||
_sprites = null; | ||
|
||
} else { | ||
// Populate _sprites with the Sprite at each keyframe, reusing consecutive symbols | ||
_sprites = Arrays.create(layer.keyframes.length); | ||
|
@@ -223,17 +259,25 @@ private class LayerAnimator | |
} | ||
} | ||
|
||
public function composeFrame (frame :Float) | ||
public function composeFrame (frame :Float, wrapped:Bool) | ||
{ | ||
if (_sprites == null) { | ||
|
||
labelChanged = false; | ||
|
||
if (wrapped) { | ||
needsKeyframeUpdate = true; | ||
keyframeIdx = 0; | ||
} | ||
|
||
if (_sprites == null) { | ||
// TODO(bruno): Test this code path | ||
// Don't animate empty layers | ||
return; | ||
} | ||
|
||
var keyframes = layer.keyframes; | ||
var keyframes = layer.keyframes; | ||
var finalFrame = keyframes.length - 1; | ||
|
||
if (frame > layer.frames) { | ||
// TODO(bruno): Test this code path | ||
// Not enough frames on this layer, hide it | ||
|
@@ -247,11 +291,12 @@ private class LayerAnimator | |
++keyframeIdx; | ||
needsKeyframeUpdate = true; | ||
} | ||
|
||
var sprite; | ||
if (needsKeyframeUpdate) { | ||
needsKeyframeUpdate = false; | ||
// Switch to the next instance if this is a multi-layer symbol | ||
currentLabel = null; | ||
// Switch to the next instance if this is a multi-layer symbol | ||
sprite = _sprites[keyframeIdx]; | ||
if (sprite != content.get(Sprite)) { | ||
if (Type.getClass(sprite) == MovieSprite) { | ||
|
@@ -263,22 +308,30 @@ private class LayerAnimator | |
} else { | ||
sprite = content.get(Sprite); | ||
} | ||
|
||
|
||
|
||
var kf = keyframes[keyframeIdx]; | ||
var visible = kf.visible && kf.symbol != null; | ||
sprite.visible = visible; | ||
if (!visible) { | ||
|
||
var label = kf.label; | ||
if (label != currentLabel) { | ||
currentLabel = label; | ||
labelChanged = true; | ||
} | ||
|
||
if (!visible) { | ||
return; // Don't bother animating invisible layers | ||
} | ||
|
||
} | ||
var x = kf.x; | ||
var y = kf.y; | ||
var scaleX = kf.scaleX; | ||
var scaleY = kf.scaleY; | ||
var skewX = kf.skewX; | ||
var skewY = kf.skewY; | ||
var alpha = kf.alpha; | ||
|
||
if (kf.tweened && keyframeIdx < finalFrame) { | ||
var interp = (frame-kf.index) / kf.duration; | ||
var ease = kf.ease; | ||
|
@@ -295,7 +348,7 @@ private class LayerAnimator | |
} | ||
interp = ease*t + (1 - ease)*interp; | ||
} | ||
|
||
var nextKf = keyframes[keyframeIdx + 1]; | ||
x += (nextKf.x-x) * interp; | ||
y += (nextKf.y-y) * interp; | ||
|
@@ -310,14 +363,14 @@ private class LayerAnimator | |
var matrix = sprite.getLocalMatrix(); | ||
var sinX = Math.sin(skewX), cosX = Math.cos(skewX); | ||
var sinY = Math.sin(skewY), cosY = Math.cos(skewY); | ||
matrix.set(cosY*scaleX, sinY*scaleX, -sinX*scaleY, cosX*scaleY, x, y); | ||
matrix.set(cosY * scaleX, sinY * scaleX, -sinX * scaleY, cosX * scaleY, x, y); | ||
|
||
// Append the pivot | ||
matrix.translate(-kf.pivotX, -kf.pivotY); | ||
|
||
sprite.alpha._ = alpha; | ||
sprite.alpha._ = alpha; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's a lot of weird reformatting in this PR :) Please try to match the project code-style and avoid cluttering the diff with lots of reformatting. |
||
} | ||
|
||
// The sprite to show at each keyframe index, or null if this layer has no symbol instances | ||
private var _sprites :Array<Sprite>; | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really like the restriction of requiring a
labels
layer. Shouldn't it be possible to search for labels across all layers? If you have multiple different frames with the same label, the behavior could be undefined.The label searching and mapping should happen in the MovieSymbol/MovieLayer/MovieKeyframe data classes at Library load-time. Since you can have many MovieSprites that point at the same symbol data, that would save a lot of memory/CPU.