Jump to content


  • Content Count

  • Joined

  • Last visited

Everything posted by MullinRJ

  1. Hi _c_, When I try to open your WebArchives in Safari I get a flurry of errors repeating in a new blank Tab. The following message keeps flashing on the Safari screen as if it's stuck in an infinite loop, or there are just so many errors queued up I close the Tab before they finish. I've also tried to open the files with Firefox and I get a message asking if I want to open them with Safari. That's kind of funny. Can you open the webarchive files on your system? If so, it may be an OS thing. I am still on OS 10.11.6, and Safari is v11.1.2. I may need newer software. Raymond
  2. Hi Michael, I didn't read through all of your code, but I do see a mistake in your first FOR loop. You only index to the next layer inside an IF statement testing for Design Layers. If the layer is not TYPE 1 (a Design Layer) you don't index through the Sheet Layers. You need to move the NextLayer() call to the bottom of the FOR loop like this: For Counter := 1 to HowManyLayers DO BEGIN LyrTypInt := GetObjectVariableInt(LayerInQuestion, 154); {***************************************************************************} {Layer type 1 is a design layer. Ignore and go to the next layer.} IF (LyrTypInt = 1) THEN Begin { LayerInQuestion := NextLayer(LayerInQuestion); } {vvv Move to bottom of FOR loop vvv} { Do Design Layer stuff here, or remove this IF if there is nothing to do } End; {If LyrTypInt is 1 (i.e. Design Layer)} {***************************************************************************} {Now we're in business. Layer type 2 is a Sheet Layer} IF (LyrTypInt = 2) THEN Begin ShtLayer[SheetsOnly] := LayerInQuestion; ReportStr := Concat(ReportStr, GetName(ShtLayer[SheetsOnly])); SheetsOnly := SheetsOnly + 1; End; {If LyrTypInt is 2 (i.e. Sheet Layer)} LayerInQuestion := NextLayer(LayerInQuestion); {**** It works best here ****} END; {1 to number of layers} HTH, Raymond
  3. You're welcome. I like the easy answers. You get full credit, just for using your memory. 😉 Raymond
  4. @relume , Use: def vs.ConvertToPolygon(h, resolution):    return HANDLE Setting integer "resolution" higher creates more vertices. Notes: 1) This function creates a duplicate object, so you don't have to duplicate it beforehand. 2) If the original is selected, the duplicate will be selected, and vice versa. 3) Magic numbers for the resolution are powers of 2. Raymond
  5. Hi Dave, Use SetName(). If you have a symbol named 'Bob', the following will change the symbol's name to 'Larry', where 'H' is a variable of type HANDLE; H := GetObject('Bob'); SetName(H, 'Larry'); HTH, Raymond
  6. 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
  7. Hello Ralph, I sent you a private message. Thank you, Raymond
  8. 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, PointSize, dInt, dReal, dInt, dInt, 60); { correct Point Size ommission - RJM 7 Oct 2020 } ForEachObject(ChangeFont, INSYMBOL & INOBJECT & INVIEWPORT & ALL); END; Run(ChangeAllFonts); Raymond
  9. 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
  10. 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
  11. 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
  12. 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
  13. 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
  14. @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
  15. 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
  16. 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
  17. @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
  18. 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.
  19. @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
  20. 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
  21. 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
  22. @hagemeijer , Try 695, but note it is a Longint ObjVar. Raymond
  23. 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
  24. 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
  25. 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


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