Can ASP control a switch, based on its bone angle?

Wondering how to accomplish a certain animation task? Ask here.

Moderators: Víctor Paredes, Belgarath, slowtiger

ruibjr
Posts: 113
Joined: Mon Apr 20, 2009 12:29 am
Location: Brazil

Post by ruibjr »

That's awesome.

Thanks, Genete.

Vern, any ideas on why the shape won't rotate, and is there a way to make it work with any control bone?
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

ruibjr wrote:Vern, any ideas on why the shape won't rotate, and is there a way to make it work with any control bone?
These are switch layers. You would need to bind the switch to a bone so you can rotate the whole switch. Genete mentioned in his last post that he would be working on that. Most likely it will need a special name for the bone and switch layer to "match" them up.

-vern
Last edited by heyvern on Tue Apr 21, 2009 6:37 pm, edited 1 time in total.
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

Thanks Gente!!!!!! It works GREAT now! Woooohooooo! This is great! I always wanted this script for switching hands and other things.

-vern
User avatar
rylleman
Posts: 750
Joined: Tue Feb 15, 2005 5:22 pm
Location: sweden
Contact:

Post by rylleman »

What a useful script!, thanks you guys.

For the control bone, couldn't you use one called nameofswitchlayer.control? If one doesn't exist, automatically create one in the topmost bone layer.

Too bad you can't create note-layers by lua, would be nice to have one close to the control-bone with the name of the current switch-layer.
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

heyvern wrote:Thanks Gente!!!!!! It works GREAT now! Woooohooooo! This is great! I always wanted this script for switching hands and other things.

-vern
Nah! not much code there!. Just a bit of maths.

I left you or others to try to use other bones than the bone 0 to control the switch layer.

One proposal for that:
The control bone's name must be the same than the switch layer name that want to control. Using bone 0 every switch layer would turn with it, what is not useful.
Also I think that it would be interesting to have the control bone and the script in the switch layer. It would allow to have other script in the bone layer (that's very important in some circumstances)
Maybe I can do something on those proposals.
-G
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

1) Save as Switcher.lua
2) Embed it in a switch layer
3) The bone number 0 in the switch layer controls the switch value.
4) Keyframes on the switch layer seems to be updated after press play.
5) It doesn't work for negative turns. I've tried to enable it but failed.
6) You can embed a script in each switch layers what gives control independence.
7) Move the bone keys and the switch keys will follow.

Based on first script from heyvern.

I hope you like it.
-G

Code: Select all

function LayerScript(moho)

    local layer = moho.layer
    if (not layer:IsBoneType()) then
        return
    end

    local group = moho:LayerAsGroup(layer)
    local layerCount = group:CountLayers()
    if ( layerCount == 0 ) then
        return
    end

    local skel = moho:Skeleton()
    local boneCount = skel:CountBones()
    if ( boneCount == 0) then
        return
    end

    local SwitchLayer = moho:LayerAsSwitch(layer)
    if(SwitchLayer==nil) then
        return
    end

    local crtlBone = skel:Bone(0)
    local keySwitch = nil
    local Oneturn = math.rad(360)
    local TurnsPerLayer = Oneturn /layerCount
    if ( moho.frame > 0 ) then
        if ( crtlBone.fAnimAngle:HasKey(moho.frame) ) then
            keySwitch = math.mod(crtlBone.fAngle,Oneturn)
        end
        for b = 0, layerCount-1 do
            local swLayer = group:Layer(b)
            local swName = swLayer:Name()
            if ( keySwitch ~= nil ) then
                local Bottom = b * TurnsPerLayer
                local Top = TurnsPerLayer + Bottom
                if (keySwitch <= Top and keySwitch >= Bottom) then
                   SwitchLayer:SwitchValues():AddKey(moho.frame)
                   SwitchLayer:SwitchValues():SetValue(moho.frame, swName)
                end
             elseif ( keySwitch == nil) then
                    SwitchLayer:SwitchValues():DeleteKey(moho.frame)
            end
        end
    end
end
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

Btw, all those scripts are just a workaround for a better interface that allows easy visual selection of the switch layer. It should be added as main feature in the next version but with the proper interface and not need to sacrifice to use a script in the switch layer to achieve the feature.

-G
ruibjr
Posts: 113
Joined: Mon Apr 20, 2009 12:29 am
Location: Brazil

Post by ruibjr »

I am so glad I found this forum.

Thank you so much.
This is amazing.
And you guys are so proactive. This is trully amazing.

On the better inteface for switching, I think besides having that, we still can use this script.

The way I plan to use it is to implement it in every problematic connection, such as the knees and the elbows.
This script allows me to hand-draw the specific drawing for each problematic angle range.
This way, I can simply rotate the lower arm bone and have the script select the perfect drawing for a perfect macth.
So, we can build characters that look perfect every tme, without having to worry about bone bending, loops and collapsing.

Thanks Vern, Thanks Genete, thank you so much.

SO cool. And useful.
Thans, guys.
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

That's a fantastic idea ruibjr!!!!

The angle of the limb itself controls the switch.

This should be done with a modified script though. Instead of evenly spaced rotations selecting a random number of layers in the switch you would want to put in SPECIFIC rotation values that only change the switch layer when that angle is reached.

COOOL idea. With smooth interpolation of switches this would be a great way to adjust joints on limbs as bones turn.

-vern
ruibjr
Posts: 113
Joined: Mon Apr 20, 2009 12:29 am
Location: Brazil

Post by ruibjr »

That would be perfect, I mean, being able to specify the actual angles.

But the script is most useful already, the way it is.
What I am going to do, is I am going to use 10 options for each limb; every time.
Then, I can simply replicate the "default" shape for the lower arm (for example) 10 times.
This will result in one different image for each 36 degrees "slice", which I believe will be pretty good.
Then, I can go and edit the ones that are looking bad.
I will try this technique and will let you know what kind of results I get.
Cheers.

edit
==============
As a matter of fact, most limbs will rotate about 120 to 140 degrees, so the accuracy would be of about 12 to 14 degrees - pretty good, actualy.
==============
/edit
ruibjr
Posts: 113
Joined: Mon Apr 20, 2009 12:29 am
Location: Brazil

Post by ruibjr »

Guys,

Do you think it is possible to retrieve the control bone's angle constraints?
Like, for instance, if one limits the rotation to -10 to +120 degrees.
This would allow the script to divide that actual range (130 dgrees) by the (say) 10 options in the switch layer, instead of dividing the full 360 degrees.
This would be incredibly useful.
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

ruibjr wrote:Guys,

Do you think it is possible to retrieve the control bone's angle constraints?
Like, for instance, if one limits the rotation to -10 to +120 degrees.
This would allow the script to divide that actual range (130 dgrees) by the (say) 10 options in the switch layer, instead of dividing the full 360 degrees.
This would be incredibly useful.
It doesn't work for negative values but why don't you do it externally? the control bone can be also controlled by other bone that can be angle limited, and angle scaled to the control bone.

For example:
b= bone that control the script
c= bone that you effectively would animate
limit c.angle to [0,130]
b.angle=360/130*c.angle
Then to offset the bone c just make it child of a bone that actually is rotated -10 deg. And voila! your control bone is in the range of -10,120 and controls all the sublayers of the switch layer!
:D
-G
ruibjr
Posts: 113
Joined: Mon Apr 20, 2009 12:29 am
Location: Brazil

Post by ruibjr »

That is a very clever solution, Genete.

Thanks for sharing the idea.
ruibjr
Posts: 113
Joined: Mon Apr 20, 2009 12:29 am
Location: Brazil

Post by ruibjr »

Hi guys.

I was able to make it work exactly the way I needed.

Here is the script:

Code: Select all

function LayerScript(moho)
    ------------------------------------------------------------------------------------------
    local layer = moho.layer
    if ( not layer:IsBoneType() ) then
        return
    end
    ------------------------------------------------------------------------------------------
    local group = moho:LayerAsGroup(layer)
    local layerCount = group:CountLayers()
    if ( layerCount == 0 ) then
        return
    end
    ------------------------------------------------------------------------------------------
    local skel = moho:Skeleton()
    local boneCount = skel:CountBones()
    if ( boneCount == 0) then
        return
    end
    ------------------------------------------------------------------------------------------
    local ctrlLayer = nil
    local ctrlBone = nil
    local keySwitch = nil
    local Lcount = nil
    local SWunits = nil
    local keySwitch = nil
    local nextBone = nil
    local theBoneName = nil
    local tUnit = nil
    ------------------------------------------------------------------------------------------
    for nextBone = 0, boneCount - 1 do
        ctrlBone = skel:Bone(nextBone)
        theBoneName = ctrlBone:Name()
        if (string.sub(theBoneName, 1, 3) == "cb.") then
            tUnit = ctrlBone.fMaxConstraint - ctrlBone.fMinConstraint
            if (moho.frame > 0) then
                local subSwitch = nil
                if (ctrlBone.fAnimAngle:HasKey(moho.frame)) then
                    keySwitch = ctrlBone.fAngle
                    keySwitch = keySwitch - ctrlBone.fAnimAngle:GetValue(0) - ctrlBone.fMinConstraint
                end
                Lcount = -1
                for i = 0, layerCount - 1 do
                    local testlayer = group:Layer(i)
                    if (testlayer:LayerType() == MOHO.LT_SWITCH) then
        	        if (testlayer:Name() == theBoneName) then
                            group2 = moho:LayerAsGroup(testlayer)
                            subSwitch = moho:LayerAsSwitch(testlayer)
                            Lcount = group2:CountLayers()
                            SWunits = tUnit / (Lcount)
                            break
                        end
                    end
                end
                if (Lcount > 0) then
                    for b = 0, Lcount - 1 do
                        local swLayers = group2:Layer(b)
                        local SWname = swLayers:Name()
                        local swUnit = (b * SWunits)
                        local swUnitB = swUnit + SWunits
                        if ( keySwitch ~= nil) then
                            if (keySwitch <= swUnitB and keySwitch >= swUnit) then
                                subSwitch:SwitchValues():SetValue(moho.frame, SWname)
                            end
                        elseif ( keySwitch == nil) then
                            subSwitch:SwitchValues():DeleteKey(moho.frame)
                        end
                    end
                end
            end
        end
    end
    ------------------------------------------------------------------------------------------
end
It was built on top of HeyVern's original script.
It also includes the changes made by Genete.

Here's how it works:

Just give all limb control bones names that start with "cb.", which stands for "control bone".
Then, create the switch layer that you want to control, as usual, and give it the exact same name you have assigned to the bone.

You can have as many limbs, controlling their corresponding switch layers as you wish.

The script takes care of computing the angle constraints, to give you the best angle-to-switch ratio (a typical 120 degrees limb with 6 optional drawings will result in a 20 degrees accuray - pretty good).
You can use as many optional drawing as you want - it just works.

The onlye three things you have to pay attention to are:

1. You must attach this script to the bone layer
2. You must name the control bones starting with cb.
3. The switch layers must have the same name as the control bones

Thank you so much, guys.
Cheers.
[/code]
User avatar
Víctor Paredes
Site Admin
Posts: 5818
Joined: Wed Jan 26, 2005 12:18 am
Location: Barcelona/Chile
Contact:

Post by Víctor Paredes »

Hey, I didn't know the existence of this script (I just found it via animatorsforums).
It's fantastic, I really don't like to be going over and over to the layer window (I don't like much the menu use of secundary click neither), so it's just perfect.


Thanks!
Image Image Image Image Image Image
Moho co-owner

Previously Rigged animation supervisor: My father's dragon, Wolfwalkers & Star Wars Visions "Screecher's Reach"
My personal Youtube Channel
Post Reply