Jump to content
lucid

scml documentation (deprecated - use reference implementations instead)

Recommended Posts

Deprecated : Use Reference Implementations pinned in this forum

Hello again everyone,

This is the preliminary edition of the scml documentation. It takes the form of an interactive document with a side by side of pseudo code and the scml format specification.

This will be expanded over the coming weeks with detailed descriptions of the functions and dom elements being described, but as is, it should provide a good jumping off point for developers creating implementations, and also for anyone attempting to update or troubleshoot an implementation.

I'll be out of town and away from my dev PC for the next few days, but when I return this document will be continually updated along with Spriter to be as useful and clear as possible. In the meantime however, I'll provide you with a few key points to get you started.

â—¾the document is written in a c-like pseudo-code ignoring as many language specifics as possible. This means there is no concept of pointers or references. brackets[] at the end of a type name indicate an array

â—¾float, int, string are intended as general types and can be replaced by double, short, cstring, etc as you see fit

â—¾as all xml parsing will be language specific, this is not addressed in this document, however, the scml and code are side by side. Where the data structures should contain information directly from the file, those items are highlighted, and hovering them reveals the relationship to the scml file.

The pseudo code is released to the public domain under the cc0 license. This means you are free to use it in any way you see fit. ("You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission")

There is a checkbox to hide the scml side, so you can copy paste the code into your IDE or text editor, do a few find/replaces, and you have a basic scml implementation you are free to release it for anyone to use or keep for use in your proprietary engine for your game.

This version only includes a Set Current Time, and Apply Character Map function, and provides a data structure to translate spriter data to be drawn at the position and orientation of your character on screen. In time this will be expanded to provide a full suite of features to make your playback engine as complete and powerful as possible.

This document is the first part of a larger strategy to get Spriter universally supported on all platforms, languages and authoring tools, and we will get into those in greater detail over the coming weeks.

view the documentation here:

http://www.brashmonkey.com/ScmlDocs/ScmlReference.html

and please leave any feedback in our forums

Share this post


Link to post
Share on other sites

Tried implementing with this document today and found some typos:

In SCML format spec of Timeline

attribute "type" should be "object_type"

In SpatialInfo::unmapFromParent()

line 8,9: xScale and yScale should be scaleX and scaleY

In SpriteTimelineKey::linear()

line 3: useDefaultPoint should be useDefaultPivot

Otherwise this doc works great, have successfully implemented mine with it.

Share this post


Link to post
Share on other sites

There are more discrepancies, like when you say "for o in blah blah" in a part and then forget to refer to "o"

And in other places I think you return the TimelineKey class when you should be using SpriteTimelineKey or SpatialTimelineKey, not sure.

It's been a big heavy going for me unraveling how everything is supposed to work together. It's a pretty good doc though.

Share this post


Link to post
Share on other sites

I've been on a long hiatus from development, and haven't updated my Shiva3D implementation for about 6 months. Now that I'm about to start again, how much different do you think the docs above are, compared to the current implementation?

Do you have an ETA on an update? Should I wait, or go ahead an try to figure it out myself?

Share this post


Link to post
Share on other sites

Hi 8DashP. The current implementation is a little further along than the documentation above, but the implementation above should work for everything that is there. I will complete the documentation after Spriter 1.0, which is still at least several weeks away. Feel free to ask specific questions where the documentation is inadequate here, or via email lucid@brashmonkey.com.

Share this post


Link to post
Share on other sites

In SpatialInfo::unmapFromParent()

line 8,9: xScale and yScale should be scaleX and scaleY

Hey, I'm rewriting my implementation to use your definitions here, so I'm just starting converting this to C++ code. I note the current doc had most of AzureBlaze's fixes, but you seem to have missed this one.

And as per what sonder says, having some issues getting the pseudo code mapped correctly, as it seems in multiple places you are referring to a TimeLineKey and expecting it to have a .info member, but that only exists in a SpacialTimelineKey, so I'm having to do a bit of decrypting to figure out the correct class usages, as I don't really want to throw upcasts() in there if not necessary. If you could have a look at the updateCharacter() method and clarify key usage a bit, that'd be good.

Share this post


Link to post
Share on other sites

Hey again,

Found several other issues with the doc, that I won't bother going through currently, as I know you are still working on this.

One question though. As I'm refactoring my old code, I see there is a lot of stuff missing from the doc above, that was in the original file spec provided way back when. Since I already have code that has these additional values (such as pixel_art_mode, all of the extra file fields for atlas, offsets etc etc) am I safe to keep using the code I have, or are you likely to redefine the spec so those features change or are no longer usable?

*EDIT*

OK more questions. Trying to implement the XML load for the Timeline Keys and having a hard time deciding on what the structure should actually be. The whole TimelineKey pseudo-code section seems messed up. I realise it isn't supposed to be direct C++ code, but it's close enough that trying to fit it should be easy, however there are big discrepancies with the XML definition.

The biggest question I have is whether the bone and object attributes are a hierarchy under the key attributes, or simply alternate versions of the 3 (or 4?) different types of keys. If they are a hierarchy, then really the TimelineKey definition should have them as sub-classes, acting as members within the TimelineKey class. That however will mess up the pseudo code for the other functions that do the updating.

The alternative, trying to keep the TimelineKey as a base class, from which the others are derived, is going to require some fancy footwork to store a list of void pointers and then typecasting operations on them to find out the appropriate operators. The Timeline has an array of Timelinekeys to store the data, but looking at the XML, it's a 2-level structure, not a single level, even though by virtue of making all the keys inherited classes, it represents a single object structure.

Looking at the sample file, it appears there is only one ever "sub-key" underneath the key entity. If this is always true, then maybe just a type specifier for the key, and collapsing the hierarchy down to one "key" level will suffice. Can we rely on only a single sub-key element type with each key element?

A minor but significant point while I'm here, is that the spin attribute is in SpatialInfo, which is not part of the TimelineKey structure, but the XML attribute is part of the TimelineKey structure.

All very confusing to try and implement consistent with the definition.

Thanks.

Russell.

Share this post


Link to post
Share on other sites

In SpatialInfo::unmapFromParent()

line 8,9: xScale and yScale should be scaleX and scaleY

Hey, I'm rewriting my implementation to use your definitions here, so I'm just starting converting this to C++ code. I note the current doc had most of AzureBlaze's fixes, but you seem to have missed this one.

And as per what sonder says, having some issues getting the pseudo code mapped correctly, as it seems in multiple places you are referring to a TimeLineKey and expecting it to have a .info member, but that only exists in a SpacialTimelineKey, so I'm having to do a bit of decrypting to figure out the correct class usages, as I don't really want to throw upcasts() in there if not necessary. If you could have a look at the updateCharacter() method and clarify key usage a bit, that'd be good.

Thank you for pointing out the typos. This documentation will have a massive overhaul and update once 1.0 is out.

I'll start off by just fixing what you mentioned (separating changed lines. Let me know if you need any further clarification:

16: BoneTimelineKey currentKey=keyFromRef(currentRef,newTime);

21: SpatialTimelineKey objectKeys[];

34: SpatialTimelineKey currentKey=keyFromRef(currentRef,newTime);

Hey again,

Found several other issues with the doc, that I won't bother going through currently, as I know you are still working on this.

One question though. As I'm refactoring my old code, I see there is a lot of stuff missing from the doc above, that was in the original file spec provided way back when. Since I already have code that has these additional values (such as pixel_art_mode, all of the extra file fields for atlas, offsets etc etc) am I safe to keep using the code I have, or are you likely to redefine the spec so those features change or are no longer usable?

I would wait on anything you haven't added back in already. I want to be able to make small improvements to the format for features that haven't been available in any Spriter version yet

The biggest question I have is whether the bone and object attributes are a hierarchy under the key attributes, or simply alternate versions of the 3 (or 4?) different types of keys. If they are a hierarchy, then really the TimelineKey definition should have them as sub-classes, acting as members within the TimelineKey class. That however will mess up the pseudo code for the other functions that do the updating.

The alternative, trying to keep the TimelineKey as a base class, from which the others are derived, is going to require some fancy footwork to store a list of void pointers and then typecasting operations on them to find out the appropriate operators. The Timeline has an array of Timelinekeys to store the data, but looking at the XML, it's a 2-level structure, not a single level, even though by virtue of making all the keys inherited classes, it represents a single object structure.

I'm not sure if this answers your question (please elaborate if not), but if it's the structure that's confusing you, basically the pseudo code as one structure. They are separate in the format, because it was decided early on to make it open for one key to contain multiple objects to keep the format flexible for future expansion. In retrospect, I may have done it differently, but it shouldn't cause any issues with implementation to just treat it as one object.

Looking at the sample file, it appears there is only one ever "sub-key" underneath the key entity. If this is always true, then maybe just a type specifier for the key, and collapsing the hierarchy down to one "key" level will suffice. Can we rely on only a single sub-key element type with each key element?

see above. At this point, with so many implementations being worked on or already complete, I'm not going to change anything that's already been working, but yes, that would have been another option. The reason for separating will make more sense down the line when more advanced (unannounced) post 1.0 features are revealed.

A minor but significant point while I'm here, is that the spin attribute is in SpatialInfo, which is not part of the TimelineKey structure, but the XML attribute is part of the TimelineKey structure.

Right, the DOM doesn't correspond on a one to one basis with the elements. The future documentation will have complete descriptions of why and how one should/could translate the file structure to a data structure, but in the meantime, please feel free to continue asking specific questions until it all makes sense.

Share this post


Link to post
Share on other sites

Thanks for the clarifications.

I don't want to be annoying by continually pointing out stuff you already know, so I'll try to keep my clarifications to things confusing me.

As such, one other minor question. In the mainlineKeyFromTime() and keyFromRef() methods, you are passing in "time" and "newTime" parameters, but in both functions, you only use "currentTime". I'm assuming currentTime should be replaced with the appropriate parameter?

*EDIT*

Something else I just found. The function GetTWithNextKey() has a parameter of NextKeyTime, which is unused. I assume since you can get NextKey.time directly, then this is an unnecessary parameter, or do you want to disassociate the nextkey time from the nextkey key?

Thanks again. Russell.

Share this post


Link to post
Share on other sites

Me again.

Question on time values now. There's a mixture of Float and Int in the pseudo code, mainly around interpolating time values and animation time. This of course is giving C++ a heart attack of warning with float<->int conversions. Now, I could explicit cast them all, but I think time is in milliseconds, right? So why would float values ever be needed. The only place I can find is an interim calculation when interpolating from one time to another, but the end result should be Int anyway.

So, is there some reason all the floats shouldn't become Ints?

Thanks. Russell.

Share this post


Link to post
Share on other sites

Hi lucid,

I am a little bit confused about calculating curved interpolation.

It is no problem to calculate the curves, saved in the timeline keys.

But I don't know how to combine them with the curves, saved in the mainline key frames.

Let's say the mainline looks like this:







...
...

and now I am also applying another curve on the root bone, let's say:










...

How do you combine those two curves?

Another problem is, that I don't know how you apply the x1,y1,x2,y2 values, saved for the bezier curves, to the angle or to the alpha parameter.

Are you just taking the x-values or y-values or do you have a specific formula?

Edit: I found a solution for the bezier problem. For anybody who is going to have the same problem: have a look at this post.

Edit 2: Ok, I solved the other problem on my own. The trick is to interpolate the normalized time t with the mainline key curve.

Thanks for your help!

-Trixt0r

Share this post


Link to post
Share on other sites

Hi all,

I use Spriter to generate traditional, frame-by-frame animations. At key frames, I delete the sprite used in the previous frame, and add the next sprite in the sequence.

In Spriter b5's SCML, for each sprite added and deleted, there used to be a pair of "key" elements inside of an "animation" "timeline" element. The first gave the start time for displaying the sprite, and the second gave the end time. However, in Sprite b6.1's SCML there is only a single "key" per sprite, which contains the start time.

My question is: how can I derive at what time an "object" has been removed from a "timeline" without the second "key" element? Is this information being stored elsewhere in the SCML?

Cheers,

Sunkai.

Share this post


Link to post
Share on other sites

@sunkai

The mainline keys tell you the draw order of the different objects. If a reference to that timeline doesn't appear in the mainline key of the current time, it shouldn't be drawn there.

Share this post


Link to post
Share on other sites

I jus realised there's an issue with the defaults for the parent of a Ref. While your pseudocode shows -1 as the default, the example on the right shows -1 only for bones, but 0 for objects. I assume it should always be -1, otherwise if an object default of 0 is used with no bone_refs, the updateCharacter function will fail with an invalid index to non-existent pone_refs.

The examples on the right should show default values for consistency.

Russell.

Share this post


Link to post
Share on other sites
Something else I just found. The function GetTWithNextKey() has a parameter of NextKeyTime, which is unused. I assume since you can get NextKey.time directly, then this is an unnecessary parameter, or do you want to disassociate the nextkey time from the nextkey key?

Can I get a clarification on this? I'm having an issue with the transition from the last key back to the first, in a looping animation, and am wondering if something is amiss here.

*EDIT*

OK, after replacing all nextKey.time with NextKeyTime, the wrap around seems to work. So, I'm guessing the correct code is to make my substitution, and also this should mean that nextKey is not required as a parameter?

Russell.

Share this post


Link to post
Share on other sites

Hello,

I'm looking at the documentation as well and it looks like there's a big gap between what has been released and what is written in the specification. I was hoping on building a C# library on this, but it looks like I have to wait until v.1.0 is out -- which is a little frustrating, since I'd like to get working on things now.

In the very least, how much do things change in the SCML object model? I imagine you only really "add" fields in -- you don't actually just completely tear out what works and intend on replacing pieces? Is there anything that will be useful to keep track of what the old and new look like, and specifically, what will need to be added (ala something like a merge tool view of things)?

What language are you guys building the tools in? Is there any chance of you just publishing the libraries that you're using already internally? Or, as I hate to ask, is there any time table for when v.1.0 will be ideally released (something even as simple as quarter of the year/etc)?

I just don't want to start working on this and have half of my work be pointless and get nuked.

Warm regards.

Share this post


Link to post
Share on other sites

Apart from the bugs in the reference code, I think it's still pretty much valid and should just need adding to with new features.

My Shiva implementation is in C++, but using Shiva API's for image, object and screen manipulation as Shiva is a 3D environment, not 2D. I've had to modify some of the reference data structures to make sense in my environment, mainly around the timeline, bone and object keys, as turning 2D images into 3D objects but still treating like 2D objects requires some lateral thinking, and coding.

I started with the generic C++ code! but have virtually rewritten it all as my deviations for my environment were turning it into spaghetti code, and I wanted to stay closer to the reference implementation.

So overall, the basic algorithms and data structure are sound. It's getting it into your runtime environment that takes all the work.

Share this post


Link to post
Share on other sites

what is this "a" value in SpatialInfo supposed to be?

There are chances that this means "alpha" but not sure and do not see it set by any of the Spriter examples (I might missed this). I do not know why should i need this "a" value :/

BTW I think "spin" should belong to TimelineKey instead of "SpatialInfo"

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...