re: Formatting - Absolutely. For most folks this is no big deal. Me however, I tend not to read code that isn’t well formatted and very legible. Let’s call it a quirk. I’m just anal and lazy that way.
I’m like the Goldilocks of reading code.
- No, this formatting is too narrow (2 spaces)…
- No, this formatting is too wide (8 spaces) and it wraps!
- Oh! This formatting is just right! 3 or 4 spaces per indent, nice vertical separation, no wrapping, and nice clear naming. Nom, nom, nom…
re: The Code - That looks exactly right and does much what I would expect.
I think the problem is you’re expecting a lot more ‘state’ tracking from the transition.* library than it does.
Let’s step through what is happening and see if I can help clarify.
- You create some objects, define listeners, and then start two transitions (one per object). These transitions are identical in all respects and should complete on the same frame in the order they were schehduled.
in this discussion we are ignoring the onStart listener
approximately 1000 ms goes by… b__oth transitions complete and are scheduled to be handled in the next available frame.
- obj1.onComplete() executes:
- For each object in table objs, it checks to see if the ‘atTargetPosition’ flag was set to true and if so, transition.cancel() is called.
- No cancels are scheduled.
- It then marks the ‘atTargetPosition’ flag for this object (obj1) as true.
- obj2.onComplete() executes:
- For each object in table objs, it checks to see if the ‘atTargetPosition’ flag was set to true and if so, transition.cancel() is called.
- cancel is scheduled for obj1 and placed in the transition.* onCancel event queue for the next available execution time.
- May be at end of this frame’s queue or next frame.
- _ Note: I’m not clear if it is one queue per event type or unified._
- It then marks the ‘atTargetPosition’ flag for this object (obj2) as true.
This frame ends, more processing is done, then the next frame comes around.
- transition.* processes all events scheduled for this frame, including the cancel that got scheduled by your code last frame.
The issue is, transition.* doesn’t care if the object is valid. It doesn’t check to see if the transition for this object was completed.
I know you want it to, but it would be much more onerous and costly in terms of computing than you might thing.
If only one transition per object was allowed, this could tracked via some flag or table. However, any object may have any number of transitions scheduled at any time. Thus, the logic for tracking explodes as does the time needed to traverse it.
So, instead, transition.* blindly executes queued events. It is our responsibility not to create scenarios like the one you are creating.
(Blind that is, except in the case the object is destroyed. It does catch this.)
Options, options, … Corona Rocks yes?
At the end of the day, you have these options.
-
Hate the way it works and ask it be changed. - I don’t think you’ll get much traction here.
-
Know what is happening and avoid it in your code - Pretty straightforward and easily accomplished with an extra flag (obj.transitionCompleted) and a bit more logic.
-
Stop using transition.* and roll your own or borrow another implementation, the make your new lib avoid this issue.
Even cooler, you can grab an awesome library (transition2.* ) that is publicly available, including source:
https://forums.coronalabs.com/topic/69305-transition2-a-customizable-extension-to-the-transition-library/page-2#entry369091