Jump to content

Script help for classes

Recommended Posts

At risk of being on the wrong track:


I would create a 2nd Lighting Layer for those lights and turn it on/off in my Layouts as needed.

Locking an object prevents it from being changed, irrespective of what class/layer it's in/on. Right click>Lock



Share this post

Link to post

I did exactly what you suggest: I created a special layer (and class - for objects that are in a group or for some text etc in a layout) to be invisible.

What I am looking for now is a faster way to put the lighting objects into this layer (or class).


Okay, thank you. So I used locking before, but didn't know the english expression.

Share this post

Link to post

I am a Vectorscript guy far more than Python, but since this started in Python I will try to play along.


I think you can actually simplify things greatly by using your criteria to limit the objects tested to the active layer. The following modification to the previously posted script shows how to do that.  If you limit this to objects on the active layer, you probably don't want or need the InSymbol, InObject, InViewport portions of the criteria. Those only EXPAND where the criteria searches and only matter if you want to handle objects inside other container objects.

The vs.Message line is just there to make debugging the criteria easier.


c='Test Class'
def DoIt(h):
    vs.SetClass(h, c)
S1= vs.GetLName(vs.ActLayer())   
criteria= "(INSYMBOL & INOBJECT & INVIEWPORT & (SEL=TRUE) & (L='" + S1 + "'))"

vs.Message(criteria," • ",S1)
vs.ForEachObject(DoIt, criteria)


Share this post

Link to post

Hello Pat,


thank you very much!


I tried your script and tried to find the right criteria.

It seems my main problem is selected objects in not-selected groups.

I found the criteria for "object is not a group", but the script still works on selected objects _inside_ groups that are not selected.

Do you have any idea how to avoid that?


I already thought about having a script to deselect all objects (so no objects inside of groups are selected), then select the objects I want to put in the special class manually, then run the script to put them into this class. This might still be faster than to do it all manually via info palette.


I exported VWX files as text files and tried to find out how for example the move-tool works.

I would like to find out how their criteria works - because this tool ignores selected objects in not-selected groups.

It just works on selected objects that are visible, not in a container object and not in a viewport/layout. That's exactly what I need.

But I didn't find it yet.

Somehow the process of the tool is not in the text - only the result. Or did I miss it?


All the best,

Lilith - away from the computer from tomorrow till monday because of a little holiday






Share this post

Link to post

If I create a script via Extras-Menue/Search and change (which might have a different name in English as I translated freely), I can choose not to work in/on groups and it leaves selected objects in non-selected groups alone.

For example:

import vs;
vs.EditProperties("((V) & (SEL=TRUE))");

But if I take the same criteria ((V) & (SEL=TRUE)) into my other script, it behaves differently.

With this script it does work on objects in groups again.

c='00 spielt nicht mit'

def DoIt(h):
    vs.SetClass(h, c)
criteria="((V) & (SEL=TRUE))"
vs.ForEachObject(DoIt, criteria)

I don't understand where the difference comes from.


Share this post

Link to post


I believe vs.ForEachObject() looks at every object in the drawing, which means your criteria string has to filter out EVERYTHING you don't want to look at. You might have better success with one of the other similar functions vs.ForEachObjectInLayer() or vs.ForEachObjectInList() that were mentioned earlier in this thread. You can very easily control the scope of their searching with the input OPTIONS for the functions. Consult the VS Function Reference or the online Developer WIKI for more info.



vs.ForEachObjectInLayer(DoIt, 3, 0, 0);     # Visible+Selected, Shallow, Current_Layer

# options can be added: Visible = 1, Selected = 2, Visible and Selected = 3


The SHALLOW option is the one that will help you here.


If DoIt returns TRUE, vs.ForEachObjectInLayer will stop processing. Typically you'll have DoIt return FALSE or nothing and vs.ForEachObjectInLayer will loop until it runs out of objects.


If you need further filtering, use IF statements in the DoIt function to exclude or include objects based on their object type, graphic attributes, attached records, etc.




Share this post

Link to post

I think Raymond is on the right track.


Also, this entire thread has been in kind of general terms. Everyone is guessing as to how your file is formatted and why you are trying to do things the way you are.


If you could upload a simplified version of the file (possibly with just one or two of the objects you are interested in and a couple in the groups/symbols/containers) it would be much easier for us to figure out how best to help and the best options.

Share this post

Link to post

Hello Pat, hello Raymond,


Thank you very much for your messages and your help.


Two thoughts: first, I am afraid I have to postpone my question / my attempt to create a script for this task because I don’t understand your answer yet, Raymond. I need to learn more about scripting in general to actually be able to put your answer into practice.


Second, I got the impression that the structure of classes and layers of the plan I am working with – which is created to meet the demands of our theatre with different multi-storey areas  -  might not work well from the point at which you try to create a script for this special task.


I try to explain better what I am doing and why, and I created a simplified version of the file.

Okay, the theatre has around 200 lighting fixtures on different storeys and different areas as standard equipment. For example in the area of the audience: orchestra seating balcony, 1.balcony, 2.balcony. Each with various lighting fixtures. Each balcony lies on its own layer to pull the overlapping balconys apart in the layout. Here I guess it would slow me down if I use a criteria like ForEachObjectInLayer. I am used to select lighting fixtures on any of those layers and put them (manually) into the hidden class.

I created a hidden layer and later a hidden class to be quick enough with the changes during lighting rehearsals. All fixtures that are thrown out in one rehearsal and shall not be in the layout anymore, can be part of the game again in the next rehearsal. To save the effort to put the fixtures in question again and new into the plan, to give them all their data, to adjust the labels and all that, I just “park” them into the hidden layer (or class) when they are not used and put them back to their original layer (or class). It started with the hidden layer. The hidden class is needed as soon as you work inside a group or on a layout. Each boom is a group for example. If there is additional text on the layout for a thrown out fixture, it needs to be managed on the layout. Here I can only use classes.


I guess I could maybe perhaps possibly change the structure to use just one layer for the standard equipment and one layer for the added lighting fixtures. I need to think that through calmly first to check all the consequences and I cannot do it in the middle of a theatre season. Or I just do this task manually like before and try with completely different tasks first.


If I would change the structure to just one (or two) layers and use vs.ForEachObjectInLayer() I could avoid affecting selected objects in groups on other layers and anything on layouts as I understand and I would avoid running the script several times because of several layers. That sounds great. But – maybe as I don’t understand the possibilities of the IF statements enough – I don’t know yet how to avoid affecting selected fixtures in groups (in the same layer). Is the solution to just put my booms on a separate layer?                 


I tried to understand how the code differs between lighting fixtures outside and inside a group. I can find the code for the creation of the group, but don’t find any mark which fixture is in the group, so I don’t know how to exclude objects in a group.


In the simplified version of the plan there are four lighting fixtures on three different layers. One layer is hidden. The lighting object on this layer is selected.

There is a group with four lighting fixtures (the boom), with two lighting fixtures selected.

There is a test layout.

If I run the (second) script with vs.ForEachObject() I can exclude the non-selected and non-visible objects, but not the selected objects that are inside a non-selected group and not the selected objects on the test layout (again both inside and outside of a non-selected group).


I hope now you can understand better what I am doing and why.

And maybe we find the point in the code about the difference of being in a group or not. Or find out, how a tool in VWX makes its selection. A tool ignores any selected object that lies on a hidden layer or class, or that lies on a layout I am not working on at the moment, or that lies in a group. That’s exactly what I need.


Best wishes from Zurich,



Share this post

Link to post

Let me see if I can simplify this.


You have a bunch of objects (does not matter if they are lights, or walls or groups or anything else). These objects in the stock drawing need to be in a certain set of layers and classes. Sometimes the objects are inside a group, and you don't want all of the group to disappear, only some of the objects.


For some uses, you need to make some of these objects disappear to simplify the drawing.


You then need to be able to make any "hidden" objects reappear quickly so you can reset them for the next event.


Are there any other special cases that are not described above?



My first thought is to use records to store the original class so the objects can be restored to what they were before they were hidden. Basically you need a "flag" to indicate which objects need to be hidden and then use that flag in a ForEachObject loop to selectively hide or unhide (change class) of the objects.


So this will probably end up as a series of scripts.

    Store Current Class (will also attach record if it doesn't already exist)

    Reset To Original Class

    Reset "flags"

    Hide Objects


You can probably make a more sophisticated version that would let you store the class for different shows/scenes and then hide only objects that are not being used in that show/scene.  This depends on how may shows/scenes you need. I would say 5 or six would be relatively easy.


One of the things I have found in many years of teaching VW is that everyone needs to use it based on how their brain works. If my description above works with your brain, I am happy to discuss it more. If not, I will keep watching and see where I can help out.




Share this post

Link to post

Hello Pat,

thank you very much for reading and figuring out my long message and for your support.


At one point my explanation still seems to be misleading.  

The selection I need is the same selection a tool uses.

It only works on visible selected objects.

It does not work on selected objects on a layout - as long as you are not working on this layout while using the tool.

It does not work on selected objects in a non-selected group – as long as you are not inside this group while using the tool.

It does not work on selected objects on a layer or a layout or in group B – as long as you work and use the tool inside of group A.

It does not work on selected objects on a layer or a layout Y or in a group – as long as you work and use the tool on layout X.

That’s what I am searching for.

I don’t want the script to work on any selection that I don’t “see” in the moment I am using the script – which would be a selection inside a group or on a layout I am not working on at that moment.


Each show has its own plan, so I don’t need different classes for different shows. But I could sometimes use it for different scenes. Each show starts with the standard plan with all the standard equipment in it but the original standard plan stays untouched.

I need to “hide” lights that are not being used – via putting them in a hidden class. As things change during the rehearsal process, I need to let those “hidden” lights reappear that are being used again in the next rehearsal – via putting them in their original class. I need to be able to select from those which are hidden. Not all of the hidden lights will be used/reappear. (Well, in my structure it’s mostly about layers and not classes, but that’s not relevant at that moment and there isn’t a SetLayer command anyway. Who programs the commands actually? If there is a SetClass, there could be a SetLayer, couldn’t it?)


I like the idea of having the original class (or layer) saved in the light info record and being able to use a script to put it back to this original class via this stored information instead of via the info in my head. But I am afraid that for this we still have to solve the fundamental problem of the selection first, don’t we?

I have not yet found a criteria which looks at a certain entry inside a record. I can just set the criteria: linked or not linked with a certain record/database.

How does the Reset to Original Class script get the info from the record?

I am not sure I understood the part about the “flag” that indicates which lights need to be “hidden”. Manually I just select the lights and change their class (layer) via info-palette. Would I need to do the little detour to first manually write a “hide-flag” into the  record and then use the Hide objects script?


If I got it right, I would translate my manual workflow into this:

Store Current Class (=Writes Class-Name into a user-defined input-field “Original Class” in the record?) – first with all the standard equipment in the standard plan, so this is fixed, and then, working on a certain show, for every new light that I insert additionally into the plan.

To hide certain lights, I manually select and write a “Hide-flag” in a second user-defined input-field “Hide” in the record, so I can use the Hide Objects Script which changes the class into “Hidden Class”.

To let certain hidden objects in the “Hidden Class” reappear, I manually select them and write a “Reappear-flag”, and then run a Reset to Original Class script, combined with a script that erases any “Hide” or “Reappear”-flag.

Did I get you right?

Or work via linking and unlinking a database “Hide” and a database “Original Class” if you cannot grab the info inside of a database?

I'd love to sort this out. It sounds quite promising.


Best wishes,


Share this post

Link to post

Hi Pat,

I found a SetLayer script in Marionette.


class Params(metaclass = Marionette.OrderedClass):
	this = Marionette.Node( "Set Layer" )
	this.SetDescription( 'Adds an object to a specified layer' )
	object = Marionette.PortIn(vs.Handle(0), 'obj')
	object.SetDescription( "The input object" )
	list = []
	h = vs.ActLayer()
	for i in range(0,vs.NumLayers()):	
		h = vs.NextLayer(h)
	layer = Marionette.OIPControl('Layers', Marionette.WidgetType.Popup, 0, list)
	layer.SetDescription( "A list of available layers" )
	obj = Marionette.PortOut()
	obj.SetDescription( "The result object" )

def RunNode(self):
	l = self.Params.layer.value
	o = self.Params.object.value
	list = self.Params.list
	new = list[l]
	new1 = vs.GetLayerByName(new)
	created = vs.CreateDuplicateObject(o, new1)
	self.Params.obj.value = created

Don't know how to use it yet, but it does exist.



Share this post

Link to post



I am pondering this. It is all doable. I think it will all be easy, I should have some time later today to respond in more depth.



Share this post

Link to post

I think I have a way to do what you want. How does this sound.  


A single tool with multiple modes.


Mode 1 - Click on an object and the tool will attach a record and save the current class, change the class to a different one specified in the tool preferences. If that class is set to invisible, the object will be hidden. If the object is already in the "hidden" class, it will reset the class of the object to what was stored in the record and remove the record. You may have to try and click on blank areas of the drawing to "unhide" invisible objects. I am trying to find a way to give some kind of graphical highlighting to the invisible objects, but don't have a good way so far.


Mode 2 - Toggle the visibility of the "hidden class." This will show/hide all of the objects that are in the hidden class. This could also use Grey instead of visible.


Mode 3 - Reset all objects to original classes. To restore the visibility of all the objects.


Does this sound like to does what you need? Or am I still missing something?





Share this post

Link to post

So cool!

I didn't know that it's possible to actually build your own tool.

So it could be like any other tool in the construction palette? And be selectable via short key, even the modes?

That would make it even quicker.


Mode 1 and 2 sound perfect.


What do you mean with giving graphical highlighting to the invisible objects?

When I change the visibility of the "hidden class" -  for example with mode 2 - I can see the previously invisible objects and pick those that need to be visible again.


There will not be the case that all objects need to be reset to original class. It is always only a selection.

Therefore I don't need Mode 3.


Is the problem with the selection solved?


Would it be possible to combine this with the SetLayer Script I found in the Marionette library?

For a second tool or for another "class of modes" for a choice between class and layer?

Like: choose between class and layer - then choose between mode 1 and 2.



It feels like I will be able to build my own new world.


Have a great day,








Share this post

Link to post



in a Marionette workshop last week we put together a script to dublicate selected objects on the design layer 'unused' and then delete the original object - which does the job of changing the layer to the design layer 'unused'.

I tested it and added the criteria "layer is not 13 / 14 / 15" - those are sheet layers. The discovery of today.

Otherwise it would work on activated objects on the sheet layers also which I don't want to happen.


I guess this is it.

At least I haven't found any other problems with it so far.


When I manage to change this script into a tool and give it a shortcut key the workflow gets really quick.


Have a great day,




l = 'unused'
GefundeneObjekte = []

def DoSomething(h):
vs.ForEachObject(DoSomething, "NOTINDLVP & NOTINREFDLVP & (SEL=TRUE) & (L<>'13') & (L<>'14') & (L<>'15')")

for element in GefundeneObjekte:
    new1 = vs.GetLayerByName(l)
    o = element
    created = vs.CreateDuplicateObject(o, new1)


Share this post

Link to post



Happy to see you pulled some launch assistance out of my workshop and are on the way to speed up some workflows :-) 

I think your script will work fine. By the way, if you want to exclude all sheet layers (If you create a New Sheet, your script had to be adjusted) in your "object-collecting-function", you can do this as follows:


def DoSomething(h):
	t = vs.GetObjectVariableInt(h,154)
	if t == 1: #Vectorscript Appendix 1-> Design Layer, 2-> Sheet layer




Share this post

Link to post

I haven't read the entire thread, but if all you want is to put selected objects within a layer into a certain class, this will do it.  It doesn't select other objects.  It doesn't put other objects into a class.  It works just on what is selected.  Added the Refresh Instruments for spotlight instruments in case you are using them...they often like to be refreshed after script operations.  If you aren't using Spotlight, you can remove that line.  


I'm sure you're looking for something with more options or to dig deeper, but if you just want something quick and easy....



    obj : HANDLE;
    while obj<>nil DO BEGIN
        SetClass(obj,'The New Class');
    DoMenuTextByName('Refresh Instruments',0);

Edited by SamIWas

Share this post

Link to post

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.

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.


7150 Riverwood Drive, Columbia, Maryland 21046, USA   |   Contact Us:   410-290-5114


© 2018 Vectorworks, Inc. All Rights Reserved. Vectorworks, Inc. is part of the Nemetschek Group.

  • Create New...