Technical question

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

Moderators: Víctor Paredes, Belgarath, slowtiger

User avatar
synthsin75
Posts: 10280
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

I'm having a bit of trouble with this. So far I have this:

Code: Select all

for i = 0, layerid do
      layerobj = moho.layer:Parent():Layer(i)
      local layertable = {}
      layertable[i] = layerobj
      --print(i .. " equals " .. tostring(layertable[i]))
      if (tostring(layertable[i]) == tostring(moho.layer)) then
        print(tostring(layertable[i]) .. tostring(moho.layer))
        --if (i ~= layerid) and (i ~= 0)then
          uplayer = layertable[i+1]
          print(tostring(uplayer))
          downlayer = layertable[i-1]
          print(tostring(downlayer))
        --end
      end
    end
Obviously I'm ending up doing arithmetic on layer objects here (which makes the variables 'uplayer' & 'downlayer' nil). I have the feeling I'm making this harder than it needs to be.

I'm trying to increment the table index [i+1]. This would probably work, but I'm also trying to assign the layer object as the value of this index. I'm I just trying to abreviate the code too much?
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

You are close to what you want but here is the problem. I think what is happening is that you are trying to do "too much" inside one loop. The "uplayer" and "downlayer" don't exist in your table before you call them.

I split your code into two different loops, creating the table first so all the layers exist in it before comparing the selected layer to the table fields and it works.

However there is the problem that the variables aren't reassigned on the click after a different layer is selected (I plugged this code into your original select layer script for testing). You get the results of the last click... you have to click twice on the same layer to get the layer variables to update. I haven't played with it enough to see what is causing this. I think that is just the issue. The layer switching ocurrs AFTER the variables are called. They are not reset until you click again so you are always off by which ever the last layer was selected.

What you can do is make sure the layer variables (uplayer, downlayer, layer) are reassigned AFTER you switch layers.

Here is a test I did just to see that it works. I moved the layertable variable and declared it outside the loop so it can be read by the second loop. I changed the "layerid" variable to "layercount" so it made more sense to me. It isn't the "ID" it is actually the layer count... this is a nitpick ;):

In the first part I create the layertable. Note I use local outside the loop and just the variable inside the loop to assign the values. Just the table with layer "objects" indexed by the ID number is created by the first loop.

Code: Select all

  
  local layer = moho.layer
  local layertable = {}
  local layercount = layer:Parent():CountLayers()-1

  for i = 0, layercount do
      local layerobj = layer:Parent:Layer(i)
      layertable[i] = layerobj
  end
In the next part I loop through the table itself using the same layercount variable. That variable will be the same as the number of items in the table. I compare the layers in the table to "layer" (moho.layer). Bingo! Success.

Code: Select all

  for i = 0, layercount do
      if (tostring(layertable[i]) == tostring(layer)) then
          print(tostring(layertable[i]) .. tostring(layer))
          uplayer = layertable[i+1]
          print(tostring(uplayer))
          downlayer = layertable[i-1]
          print(tostring(downlayer))
      end
  end

I didn't spend a ton of time on this short of just getting it to work without errors.

I was a bit annoyed at one part... using "tostring()" to compare those dang layers. It SHOULD work by just comparing layers for goodness sakes. Those layers should be able to be compared. It works with bones dangit. ;)

Oh well, converting the userdata to strings works too. Just keep in mind those strings from the layer objects will change every time AS is opened or each time the same project file is opened. Never expect them to stay the same. It doesn't really matter since it works fine in a "session". I do this myself sometimes. In fact I think I used that technique for the same reason.

EDIT: You still get "nil" at the "top" and "bottom" of the loop since there are no more layers for "uplayer' and "downlayer". layertable[i+1] is nil if there is no layer above the last layer. Same with the first layer.

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

Post by heyvern »

You could... expand the table so that the "uplayer" and "downlayer" are part of the same table...

Code: Select all

  for i = 0, layerid do
      local layerobj = layer:Parent:Layer(i)
      layertable[i] = layerobj

      if (layer:Parent:Layer(i+1) ~= nil) then
            layertable[i].uplayer = layer:Parent:Layer(i+1)
      else
            layertable[i].uplayer = layer
      end

      if (layer:Parent:Layer(i-1) ~= nil) then
            layertable[i].downlayer = layer:Parent:Layer(i-1)
      else
            layertable[i].downlayer = layer
      end

  end
Then you can call the uplayer and downlayers easily from the table. Even if the up and down layers don't exist it's been handled in the table creation:

Code: Select all

....

local downlayer = layertable[i].downlayer
local uplayer = layertable[i].uplayer

...
The only reason I might suggest this is that it would eliminate resetting those up/down variables when the selected layer changes. All you have to do is make sure the variable "layer" is correct and everything handles itself.

-vern
User avatar
synthsin75
Posts: 10280
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

Thank you VERY much, Vern! I figured I was trying to do too much in that loop. One of those cases of knowing the problem, but unable to get a solution.

In the script, I already have that update problem solved. I'm using this in an OnKeyDown function.

Thanks! :wink:
User avatar
synthsin75
Posts: 10280
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

Well I used that first method you mentioned, Vern. It took me a while to figure out why I was getting a "Group:Layer out of range" error, but I finally did.

So now I've added the ability to move layers. Up/down arrows move the currently selected layer up and down within its group. I added this OnKeyDown function to my select shape tool so that if no shape is selected I can use it (without a modifier). I had to add the Redraw function so it'd show the shapes/layers being moved.

Now if only LM could provide access to the layer ordering animation channel, this tool could provide more streamlined layer ording.



Now I'm off to see about selecting layers by shape & curve document-wide. Wish me luck. :wink:
Post Reply