• Runtimes
  • Implementing my own runtime, Qs about assumed behavior

I'm working on my own runtime because I want to run stuff in iOS using swift and SpriteKit and the third party runtimes available don't work for my needs.

I've progressed nicely, but I have a couple of open questions I can't really figure out from the official C runtime source. I want a decent level of conformance for my runtime to get the most out of the editor. So here goes:

1) What is MixPose used for? I understand what each value means, but what is it used for and why?

2) Interrupting an animation that has slot color or draw order keyframes before it ends can disrupt other animations pretty nastily. It's generally good practice to key all bones that an animation works on in the first frame, which usually resets relevant stuff for an animation as it starts, but most of the examples like spineboy don't have initial keyframes for everything including color and draw order, and I don't think they should either. How do the official runtimes deal with this? Are draw orders and colors implicitly reset whenever an animation starts?

That's it for now, thanks for any help.

Related Discussions
...
  • Изменено

1) Note MixPose is gone in 3.7 and is replaced by MixBlend (a slightly more descriptive name). We'll update the API reference when 3.7 is released on January 7, 2019. Until then you can see the latest documentation in the reference implementation here:
spine-runtimes/Animation.java at 3.7-beta
spine-runtimes/Animation.java at 3.7-beta
To answer your question, MixBlend controls how the timeline value is mixed with the setup pose value or current pose value. For setup, first, and replace, those only matter when the alpha passed to Timeline apply or Animation apply is < 1. AnimationState uses those in various situations to get the desired mixing. For add, this tells a timeline to add its value to the current pose, which can be used for combining animations additively rather than using tracks/layers.

2) It's not great to key everything on the first frame. Eventually that leads to every animation keying absolutely everything on the first frame, making for many more timelines than necessary and forgetting to key something makes it error prone. In previous versions of Spine, keying everything at the start was needed. More recently, AnimationState handles this by setting values back to the setup pose when a track entry is no longer being applied. This means changes an animation has made cease when that animation is no longer applied.

FWIW, I suggest porting the official Spine Runtimes to Swift/SpriteKit 1:1 as much as possible. This way you will have all the functionality and fixes and especially new features are easy to port. This is what we do: first the reference implementation (spine-libgdx) is updated, then ported to the other languages and game toolkits.

Thank you for the reply. Should have figured that the java version would be a bit easier to follow and closer to swift, but better late than never.

Could you point out the bit(s) of code where the setup pose application is done when animations are not applied? This would probably answer the remaining bits of confusion I have, mostly related to specifics like how this works with multiple tracks etc.

I wanted to make the runtime 100% swift/spritekit and make the rest as close to the official runtimes as possible. This meant using the Codable system for parsing JSON, which required architecting the classes based on the JSON and not the structure in the existing runtimes. (I might add that this worked really well, had the parser up in a couple of hours.) Also I wanted to make the skeleton instance a SpriteKit node, which made it fit better in a custom structure. I noticed pretty soon that trying to make the animation system work on top of SpriteKit actions would lose a lot of the functionality, so that's where I'm looking at the reference implementation a bit harder to make sure any future updates will not need to go against the grain.

It is done in AnimationState:
spine-runtimes/AnimationState.java at 3.7-beta
AnimationState is a beast, as it has to cover a lot of use cases for applying queued and layered animations. In a nutshell, when a track entry is done, it is set on the TrackEntry mixingFrom field of the new current entry. Later, AnimationState applyMixingFrom applies the previous mixingFrom entries first, then the current entry. When the mix is complete, the last time the mixingFrom entry is applied will set the values back to the setup pose. After that, when the current entry is applied, those values will stay at the setup pose values if the current entry did not key them. Note even if there is no mix, the old entry is still set as the mixingFrom entry so the values it keys can be reset to the setup pose in applyMixingFrom.

If you are attempting re-implementation rather than porting, it would be much easier to just port. Please note the Spine Runtimes license applies whether you are doing a direct port or a re-implementation, unless you are doing a clean room implementation (in which case you'd probably want to avoid digging around the Spine Runtimes source so your work is not contaminated).

FWIW, I would not sacrifice matching the official runtime classes for JSON parsing. IMHO, any benefits of doing that are outweighed by keeping closer to the reference implementation. Besides, only JSON parsing is needed (no emitting) and the binary format is likely more useful (smaller files and faster parsing).

Also, I would also not make Skeleton a scene graph node


better to have a scene graph node that has a Skeleton instance. In general the less tied to the scene graph the better, but the main reason is that that coupling is unnecessary and in some cases unwanted. Eg, an army with many hundreds of enemies can be animated by a dozen or so skeletons (when it doesn't matter if each enemy is not unique). Or you can use a skeleton to animate a UI, or otherwise use the skeleton's bone positions and other pose information and you do not need or want the skeleton in the scene graph.