Save and load bone animation to any file!!!

General Moho topics.

Moderators: Víctor Paredes, Belgarath, slowtiger

User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

Heres the test file I am using. Just drop in the scripts/menu folder. Or put it in scripts/tools and edit _tool_list.txt to make it a button.

http://www.lowrestv.com/anime_studio/sc ... sefile.lua

Use it only on a bone layer. It will print out all the animation channels and key frames and interpolations used for each bone. There are 5 "main" channels for a bone;

dynamics
Position
rotation
scale
lock (3 channels)

There are actually 7 "keys" or channels for each bone in the file format. The lock channel uses 3 so that is what the extra two are for.

I'm not sure what the other two keys for locking are for. Probably has to do with the IK solving algorithm used by AS for the bone chain.

-vern
User avatar
synthsin75
Posts: 10276
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

:shock: Wow, that's crazy. It looks like you had to write a temporary file with the string 'keys' to be followed by a new line, and then read this back in? It'll take me some time to understand half of that.

Love those wacky variable names though. :lol:

That looks like a lot of code to add to other scripts. I assume, if need be, it could be called from a utility?
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

It could be a utility but probably won't be. I will just stick the needed code in another function and call it from the main function only for extracting the interpolation keys.

That bit where I change the file format in a string variable is quite simple actually. I am only changing one thing throughout the file using a simple string.gsub replace.

Code: Select all

mystuff = string.gsub( mystuff,"keys ","keys \n" )
This puts the number after "keys" onto a new line. I'm adding a new line "\n" after the word "keys". The reason I have to do this is because of this bit of code:

Code: Select all

DataFile:read("*n")
This code only reads the next number if there is no other characters in front of it. It skips over spaces but not other characters. Bummer. The number AFTER the "keys" is very important. It tells the script how many keys there are so how many lines it should read to get the interpolation for each key. the problem is that "keys" is in front of the number so it can't be read in.

What I did in the script is just bump the number after every "keys" line to a new line so I can read it in with that "*n" code.

Fiddling with strings even huge gigantic ones is actually quite simple using loops. If the string or file you are reading is perfectly formatted like the AS document it's really easy. As you can see from this sample code it runs like lightening even though it reads the WHOLE FREAKING FILE from start to finish for each freaking bone! It's very very fast. In all of the lua references they strongly recommend reading the whole file into a variable first, tweak it, and then work with that rather than reading line by line from the actual file.

p.s. I could actually make this code even simpler if I stripped out more of the file format. I may do this but it works great the way it is. It hardly seems worth the effort. Saving and loading of animation isn't an "interactive" process. The user isn't doing anything while the script is working so there's not as much need to streamline it for performance.

-vern
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

synthsin75 wrote:Love those wacky variable names though. :lol:
How embarrassing. I was about to change the name of that crazy function (idiotheadloser) when I got a phone call from my sister visiting the parents and had to run off for dinner. :)

I will of course change these names for any "real" code in other scripts. Sometimes I get annoyed and frustrated when the code doesn't work right and take it out on my functions and variables.

"alex" the "idiotheadloser" keeps using all "mystuff". ;)

-vern
User avatar
synthsin75
Posts: 10276
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

Yeah, I've read that io.lines can have some drawbacks on memory consumption, thus your use of io.open/io.read. I had been thinking that it might take the info being read in and that being processed (stripping the format as you say).

I see what you mean about needing those new lines. I haven't come across that write to temporary file function yet, looks very useful. I had been wondering how you'd do certain things without having to write them to the file itself. (I have seen a write to backup function which I had thought might work)

Great work Vern.
User avatar
Víctor Paredes
Site Admin
Posts: 5817
Joined: Wed Jan 26, 2005 12:18 am
Location: Barcelona/Chile
Contact:

Post by Víctor Paredes »

I made two icons for the buttons, if someone wants to use them
Image Image
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

Well, it works. Saving and loading key frame interpolation is working in my tests with one small little problem... or big one depending on how you work with AS. I haven't uploaded yet because of this problem. It has to do with an interpolation mode I never even considered...

"Pose" interpolation. That is the "funky" key frame you get when inserting references to Actions. This is actually a GOOD thing. It solves my "import action" problem.

The key frames for each action are stored as a subset of the bones animation channel. If you insert a "copy" of an action it is just regular keys copied from the action.

Unlike what I thought previously an action is stored multiple times for each bone effected. An action is NOT stored in the file in one location. If a bone is animated by an action the name of the action and the keys are stored in that bones channel. If only translation, then only translation has the action information, if rotation and position, then the action is listed TWICE once for position, once for rotation. This is the same for all bones.

So... it means more work to figure this out... BUT it also means being able to import the actions directly!

I would first have to check if the action exists first, if it does then I can just insert the key frame for the reference. If the action doesn't exist I will read the action name from the file format just like I'm reading the interpolation and CREATE it, activate it using the script (that IS allowed) and insert the keys.

In the meantime should I upload the current version WITHOUT action support? It works perfectly saving and loading interpolation modes. It just chokes on any file using actions.

I'm both happy and annoyed. I found the solution for actions but it will require some more work. At least at the end you can import actions which should be pretty cool.

-vern
User avatar
mkelley
Posts: 1647
Joined: Fri Nov 02, 2007 5:29 pm
Location: Sunny Florida
Contact:

Post by mkelley »

I'd like the current version now, Vern.

While I use actions extensively I don't import them to the mainline except as copies (so they are just regular keys). I haven't yet found a use to do it any other way.

The idea of putting an action in the main timeline is that you can change the action and the occurrences will change... but in actual practice (at least in my workflow) this is rather pointless. Let's face it, the life of any scene is pretty ephemeral -- you render the scene and move on. An improvement to an action can and should be made, of course, but only in your "core" characters (which you'd load into a brand new scene).
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

The problem right now is that ANY actions in a bone layer will "break" the save script. The stupid actions are stuck INSIDE all the keys for the bones in the AS file format. I have to fix the code to skip over or ignore the section of actions before it will work.

This only came up since I am reading the file format. The actions change the structure of the file format.

Right now the script would only work on a bone layer that has ZERO actions. It won't take me long to do but I have to take a break from this right now.

-vern
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

Yikes! What a pain in the arse.

I got lost in the file format. It's like miscounting the number of streets before taking a right or left on some map directions. If you count wrong you could end up anywhere.

If I didn't read the exact line numbers in properly the whole script broke. The line numbers get "offset" and the values don't match. Eventually I just kept ticking it up one line at a time until I hit the right one.

--------
Right now the script works but skips over actions. If you save animation data from a file with actions it will load perfectly into another file with the same actions, it keeps the action reference. If you load into a file with no actions the key frame still indicates an "action" key frame but since the action is not there no channel information is imported. This is temporary until the next phase. (I have not uploaded this new version yet).

The next step is to grab the keys for the actions (if they exist) and save those keys so they can be read into an AS file and new actions created. This is the huge improvement. Saving and loading of actions.

Theoretically you will be able put all of your actions in actual actions with no main timeline keys at all. The actions will be saved to the animation data file. When imported those actions are created. that is the tricky part. There is action data at the beginning of the bone layer in the file format. however it should be simple since I can use the script interface to just create those actions on the fly.

Piece of cake! (yeah right).

Seriously though this will be very cool. Being able to save and import actions directly will be a big time saver. Create actions in actions if you want. When you save the animation data the actions will be saved in the animation data.

You won't have to import to the main timeline and then add to an action, unless you want to do that. The actions will be imported and created just like the keys. If the animation saved has no action data it will import just like before, as keys on the main timeline.

This is cool.... but I absolutely HATE reading the file format. It is SO easy to get lost reading lines in trying to find things and skip over things. The biggest problem was the stupid "keys" search. Actions use "keys" just like non action "keys". I have to break down the process to keep them separate. Real pain in the arse as I said. Knowing what I know now I am sure there is a better way to do this.

I seriously hope a future version adds actions to the script interface.

-vern
Last edited by heyvern on Fri Aug 01, 2008 4:20 am, edited 1 time in total.
User avatar
synthsin75
Posts: 10276
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

Sorry about that can of worms, Vern.

I have some idea what you're going through. It'd be nice if Mike could at least allow some better 'landmarks' in the file format. I looked at those action keys and nearly passed out. I know I couldn't dig them out of there.

Sounds like good progress though.
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

I realize my mistake now. What I should have done is parse the entire file into a table. Then I wouldn't have to count lines and do all that fiddly stuff. I could have used the brackets in the file format for the basis of creating the huge lua table of the whole file format... which could be why Mike used brackets in the file format in the first place.

Then I would have a cool bit of code for any purpose down the road unrelated to the key interpolation or actions. I would have a neat little function to access anything in the file format. I got lazy. <sigh> I could still do that of course.

-vern
User avatar
synthsin75
Posts: 10276
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

I had wondered about that vaguely. I don't quite understand how that helps find stuff though.
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

synthsin75 wrote:I had wondered about that vaguely. I don't quite understand how that helps find stuff though.
It helps because tables can be indexed or searched much easier.

If line 112, 237, 309 of the AS file all have the same text; "keys 2", there is no way to easily extract that value or find out it's meaning. However a few lines above that "keys 2" would be the name of the bone or action and then the skeleton, and then the layer etc.

So by putting this into a logically structured table with all the proper names and IDs as part of the table I could find for example the inerpolation of the translation key value for "bone 6" of layer "body" on frame 12.

(this is made up as an example)
for the example the table is called "fileFormat" and the table is indexed by the layer name. Each layer has a table for bones. Each bone is a table for the animation channels. Each channel is a table with a key frame each key frame has an interp value.

Code: Select all

fileFormat.layer["body"].bone[6].fPos[12].interp
If I called that it would return the position value of that key frame for bone 6. this probably isn't the best set up. You could also set it up to cross reference on the values as well. It would probably be easier to get all the stuff through the script interface into a table and only add the interp value.

Without using a table I have to scan the WHOLE file format from top to bottom looking for layer 3, then bone 6 then count through the identical "keys" values under bone 6 to determine which one is the "fPos" section, then read the frame number etc etc.. this is pretty much what I've got now. <sigh>. It still works... it's just not the easiest code to understand. A table would be better.

That is completely fictional example but shows how the table format is easier to access. Once everything is put in the correct spot you can use it like a look up for finding anything in the file... it's putting it IN that structure you have to plan out though.

This is a tough part of creating scripts. Trying to figure out the best "design" for the table so it's easy and fast to use.

-vern
User avatar
synthsin75
Posts: 10276
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

That sounds brilliant! Using the data from the file format and what's available in the scripting interface to make a 'complete' table. I'm sure that would be invaluable to future scripting endeavors.
Post Reply