Set Key on Main Timeline but not Action timelines

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

Moderators: Víctor Paredes, Belgarath, slowtiger

Post Reply
GaryC
Posts: 53
Joined: Tue Feb 03, 2015 1:02 pm

Set Key on Main Timeline but not Action timelines

Post by GaryC »

I have an old layerscript to embed in switch layers that I've updated and tweaked a bit to add more functionality to, but I've come across a problem with it adding keys to action timelines.

The gist of the script is that it will find pairs of folders and take a key from the master layer and apply it to a slave layer. So whatever you set the master layer to be, the slave will always match that key.

However I've recently had a problem where actions' timelines will also have these keys set in them, instead of just the main timeline. Which is obviously a problem as I don't want the actions to get filled up with keys that should be only on the main timeline. What's confusing is that the docs don't seem to indicate any ways to distinguish an action timeline from the main timeline when setting a value on a switch animation channel. I'm not sure if I'm doing something wrong or I need to take special care to avoid this happening.

Here's the snippet where the keys actually get set (layer is the master layer and then switch is the layer that's being updated)

Code: Select all

        if layer:SwitchValues():HasKey(frame) then
            local switchName = layer:SwitchValues():GetValue(frame)
            switch:SwitchValues():SetValue(frame, switchName)
        end
Can anyone think why this might not be working?
User avatar
synthsin75
Posts: 9972
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: Set Key on Main Timeline but not Action timelines

Post by synthsin75 »

Is this script also editing actions, or are you running it from an open action? If not, I don't know how you are opening an action for editing.
GaryC
Posts: 53
Joined: Tue Feb 03, 2015 1:02 pm

Re: Set Key on Main Timeline but not Action timelines

Post by GaryC »

It's a layerscript, so it's embedded in a switch layer. Not run from any actions.

After digging deeper, it's oddly specific. It doesn't always happen and seems to be tied specifically to being placed inside bone layers. This is the structure that definitely triggers it:

Code: Select all

Bone Layer
    > Switch Layer (with script embedded)
    > Bone Layer (with Smart Bone actions)
        > Switch Layer (that script targets)
    > Bone Layer (with Smart Bone actions)
        > Switch Layer (that script targets)
In that layer structure, the timelines for the smart bone actions on those bone layers end up being keyed too. Given that it's more specific and confusing than I first thought, it likely has more to do with how I find the target folders.

I have the full script below. As I said it's based on someone else's script, I just added the ability to target multiple slave layers and to target layers that are nested deeper in folders. So it recursively searches through all the folders adjacent to the master layer (the switch with the script embedded in it) and will add keys to any switch slave layer it finds. It's possible that somehow the recursion is finding the other timeline, but I'm unclear how that would happen and how to avoid it.

Code: Select all

function LayerScript(moho)
    -- ************************************************************
    -- SlaveSwitch (c)2005 B. Quinn
    --     Updates (c)2016 G. Chadwick
    --
    -- Can now deal with slaves being nested in folders.
    -- And can operate on multiple slaves.
    -- 
    -- V 3.0
    -- ************************************************************

    local frame = moho.frame
    local layer = moho:LayerAsSwitch(moho.layer)
    if layer == nil then return end
    local target = layer:Name() .. ".sslv"
    local layers = {}
    local layerCount = 0

    local function searchAllChildren(currentLayer, moho, layerCount, layers)
        for count = 0, currentLayer:CountLayers() - 1 do
            local testLayer = currentLayer:Layer(count)
            
            -- return if it matches target
            if (testLayer:Name() == target) then
                layers[layerCount] = moho:LayerAsSwitch(testLayer)
                layerCount = layerCount + 1
            else
                testLayer = moho:LayerAsGroup(testLayer)
                if (testLayer ~= nil and testLayer:CountLayers() > 0) then
                    layerCount, layers = searchAllChildren(testLayer, moho, layerCount, layers)
                end
            end
        end
        return layerCount, layers
    end

    local parent = layer:Parent()
    local currentLayerGroup
    if (parent == nil) then
        currentLayerGroup = moho.document
    else
        currentLayerGroup = moho:LayerAsGroup(parent)
    end
    layerCount, layers = searchAllChildren(currentLayerGroup, moho, layerCount, layers)
    
    --These make sure to adjust the value of a keyframe if it exists and if none exists make sure to not create one.
    for i, switch in pairs(layers) do
        if layer:SwitchValues():HasKey(frame) then
            local switchName = layer:SwitchValues():GetValue(frame)
            switch:SwitchValues():SetValue(frame, switchName)
        else
            switch:SwitchValues():DeleteKey(frame)
        end
    end	
end
GaryC
Posts: 53
Joined: Tue Feb 03, 2015 1:02 pm

Re: Set Key on Main Timeline but not Action timelines

Post by GaryC »

On further inspection I have finally cracked it. Re-thinking what you said synthsin, it is correct. It seemed like the keys were being added to the main and action timelines at the same time, but it was actually only causing a problem when I would open the action's timeline.

I can embed the script, use it a bit and then remove it without opening the smart action timeline at all. Then it's perfectly fine. It's only an issue when I have the script still embedded and I open the smart action timeline, because then it starts adding the keys. It seems that the timelines are just considered to be the same, so Anime Studio will add the keys regardless of what timeline it is. Thanks for the point that made me rethink an assumption.
User avatar
synthsin75
Posts: 9972
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: Set Key on Main Timeline but not Action timelines

Post by synthsin75 »

Sounds like you just need to make sure it doesn't run in an action. Just make the keyframing bit dependent on this:

if (moho.layer:CurrentAction() == "") then

This means there is no active action.
GaryC
Posts: 53
Joined: Tue Feb 03, 2015 1:02 pm

Re: Set Key on Main Timeline but not Action timelines

Post by GaryC »

Strange, I tried that method but it's just constantly returning empty strings. I've just decided for now to detach the script if I need to edit smart actions, but to otherwise not open up the smart actions. This way the script wont do anything to it anyway.
User avatar
synthsin75
Posts: 9972
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: Set Key on Main Timeline but not Action timelines

Post by synthsin75 »

GaryC wrote:Strange, I tried that method but it's just constantly returning empty strings. I've just decided for now to detach the script if I need to edit smart actions, but to otherwise not open up the smart actions. This way the script wont do anything to it anyway.
That's the point. If moho.layer:CurrentAction() returns an empty string then you are on the main timeline, and it's safe for your script to run its code. If you're in an action, it will return the action name. "" means an empty string.
GaryC
Posts: 53
Joined: Tue Feb 03, 2015 1:02 pm

Re: Set Key on Main Timeline but not Action timelines

Post by GaryC »

synthsin75 wrote:
GaryC wrote:Strange, I tried that method but it's just constantly returning empty strings. I've just decided for now to detach the script if I need to edit smart actions, but to otherwise not open up the smart actions. This way the script wont do anything to it anyway.
That's the point. If moho.layer:CurrentAction() returns an empty string then you are on the main timeline, and it's safe for your script to run its code. If you're in an action, it will return the action name.
I meant regardless of whether I'm in a Smart Action or not it gave an empty string. On double checking, it does print the name of a morph action, it's the smart bone actions that just return empty strings. So there's presumably some difference between the types.
User avatar
synthsin75
Posts: 9972
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: Set Key on Main Timeline but not Action timelines

Post by synthsin75 »

GaryC wrote:I meant regardless of whether I'm in a Smart Action or not it gave an empty string. On double checking, it does print the name of a morph action, it's the smart bone actions that just return empty strings. So there's presumably some difference between the types.
If the action, smart bone or otherwise, shows in the actions windows for that layer, moho.layer:CurrentAction() will give the action name. Are you checking the layer you don't want to keyframe in an action? Actions exists for each layer, so you have to check for the relevant layer/s.
Post Reply