Jump to content
Developer Wiki and Function Reference Links ×

ForEachObjectInList questions


PeterT

Recommended Posts

I am using the ForEachObjectInList procedure in a script, and I do not fully understand how the objects in the list are traversed.

In my script I gave a handle to FObject as the "List" parameter, and for the "Object Options", I was filtering for Visible Objects only.

This script failed, so I got to thinking that perhaps the first object in the document was not on a visible layer. Would that cause the script to fail?

Next, I tried a handle to LObject as the "List" parameter, since I am pretty sure the last object is on the active layer, but the script also failed.

I got the script to run by giving a handle to LNewObj which I know is on the active layer since it was just created in the script.

Through this trial and error, I seem to have found more questions than answers.

The documentation says the "List" parameter is a handle to the first object in the list. Does this mean, literally, the first object in the list (FObject if the list is of all objects)?

Or does this mean that whatever object handle you give as the "List" parameter becomes the starting point of the traversal through the list?

When I gave the handle to LNewObj and the script worked, why? LNewObj is certainly not the first object in the list, wouldn't it be the last object in the list?

I am a bit of a beginner with document list traversal. Can anyone help me to understand it better?

Thanks,

Peter

Link to comment

Peter, It's hard to say what's going wrong with your scripts without knowing your syntax or the error messages, but for list traversal, it helped me to try not to think of the order of items in lists if it's not necessary...but only that you want to do something with a group of objects (that are inherently ordered or listed by Vectorworks) . Most of the lists I traverse, I'm not concerned with their order, only what I want to do to the items in that list. When I first started learning VS, getting a handle on handles (pun intended) was definitely the hardest part.

Now you stated that you used the "ForEachObjectInList" Procedure and "gave a handle to FObject as the "List" parameter. Think of objects as pots with no handles, and these pots are full of information (color, size, orientation, etc) and if you want to do something to these pots or change something (attribute) in the pot, you have to attach a handle to it to work with the pot(the object).

There are several functions that you can choose to connect to the multiple pots(objects) in your document. FObject will allow you to work with the First object created in your document. FSActLayer allows you to work with the first selected object on the active layer, NextSObj allows you to work with the next selected object in a list (assumes more than one item is selected). ForEachObjectInList applies an action to a list of object (visible objects, selected objects, locked objects, etc) and the "list" is not a parameter you assign a function, but a variable to the first item in the list. The way you would use ForEachObject in list would be as follows:

PROCEDURE test;

VAR

hobject :HANDLE {declares a variable named "hobject" of the HANDLE type}

{-------SOME HYPOTHETICAL PROCEDURE THAT DOES SOMETHING TO SELECTED OBJECTS----}

PROCEDURE SomeOperation;

BEGIN

Rotate Object 10 degrees;

END;

{-------------------------------------------------------------------}

BEGIN {Main Program}

hobject:=FSActLayer;

ForEachObjectInList (SomeOperation,2,0,hobject);

END;

Run (test);

OK, this is conceptual so the above program is schematic, not what you would actually type, but let's say you've selected 5 objects that you want to rotate 10 degrees to the left. The line "hobject:=FSActlayer" will provide a handle (or link) to the first selected object. Now there's some confusion as to whether it's the first object you selected, or whether it's the first object you created that is now selected. Mostly I don't care, since VW keeps track. When you use the "ForEachObjectInList" procedure, VW will look at the "hobject" variable which represents the first selected object (remember "hobject:=FSActLayer) It will then execute the "SomeOperation" procedure on that first object. After that, it will go through each object in the list (selected objects in this case) and execute the "SomeOperation" procedure on each object.

Remember that the "list" parameter in this function is a variable name that is assigned to a object using another function. You said you used FObject as the list parameter. This is how FObject would be used in your example

VAR

hobject :HANDLE;

BEGIN

hobject:=FObject;

ForEachObjectinList(SomeFunction,2,0,hobject);

Hope this lengthy explanation helps a bit.

Link to comment

Hi Tom,

Thanks for the response. Maybe I am worse at explianing my understanding of VectorScript than the understanding itself.

I have a working script that is very slow to execute. So now I am trying to look at the individual portions of the much longer script, and see if I can streamline anything.

The portion I am working on now is meant to select objects in the drawing that meet certain criteria. The loop I have been using to this point is as follows:

layerhndl:=FLayer;

WHILE layerhndl<>NIL DO BEGIN {loops through layers}

hndl:=FInLayer(layerhndl);

WHILE hndl<>NIL DO BEGIN {loops through objects}

IF {-certain criteria is met-}

THEN SetSelect(hndl);

hndl:=NextObj(hndl);

END;

layerhndl:=NextLayer(layerhndl);

END;

The problem with this loop is that it processes every object on every layer. In my file I have 16 layers, but only 6 of them are visible when I execute the script. Furthermore, all the objects I care to select are on only two of the visible layers.

My first thought was by using "ForEachObjectInLayer" maybe I could filter for only visible objects thus eliminating the processing of all the objects on the 10 invisible layers. So I was using the "ForEachObjectInLayer" to process the objects on each visible layer, and a loop to process through the layers:

FUNCTION SelectIt(hndl:HANDLE):BOOLEAN;

BEGIN

IF {certain criteria is met}

THEN SetSelect(hndl);

END;

{------------------------------}

layerhndl:=FLayer;

WHILE layerhndl<>NIL DO BEGIN {loops through layers}

ForEachObjectInLayer(SelectIt,1,0,2);

layerhndl:=NextLayer(layerhndl);

END;

{------------------------------}

Next, I figured if I used "ForEachObjectInList" instead, I could skip the layer loop, and just process through visible objects regardless of the layer, so I tried this:

FUNCTION SelectIt(hndl:HANDLE):BOOLEAN;

BEGIN

IF {certain criteria is met}

THEN SetSelect(hndl);

END;

{------------------------------}

Obj1:= FObject;

ForEachObjectInList(SelectIt,1,0,Obj1);

{------------------------------}

The problem with this, I realized, is the first object in the document is on one of the invisible layers, so by filtering for visible objects, maybe it was never finding the first object.

(In this version of the script, no objects were ever being selected.)

By setting Obj1:=LNewObj the script now selects the objects again, but I am not confident that it isn't just luck. LNewObj would have been the last object created in the script, but I am not sure that would always be in the stacking order below the two layers I care about selecting objects on.

I really only want to process through the objects on two layers, and I am not thinking I can do that with "ForEachObjectInList".

I would need to define the list of objects on just those two layers. These two layers happen to be the two top-most visible layers.

I tried starting with the first object on the lower stacked of these two layers by getting the layer's name:

hBasePln:=GetLayerByName('BASE PLAN');

FirstObject:=FInLayer(hBasePln);

ForEachObjectInList(SelectIt,1,0,FirstObject);

I was thinking maybe this would process through the "BASE PLAN" layer and then proceed to the top-most layer (last layer), and process through that. Of course, it did not do that, I think because by defining the list parameter as the first object on a specific layer, it processed the objects on that layer only.

One of the concepts I am trying to understand is, if I define an object in the middle of a list as the "list" parameter, will "ForEachObjectInList" process only the objects in that list that are higher in the list stacking order, or will it still process the entire list, or will it process nothing because it was not the first object in the list?

This is where I am now. Maybe I should just get both layers by their names and process through them specifically, but I was trying to keep the script more flexible by not naming them specifically.

Any further comments welcome.

Thank You,

Peter

Link to comment

Did you try using

ForEachObjectInLayer(SelectIt,1,0,2);

without the enclosing loop? From my reading of the dox this should process all visible objects on all visible layers.

In a document with 16 layers, this:

layerhndl:=FLayer;

WHILE layerhndl<>NIL DO BEGIN {loops through layers}

ForEachObjectInLayer(SelectIt,1,0,2);

layerhndl:=NextLayer(layerhndl);

END;

may be processing each visible object on each visible layers 16 times,which could cause a slowdown.

You might try putting a counter inside "select it" to see how many times this is being called. To do this, declare c as a variable of integer then put c:=c+1 in "select it".At the bottom of your script put Message©.

This is a very useful tool for trouble shooting loops of all kinds.

Maybe it should be called ForEachObjectInLayerOrLayers.

Just wanted to add something else RE. the loop that you first used (i.e. the homegrown without F.E.O.) ....I doubt that you'll see much speed improvement by changing this.V-script is very quick to look at an object and see if it meets criteria.

Use the counter strategy on some simple docs to see if some sub-routines in the larger script are being called more than they should be.

[ 10-08-2004, 11:09 PM: Message edited by: ccroft ]

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...