Jump to content

Retrieving the stacking order of objects and layers


Recommended Posts

Is there a way to retrieve the stacking order (may be relative) of objects in a layer, and is there a way to retrieve the stacking order (number?) of a layer?

I want to create some objects based on the visual stacking order of other selected objects.  "FSActLayer" and "FSObject" will retrieve object handles in their creation order, and that would yield their stacking order, except when the stacking order is changed by the user.  Additionally, I would need to know the relative stacking order of the layers the selected objects are in, because that would change their visible stacking order in the drawing from their creation order.

Too much to ask??

Link to comment

I believe the actual order of the objects is changed when the user uses Send Forward/Send to Front and Send Backward/Send to Back.

 

So FInLayer will get you a handle the the object at the bottom of the stacking order on the chosen layer. NextObj will get you the objects on that layer each one step higher in the stacking order than the previous.

 

Flayer gets you the Layer at the bottom of the Layer Stacking Order. NextLayer will get you the next layer up in the stacking order.

 

So you can walk the double tree of Flayer ...  FInLayer.... NextObj... Nil... NextLayer...  To get the entire document list.

 

FYI, Object... NextObject returns Nil at the end of the objects on the first layer.  So Object is really just shorthand for FinLayer(Flayer).  Ask me how I know.  😞

 

 

So if you have a reasonable way to test for the objects you want, you should be able to walk the tree and find them pretty easily.

 

H1:=FirstLayer;
While H1<> Nil do
  Begin
    H2:=FInLayer(H1);
	While H2<> Nil do
	  Begin
		{Test is it your object and mark/save it}
		H2:=NextObject(H2);
	  End;
	H1:=NextLayer(H1);
  End;

 

  • Like 1
Link to comment
  • Vectorworks, Inc Employee

This is a little bit of a hack but I think it still works. Convert the object handle to a string then to a number. Lower numbers are at the bottom of the stack, higher numbers at the top? I don't remember if this works across layers or not.

Link to comment

Pat,

I don't think this works with stacking reordered by the user, but i need to make a test file and isolate the issue.

 

1 hour ago, klinzey said:

Convert the object handle to a string then to a number

 

@klinzeyHow do I convert a handle to a string.

 

Link to comment

Concat(H1) will get you the string version of a handle.

 

And you are right. At some point they have "smartened" Send Back/Send Forward Now they only work with overlapping objects.  In the ancient past (when I last played with this) the code I provided did change the entire stacking list.   If they are not changing the stacking order while running your code, it may still get you what you need as it appears that overlapping objects will still "stack" properly.

 

I would not be surprised to find that Kevin's won't do what you want either. I can't imagine that the handles to every object get changed when a user moves something up or down in the stacking order.

Link to comment

I have not tested this, but if you are concerned about visibility and overlapping objects, my sample code may work as I "think" what is happening is that the stacking code is now working on "overlapping groups" of objects.  The one at the bottom of the overlapping group should be lower in the stacking order that are overlapping it. No matter if there are other objects that are lower or higher in the stacking order that do not overlap.

 

While you can use Send to Front or Send to Back to completely change the stacking order, Send Forward/Send Backward will only change the order if there are overlapping objects.

 

Here is the test file I used to play around with this.

 

I don't know about the layer stacking part of this, but the object stacking within the layer should still work.

 

Use Script-2 to give you a series of AlrtDialogs that show the stacking order. Play with the various Send and see if you can find a cast where something is higher in the stacking order and hidden by something lower.

 

 

Stacking Order Test.vwx

Link to comment

@Sam Jones,

   If Kevin Linzey's method doesn't work, you can build an array of layer handles, stored in order of course. Then use GetLayer(objHnd) to get an object's layer handle. To compare two objects, get their layer handles and search the array of layer handles. The object with the higher array index number is on top. Tedious, but doable. If you need more help, you know where to find me.

 

Raymond

Link to comment
1 hour ago, Pat Stanford said:

At some point they have "smartened" Send Back/Send Forward Now they only work with overlapping objects.  In the ancient past (when I last played with this) the code I provided did change the entire stacking list.

 

Hi @Pat Stanford,

   I don't think this has ever changed. If it had, a lot of the scripts I've written over the years would have failed miserably. If you use HMoveForward() or HMoveBackward(), they will change the stacking order whether you move an object one position, or all the way to the front or back. Overlapping objects was never a condition of how the functions work. It is true however, that you won't perceive a difference of a changed stacking order if objects don't overlap.

 

   Of course, if you are referring to another way to, as you say above, "Send Back/Send Forward", then I may have completely misunderstood and I will gladly ingest this post if I did.

 

Raymond

Link to comment

@MullinRJ Try it and see. I have not researched how HMoveForward works, but the menu commands do not operate without overlapping objects.  I know that long ago they did.

 

In the file I attached earlier I have three sets of  text blocks. 1-9, ABC, XYZ.  Inside each block the objects are overlapping.

 

Pick the C object (which is in the middle of the overall stacking order and choose Send Forward.  You will get an error message that says "No overlapping objects to move in front of." and the position of the object in the entire stacking order is not changed.  Now try Send Backward. You will see that the object moves behind the B object.  (Actually I am not positive if C was in front of B when I saved the file so if not, use B instead of C.)

 

Run Script 2.  You will get a series of AlrtDialogs showing the stacking order and the text of each object.  You should see that C is position 11 and B is position 12.  Swap them again (send forward/send backward depending on which you have selected) and run the script again.  C will now be12 and B will be 11.

 

Now Select C and Send to Back.  Run Script-2.  C will be in position 1.  Everything else will move up one position.

 

Select C and Send to Front.  Run the script.  C will be in position 15.

 

Select A, B, & C.  Try Send Forward or Send Backward. You will get the No Overlapping Object message.

Select 9, A, B & C.  Send Backward.  Only 9 will swap positions with 8. A, B, C will all retain their position in the stacking list.

 

It is a little weird, but since @Sam Jones appears to only care about objects that are in front of other objects, Then the actual stacking position does not matter. The object in the front will always be in a "higher" position in the stacking list.

 

And since layers also have a stacking order you can check and see if the object is on a higher or lower layer if they are not on the same layer.

 

Or maybe Sam would like to tell us more about what he is trying to do so we can quit guessing about what he really needs. 😉

Link to comment

@Pat Stanford,

   OK, I see what you mean, but that behavior only applies to menu commands Send Forward and Send Backward. Menu commands Send to Front and Send to Back still work "the old fashioned way."

 

   However, from a script, HMoveForward() and HMoveBackward(), work by adjusting the stacking order of the object list, regardless of visible overlapping. I assume @Sam Jones is wanting to use a script to do his dirty work, but if he is tempted to use "DoMenuTextByName('Send Forward', 0)", he's all yours, and I shall remain politely silent.

 

Raymond

 

PS - Whenever the behavior changed for menu commands Send Forward and Send Backward, it has been longer than that that I have used either of those commands. Menu commands Send to Front and Send to Back, I use daily. It's interesting how habits get engrained.

Link to comment
Posted (edited)
33 minutes ago, Pat Stanford said:

Or maybe Sam would like to tell us more about what he is trying to do so we can quit guessing about what he really needs. 😉

 

Now that would take all the fun out of our late nights, wouldn't it?

 

Do you think Sam's ears are burning, yet?

Edited by MullinRJ
  • Laugh 1
Link to comment

I want to collect the handles of all the selected editable objects and then place different symbols based on what the selected objects are.  I don't want to replace the original selected objects.  I just want to place other different symbols (dopplegangers) down in the same stacking order as the stacking order of the original selected symbols.  That way the dopplegangers obscure (or not) each other in exactly the same way as the original objects obscure (or not) each other.

Link to comment

So you should be able to determine the layer and the "stacking position" of each selected object within the layer using something like the pseudo code I posted.

 

Then if you create your new objects and Send to Back, you should be able to HSendForward so the new object is "next to" the existing object I the stacking order.

 

Without knowing your use case, I can't say if that will be close enough.

 

You will probably also want some edge case logic to determine if the doppelgänger should be lower or higher in the stacking order than the original. And if you are putting multiple new objects into the stacking order of a single layer, you will have to take into account the potential for changing the stacking order positions. If you do them highest in the stacking order to lowest, then you shouldn't have to care about any offset as you will always be working "below" the objects that have been offset.

 

 

Link to comment

Do you are about other objects, or just the relative position of the selected objects?  If only the selected objects then it should be relatively easy.

 

Start at bottom layer and work up through stacking order.

If selected then place doppelgänger on other layer.

Repeat for all objects in layer.

Move to next layer.

Repeat.

 

At the end you should have doppelgängers of all the selected objects on the "new" layer in the same visual order as the combined Layer and Object Stacking.

Link to comment
47 minutes ago, Pat Stanford said:

Start at bottom layer and work up through stacking order.

How do I know what the stacking order is?  If I don't need to know what it is, how do I work up through it?

I need to make a list of selected symbols, in order to place the dopplegangers.  I can then sort the list on any criteria I know about or collect.  Theoretically, that would first be by layer order, and then by stacking order.  Getting the stacking order is the trick.  My preliminary investigations indicate that the handles to the objects do not provide a reliable stacking order, but I am refining my test file and the code to test indications of stacking order.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...