Jump to content

Jesse Cogswell

  • Posts

  • Joined

  • Last visited


395 Spectacular


Personal Information

  • Location
    United States

Recent Profile Visitors

2,832 profile views
  1. I've attached a couple other menu commands that I've done in case you want to borrow any other features from them. Set Emitters by Fixture Type: This is a command that I wrote to take advantage of new object variables added in VW2020 to deal with emitter settings. I often use emitters to get more realistic output for Renderworks renderings (don't work in Redshift unfortunately), and was getting frustrated with having to manually input the emitter data every time I changed a fixture type. This command will detect the selected fixture types and scale a dialog box allowing you to set the emitter settings for each type. Once you click OK, the settings will be updated for all selected Lighting Device objects. Set Light Levels by Channel: This command will likewise scale a dialog by number of selected lighting fixtures (up to 100 channels), allowing you to quickly set levels based on a bunch of channels at once. Set Emitters By Fixture.vsm Set Light Levels by Channel.vsm
  2. I've hit a serious roadblock dealing with version control, updating, and copy protection on several of my plug-ins and am curious about how some of you handle it. I have managed to embed version numbers into the plug-ins themselves by adding a popup parameter called '__version', then using GetLocalizedPluginChoice(<plug-in name>, '__version', 1, versionNum), but what's a good method of handling updating? Using Python to poll an online manifest to determine if a plug-in is out of date? Then using Python to download the new version from an online depository and overwrite the existing plug-in definition? Then there's the whole issue of copy protection. Right now, I sell my plug-ins on Gumroad.com but there's nothing really stopping one person from purchasing the plug-ins and then sharing the .zip package with others. I've thought about ways to create a key based on a user's serial number, but what is the best way to manage users? Should I consider writing an external application to manage things? I'm open to any and all ideas and methods.
  3. Here's a snippet from my own code that I use to toggle whether a light is on or off. I wrote it to combat the annoying "feature" introduced in VW2022 where new Lighting Device objects defaulted to being "on." It will take any selected Lighting Device object and toggle the state of the internal light. It works for standard Light Devices as well as Lighting Devices using the Emitter settings. PROCEDURE ToggleState(h:HANDLE); {Polls embedded Light object and toggles its on/off state} CONST kLight = 81; kLightOn = 50; VAR h2,lightHd:HANDLE; currentState:BOOLEAN; BEGIN selDeviceCount:=selDeviceCount+1; h2:=FInGroup(GetCustomObjectProfileGroup(h)); WHILE(h2<>NIL) DO BEGIN IF(GetTypeN(h2)=kLight) THEN BEGIN lightHd:=h2; currentState:=GetObjectVariableBoolean(lightHd,kLightOn); h2:=NIL; END ELSE h2:=NextObj(h2); END; SetObjectVariableBoolean(lightHd,kLightOn,NOT currentState); ResetObject(h); END;
  4. The pre-2021 version of Vectorworks handled this with the Focus Instruments menu command, which was bound to the Ctrl+Alt+Shift+F shortcut by default (on Windows that is). In 2021, they changed the dialog to the Focus Lighting Devices menu command, which doesn't use Focus Point objects at all. As part of my workflow, I lay out all of my focus points before I plot any fixtures, so I've imported the old menu command into the newer copies of VW as Focus Instruments Old.vsm and using it instead.
  5. I have seen this in both VW2022 and VW2023, but it only affects the Shaded render type. If you do a Hidden Line, Redshift, or Renderworks rendering, it all works fine. I suspect it has something to do with the new Shaded code in regards to Lighting Devices by trying to keep the 3D geometry simple when you have a lot of lights. Shaded w/ Lighting Device next to Symbol, quality set to High It's almost like it's defaulting the Shaded quality to Low. When I make any change to the Shaded quality, even setting it to Medium, the geometry resets and displays properly, but only sometimes and not on all Lighting Device objects. After changing the Shaded Quality from High to Medium Zoomed out from above, left two fixtures still low quality Elsewhere in the drawing, correct fixture is of a different type and using a different symbol than example above The drawing has 61 lighting fixtures currently visible, and only 1 or 2 of the fixtures are rendered properly at any given time. Which fixtures display properly appears to be random and change each time I change the Shaded quality level. I have also found that this only affects design layers, if you have a viewport set to Shaded background render mode, everything renders as it should.
  6. @michaelk I've attached an example that should be able to answer most of your event-enabled questions (and probably raise some new ones) as well as provide an example of symbol and texture pickers. Unfortunately, they are quite complicated, but you can copy and paste my code to get it set up. The procedure you are looking for is the PopulateResourceArray procedure, which allows you to pass in a resource type and will return the number of parents (IE Resource Manager Folders) and resources, which can then populate the Thumbnail Popup. My method allows for sorting by folder, so it's easier to stay on top of drawings with a lot of symbols or textures. The PIO itself is fairly straightforward, it takes the selected Symbol and separates out the 2D and 3D components. The 2D components get their fill set by the Color Index parameter, and the 3D elements get their overall texture set to the selected Texture. Double-clicking the object will advance the color index by 1. I know the preview for the texture selection is muddy and backward, but it is the best I've been able to figure out with the CreateImageControl procedure. There is a CreateImageControl2 added in 2012, but I've never been able to figure out how to get a texture into it. As for PIOs and Object Styles, I haven't gone through with adapting my plug-ins to using them (I overhauled all of my plug-ins during the 2020 quarantine JUST before VW2021 came out, and I haven't had enough time to incorporate styles since), but @Julian_Carr and @_c_ included a ton of good information in this thread: Event Enabled Example.vso
  7. It would appear that the online function reference is out of date and incomplete. Looking at the local function reference (found in the Vectorworks application folder in a folder called "VWHelp"), it lists 1166 as Parametric Localized Name. It looks like the online appendix is missing a bunch of these.
  8. The INVIEWPORT flag only affects objects that are in a viewport's annotation or crop space. Looking at the code above and doing a quick test with it, it is working as intended. The viewport is only relaying the visual information from Design Layer space, so if objects on Design Layers are now set to By Class, those changes will be reflected in the viewports as well. You could lock in class overrides per viewport to combat this, but that would be a tricky thing to script out. If you don't want your code to be reflected on Sheet Layers, there is a fix I can recommend. What you sill want to do is poll whether an object is on a layer using a combination of GetParent and GetTypeN. GetParent will return a handle to an object's parent, which could be a symbol, group, PIO, layer, or viewport. GetTypeN will return a number based on the type of object passed to it. In this case, we're looking for 31, which is the internal object number of a layer. From there, we can use GetObjectVariableInt on the handle to the layer and selector 154 to poll whether the layer is a Design Layer (return 1), or a Sheet Layer (return 2). If it returns a 1, we execute the code. The finished code would look something like this: Procedure UseClassAttribs; Procedure Execute(Hd1:Handle); CONST kDesignLayer = 1; kLayer = 31; kLayerType = 154; VAR hParent:HANDLE; BEGIN hParent:=GetParent(Hd1); IF(GetTypeN(hParent)=kLayer) THEN BEGIN IF(GetObjectVariableInt(hParent,kLayerType)=kDesignLayer) THEN BEGIN SetFillColorByClass(Hd1); SetPenColorByClass(Hd1); SetFPatByClass(Hd1); SetLWByClass(Hd1); SetLSByClass(Hd1); SetOpacityByClass(Hd1); END; END; End; BEGIN ForEachObject(Execute, (INOBJECT & (ALL))); End; Run(UseClassAttribs);
  9. Here you go. This script will open up a dialog window so you can select the target class. PROCEDURE ChangeTextClass; VAR targetClass:STRING; dialog,layoutDialog:LONGINT; check:BOOLEAN; PROCEDURE Execute(h:HANDLE); {Changes class of given object to targetClass} BEGIN SetClass(h,targetClass); ResetObject(h); END; FUNCTION DrawDialog(DName:STRING) : LONGINT; {Creates dialog box and returns dialog ID} CONST kClassWidth = 25; VAR dia:LONGINT; BEGIN dia:=CreateLayout(DName,FALSE,'OK','Cancel'); CreateStaticText(dia,11,'Select Target Class',-1); CreateClassPullDownMenu(dia,21,kClassWidth); SetFirstLayoutItem(dia,11); SetRightItem(dia,11,21,0,0); DrawDialog:=dia; END; PROCEDURE DialogHandler(VAR item,data:LONGINT); {Handles dialog box} VAR int:INTEGER; BEGIN CASE item OF SetupDialogC: BEGIN END; 1: {OK} BEGIN GetSelectedChoiceInfo(dialog,21,0,int,targetClass); check:=TRUE; END; 2: {Cancel} BEGIN check:=FALSE; END; END; END; BEGIN dialog:=DrawDialog('Select Text Class'); layoutDialog:=RunLayoutDialog(dialog,DialogHandler); IF(check) THEN ForEachObject(Execute,INSYMBOL & INOBJECT & INVIEWPORT & (T=TEXT)); ReDrawAll; END; Run(ChangeTextClass); Slight word of warning: This script will change the text within Plug-in Objects as well. With most PIOs, the text objects inherit the class of the PIO itself, so if anything causes the PIO to be reset (layer changed, OIP value changed, moved or rotated with certain PIOs, etc), the text class will be reset to the PIO class. But the script above WILL work until the object is reset. There is no way to permanently change the text class for PIOs without editing their code directly, which no script can (or should) do.
  10. That was the first thing I tried. But the only way the texture would reset was if a parameter in the OIP was changed or if the object was moved to a different layer. Moving the object to a different layer and back worked, but only in drawings with more than one layer, and it didn't work with objects inside symbols. The duplication turned out to be the easiest solution in this case.
  11. What you are looking for is a combination of two different commands to get Auto-Align Plane and one command for World Z Origin: SetTexMapIntN(<Handle>,<texture part>,0,1,0); {Sets map type to Plane} SetTexMapBoolN(<Handle>,<texture part>,0,7,TRUE); {Sets map to Auto-Align} SetTexMapBoolN(<handle>,<texture part>,0,6,TRUE); {Sets map to use World Z Origin} One major thing if using VW2022 or later when using objects with class textures is that you MUST have a texture assigned to the class. If not, all of the mapping gets set back to default regardless of the script commands. I've attached a little plug-in that I used to learn texturing in VS that might help you out. For your extrude, you will likely be using texture part 3 for Overall or 4 for Top, 5 for Bottom, or 6 for Sides. Texturing Test No Event.vso
  12. In this case, there's no need to make the tool event enabled (though I am a huge proponent of event enabled plug-ins, you can do a lot of cool things with them). I've attached the same plugin above with all of the event script removed. Texturing Test No Event.vso
  13. As for the texture By Class, it's a wee bit trickier. Objects can have multiple components, such as an Extrude's top, sides, and bottom, or a Wall's top, left side, right side, cap, hole, etc. These are known as "Texture Parts." There's not really a script command to pull an object's texture parts, so doing a full reset to By Class is kind of tricky. Texture Part 3 is considered an object's "overall" texture, so the code below will force all objects' Overall part to be by class. PROCEDURE TextureByClass; PROCEDURE Execute(h:HANDLE); BEGIN SetTextureRefN(h,-1,3,0); ResetObject(h); END; BEGIN ForEachObject(Execute,INSYMBOL & (ALL)); END; Run(TextureByClass); However, what you'll discover is that the above script will technically work, with the texture properly updating in the Render tab of the OIP, but the object won't reflect the change until you change a value on one of the object's properties to force the object to reset. I tried this with extrudes, sweeps, and 3D polygons and all of them exhibited this issue. I found a solution by creating an array of handles to texturable objects, then running code to set the texture, then duplicate the object, and delete the original. It's complicated, but I think it works. PROCEDURE TextureByClass; VAR objectArray:DYNARRAY[] OF HANDLE; numObjects:INTEGER; PROCEDURE SetTextureByClass(arr:DYNARRAY[] OF HANDLE; num:INTEGER); VAR i:INTEGER; hParent,hDup:HANDLE; sName:STRING; BEGIN FOR i:=1 TO num DO BEGIN sName:=GetName(arr[i]); hParent:=GetParent(arr[i]); SetTextureRefN(arr[i],-1,3,0); ResetObject(arr[i]); hDup:=CreateDuplicateObject(arr[i],hParent); DelObject(arr[i]); SetName(hDup,sName); END; END; PROCEDURE BuildArray(h:HANDLE); BEGIN IF(GetObjectVariableBoolean(h,500)) THEN BEGIN numObjects:=numObjects+1; ALLOCATE objectArray[1..numObjects]; objectArray[numObjects]:=h; END; END; BEGIN ForEachObject(BuildArray,INSYMBOL & (ALL)); SetTextureByClass(objectArray,numObjects); END; Run(TextureByClass);
  14. I'm not sure which version of Vectorworks you are using, but I would add the SetPref(6839,TRUE) call before the ForEachObject call. If you are running version 2022 or newer, the screen plane is disabled by default, so running your script to force objects onto the screen plane will technically work, but if the Legacy 2D Features option isn't enabled for the drawing, the Plane field in the OIP will be blank. This command will enable the feature before placing objects on the screen plane. If you are on an older version of VW, please disregard this message but keep it in mind in case you upgrade. Screenshot without SetPref code with Legacy 2D Features disabled at runtime: Screenshot with SetPref code with Legacy 2D Features disabled at runtime:
  15. The script to change all screen objects to the layer plane is listed below: PROCEDURE ScreenToLayer; PROCEDURE Execute(h:HANDLE); BEGIN SetObjectVariableBoolean(h,1160,FALSE); END; BEGIN ForEachObject(Execute,(PLA='Screen Plane')); END; Run(ScreenToLayer); VERY IMPORTANT IN THIS CASE: Do not put the INSYMBOL and INOBJECT flags in the criteria for the ForEachObject call. Vectorworks uses the screen plane to determine which objects exist within the 2D component of hybrid symbols and plug-in objects. So, if you include those flags, all of your hybrid symbols will be turned into 3D only symbols, and plug-in objects that contain 2D and 3D geometry will project the 2D geometry into 3D space. You don't need the INVIEWPORT call because annotations ignore the plane anyway. As for ObjectVariable 1162, "Object is in Layer Plane", it is read-only, so using SetObjectVariableBoolean(h,1162,TRUE) won't do anything. EDIT: Looking back over this post, I'm a little confused about what you are looking for. Are you looking to force things onto the Screen Plane or taking objects existing on the Screen Plane and forcing them to Layer Plane? If you are looking to force all objects to the screen plane, you can use the code below: PROCEDURE ScreenToLayer; PROCEDURE Execute(h:HANDLE); BEGIN SetObjectVariableBoolean(h,1160,TRUE); END; BEGIN SetPref(6839,TRUE); ForEachObject(Execute,ALL); END; Run(ScreenToLayer); Please note that in this case, you will need to engage the legacy 2D features with SetPref(6839,TRUE) to enable the screen plane before you can assign objects to it.
  • Create New...