Jump to content
Martin Crawford

Custom Tool Question

Recommended Posts

Can you have a Custom Tool Object that has items on multiple layers?


I would like to have a viewport object on the Sheet Layer that draws the bounding box on a Design Layer.


I'm thinking this is not possible??



Share this post

Link to post

My first thought would be NO. Each object can only be on a single layer.


But you might be able to create s tool that would create multiple objects on different layers and then Associate them together. But I am pretty sure they would have to be Event Enabled objects and that the code to get them to work together would be pretty ugly.


What are you trying to do?

Share this post

Link to post

i am trying to create a viewport object that will be on Sheet layer that draws the bounding box for a viewport.


The main object would have a few parameters that turn select objects and draws the box that will become the viewport.


i don't mind event driven (i think) as i have a few other tools that should be event driven.

Share this post

Link to post

I guess I'm having a hard time understanding what it is you are trying to do.  Are you trying to draw a rectangle on a design layer to dynamically reflect the crop of a Sheet Layer Viewport or are you trying to convert the bounding box of selected items into the crop object of a Sheet Layer Viewport?


If you are trying to create a rectangle object representing a Sheet Layer Viewport crop, that is certainly doable but you wouldn't be able to make it dynamically resize if you changed the crop of the viewport.  There is a object events command called AddAssociation, but it is very limited, being limited to deleting an object if its associated object is deleted, or resetting an object if its associated object is deleted.  Unfortunately, there doesn't seem to be a way in Vectorscript / Python to force a plug-in object to reset if an associated object is reset (though I'd be very, very happy to be wrong about this).  In other words, the bounding box rectangle has no way of knowing if the viewport crop is changed, so it would have to be manually told to redraw.


So, if this is what you are asking for, you could feasibly write a menu command script that uses GetVPCropObject to get the handle to a selected viewport's crop object, then uses GetBBox to get the dimensions and location of the crop object (though I'm not positive what it would consider 0,0 in the instance of a crop object, you'll want to do some experimentation to figure out what calculations you'd need to translate to the internal origin), then use the returned points to draw a rectangle on a chosen design layer (either hard coded in the script or you could write a GUI to select one from a drop-down list).  One approach is that you could devise a naming scheme to name the rectangle object, so when you run the command on a viewport a second time, it deletes the existing rectangle before drawing a new one with the updated crop.  It's messy, but it would technically work.  You could even use CreateDuplicateObject with the design layer as the containerHandle to copy the crop object directly on the design layer rather than a representation of its bounding box.


If you instead want to use selected objects on a design layer to determine the crop of a sheet layer viewport, this is also very possible (but a bit more complicated).  I wrote a script to generate hang cards for theatrical lighting plots that works exactly like this.  You can even allow it to use objects from multiple design layers, though it makes the code slightly more complicated.  If this is your goal, you'll want to follow these steps:

  1. Build array of handles for the selected objects.  I used a ForEachObject procedure with SEL=TRUE as the criteria to add the handle to a DYNARRAY OF HANDLE.
  2. Build an array of parents / design layers for the selected objects using GetParent.  I did this in the same ForEachObject procedure so that the indexes would line up.  In other words, my parentArray[1] would be the parent of objectArray[1].
  3. Use Group to group all of the objects together.  This will give you a bounding box for all of the selected objects, but will put all of them on the same design layer (not to worry, though, that's why we have an array of handles and parents).
  4. Use GetBBox on the resulting group (you can use LActLayer to get a handle to it) to get the dimensions and location of the desired crop object.
  5. Use Rect with the dimensions given from the above GetBBox to draw your crop object.  Use LNewObj to assign the rectangle to a handle.
  6. Use HUngroup on your created group to release the selected objects.
  7. Use a FOR loop using the bounds of the object handle array and SetParent to restore the selected objects back to their respective design layers.
  8. Use CreateVP to create a viewport on a target sheet layer.
  9. Use SetVPCropObject to assign the rectangle you made earlier as the target viewport's crop object.
  10. Use SetObjectVariable commands on the viewport to set things like its scale, view, etc.  The pointers to these variables can be found in the appendix, but know that the viewport will be drawn at 1:1 scale by default, so it's best not to skip this step.
  11. Use SetVPClassVisibility and SetVPLayerVisibility to set visibilities for the viewport.
  12. Use ResetObject to reset the viewport.

Like I said, a bit complicated but very doable.


Did this answer your question or did I entirely miss the mark of what you are trying to do?  I should mention that I am not as familiar with the Python side of things as I am with the Vectorscript side, but because you are restricted to the Vectorscript function library anyway, the above should get you well on your way to figuring out the Python.

Share this post

Link to post

I am currently doing option 2, where I select an object(s), draw a rectangle, create the viewport and move it to a Sheet Layer. This works great as a menu command.


I was trying to see if there is a way to convert this to a tool command. My thought was while on the Sheet Layer, you use a tool command (Create ViewPort) that has a few parameters that control what is being displayed. Then when changing the parameters I could reselect and redraw the viewport. This would make it a bit faster to create the sheets layers and eliminate the bouncing between Design and Sheet Layers that we currently doing.


The part that I think is stopping me is having the Custom Object one a sheet layer draw the rectangle that will be used as the crop object as that needs to be on the Design Layer.


I'm not clear on where the crop objects lives after it is part of the viewport. Is it part of the viewport or is it an object on the Design Layer.



Share this post

Link to post

The crop is part of the Viewport. It has to be a single closed screen plane object and it lives in the Crop Group of the viewport.


Most of the information on Viewports is in the Object-Groups section of the Function Reference.

Share this post

Link to post

I just had a thought.....


If I draw the correct size box while on the Sheet Layer, then change it's parent to the Design layer, then the box shows up in the correct Design Layer & in the correct position.


I'm not think this may actually work, I will report back if I get it working.



Share this post

Link to post

But when you are on a sheet layer you can not see the design layer. How are you going to know where to draw the box?



Share this post

Link to post

My goal is not select visually, but use the vs.SelectObj(searchCriteria) to select everything. Image a LED panel that I have assigned a display number, processor and port id. Using the SelectObj I can select everything I need, draw a rectangle, and change the rectangle parent to the Design Layer. This this part works nicely.


My hope was I could then create a ViewPort, assign the VPCrop and have a Custom Object on the sheet layer that I could change the parameters and get an updated viewport.


I don't think this is possible as the viewport can only have a parent of a layer (or nested layer) and can't be inside my custom object.


From VectorWorks : "Creates a viewport object. The specified parent handle may only be a layer or a group contained within a layer, nested or otherwise."


It's not completely tragic as I will rework the code to run from the menu. The Custom Object would have been a cleaner solution, but the menu option will work.


Thanks for all the Help on this!!



Share this post

Link to post

Your description of what you are trying to do still does not make sense to me, but here is what I think you are trying to do.


Click on an object in a design layer. Use some information from that object to then select a bunch of related objects. Create a crop object that will surround those object and then create a viewport on a sheet layer that is defined by the setting of the tool used to do the selection.


Does that sound basically correct? If so, I think that is all doable.


If you want to run it from the sheet layer, I think you will have more problems but it might be doable.


Also, you do realize that a VS Tool does not have to create an object. it can just run on existing objects or create a standard object of some kind, not a custom object. I guess I am also having a hard time understanding why you would want a Viewport inside your PIO.


And you statement about Viewports having to have a layer as a parent is not completely correct. You can make viewports part of a group, so they don't always have to have a layer as their parent. I have never tried to make them part of an object though.

Share this post

Link to post

Currently I do something similar to what you descibe, where you select everything from design layer and it will create the viewports on the raster layer. It works, however any changes can mean deleting the raster and starting over, or worse a change can occur in the layout and not get caught in raster. The new guys make this mistake more times than I would like.


Why is a good question. We create our LED displays at actual size and according to the physical layout. We also create a sheet that shows the raster and how the pixels need to be within the raster. This is often very different from the physical layout. On a recent large project the raster had no resemblance to actual layout. Our goal was to reduce the number of raster and cram as much into one raster as possible. It was a game of Tetris coming up with the optimal layout, however the team did miss one small section of the physical display that caused a last minute scramble to resolve.


We could have as many as 30-40 different viewport to create the raster. The thought was if I could use a custom object that creates the Viewport, then I can place one object on sheet layer, then copy and paste and change the parameters to get what I need. And if a change occurs (add a panel, change a panel, change the size of the panel), it would automatically be reflected in the raster layout.


It also allow me to enforce some rules on not what can be split in the raster and what cannot.


A second benefit to have everything in the custom object is it is easier to run an error check to make sure all sections of the display are mapped in the raster. On small systems, it's not an issue, on the bigger system that span multiple floors in a high rise with multiple rack room, it can be easy to miss a display and not have it appear on any raster.


From reading the website, a viewport can be in a group, as long as the group is on layer. When I try to create a VP in code, it returns nil as the handle and create the Viewport on the Sheet Layer.


I'm not sure of a good way to do the error checking other than a lot of ugly code to see what panels are in what viewport and what viewport is in what raster. Doable, but a lot of code.





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