Jump to content


  • Content Count

  • Joined

  • Last visited

Everything posted by MullinRJ

  1. MullinRJ

    Script error

    Hello @G.B , It is a problem with the "Interior Elevation Marker" tool. Does the problem repeat after you restart VW? If so, someone at the factory will have to answer your questions. I tried it on my licensed version of VW and it works. It could be related to the evaluation version, or it could be a problem with the tool and the way you are using VW (setup, units, view, etc.). It's hard to tell from here. Restart and write back. Raymond
  2. Hello Ralph, I sent you a private message. Thank you, Raymond
  3. Hi Andrew, I adapted Pat's script to also set the Point Size of the text. This will set all objects to the same size which could make some documents look weird. You could break the script into two scripts to give you more control. To just set the point size, comment out (or remove) the SetTextFont() command. You can also make the script work only on SELECTED text objects only by changing the "& ALL" to "& SEL" in the ForEachObject() command near the bottom. PROCEDURE ChangeAllFonts; { Changes the font of all text on a drawing to the selected font } { Traverses into groups, symbols and viewport annotations } { January 6, 2012 } { © 2012, Coviana, Inc - Pat Stanford pat@coviana.com } { Licensed under the GNU Lesser General Public License } { 17 February 2020 - R. Mullin } { Added ability to set the Point Size of all text objects at the same time. } { Same GNU License as above. } VAR Hd :Handle; Font :String; FontID, dInt :Integer; PointSize, dReal :Real; Procedure ChangeFont(Hd:Handle); Begin if (GetTypeN(Hd) = 10) then begin SetTextFont(Hd, 0, len(gettext(Hd)), GetFontID(Font)); SetTextSize(Hd, 0, len(gettext(Hd)), PointSize); end; End; BEGIN Font := 'Arial'; FormatTextDialog(Font, dInt, dReal, dInt, dReal, dInt, dInt, 60); ForEachObject(ChangeFont, INSYMBOL & INOBJECT & INVIEWPORT & ALL); END; Run(ChangeAllFonts); Raymond
  4. Hello Benedick, Try this, instead of setting "Make All Attributes By Class", set the attributes to "Remove By Class Settings" before you create any text. Also, make sure the "Use At Creation" check box (in the top left corner) is OFF in the "Edit Class(es)" dialog. Leave the "Text Style - Use At Creation" checkbox ON. Lastly, use a different color for the Text Style than for the Class Pen Color. That way you'll see which color is making it through. Whatever the deal is with this feature, it is not designed to work well. I only just now discovered that using "Make All Attributes By Class" would improve the expected response, and that was on a whim. I've messed with this feature several times over the last few months and had the same confusion you're experiencing. It seems that using "Make All Attributes By Class" comes in after everything is created and overwrites the Pen Color, and possibly the Fill Color, too. I haven't tested the class Fill Color yet. WAD or not, this feature needs improvement. This is anything but intuitive. Raymond
  5. Hi Allison, Is this problem only in one file or does occur in a new blank document? Can you post a sample file showing the problem? Thank you, Raymond
  6. Hi @AllisonCPA , That sounds strange. Did you restart VW? Sometimes quirky things happen that vanish after a restart. Can you select the dimensions individually with the Selection Tool? Raymond
  7. Hi @AllisonCPA , Could you elaborate a little more? I just drew 5 dimension objects in a Viewport Annotation and I was able to select them all using Object Type as the criteria. It also works if I only have Font as my lone criteria. What option(s) do you have selected for the tool? Do you get a dialog stating "The selected activation options can't be used for this object."? Raymond
  8. Thanks, Josh. @JBenghiat Advice heeded. I've wanted to do this in the past only for investigative purposes, but never for anything practical. On one occasion (only one) I stored the string values of handles so I could sort them and do a binary search of the Symbol Library. It worked perfectly. Thanks for the warning. Raymond
  9. @twk , The Always Execute Scripts button will reset when VW re-launches, so you are not giving up your ability to block script execution forever. That was my biggest concern when I first ran into this dialog. Was afraid to press the button. I don't know if this is documented, I found it out by trial and error and I was very pleased to see the function resets at the end of a VW session. I feared it would open the door for scripts to execute forever. On a tangential note: it would be extremely helpful for this dialog to have a Help window to explain the scope of each button's functionality. HTH, Raymond
  10. I wish this were possible. To the best of my knowledge you can only look at a handle value, but you cannot cast the value back to a handle. On a similar track, since the VW App went to 64 bit, I've seen some handle values (not all) that exceed the Longint range. There is no 64-bit integer type in VS that would accommodate really large integers. @Pat Stanford if I'm wrong and you do know of a way to convert values back to a handle, would you mind sharing. I could use this. Thanks, Raymond
  11. And I am hoping you figure it out Pat, so I may ask you questions. If you want a another blind minion to walk with you through the maze, I'll offer my directionless services. I've often wanted to do the same. Raymond
  12. @sully8391 , Although Pat's advice is pretty much spot on, let me lessen the gravity of it a little. If you're tenacious, patient, and inquisitive, you can probably have your dialog up and running within a day or two. Once you get the first one done all the hurdles come down a bit. And as with all other disciplines: practice makes perfect, and failure is mandatory. Modern Dialogs are constructed in three parts. The first part can be a procedure, or inline code, that contains all of the statements that define the dialog, while the second part is a procedure containing code to run the dialog (the event loop). The last part is typically one or two lines in the main program that call the dialog code. Here is a short example in Pascal (sorry, I think faster this way.) Translating it shouldn't be too hard. The CASE statement in the Event Loop can be replaced with an "if / elif" tree. PROCEDURE DialogExample; { This is a relatively simple example of a Modern Dialog that converts temperatures. } { It has 6 fields, 3 static text labels, and 3 Edit Text fields. } { It also as a basic event loop to control the dialog when it is running. } { Every key press and every click generates an event which is handled by the event loop. } { Events can be handled or ignored as you see fit. } { 03 Jan 2020 - Raymond J Mullin - Use or modify to your wildest whims. } VAR dlogID, dlogResult :Longint; function BuildDialog :Longint; { This dialog returns the Dialog ID and has 2 parts. } { 1) Code that creates the dialog elements. } { 2) Code that arranges the elements in the dialog, either below or to the right of the previous element. } { This function could also contain two more parts... } { 3) Code that controls the alignment of the elements to each other. This is optional. } { 4) Code that defines Help Strings when the cursor hovers over dialog elements. This is also optional. } Var dlogID :Longint; Begin { This is the most common way to start. } dlogID := CreateLayout('Temperature', False, 'OK', ''); { No HELP text, OK button and no Cancel button } { create 1st element at 4 or higher, it's arbitrary. I usually start at 10 for static text and 20 for the edit fields } CreateStaticText(dlogID, 10, 'Fahrenheit (°F)', 13); { Name says it all - it's static (usually) } CreateStaticText(dlogID, 11, 'Celsius (°C)', 13); { the last number is its width in characters (approximately))... } CreateStaticText(dlogID, 12, 'Kelvin (°K)', 13); { ...average characters, not the skinny ones } CreateEditReal(dlogID, 20, 1, 32, 16); { a field you can type in } CreateEditReal(dlogID, 21, 1, 0, 16); { another field you can type in } CreateEditReal(dlogID, 22, 1, 273.15, 16); { a third field you can type in, or write to } { The next section arranges the dialog elements either right or down } SetFirstLayoutItem(dlogID, 10); { everything else is anchored to this item } SetBelowItem(dlogID, 10, 11, 0, 0); { item 11 goes below item 10 } SetBelowItem(dlogID, 11, 12, 0, 0); { item 12 goes below item 11 } SetRightItem(dlogID, 10, 20, 0, 0); { item 20 goes to right of item 10 } SetRightItem(dlogID, 11, 21, 0, 0); { item 21 goes to right of item 11 } SetRightItem(dlogID, 12, 22, 0, 0); { item 22 goes to right of item 12 } BuildDialog := dlogID; { this is your "return" value in Python } End; { BuildDialog } procedure DialogEventLoop(var item :Longint; data :Longint); { this procedure is always defined this way } { This is the Event Loop. For every event (keystroke or click) this procedure is executed } Var Fahr, Cel, Kel :Real; Begin { use this next line for debug to see what events are called and when. Comment it out when done. } { AlrtDialog(concat('item= ', item, ' data= ', data)); } { if you want something to happen when an event occurs, put the item # (aka, the event #) in the case statement } case item of SetupDialogC : begin { initialize all dialog values here } { this event only gets called once at the beginning of dialog execution } end; { SetupDialogC } 1: begin { OK button was pressed } SysBeep; { BEEP for joy - it worked } end; { 1 } 2: begin { code for CANCEL button was pressed, if you had one (but you don''t) } end; { 2 } 20: begin if GetEditReal(dlogID, 20, 1, Fahr) then begin Cel := (Fahr-32) * 5/9; SetEditReal(dlogID, 21, 1, Cel); SetEditReal(dlogID, 22, 1, Cel+273.15); end; { if } end; { 20 } 21: begin if GetEditReal(dlogID, 21, 1, Cel) then begin Fahr := Cel * 9/5 + 32; SetEditReal(dlogID, 20, 1, Fahr); SetEditReal(dlogID, 22, 1, Cel+273.15); end; { if } end; { 21 } 22: begin if GetEditReal(dlogID, 22, 1, Kel) then begin Cel := Kel - 273.15; SetEditReal(dlogID, 21, 1, Cel); SetEditReal(dlogID, 20, 1, Cel*9/5+32); end; { if } end; { 22 } end; { case } { the dialog exits when (item == 1) or (item == 2) at the end of this procedure. } { this procedure will "return item" in Python } End; { DialogEventLoop } BEGIN { main program } { This line builds the dialog and returns its ID. } dlogID := BuildDialog; { VerifyLayout() checks the dialog, if it passes then it runs the dialog } { in the next statement with the Event Loop specified. } if VerifyLayout(dlogID) then dlogResult := RunLayoutDialog(dlogID, DialogEventLoop); { Check the "dlogResult", 1 = OK; 2 = Cancel. Proceed accordingly. } END; { main program } Run(DialogExample); Keep the Function Reference close. Even with all its shortcomings it is still an invaluable aid. The next best reference source is this forum. Write back when you have more questions and @Pat Stanford will most likely beat me to a response. 😉 Raymond
  13. Hi @sully8391 , The "vs.BeginDialog()" and "vs.EndDialog()" commands are part of the Classic Dialog set which were discontinued in VW 2010. They continued to run for several years after that, but the shift was toward the Modern Dialog commands introduced in VW 9. They are the currently supported dialog calls. Consult the Developer Wiki at http://developer.vectorworks.net/index.php/VS:Function_Reference or the HTML Script Reference that ships with the application in the VWHelp folder @ "VWHelp/Script Reference/ScriptFunctionReference.html". Start with "CreateLayout()" and peruse that section. There are several examples in that section. If you're looking at the HTML Reference,, search for "Example" when you're in the "Modern Dialog" area. Simple dialogs are pretty easy to layout by hand. More complicated dialogs might require the use of the Dialog Builder. Good luck and write back. Raymond PS - Please create a signature with a basic description of your computer and VW version. It will help us answer your questions a little faster and possibly allow us to offer advice that is pertinent to your setup.
  14. @hagemeijer , If you have a handle to an ARC (or CIRCLE) object, you can't GET the radius directly, but you can calculate it: GetArc(H, Start, Sweep); Radius := hPerim(H) / Deg2Rad(Sweep); where "H" is the handle to the object. OR as Josh says: Get2DPt(H, 1, Pc.x, Pc.y); Get2DPt(H, 2, P1.x, P1.y); Radius := Norm(P1-Pc); where "H" is a Handle to the object and Pc and P1 are Vectors. Raymond
  15. Sam, I assume from your description you want to preserve the "L" shape. If the objects are drawn in a way that adjacent objects are next to each other in the stacking order, AND each object's BBox overlaps (or touches) the BBoxes next to it, you could create a Polygon for each object's BBox and add the Polygons together with the AddSurface command. When you are done they will all be connected but not necessarily in a "pretty" fashion. However, if there are gaps between the individual BBoxes, this approach won't work. Any approach you take that will work will be very dependent on the configuration of shapes before you start. Raymond
  16. Sam, A new Group is always created on top of the stacking order, so if you are on a design or sheet layer, LActLayer will return a handle to a new Group. If you are drawing inside a container, you can use the Waldo method that Pat mentioned. With the handle you can then get the Group's BBox. Raymond
  17. @hagemeijer , Try 695, but note it is a Longint ObjVar. Raymond
  18. Samantha, "Sanctuary Floor Plan.vwx" and "Eaton Hall Floor Plan Renovations.vwx" do not appear to be VW files when opened with a text editor. They both start with headers that look like they may be AutoCAD files. "Sanctuary Floor Plan.vwx" starts with "AC1018" and, "Eaton Hall Floor Plan Renovations.vwx" starts with "AC1021". Change their file extensions to".dwg" and open them with AutoCAD, or import them into the program of your choice (that reads DWG files). The other two files are VW files. I'll let someone with better experience in doing DWG Exports help you there. Raymond
  19. Hi Sam, That's the change I thought would have the most impact on your problem, yet I'm not exactly sure what vsoStateAddCurrent() does under the hood. It's one of those things that works and I have not spent any time trying to figure out more about it. As you surmised, that is the only statement I have under that event in all of my PIO's. If you ever find another example on how it's used differently, please let me know. Happy New Year, Raymond
  20. Hi Sam, I have only two suggestions which I've marked with comments in your code. Try them one at a time to see if either of them works. Then try them together if neither works. After that, I'm out of ideas. GetVersion(Major,Minor,Maintenance,Platform); GetUnits(Fraction,Display,Format,UPI,UnitName,SquareName); Result := GetCustomObjectInfo(PIOName,PIOHan,PIORec,WallHdl); vsoGetEventInfo(EventMessage, MsgData); OK := GetLocalizedPlugInName(PIOName,LocalPIOName); IsNew := IsNewCustomObject(PIOName); BoxBottom := 3 * UPI; CASE EventMessage OF kResetEventID: { 3 } BEGIN { MOVE vsoStateGetParamChng LINE FROM EVENT 44 TO EVENT 3 } ParamChangeFlag := vsoStateGetParamChng(PIOHan,ParamChangeWidget,ParamChangeIndex,OldParam); GetSymLoc3D(PIOHan, PIOX, PIOY, PIOZ); ParamChangeFlag := vsoStateGetParamChng(PIOHan,ParamChangeWidget,ParamChangeIndex,OldParam); AlrtDialog(concat('Event 3, kResetEventID triggered', kcr, 'ParamChangeFlag = ', ParamChangeFlag, kcr, 'EventMessage = ', EventMessage, kcr, 'MsgData = ', MsgData)); IF (ParamChangeFlag=True) THEN BEGIN {Do Stuff} END; {IF (ParamChangeFlag=True) } ParamChangeTrig := FALSE; PIOChangeTrig := FALSE; SetUp; MainConstruct; vsoStateClear(PIOHan ); END; { 3 - kResetEventID } kObjOnAddState: { 44 } BEGIN {This event is needed to track state changes} { CHANGE EventMessage TO MsgData (x2) in following line } MsgData := vsoStateAddCurrent(PIOHan, MsgData); AlrtDialog(concat('Event 44, kObjOnAddState triggered', kcr, 'ParamChangeFlag = ', ParamChangeFlag, kcr, 'EventMessage = ', EventMessage, kcr, 'MsgData = ', MsgData)); END; { 44 - kObjOnAddState } kObjOnInitXProperties: { 5 } BEGIN Result := SetObjPropVS (kObjXPropHasUIOverride,True); Result := SetObjPropVS(12, TRUE); {kObjXHasCustomWidgetVisibilities} SetPrefInt(590, 1 ); {kParametricEnableStateEventing} Result := SetObjPropVS (18,TRUE); {kObjXPropAcceptStates} Result := vsoInsertAllParams; Result := SetObjPropVS(kObjXPropDataNameDisabled, TRUE);{kObjXPropDataNameDisabled} SetPrefInt (590,1); {varParametricEnableStateEventing,ResetStatesEvent} END; { 5 } kObjOnWidgetPrep: { 41 } BEGIN WidgetPrep; END; { 41 - kObjOnWidgetPrep } END; { case } Have a Merry Xmas, (or holiday of your choice), Raymond
  21. Hi Sam, Do you have your call ParamChangeFlag := vsoStateGetParamChng(PIOHan, ParamChangeWidget, ParamChangeIndex, OldParam); in Event 3 (kResetEventID)? Everything else you have in your kObjOnInitXProperties event is what I have, though you call SetPrefInt(590, 1 ); {kParametricEnableStateEventing} twice, where I only call it once at the end of Event 5 (kObjOnInitXProperties). I doubt it makes a difference, but I don't know. Also, do you have "Event-Based" checked in the "Edit Plug-in Definition" dialog, Options tab? Lastly, I execute these 3 commands first before I enter the CASE statement testing the events: result := GetCustomObjectInfo(PIOName, PIOHand, recHand, wallHand); IsNew := IsNewCustomObject(PIOName); vsoGetEventInfo(theEvent, theMessage); The first line makes sure the PIOHand variable is valid, and the third line returns the current EVENT. Raymond
  22. Hi Andrea, You forgot to mention which version of VW you are currently using. Since the latest versions will open at least back to VW 2013, I saved your files in that format. If you need an earlier version, let me know. MC4 to VW2013 Files.zip All the best, Raymond
  23. @PatW , This may be related to a bug I filed in May (for regular VectorScript, not SDK) – (VB-160901) VS SetStaticTextColor() does not work in VW 2020. StaticText color assignment works is VW 2019, but not VW 2020. It still shows to be unresolved. Raymond
  24. To which release version are you referring? SP0 - it's broken. SP1 - is usually a release for localization changes and not bug fixes. SP2 - is not out yet. I expect it in this or SP3 at the latest. Just guessing here. As recommended above, I'd use VW 2019 for your designs needing this feature until VW 2020 is updated and working. The file(s) can be moved forward after it's working. I feel your pain. Raymond
  25. Nicolas, thank you. That is exactly what I was looking for. Usually I look at the HTML and the Dev Wiki pages for calls that are confusing or under documented. I missed this one. I guess it wasn't confusing enough. Now to find out why WriteXMLMemory() seems to work, yet kicks a -21 error (Invalid XML handle). Oh the joys of programming. Again, thank you. Raymond


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