Animating shape stack ordering, proof-of-concept

Moho allows users to write new tools and plugins. Discuss scripting ideas and problems here.

Moderators: Víctor Paredes, Belgarath, slowtiger

Post Reply
poetbeware
Posts: 11
Joined: Sun Dec 03, 2006 2:15 am

Animating shape stack ordering, proof-of-concept

Post by poetbeware »

The following script, if embedded in a vector layer, raises the shape on the very bottom to the very bottom every time the frame changes:

Code: Select all

function LayerScript(moho)
        local mesh = moho:Mesh()
        if (mesh == nil) then
                return
        end

        if (mesh:CountShapes() <= 0) then
                return
        end

        mesh:RaiseShape(0, true)
end
So it would appear that it's possible to use scripting to provide a "shape stack ordering". This is made more difficult, though not impossible, by the fact that there's no programmatic access to shapes' names.

My idea is to reify the shapes of one layer in a group layer. That is, if you have a layer "Person" whose stacking order you want to animate, you would select your Person layer then click the "Animate Shapes" tool. That tool would create a new Group Layer, set to invisible, called "Person Shapes". The Person Shapes layer would be automatically populated with one sublayer per shape in the original Person layer. Each sublayer would contain a duplicate of the shape at frame zero. These duplicate shapes would not be rendered (the Group Layer would be set to invisible). However, since the shapes are exact duplicates of the Person layer shapes, an embedded script could match group-sublayers to shapes in the original layer.

One could then animate the shape stack ordering for the Person layer by modifying the Z coordinates of the shape sublayers. The embedded script would, for every frame, create an array of shapes ordered by the Z coordinates, and then iterate over the array, invoking raiseToFront.

To make the example more concrete: Let's say you have a Person layer, that has five shapes: Left Leg, Right Leg, Body, Left Arm, Right Arm. Then after using the Animate Shapes tool on the Person layer, your layers would look like:

Code: Select all

+ Person
+ Person Shapes
---+ Left Leg
---+ Right Leg
---+ Body
---+ Left Arm
---+ Right Arm
...where only the Person Layer is visible.

This technique would provide a number of advantages:

1. It's persistent across loading and saving of the document. The only caveat is, if you change a shape, you'd have to somehow re-save that shape into the group layer.
2. Each shape gets its own animation channel for stack ordering; altering the ordering happens with ordinary keyframes. So working with this should be intuitive.
3. By making Person invisible and Person Shapes visible, you can see the stack ordering as you're animating it.

Can any of the script gurus out there think of a reason why this won't work? It's going to take some effort...
User avatar
Rasheed
Posts: 2008
Joined: Tue May 17, 2005 8:30 am
Location: The Netherlands

Post by Rasheed »

Not seeing myself as a script guru, I can see a real problem (or restriction) to this solution.

What if the shapes are put on a mesh that consists of points that are all connected with each other? If you rip the points from the shapes' layer to a new layer, the shape is lost, and you have to re-apply the shape to the new points. Furthermore, the form of the new mesh will probably deviate from the sub form in the original shapes' layer.

So, the restriction would be that you must draw each shape using a separate group of connected points. In that case you could just as well have drawn each shape in its own layer. Then the problem is layer ordering, and that problem has been solved, see Order layers by true distance? NO PROBLEM.

The solution really has to come from the developer. I can see two prerequisites:
  1. shape names should be accessible through the scripting interface
  2. scripts should have the possibility to store data inside a layer
The first prerequisite is clear. The second is necessary to tell the script how to deal with each shape during the animation and store that permanently into the file, so you don't have to redo this every time you reload the document containing the layer script. You could hard code this into the script, but that would require the user to have scripting abilities, and that limits the user base of such a solution.
poetbeware
Posts: 11
Joined: Sun Dec 03, 2006 2:15 am

Post by poetbeware »

What if the shapes are put on a mesh that consists of points that are all connected with each other?
That is the scenario I'm thinking of.
If you rip the points from the shapes' layer to a new layer, the shape is lost, and you have to re-apply the shape to the new points.
No. Part of the code I intend to write automates this process. It would duplicate a shape on one layer in a new layer, without erasing the shape or its points in the original layer.
The solution really has to come from the developer.
I agree, but the developer isn't saying when the next release is coming, nor what changes it will include. So I'm looking for a partial solution.
1. shape names should be accessible through the scripting interface
This could be done by parsing the .anme file, though you'd have difficulties if you renamed shapes after the fact.
scripts should have the possibility to store data inside a layer
My approach above is to store the data in a "parallel layer". If I had the shape names, then I could just name empty switch sublayers with the stack orders I want and animate the switch.
You could hard code this into the script, but that would require the user to have scripting abilities, and that limits the user base of such a solution.
And also isn't fast enough for my own use. I'm looking for something fast to apply, at least after your character is mostly designed (its shapes are unlikely to change).

Parsing the .anme file is probably faster than duplicating all the shapes into sublayers, though, and I just checked the file format, which seems simple enough to parse. Hm.

Thanks...
Post Reply