Group layer Depth Sort: Sort layers by Y-Position

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

Moderators: Víctor Paredes, Belgarath, slowtiger

Daxel
Posts: 1081
Joined: Wed Mar 27, 2019 8:34 pm

Re: Group layer Depth Sort: Sort layers by Y-Position

Post by Daxel »

Thank you! It means a lot coming from some of the people I've learnt from (:
User avatar
gilcartunista
Posts: 55
Joined: Mon Mar 14, 2016 7:13 pm
Location: https://www.facebook.com/gil.cartunista
Contact:

Re: Group layer Depth Sort: Sort layers by Y-Position

Post by gilcartunista »

Dear Daxel, it would be possible to post an example file, as I still can't understand ... thank you.
Daxel
Posts: 1081
Joined: Wed Mar 27, 2019 8:34 pm

Re: Group layer Depth Sort: Sort layers by Y-Position

Post by Daxel »

I'm not allowed to share this rig, but It will be more useful to explain it. I don't know how much experiece you have but I will try to explain for begginers, so they can benefit. If you don't have experience with smartbones, then start learning that first, and come here later. This is a more advanced technique that makes use of them.

How to download and install the script

This layer sorting system is only possible thanks to LK_SortByZScaleSSamFix, a script made by Lukas and fixed by SimplSam that I uploaded here: https://1drv.ms/u/s!AiyKCw6Xey5TgZR_AfevEDlXwQQBVw

There are different types of scripts, but this one is a layer script that is only activated this way: open a layer's settings and, at the bottom of the General tab, you have the option to use an embbeded script. Select this script, press apply, and that's it.


Function of this script

It sorts the layers by their Z scale value, a number that you can see, edit or keyframe selecting one layer and then the Layer Transform Tool. The Z scale value doesn't have a purpose for 2D and that's why Lukas decided to use it to control the layer order with this script.
You don't need to activate the script on all the layers. You activate it on a parent layer like a group or a bone layer, and all its children layers are automatically sorted by their Z scale value, so the layers that have a higher Z scale value will be seen on top, and you can keyframe their Z scale value at any given time to change the layer's order.


Controlling the Z scale value with smartbones

Now that you have a parent layer with the script activated, the layer order of its children layers will depend on their respective Z value, that you can manually change with the Transform Layer Tool, but as you probably know, you can also control almost any keyframeable value with a smartbone. So the idea is to have a bunch of smarbones that are set to control the Z values (and therefore the order) of each layer just rotating the smartbone at any given time. It helps to make them horizontally, and that the layer's Z scale value is set higher the higher the smartbone is pointing. This will make easier to visually understand and control them, but there will be moments where you have too many layers and it will be harder to see wich smartbones are pointing higher or lower, and wich layers correspond to each of those smartbones, and that's why I made the HalfMoon System, just to make it easier to see and control.


The HalfMoon System

The trick is to use target bones. Any bone can be set to be a target bone of another particular bone, and then this particular bone will always automatically be pointing at the target bone.
We will create a pin bone, and then select one of those smartbones we created to control the Z scale of some layer, and open the Bone Constraints panel, look for the Target option and select the pin bone that you want to set as the target. From now on, the smartbone will always automatically point to the target bone, so now you can control the layer order moving that pin bone up and down. If you arrange the smartbones and the target pin bones like in this photo, you can always see, understand and control the layer order in a second.
To differenciate between these Z scale controlling smartbones and smartactions and the ones controlling the actual body parts positions, I named them Z ______. For example: Z Arm Left for the smartbone, always the same name for its smartaction, and Arm Left Z for its target pin bone. That's just a tip to make your life easier.


I will keep experimenting with this system, and it may have perks or limitations that I still haven't noticed, and this could probably be improved so any suggestions are welcomed.
One little annoyance that it has is that when you change the Z scale vale on, lets say, the frame 24, it needs another frame to process the change and sort the layers, so the order will actually change on the frame 25. Once you know this, you can just remember to make the keyframe one frame before you need the change. If someone knows how to modify the script to make the change on the same frame, that would be nice. And of course if Victor and Mike are reading this, as you already know, layer sorting is one of the things that give us more work and headaches, so any improvement on this area would be amazing.
User avatar
Lukas
Posts: 1336
Joined: Fri Apr 09, 2010 9:00 am
Location: Netherlands
Contact:

Re: Group layer Depth Sort: Sort layers by Y-Position

Post by Lukas »

hayasidist wrote: Sun Feb 07, 2021 11:06 am
Lukas wrote: Tue Jun 23, 2020 9:08 am
Daxel wrote: Sat May 23, 2020 2:22 amI'm using your script and it is amazingly useful, but I keep getting this error "LK_sortByZScale.lua:20: attempt to call method 'Layer' (a nil value)" very often.
'''
Sorry, I don't have any time to look into it, but I'll try and remember to check it out some other time.
I think SimplSam has cracked the "attempt to call method 'Layer' (a nil value)" issue .. http://www.lostmarble.com/forum/viewtop ... 12&t=33764
Oh nice! Thanks SimplSam :)

Nice work Daxel, that's an interesting way of using the script
User avatar
lucasfranca
Posts: 180
Joined: Sat Oct 07, 2017 11:47 pm

Re: Group layer Depth Sort: Sort layers by Y-Position

Post by lucasfranca »

Oh my God, I didn't know I needed this until I met**
An old guy [since 1983] who was raised in front of the TV.
Passionate about animation, after getting old, he decides to make it his hobby.

I share tutorials, reviews, tips and tricks from this vast world of animation on my channel.

https://youtube.com/animai2D
User avatar
lucasfranca
Posts: 180
Joined: Sat Oct 07, 2017 11:47 pm

Re: Group layer Depth Sort: Sort layers by Y-Position

Post by lucasfranca »

Eagerly waiting for update to Mh 14.2.
An old guy [since 1983] who was raised in front of the TV.
Passionate about animation, after getting old, he decides to make it his hobby.

I share tutorials, reviews, tips and tricks from this vast world of animation on my channel.

https://youtube.com/animai2D
User avatar
Lae82
Posts: 37
Joined: Tue May 02, 2023 5:44 pm
Location: Sweden

Re: Group layer Depth Sort: Sort layers by Y-Position

Post by Lae82 »

Thank you Lukas! Two thumbs up. You really help improving moho workflows and solving production problems.
User avatar
bibendumchamalow
Posts: 24
Joined: Mon Jul 05, 2021 9:15 pm

Re: Group layer Depth Sort: Sort layers by Y-Position

Post by bibendumchamalow »

ImageHi everyone, I'd like to share my research inspired by the scripts "LK_SortByYPos" and "LK_SortByZScale" by Lukas Krepel.

To simplify and expand upon these concepts, I've developed a script that utilizes a tagging system within the names of group layers or bone layers. The goal is to automatically organize child layers based on their positions along the X, Y, Z axes, or by their ZScale (where larger scales bring the layer to the foreground and smaller scales push it to the background).

To use this script, simply load the AC_SortByTag.lua script through the embedded script options in a group or bone layer. This script dynamically and automatically organizes the order of layers according to different modes (X, Y, Z, ZScale) based on the tags in the layer's name.

You can rename the group layer as you wish, but it must include one of the following tags: "_X", "_Y", "_Z", or "_ZScale". Additionally, you can add a "_Reverse" tag to any of these to invert the sorting order, regardless of the mode. For example, renaming a layer to "LayerName_ZScale_Reverse" will sort the layers by ZScale in reverse order.

Code: Select all

-- **************************************************
-- Script Name: AC_SortByTag.lua
-- Original Script: "LK_SortByYPos" and "LK_SortByZScale" by Lukas Krepel
-- Modified and Extended by: Alexandre Cousin
-- Assistance Provided by: ChatGPT
-- Description: This script allows sorting of child layers within a group or bone layer based on X, Y, Z position, or Z scale, determined by a tag in the group's name or a preset mode. It can also reverse the order if a '_Reverse' tag is present.
-- **************************************************

function LayerScript(moho)
    -- Check the layer type
    if (moho.layer:LayerType() == MOHO.LT_GROUP or moho.layer:LayerType() == MOHO.LT_BONE) then
        local thisLayer = moho:LayerAsGroup(moho.layer)
        thisLayer:EnableLayerOrdering(true)
        local order = {}
        local layerOrderChan = thisLayer:GetLayerOrdering()

        -- Sorting mode - default is ZScale, or determined by a tag in the layer's name
        local sortMode = "ZScale"
        local layerName = moho.layer:Name()

        -- Conflict resolution: check for ZScale before Z
        if string.find(layerName, "_ZScale") then
            sortMode = "ZScale"
        elseif string.find(layerName, "_X") then
            sortMode = "X"
        elseif string.find(layerName, "_Y") then
            sortMode = "Y"
        elseif string.find(layerName, "_Z") then
            sortMode = "Z"
        end

        -- Check if reverse order is needed
        local reverseOrder = false
        if string.find(layerName, "_Reverse") then
            reverseOrder = true
        end

        for i = thisLayer:CountLayers() - 1, 0, -1 do
            local layer = thisLayer:Layer(i)
            local sortValue = 0

            -- Choose the sorting value based on the selected mode
            if sortMode == "X" then
                sortValue = layer.fTranslation.value.x
            elseif sortMode == "Y" then
                sortValue = layer.fTranslation.value.y
            elseif sortMode == "Z" then
                sortValue = layer.fTranslation.value.z
            elseif sortMode == "ZScale" then
                sortValue = layer.fScale.value.z
            end

            table.insert(order, {i, sortValue})
        end

        -- Sort the layers based on the selected value, with optional reverse
        table.sort(order,
            function(a, b)
                if reverseOrder then
                    return (a[2] > b[2])
                else
                    return (a[2] < b[2])
                end
            end)

        -- Apply the new layer order
        local newOrder = ""
        for i, v in ipairs(order) do
            newOrder = newOrder .. thisLayer:Layer(v[1]):UUID() .. "|"
        end
        layerOrderChan:SetValue(0, newOrder)
        order = nil
    else
        print("''AC_SortByTag.lua'' should only be embedded into group or bone layers, ''" .. moho.layer:Name() .. "'' is not a group or bone layer.")
    end
end
Image
Image
Image
Image
Image
Image
Post Reply