Rasheed? Anyone? Need a function to get all bone layers
Moderators: Víctor Paredes, Belgarath, slowtiger
Rasheed? Anyone? Need a function to get all bone layers
I understand the concept on an intellectual level but my thick crusty old brain can't get a handle on it.
I need a way to iterate the layer list and retrieve all the bone layers or (group layers I can work from that) no matter where they are or how deep inside other folders.
My problem is trying to create an iteration that can go into a group layer check those for groups and so on... until there are no more to check. I get closer and closer but always end up stopping short. I understand how it should work... I just get overwhelmed.
I know this involves some kind of "stateless iterator" or something... I just don't have the brains for it... my head... is... spinning... it hurts... it hurts.
No really... I got a bad headache the other night and had to go to bed.
-vern
I need a way to iterate the layer list and retrieve all the bone layers or (group layers I can work from that) no matter where they are or how deep inside other folders.
My problem is trying to create an iteration that can go into a group layer check those for groups and so on... until there are no more to check. I get closer and closer but always end up stopping short. I understand how it should work... I just get overwhelmed.
I know this involves some kind of "stateless iterator" or something... I just don't have the brains for it... my head... is... spinning... it hurts... it hurts.
No really... I got a bad headache the other night and had to go to bed.
-vern
Here is a simple solution:
This script collects the layer names and their hierarchy level in the table tree. The table tree is an array counting from zero, to the number of layers, minus one. Each element of this array represents the layer properties. In effect, each array element is a table, containing the layer name and the hierarchy level in the layer tree.
You can just as easily collect all other features of a layer, such as layer type. Just put them in the table definition of tree[count], like I did with the layer name and hierarchy level. The i-th layer from the bottom of the Layer window can be accessed as follows:
Here are an example with screenshots of the layer structure of a document and the Lua console output:

If you want to know what the parent of a layer is, the code becomes a little more complicated:
If you don't understand the code, just tell me, and I try to do my best to explain.
Code: Select all
function LayerScript(moho)
local tree = LayerNames(moho, moho.document, {}, 0, 0)
for i in tree do
print( tree[i].name .. ' (' .. tree[i].level .. ')' )
end
print('----------')
end
function LayerNames(moho, group, tree, level, count)
for i = 0, group:CountLayers() - 1 do
local layer = group:Layer(i)
tree[count] = { name = layer:Name(), level = level }
count = count + 1
if layer:IsGroupType() then
local group = moho:LayerAsGroup(layer)
tree = LayerNames( moho, group, tree, level + 1, count)
end
end
return tree
end
You can just as easily collect all other features of a layer, such as layer type. Just put them in the table definition of tree[count], like I did with the layer name and hierarchy level. The i-th layer from the bottom of the Layer window can be accessed as follows:
Code: Select all
tree[i].name -- layer name
tree[i].level -- hierarchy level of the layer in the layer tree


If you want to know what the parent of a layer is, the code becomes a little more complicated:
Code: Select all
function LayerScript(moho)
local tree = LayerNames(moho, moho.document, {}, 0, 0)
print(table.getn(tree) + 1 .. ' layers :')
for i = 0, table.getn(tree) do
local parent = tree[i].parent
if parent < 0 then
parent = '(no parent)'
end
print( 'tree[' .. i .. '] = ' .. tree[i].name
.. ' (' .. tree[i].level .. ')' .. ' -> ' .. parent )
end
print('----------')
end
function LayerNames(moho, group, tree, level, count)
local parent = count - 1
for i = 0, group:CountLayers() - 1 do
local layer = group:Layer(i)
tree[count] = {
name = layer:Name(),
level = level,
parent = parent }
count = count + 1
if layer:IsGroupType() then
local group = moho:LayerAsGroup(layer)
tree = LayerNames( moho, group, tree, level + 1, count)
end
end
return tree
end
Last edited by Rasheed on Sat Feb 10, 2007 12:04 am, edited 3 times in total.
I understand it perfectly.
That is my problem. I understand it if I see it and can step through in my head what is going on. Trying to come up with it from scratch is so much harder for me.
I suppose a novice car mechanic could fix something in a car but probably couldn't build a whole car from scratch.
I can see from your code that I at least was on the right track... I still have a lot to learn about LUA tables and functions. I know enough to be dangerous (just look at the crash log on my Mac!).
Thank you thank you thank you!!!
-vern
That is my problem. I understand it if I see it and can step through in my head what is going on. Trying to come up with it from scratch is so much harder for me.
I suppose a novice car mechanic could fix something in a car but probably couldn't build a whole car from scratch.

I can see from your code that I at least was on the right track... I still have a lot to learn about LUA tables and functions. I know enough to be dangerous (just look at the crash log on my Mac!).
Thank you thank you thank you!!!
-vern
Haha!
Now I know why I was having so much trouble!
Your script doesn't work if the order the layers were created is changed or shifted in the order of their levels.
For instance if the first bone layer created is placed inside another bone layer it isn't listed properly.
There seems to be a disconect somehow with the internal ordering of layers in AS and the iteration through those IDs.
If I create bone layer 2 and then create bone layer 3 and drag bone layer 2 inside bone layer 3
bone layer 2 never shows up in the iteration. It was created first and is now lower in the hierchy. It is skipped. Also group layers INSIDE bone layer 2 are also skipped... obviously since bone layer 2 is skipped.
This would explain some of my frustration and inconsistent results. Since my test file was a REAL WORLD file, one that I had been working on and moving things around, none of my iterations were working correctly.
YOUR CODE SHOULD WORK! But only if the layers are never moved around too much.
Is this a problem with AS layer ordering - moho:document:Layer(), or something to do with unordered tables in LUA?
Now that I know why it isn't working I can play around with it and maybe fix it.
-vern
Now I know why I was having so much trouble!
Your script doesn't work if the order the layers were created is changed or shifted in the order of their levels.
For instance if the first bone layer created is placed inside another bone layer it isn't listed properly.
There seems to be a disconect somehow with the internal ordering of layers in AS and the iteration through those IDs.
If I create bone layer 2 and then create bone layer 3 and drag bone layer 2 inside bone layer 3
bone layer 2 never shows up in the iteration. It was created first and is now lower in the hierchy. It is skipped. Also group layers INSIDE bone layer 2 are also skipped... obviously since bone layer 2 is skipped.
This would explain some of my frustration and inconsistent results. Since my test file was a REAL WORLD file, one that I had been working on and moving things around, none of my iterations were working correctly.
YOUR CODE SHOULD WORK! But only if the layers are never moved around too much.
Is this a problem with AS layer ordering - moho:document:Layer(), or something to do with unordered tables in LUA?
Now that I know why it isn't working I can play around with it and maybe fix it.
-vern
Remember that the elements in Lua tables are not stored in a particular order.
Yes, I can see that. I should see why that is, and how to remove this bug.heyvern wrote:If I create bone layer 2 and then create bone layer 3 and drag bone layer 2 inside bone layer 3
bone layer 2 never shows up in the iteration. It was created first and is now lower in the hierchy. It is skipped. Also group layers INSIDE bone layer 2 are also skipped... obviously since bone layer 2 is skipped.
I can't for the life of me see why this is happening. It seems strange indeed. The layers are suppose to be accessed by their order in the layer palette, according to the scripting reference.
moho.document:Layer(int)
That integer number is suppose to be the order in the layer palette starting with 0 ... or the order of the layers in a group starting with 0.
This should not be happening and I can't see how to get around it. The order of creation is somehow... changing how the layers are accessed in the Layer() table.
Weird.
I suppose the reference to the layers could be placed in a new table with a new index. I did this before with the layers. That is actually how I reference the layers in my script, by accessing a layer ID using a new unique index in a table so it matched the index of a text list.
-vern
moho.document:Layer(int)
That integer number is suppose to be the order in the layer palette starting with 0 ... or the order of the layers in a group starting with 0.
This should not be happening and I can't see how to get around it. The order of creation is somehow... changing how the layers are accessed in the Layer() table.
Weird.
I suppose the reference to the layers could be placed in a new table with a new index. I did this before with the layers. That is actually how I reference the layers in my script, by accessing a layer ID using a new unique index in a table so it matched the index of a text list.
-vern
I created tables:
toLayerList = {}
frmLayerList = {}
then put the layers in each list like this..
This seems to work since the index for the table was created using the for loop.
I can just adapt your script to this and see if it works better.
-vern
toLayerList = {}
frmLayerList = {}
then put the layers in each list like this..
for i = 0, (moho.document:CountLayers()-1 do
toLayerList.name = moho.document:Layer(i):Name()
toLayerList.layerID =moho.document:Layer(i)
end
This seems to work since the index for the table was created using the for loop.
I can just adapt your script to this and see if it works better.
-vern
I removed the bug. The problem was that the count variable was not propagated, so instead of:
I had to use:
And of course both tree and count should be returned:
That fixed the bug.
Here is the improved code:
Code: Select all
tree = LayerNames( moho, group, tree, level + 1, count)
Code: Select all
tree, count = LayerNames( moho, group, tree, level + 1, count)
Code: Select all
return tree, count
Here is the improved code:
Code: Select all
function LayerScript(moho)
local tree, count = LayerNames(moho, moho.document, {}, 0, 0)
print(count .. ' layers :')
for i = 0, count - 1 do
local parent = tree[i].parent
if parent < 0 then
parent = '(no parent)'
end
print( 'tree[' .. i .. '] = ' .. tree[i].name
.. ' (' .. tree[i].level .. ')' .. ' -> ' .. parent )
end
print('----------')
end
function LayerNames(moho, group, tree, level, count)
local parent = count - 1
for i = 0, group:CountLayers() - 1 do
local layer = group:Layer(i)
tree[count] = {
name = layer:Name(),
level = level,
parent = parent }
count = count + 1
if layer:IsGroupType() then
local group = moho:LayerAsGroup(layer)
tree, count = LayerNames( moho, group, tree, level + 1, count)
end
end
return tree, count
end
YEEEHAAAA!
I just plugged in the new code to find all the bone layers into my copy/paste bones script... WOOOHOOO! It works!
Thanks Rasheed! Couldn't have done it without you!
I have a question though about where these functions go in a menu script, if you know that is.
...uh... where should these functions go in a menu script? At the top? The bottom? I put them at the top... only because they weren't working at the bottom... but then I was calling the starting function in the wrong spot.. and initializing the variables in the wrong spot... they work at the top now... should I move them down? It probably doesn't matter as long as they work.
Is there a proper "LUA way"? I think they should go at the bottom underneath all the actually functional stuff... When I say "top" I mean before the :Run and UI initialization code.
<sigh>
Forgive me. I'm a bit light headed.
-vern
I just plugged in the new code to find all the bone layers into my copy/paste bones script... WOOOHOOO! It works!
Thanks Rasheed! Couldn't have done it without you!
I have a question though about where these functions go in a menu script, if you know that is.
...uh... where should these functions go in a menu script? At the top? The bottom? I put them at the top... only because they weren't working at the bottom... but then I was calling the starting function in the wrong spot.. and initializing the variables in the wrong spot... they work at the top now... should I move them down? It probably doesn't matter as long as they work.
Is there a proper "LUA way"? I think they should go at the bottom underneath all the actually functional stuff... When I say "top" I mean before the :Run and UI initialization code.
<sigh>
Forgive me. I'm a bit light headed.

-vern