Jump to content

JBenghiat

Member
  • Posts

    2,024
  • Joined

  • Last visited

Everything posted by JBenghiat

  1. Vectorworks loads the entire drawing into memory, and a handle is essentially a variable that can hold the location of each object in memory. That means each handle points to a unique object, but it is not a persistent object identifier — every time you open a file, objects load into different memory blocks, and memory might also get re-used if you delete an object. An empty handle means it is not currently holding the memory location of any object. Once you have a handle to an object, out can think of it as an alias to the object (hey compiler, look here and do x with this object). You can get handles to objects by creating new objects or by traversing the document’s structure, which is organized in a tree. In addition, Vectorworks also keeps an index of handles for all objects, so you can retrieve a handle via object name or UUID.
  2. The best solution depends a lot on exactly what you are trying to accomplish, and your current knowledge of Python and/or Javascript. This isn't the sort of thing where a 10-line example will give you what you need -- if you're new to coding, you may want to contract for this work on spec. One caveat -- you aren't going to be able to have a live connection between VW and GS with Python. You may be able to get some live sync by using an ODBC connection in VW and an Apps Script to build the sheet. You should also be able to build a live connection via the SDK. Possibly the most straight-forwards method is to write data to an Excel sheet on Google Drive, and then (if you don't want to manually import) create an Apps Script to import the Excel workbook into Sheets. VS has commands for working with Excel files here: https://developer.vectorworks.net/index.php/VS:Function_Reference#Excel. You can also find third party Excel libraries for Python. A tutorial for importing via Apps Scripts is here: https://spreadsheet.dev/automatically-convert-excel-spreadsheets-to-google-sheets-using-apps-script#use-apps-script-to-convert-excel-xls-xlsx-to-google-sheets Similarly, you can use Python's csv library to export your data and read via App Script. If importing to Sheets seems daunting, you can use an intermediary service like Zapier, which can monitor a cloud drive or web hook and create your Excel data: https://zapier.com If you want to create your Sheet directly from Vectorworks's Vectorworks, start with these commands to read worksheet data and formatting: https://developer.vectorworks.net/index.php/VS:Function_Reference#Worksheets Google offers a Python API for working with worksheets. You can find an overview and examples here: https://developers.google.com/sheets/api/guides/values#python Or a variant of that would be to use Python to post the data to the Sheet's web app, and process with Apps Scripts. https://trevorfox.com/2017/01/google-apps-script-doget-and-dopost-tutorial-6-web-app-examples/
  3. If you’re looking to manually move data, you can go to the file menu in the worksheet window, and export as csv or Excel, and import to Sheets. If you want to use python to do this programmatically, it is definitely possible — VectorScript can read your worksheet data, and you can either use Google’s API and an OAuth key to write directly to a Sheet, or post the data to the sheet and process with an Apps Script.
  4. What do you mean by “activate”? Are you looking to use the Google API to read or write to Sheets? On the Vectorworks side, do you want to pull from worksheets or directly from objects?
  5. Here's some additional selectors: ovRenderStyleQualityGeometry = 1261; //Short ovRenderStyleQualityAntiAliasing = 1262; //Short ovRenderStyleQualityIndirectLighting = 1263; //Short ovRenderStyleQualitySoftShadows = 1264; //Short ovRenderStyleQualityBlurriness = 1265; //Short ovRenderStyleQualityEnvLighting = 1266; //Short ovRenderStyleMaxReflections = 1267; //Short ovRenderStyleApplyLighting = 1268; //Boolean ovRenderStyleIndirectLighting = 1269; //Long ovRenderStyleHDRIRefNumber = 1270; //Long ovRenderStyleHDRIOption = 1271; //Long ovRenderStyleHasHDRIOption = 1272; //Boolean ovRenderStyleEnableAmbient = 1273; //Boolean ovRenderStyleAmbientBrightness = 1274; //Real ovRenderStyleAmbientColorR = 1275; //Real ovRenderStyleAmbientColorG = 1276; //Real ovRenderStyleAmbientColorB = 1277; //Real ovRenderStyleEmitterBrightness = 1278; //Long ovRenderStyleWhiteColorTemp = 1279; //Long ovRenderStyleApplyBackground = 1280; //Boolean There seems to be two selectors, one that's ovRenderStyleQualityIndirectLighting and one called ovRenderStyleIndirectLighting. You can see if the former will work to set the option. You may also have to set ovRenderStyleApplyLighting to true, or instead/additionally use ovRenderStyleMaxReflections to set the number of reflections.
  6. PTipo will give you the selected value as a string (‘Custom’, ‘10’, ‘20’, etc. ). You then have to use a series of if/then statements to control your code. In VS, there is no way to retrieve the index of the radio button.
  7. Here is the function Pat was referring to. https://developer.vectorworks.net/index.php/VS:Get3DCntr Modify collect() to pass the handle to Get3DCntr, and add the coordinates to the list as a tupple.
  8. Unless you need a specially formatted text file, you can also make a worksheet that displays this data, and then export the worksheet.
  9. Data Tags are an insufficient substitute for Label Legends in a number of areas, particularly when adhering to U.S. drafting standards: - Data Tags don't have a "right reading" option, which is crucial for channel and unit numbers - Data tags don't rotate with an object, so a label that is supposed to be in front of the lens or behind the unit doesn't adjust - The only way to get Data Tags aligned properly to the bounding box of a light is to edit the data tag definition for each size symbol. (so just creating a new style is insufficient) - A typical label legend consists of a combination of alignment and orientations. There isn't currently a way to add more than one type of data tag at the same time, which means a lot more work and significantly more chance for error. Data tags work well on things like hanging cards, where the text doesn't necessarily have to relate closely to the symbol. But for a standard light plot, they are not a viable solution for creating consistently places and styled labels for hundreds of symbols.
  10. No — one of my top wish list items for schematic views is that the label legend should apply to and provide control points for the schematic view and not show for lights that have a schematic view. Adjusting label legends for lights that stack vertically is a nearly impossible task, and I end up avoiding schematic views unless the label legends work without needing to adjust individual labels. My workaround is to separate out the viewport that shows the footprint (the Clip tool works great for this) and use a combination of class viabilities and Data Visualization to format the original lights correctly. Sometimes I'll use a rendered Top view (hidden line foreground, RW background) for the footprint. If your vertical position's Schematic is Front or Side (because the view relates to the unrotated position, it's sometimes Top), I find I need to create a new label legend with the light oriented as it is in schematic view (lekos pointing down, movers in elevation, etc.)
  11. Just time for a quick reply at the moment, but... #1 — correct. I think this is preferred behavior — if you save a new version of the file, or revert to a backup, you do not want all your UUID's resetting. If you copy/paste to another file, then they do indeed reset. #2 & #3 — this is incorrect. As soon as you duplicate an object, including duplicating it's container, the UUID of the copy regenerates. If you call GetObjectUuid() from an external script, you would see that. You should construct your code to read the UUID's directly, rather than from the parameter. The parameter is only useful for an object to know if it has been duplicated — if the current UUID and stored UUID do not match, then it is a copy, and resend accordingly.
  12. In the resource manager, (assuming 2023) look under MEP/Switch and MEP/Receptacle. If you don't see these folders, then they are only available for Architect and Designer licenses.
  13. This is correct. The UUID stays with the object. If you are storing the UUID to a parameter, the object's UUID and the parameter will only mismatch if the object has been duplicated, in which case the object should handle the duplication accordingly. (So if you save as, the UUID will be the same, but if you copy and paste or import layers, they will be different).
  14. I found that the MVC software model is useful when thinking about PIO’s. The OIP and drawing represent the view, and your parameters hold the data. Your code is the controller. So, for a pull-down, you’re creating a view of the available options for the selected objects at the moment of selection. That widget’s sole purpose should be for user interaction. At that point, you shouldn’t care about unselected objects, because the user can’t interact with them. You do have to take multi-selection into account, which only comes into play if all the selected objects are the same type. If each PIO has different possible menu options, you either have to include all the options for all selected PIO’s, or gray out the pull-down. In terms of the data, if the pull-down is an also parameter, the field will only store the selected value. If it is just a widget, it stores no value. Where you would get into trouble is if, for example, you have another command that creates a report based on ALL the options in the pull-down. (Or a PIO button that presents a dialog that accesses all the values, etc). If you use the pull-down values, you are using the UI View as Data, which is bad design. The better option would be to store the data in a hidden parameter (JSON strings are great for this), and think of the widget prep event where you transfer the data to the view.
  15. And just to clarify, widgets just display an object’s data in object info when the object is selected. Technically the popup is the same for all the instances, you’re only changing what’s visible when each instance is selected. In other words, don’t count on widgets for data storage, only data display.
  16. I'm curious if anyone has any experience implementing either IWSFunctionCallEventSink or VWWSFunctionCall_EventSink. First, I'm a little unclear if these can be used to create any WS function or just a QTO function. Also, can you create a custom QTO function for any object, or only your custom objects. Also VWExtensionWSFuncOptions has me completely baffled.
  17. I believe there's actually a bug in the Cable object. The total weight isn't defined properly for Braceworks, so it gets set correctly when a cable style is selected, but then the weight per length gets calculated from the total weight, instead of the other way around. It also means that the weight of the cable won't show up in any total hung weight calculations. I believe if the object were working properly, it would show up in a Hanging Position's total weight. As for Sam's point's, while I can only speculate on the engineering perspective, when we calculate a total hung weight, we're looking for a maximum limit rather than a snapshot of the position's actual weight. Calculations for motors, rigging points, hardware, etc. should assume that the entire weight of the cable applies to the position. And certainly, worst-case-scenario is that the cable is attached to a position coiled and hoisted into place before being deployed.
  18. @Maarten Jansen this seems like a bug to me. I just confirmed that Savvy Select Similar Instrument works correctly in groups; it is designed to select visible and editable objects, so that would include all the other instruments of the same type that are in the group. Objects outside the group remain unselected. https://benghiatlighting.com/software/product/savvy-select-similar-instrument-3/ @Sam Jones can comment on the analogous behavior in AutoPlot.
  19. A kindly Vectorworks engineer took pity on my coding soul and tossed me that bone. It's one of a handful of tips and tricks I keep in a running list.
  20. If you’re not familiar with DebugListView, give a search for other threads on the forum. It lets you browse the drawing structure and see all the hidden fields for an object. You may be able to deduce where the id’s for the child objects get stored so that you can also tell them to reset.
  21. I believe almost all dialogs use the SavedSettings calls. The saved settings get read from an xml file and written to the xml file on quit. One could look at the saved settings files in the user folder and see if the Alignment dialog settings are there, and then change the xml values in memory before running the menu command. You may be able to find dialog controls on the OS level (On the Mac, Automator, Better Touch Tool, or Alfred may provide a solution). I believe all the options have modifier shorty, so even a macro that called the dialog and fired those would work. Or the other way to skin the cat is write a series of scripts that align and distribute objects according to your desired parameters.
  22. @DomC thanks for the further information. I think you have two possibilities— either your script is not resetting the object, or the “update” button does more than just trigger the regenerate event. Generally, calling ResetObject() won’t actually trigger the reset event until after your script completes, so for example, if setting parameter a affects parameter b, calling: SetRField(a) ResetObj() GetRField(b) will return a value of b as if a had not changed (because it hasn’t yet). If this is your scenario, and the cabinet object is SDK based, which I believe it is, you can use ovParametricImmediateReset = 1167 on the PIO to force the reset before continuing on your script. If the cabinet has parameters that depend on each other, for example a change an affects b and changing b affects a, the PIO likely detects OIP changes and responds accordingly. As far as I know, there’s no way to trigger a parameter change as though it was made by the user. SetRField() directly changes the object’s parameters without triggering any state change events. In that case, I recommend contacting the interiorcad folks and seeing if they can provide a specific solution.
  23. You can trigger the reset event via ResetObject(). You can use states to see if the reset was internal (e.g. changing a parameter or moving) or triggered by the call. You can also use the string repository to pass information to the PIO. In terms of triaging a button event or the tool, if the event is from another one of your scripts, you can structure you code to run from the same includes. For example, construct an include file that takes a handle to your PIO as a parameter. Pressing a button on the PIO would pass the PIO’s handle to the function. Running a menu command would invoke ForEachObject() with your function as the callback.
  24. Text in viewports, symbols, and plug-in objects will auto-rotate to all face the same 90 orientation when Adjust Flipped Text is turned on. As a workaround, you can add or subtract .02° to the orientation to maintain control over which way the text faces (that's just enough virtual thumb on the scale to tell VW which way is down). The rotation is imperceptible -- even if you zoom way in, there's no visible distance to an orthogonal orientation.
  25. I'll also plug my Savvy Position Label. One of the options for the Notes field is a display of total hung weight for the position, which includes every object attached to the rigging object as a load. It works with Hanging Positions, Lighting Pipes and Ladders, Straight Truss, Curved Truss, Truss objects, Truss lines, and Truss systems. The result only appears as a note in the positions label -- if you need a report, AutoPlot is the way to go. https://benghiatlighting.com/software/product/position-label/
×
×
  • Create New...