
Anthony Esau
Member-
Posts
18 -
Joined
-
Last visited
Reputation
6 NeutralPersonal Information
-
Location
United States
Recent Profile Visitors
The recent visitors block is disabled and is not being shown to other users.
-
Request: Make 2d/3D Symbol 'Unique' script
Anthony Esau replied to MarcelP102's topic in Vectorscript
@MarcelP102 A file with a revised script to handle multiple selected symbols is attached. Try it out. I made a few other minor improvements as well such as clearer variable and function names. @Jesse Cogswell SetHDef was new to me for this occasion as well. It's pretty handy! Make Unique updated to handle multiple selected symbols.vwx -
Request: Make 2d/3D Symbol 'Unique' script
Anthony Esau replied to MarcelP102's topic in Vectorscript
Thanks for your script @Jesse Cogswell! I've been using it for a while and it's been very helpful. Occasionally I would encounter issues with mirrored/flipped objects similar to @MarcelP102, so I took a stab at writing my own version of the "make unique" command in Python (with some assistance from ChatGPT). This script has not been tested extensively so it may have errors or misbehave in some scenarios. It's more simplistic than @Jesse Cogswell's and might not have all the features, but for my use case it works and has been functioning well so far. import vs import re def FSWaldo(): """ Return a handle to the first selected object in the present context of the drawing window. """ # Drop a breadcrumb, a Locus vs.Locus(0, 0) # Get the handle to the Locus locus_handle = vs.LNewObj() # Move it to the bottom of the stacking order, but stay within the current container vs.HMoveBackward(locus_handle, True) # Get the handle to the next selected object above the locus, or None if there are none next_selected_handle = vs.NextSObj(locus_handle) # Discard the Locus vs.DelObject(locus_handle) # Return the handle to the next selected object return next_selected_handle def get_incremented_name(name): match = re.match(r"^(.*?)(-(\d+))?$", name) base_name = match.group(1) number = int(match.group(3)) + 1 if match.group(3) else 1 return f"{base_name}-{number}" obj = FSWaldo() if obj is not None and vs.GetTypeN(obj) == 15: #symbol instance sym_name = vs.GetSymName(obj) sym_def = vs.GetObject(sym_name) new_name = get_incremented_name(sym_name) # Test if an object with the incremented name already exists max_iterations = 1000 # Set a reasonable limit iterations = 0 while vs.GetObject(new_name) != 0 and iterations < max_iterations: new_name = get_incremented_name(new_name) iterations += 1 if iterations >= max_iterations: raise Exception("Maximum iterations reached, possible infinite loop.") new_name = vs.StrDialog("New symbol name", new_name) while vs.GetObject(new_name) != 0: new_name = vs.StrDialog("Name already used. Provide a unique symbol name.", new_name) if new_name != "": # Duplicate the symbol definition new_sym_def = vs.CreateDuplicateObjN(sym_def, vs.GetParent(sym_def), True) # Name the new symbol definition vs.SetName(new_sym_def, new_name) # Set the definition of the symbol instance to the new symbol definition vs.SetHDef(obj, new_sym_def) Edit: And I should say thanks to @Pat Stanford for the snippet about the CreateDuplicateObject command which got me started. -
Attach record to custom plug-in object
Anthony Esau replied to Anthony Esau's topic in Python Scripting
Ah, I didn't read the documentation for GetCustomObjectInfo() closely enough and missed one of the returned values which threw off my numbering. Thank you for identifying the mistake, @JBenghiat! Good point about accessing the object parameters rather than attaching a potentially redundant record. I have already been using the object parameters as dynamic text in a graphic legend, but I would like to do some calculations with the parameter values and make that information available to the legend. And I may attach different records based on the settings of the object. My documentation pipeline for this object is still being worked out, so we'll see if it plays out effectively. By the way, the PIO is a museum pedestal that can be made in a few different styles which affect the relative size of the vitrine (acrylic case) on top of it. Here's a snippet of the actual work-in-progress PIO script (not the test from above) incorporating the other suggestions. Thanks so much for your input @JBenghiat. So far this is working in my limited testing. pedestal_record = "Pedestal RF" # Check if record format exists pedestal_record_handle = vs.GetObject(pedestal_record) if pedestal_record_handle == 0: # Create record format vs.NewField(pedestal_record , "Style", "Step", 4, 0) vs.NewField(pedestal_record , "Width", 0, 9, 0) vs.NewField(pedestal_record , "Depth", 0, 9, 0) vs.NewField(pedestal_record , "Height", 0, 9, 0) vs.NewField(pedestal_record , "Include Vitrine", True, 2, 1) # Check if record is attached to PIO if vs.Eval(PIO_handle, "R IN ['"+ pedestal_record + "']") == 0: # Attach record vs.SetRecord(PIO_handle, pedestal_record) # Set field values vs.SetRField(PIO_handle, pedestal_record, "Style", style) vs.SetRField(PIO_handle, pedestal_record, "Width", vs.Num2StrF(width)) vs.SetRField(PIO_handle, pedestal_record, "Depth", vs.Num2StrF(depth)) vs.SetRField(PIO_handle, pedestal_record, "Height", vs.Num2StrF(height)) vs.SetRField(PIO_handle, pedestal_record, "Include Vitrine", includeVitrine) -
Hello! Is it possible to attach a record to a custom plug-in object automatically as part of the script of the custom plug-in? And then assign values to the record fields? I tried a combination of vs.GetCustomObjectInfo()[1] to get the handle to the custom plug-in object and then vs.SetRecord() to set the record to an existing record format, but it doesn't actually attach the record. A test file along with the .vso of the custom plug-in are attached. It creates a rectangle and then extrudes it based on dimensions provided by the custom plug-in parameters. And it should assign those dimensions to the record. But it doesn't even attach the record. The test is very simple to get up and running, but I do have a practical use case that is similar but with a little more to it. Here is the script for the custom plug-in. # inputs width = vs.Pwidth depth = vs.Pdepth height = vs.Pheight # define variables PIO_handle = vs.GetCustomObjectInfo()[1] direction = [1, 0] # for creating extrudes # Create the extrude bottom = 0 top = height origin = [-width / 2, -depth / 2] vs.BeginXtrd(bottom, top) prof = vs.RectangleN(origin[0], origin[1], direction[0], direction[1], width, depth) vs.EndXtrd() # Attach record and set Pedestal RF fields blockRecord = "Box RF" vs.SetRecord(PIO_handle, blockRecord) vs.SetRField(PIO_handle, blockRecord, "Width", width) vs.SetRField(PIO_handle, blockRecord, "Depth", depth) vs.SetRField(PIO_handle, blockRecord, "Height", height) Box Custom Plug-in.vsoCustom Plug-in Object Record Test.vwx
-
Graphic legend - version for non-data objects
Anthony Esau replied to Amanda McDermott's question in Wishlist - Feature and Content Requests
Not sure if it is remotely the same issue, but I have not had any luck getting a number of types of objects (3D polys, extrudes, or NURBS surfaces, 2d rectangles) to show up in graphic legends. For the source of my legend, the criteria is set to objects in a certain layer with a certain record attached. In the narrow scope of my testing, only symbols, custom plug-in objects, and tapered extrudes are included in the legend despite other types of objects meeting the criteria of being in the correct layer and having the record attached. Unchecking the "Hide Empty Cells" option of the graphic legend does include cells for all the objects (3D polys et al), but it doesn't show the visual representation of the objects that were previously excluded. Trying various settings in the "Define Legend Image" portion of the graphic legend options did not help. @Amanda McDermott perhaps this is contributing to the challenges you are having. -
Marionette object style malfunctions in Vectorworks 2024
Anthony Esau replied to Anthony Esau's topic in Marionette
Quick update: I submitted this to tech support and received the response that "This issue has been escalated as a bug and is currently being investigated by our engineering team." -
Marionette object style malfunctions in Vectorworks 2024
Anthony Esau replied to Anthony Esau's topic in Marionette
Continuing my monologue 😅 It looks like the issue arises from naming the String nodes with a prefix of a number and a space. In that last demo file, I named them "1 String," "2 String," "3 String," and "4 String." In the OIP, they all show up as "String" but are in sequential order. If they are named "String1," "String2," "String3," and "String4" then the Marionette object style functions properly. Unfortunately, in my attempts so far, the string inputs in the OIP for existing objects using the old style stick to the old String node names even when the Marionette object style is edited or even replaced. So there is a workaround for the broader bug, but not an efficient solution for my existing project. -
Marionette object style malfunctions in Vectorworks 2024
Anthony Esau replied to Anthony Esau's topic in Marionette
Since my demo file is for a very specific use case and contains custom Marionette nodes, I put together a simpler example with all standard nodes to check if the problem was unique to that Marionette network or not. The attached file demonstrates that string input is broken when a style is created from a Marionette object. It uses only standard nodes. Marionette string input issue demo.vwx -
Marionette object style malfunctions in Vectorworks 2024
Anthony Esau replied to Anthony Esau's topic in Marionette
I ask about workarounds in the last paragraph above, but ultimately a bug fix for Vectorworks would be a better solution. Can anyone else confirm if this is a bug? Or is there something that needs to be updated with the Marionette object to be compatible with the VW 2024? -
Hello! After updating to Vectorworks 2024 from the 2023 version, I am having an issue with a Marionette object style that I have used extensively previously. The purpose of it is to "clone" or duplicate the geometry of a symbol and then swap the textures. So it is essentially a symbol that has textures that can be changed per instance. Now in VW 2024, the styled Marionette object no longer changes the textures. If I convert it to an unstyled Marionette object it works though! However, if I convert each instance to unstyled, the settings of which textures to replace in the Object Info Palette also change. So I would have to manually change them back to the correct textures that are specified. If the OIP settings persisted, I would simply convert all the objects to unstyled for my current project and move on. While looking for solutions, I created a custom plug-in object that performs the same task as the Marionette object and functions properly in Vectorworks 2024, so I would transition to using that instead of Marionette objects. A simplified demonstration file is attached. Is there a way to convert all the objects to unstyled and keep the OIP settings? Or can a Marionette object be replaced with a custom plug-in object (and transfer the OIP settings)? I'm not afraid of a little scripting if that might provide a solution but would have to weigh that complexity against brute force manually changing all objects. Clone symbol Marionette object bug demo file.vwx
-
Inconsistent texture selection of Get Texture node
Anthony Esau replied to Anthony Esau's topic in Marionette
Ah. Thanks for confirming that it isn't just me. Good to know that it's already on your radar. -
Hello! The texture selected in the Get Texture node changes from time to time without user input. I believe it is related to the creation, deletion, and renaming of other textures, but this issue does not always show up regularly. Sometimes the selected texture of one node will always change to the newest created texture while other Get Texture nodes will not be affected at all. Sometimes the selected texture arbitrarily changes to something seemingly random or perhaps to a texture whose name is alphabetically next to the one that I originally selected. As you can imagine, this behavior is problematic when creating a wrapper or Marionette Object because the results shift from what is intended. And the fix is to go through and manually reset the selected texture in the Get Texture node, only for the texture to change arbitrarily in the future. Has anyone else encountered this? Any fixes? I have resorted to a modified Get Texture node that takes the name of the texture as a string input, but this is much less convenient. My main use case is a Marionette Object with some custom nodes that recreates a specified symbol but replaces selected textures with other selected textures. So it is kind of like being able to create multiple instances of the same symbol but apply different finishes to them. I work as an exhibit designer and in my models I constantly need many physical structures that are the same except with different paint colors or different graphics / signage applied to them. So I set up a symbol with placeholder textures and then create multiple copies of it with the custom Marionette Object that replaces the textures of each instance. Randomly changing textures from the Get Texture node throw a big wrench in this setup.
-
Create a texture resource from image in a folder
Anthony Esau replied to jonasfehr's topic in Python Scripting
A bit crude, but you can add the command "vs.EditTexture(hTexture)" to open the texture editor for each modified texture. The user will need to click through all of the boxes that pop up, but it forces a refresh of all the textures with the updated information. In my job, I am constantly importing graphic layouts that were generated in Adobe Illustrator. So the scripts shared in this thread have been incredibly helpful. For my situation, individual sizing of the Renderworks textures can be automated by reading the metadata from the images to calculate what size the images were designed to be. This requires installing the Pillow Python library and adding "from PIL import Image" to the top of the script. Then the following lines are added to the main loop. # Calculate the size (width) of the image with Image.open(imagePath) as pil_image: image_width_px = float(pil_image.size[0]) image_resolution_x = float(pil_image.info["dpi"][0]) image_size = round(image_width_px / image_resolution_x, 3) In my limited testing, Pillow doesn't read the dpi correctly from files created in Photoshop and I haven't tested images generated by other programs. Might need some additional tweaking to work more broadly. For setting the texture size, "vs.SetTextureSize(hTexture, image_size)" has been working well for me. -
And...I'm a little slow...but I now realize the "cp39" in that filename signifies Python version 3.9 which corresponds with the version that Vectorworks 2023 uses. I had been installing Pillow for Python 3.11 previously which resulted in the error (if I am finally understanding correctly).