"storing" Non-keyable bone properties or values?

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

Moderators: Víctor Paredes, Belgarath, slowtiger

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

"storing" Non-keyable bone properties or values?

Post by heyvern »

I hit a road block.

I was trying to modify a script from Rasheed that keys the z-depth of a layer based on a bone translation.

In my version it would "reverse" a constraint value. Change it from positive to negative and visa versa based on the translation of a bone.

The problem is that the constraint value is not a key-able value. So I can't access the "original" value. The script works but if you are on a key frame that reverses the constraint then you click directly on frame 0 the constraint stays reversed. It isn't keyed it just changes throughout the whole animation. It can't go back to the original value. So as you scrub through the animation the script still works but backwards. Until you do the same thing again.

Anyone have any ideas on how I might be able to possibly "save" or "store" these values? Can't use a variable on frame 0 because it runs on frame 0 and will reverse the values again in the same situation.

I was thinking of actually putting the value in the name of the bone somehow... like;

Bone.revconN
Bone2.revconP

revcon is the extension identifying the "reversible" constraint bone. N would be "negative" and P would be "positive". So it would check this value to determine what the constraint value should be at any specific point.

Since the constraint value doesn't change only the negation, this might work... but if there is an easier way I'm all ears.

This is a toughy. Shame too since it was working so well.

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

Post by heyvern »

Yeehaaa!

Well that worked fine!

Just have to make sure to add that "P" or "N" to the end of the bone name depending on the value of the constraint.

cool!

This might be nice way to identify values that can't be tracked any other way. Just tag an identifier on the end of the bone name or layer name or whatever.

-vern
User avatar
Rasheed
Posts: 2008
Joined: Tue May 17, 2005 8:30 am
Location: The Netherlands

Post by Rasheed »

That is the power of Lua. Because everything is an object, you can add new values to existing objects.

Try this layer script:

Code: Select all

function LayerScript(moho)
    SetReverseLayerName(moho)
    print ("reversed layer name: \"" .. moho.layer.fRevName .. "\"")
end

function SetReverseLayerName(moho)
    local layer = moho.layer
    local name = layer:Name()
    local revName = ""
    for i = 1, string.len(name) do
        local c = string.sub(name,i,i)
        revName = c .. revName
    end
    layer.fRevName = revName
end
The function SetReverseLayerName adds a value to the current layer (moho.layer), namely fRevname (the reversed name). The layer script calls this function and prints the fRevName value of the current layer.

You can even make the function more general:

Code: Select all

function SetReverseName(object)
    local name = object:Name()
    if (name == nil) then
        return
    end
    local revName = ""
    for i = 1, string.len(name) do
        local c = string.sub(name,i,i)
        revName = c .. revName
    end
    object.fRevName = revName
end
This means that if an object has a Name() member function, it will have a fRevName member value added to it.
User avatar
Rasheed
Posts: 2008
Joined: Tue May 17, 2005 8:30 am
Location: The Netherlands

Post by Rasheed »

You can even add member functions to an existing object:

Code: Select all

function LayerScript(moho)
    SetRevName(moho.layer)
    print("Reversed layer name: \"" .. moho.layer:RevName() .. "\"")
end

function SetRevName(object)
    object.RevName = dummy
end

function dummy(self)
    local name = self:Name()
    if (name == nil) then
        return
    end
    local revName = ""
    for i=1, string.len(name) do
        local c = string.sub(name,i,i)
        revName = c .. revName
    end
    return revName
end
The member function RevName is added to moho.layer by the SetRevName function. You could even pass parameters to this function, by this mechanism:

Code: Select all

function SetRevName(object, parameter1, parameter2)
    object.RevName = dummy
end

function dummy(self, parameter1, parameter2)
    ...
end
I will try to device a mechanism to add member values and member functions to existing objects, and put that in a new thread. This way future script writers can be referred to this new thread.
User avatar
Rasheed
Posts: 2008
Joined: Tue May 17, 2005 8:30 am
Location: The Netherlands

Post by Rasheed »

I just had another idea. You want to make non-keyable properties, such as bone constraints, keyable. This means you would have to add member values and member functions to the class from which an object is derived (instantiated) from.

So, perhaps I should also include how to add values and functions to existing classes, next to how to add values and functions to existing objects (remember, classes are prototypes, and all objects inherit the same properties as the class they are instantiated from).

If I'm able to do that, and I put this into an utility script, all AS bones on your computer would have keyable bone constraints, and you could use a keyed bone constraint as follows:

Code: Select all

local constraint = bone.fAnimPosControlScale:GetValue(when)
constraint.x, constraint.y = -constraint.x, -constraint.y
bone.fAnimPosControlScale:SetValue(moho.frame, constraint)
bone.fPosControlScale = constraint -- alas necessary
You would still have to update your fPosControlScale value manually, but you would also have a (virtual) animation channel for your unkeyable properties.

NB This fAnimPosControlScale member value doesn't exist at this moment, and it will never have a representation on the timeline, but I think it is possible to implement such an AnimVal object, which behaves exactly the same as the fAnimPos (that does exist), and has GetValue and SetValue member functions. Cloning the properties of one object to another isn't very hard to do in Lua.
User avatar
Rasheed
Posts: 2008
Joined: Tue May 17, 2005 8:30 am
Location: The Netherlands

Post by Rasheed »

There is a serious complication. All AS objects are of the type userdata. This means that adding new features to existing AS classes is a bit more difficult than I initially thought. I have to look into this more thoroughly before I can create new class functions and values.
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

Don't forget I made your script thread "sticky" so you can post your gems in there now.

;)

-vern
User avatar
Rasheed
Posts: 2008
Joined: Tue May 17, 2005 8:30 am
Location: The Netherlands

Post by Rasheed »

I know. Thanks, Vern :)

Until now, I haven't been able to access the C classes directly.

I can transfer a moho object into a table, though, so I can see what values and functions are available for a particular moho object:

Code: Select all

local moho_table = getmetatable(moho_object)
for i,v in pairs(moho_table)
    print(i, type(v) )
end
That's useful, but I don't seem to be able to reach the prototype of an Moho object. I'm afraid it's locked down for the Lua interface, so the application can't be modified through Lua. I guess that is a good safety feature, which prevents evil scripts doing bad things to your computer, but it also prevents me from modifying existing classes for good purposes, namely to enhance AS with new functionality. It seems that can only be done through the original source code, which is, as we all know, closed.
Post Reply