Change 20100526-maxcarlson-9 by maxcarl...@friendly on 2010-05-26 16:35:11 PDT
in /Users/maxcarlson/openlaszlo/trunk-clean
for http://svn.openlaszlo.org/openlaszlo/trunk
Summary: UPDATED: Clean up LzAnimator/LzNode interaction, cpmprehensive
Bugs Fixed: LPP-9020 - Support CSS3 transitions (partial)
Technical Reviewer: [email protected]
QA Reviewer: ptw
Details: Updated to address Andre's latest round of comments:
- for( var p in moreargs) args[p] = moreargs[p];
+ if (moreargs != null) {
+ for( var p in moreargs) args[p] = moreargs[p];
+ }
There is no need for the additional if-clause, it just bloats code.
Fixed.
- var animator = new LzAnimator( null, args );
-
- return animator;
+ return new LzAnimator( this, args );
This will cause memory leaks. The parent of the newly created animator must be
null, otherwise the animator will be added to the parent's subnodes array, but
it'll never be destroyed. In general, no one cares about the animator returned
lz.Node#animate(), people just call animate() and that's it.
Fixed. For some reason, I thought passing null as for the parent arg to LzNode
owuld attach to the canvas!
- this.__LZUID = "__U" + ++LzNode.__UIDs;
+ var uid = "__U" + ++LzNode.__UIDs;
+ this.__LZUID = uid;
+ // add a weak link for this UID
+ LzNode.__fromUID[uid] = this;
This will cause memory leaks, too. The reason is the same as above.
Fixed.
/**
+ * @access private
+ */
+ static var __fromUID:Object = {};
__fromUID isn't even used in the complete change? (Apart from adding and
removing entries.)
Fixed.
+ /**
+ * Tracks expected values and counters
+ * @access private
+ */
+ static var __animatedAttributes = {};
Memory leak. For every node which gets animated an entry is added to this
object. But that entry will never be deleted. Why didn't you leave the
animatedAttrs object on lz.Node?
I moved __animatedAttributes bqck to LzNode.
- function calcControlValues (cval = null) :void {
+ function calcControlValues (cval = 0) :void {
calcControlValues() is never called with an argument, so why does it have an
optional argument at all?
Since the arg is never used, I changed to a constant in the function.
+ var to = this.to;
+ if (to === this.__lastto) return;
+ this.__lastto = to;
'indirect' or 'motion' may have changed in the meantime, so this simple cache
check won't work. I'd just leave the code as it is.
Fixed.
- if (! this.isactive) return;
+ //if (! this.isactive) return;
+ this.isactive = false;
Why did you comment out the check? Calling stop() on an inactive animator
should be a no-op, so the check is required.
Fixed.
From the previous review round:
3) It seems to me if your counter goes negative, you have a bug. Why are we
papering over this?
Agreed. I added a warning to catch this in debug mode for now.
What happened to warning you wanted to add?
I did some testing, and read through the code - I couldn't find a way to get a
negative counter, so I removed the test/warning.
+ var counter:Number = expected[counterkey] - 1;
+ expected[counterkey] = counter;
+ if (counter == 0) {
// "to" has changed so calc new poles and K value
- this.calcControlValues();
Comment should be moved to the new position, too.
Fixed.
- targ.setAttribute(attr, from);
- var d:Number = from - targ.getExpectedAttribute(attr);
- targ.addToExpectedAttribute(attr, d);
+ targ.setAttribute(attr, Number(from));
+ expected[attr] += Number(from);
This seems to be wrong.
it was: exp' = exp + d = exp + (from - exp) => exp' = from
but now it is: exp' = exp + from
with exp the old expected value and exp' the new expected value
Good catch! Fixed.
- // set current to zero since all animators are now relative
- this.currentValue = 0;
Comment should be added to calcControlValues(), I know it did help me in the
past to understand the code in lz.Animator
Fixed.
Otherwise, the same:
Updated to address Andre's comments:
LzAnimatorGroup.__LZhalt() also sends onstop. Bret asked me to add
this to ensure onstop is fired after the screen has had a chance to
update, and this seemed like the cleanest way for now.
Could you split changes which introduce new behaviour in different change sets?
This makes it easier to test changes and to back out these changes if necessary
due to regression and so forth.
Also, moved all animator state into a single object -
LzAnimator.__animatedAttributes.
Otherwise:
Updated to address Tucker's comments:
1) Since we're removing all the substrate from LzNode, the comments that say
'inlined LzNode...' make no sense any more.
Done.
2) The logic with expectedvalue is just too convoluted for me to follow. This
expression (expectedvalue != null ? expectedvalue : targ[attr]) is repeated
over and over, which can't be efficient. AFAICT, the only time expected value
will be null is if the attribute is transitioning from not animated to
animated. So, wouldn't it be simpler to first test if there is a counter
entry, and if there is not, set the counter to 0 and the expected value to the
current value? Then the rest of the logic can simply work with the counter and
the expected value without all the redundant conditionalization. When all the
animations are done, you remove the counter (and optionally the expected
value), so that you know the attribute is no longer animating.
Agreed.
3) It seems to me if your counter goes negative, you have a bug. Why are we
papering over this?
Agreed. I added a warning to catch this in debug mode for now.
Issue:
1) I don't understand why you have to introduce another delegate to call halt
from finalize from stop? All halt does is unregister the animator.
LzAnimatorGroup.__LZhalt() also sends onstop. Bret asked me to add this to
ensure onstop is fired after the screen has had a chance to update, and this
seemed like the cleanest way for now.
Otherwise, the same:
Updated to address Andre and Tucker's comments:
+ this.__animExpected = {};
+ this.__animCounter = {};
Only a few nodes will be animated in an application, so both hashes should be
built lazily. Otherwise every node construction will cost +2 Objects.
Fixed.
[...]
+ var __animExpected = {};
[...]
+ var __animCounter = {};
Every node construction will cost +4 Objects for swf9/10
(http://jira.openlaszlo.org/jira/browse/LPP-5232).
Fixed.
@@ -218,23 +227,32 @@
var attr:String = this.attribute;
var from:* = this.from;
+ var expected = targ.__animExpected;
+ var expectedvalue = (expected[attr] != null ? expected[attr] :
targ[attr]); // inlined targ.getExpectedAttribute(attr);
if (from != null) {
targ.setAttribute(attr, from);
- var d:Number = from - targ.getExpectedAttribute(attr);
- targ.addToExpectedAttribute(attr, d);
+ var d:Number = from - expectedvalue;
+ // inlined targ.addToExpectedAttribute(attr, d);
+ var current = expected[attr];
+ expected[attr] = (current != null ? current : targ[attr]) + d;
}
if (! this.relative) {
- this.to = this.origto - targ.getExpectedAttribute(attr);
+ this.to = this.origto - expectedvalue;
This seems to be wrong:
expected[attr] is updated (inlined call to addToExpectedAttribute), but later
"expectedvalue" is used again.
Fixed.
On 5/25/2010 4:54 PM, P T Withington wrote:
Comments:
1) I'd just remove all the animator functions you commented out of LzNode.
They are clutter and will (already for one of them) rot. svn can find them if
we really need them back.
You mean to rot like setExpectedAttribute() which wasn't updated to use
__animExpected ;-)
Fixed.
2) Rather than creating multiple object hashes for the various animation
attributes, why not define a class (data structure) that holds all the
animation properties of an attribute? Thus, when animating an attribute, you
will just say something like:
var aas = this.__animatedAttributes;
if (! aas[name]) { aas[name] = new AnimationAttribute(start, end, ...);
?
Fixed.
Also in stop()
var chash = targ.__animCounter;
var counter = chash[attr];
if (counter == null || counter - 1<= 0) {
chash[attr] = 0;
targ.__animExpected[attr] = null;
} else {
chash[attr] = counter - 1;
targ.__animExpected[attr] = this.to - this.currentValue;
}
/*
var e_prop:String = "e_" + (this.attribute cast String);
if (! targ[e_prop].c) {
targ[e_prop].c = 0;
}
targ[e_prop].c -= 1; //decrement animation counter for prop
if (targ[e_prop].c<= 0) {
targ[e_prop].c = 0;
targ[e_prop].v = null;
} else {
targ[e_prop].v -= this.to - this.currentValue;
}
*/
1) the complete commented out block seems to be unnecessary
Fixed.
2)
targ[e_prop].v -= this.to - this.currentValue;
is changed to
targ.__animExpected[attr] = this.to - this.currentValue;
Shouldn't that be -= ?
Good catch. Fixed.
And I still think you cannot reuse "expectedvalue" here:
if (! this.relative) {
- this.to = this.origto - targ.getExpectedAttribute(attr);
+ this.to = this.origto - expectedvalue;
Fixed.
LzNode - Remove all animator-related code.
LzAnimatorGroup - Update comments, remove cruft, update types. Prevent
duplicate calls to doStart() or stop().
LaszloAnimation - Use LzAnimator.__animatedAttributes to track animation
counter and expected values. Shorten lookups. Fix bugs in reviewer comments.
Tests: Visual inspection, animators work as before across all runtimes.
Files:
M WEB-INF/lps/lfc/core/LzNode.lzs
M WEB-INF/lps/lfc/controllers/LzAnimatorGroup.lzs
M WEB-INF/lps/lfc/controllers/LaszloAnimation.lzs
Changeset:
http://svn.openlaszlo.org/openlaszlo/patches/20100526-maxcarlson-9.tar