Jump to content

MullinRJ

Member
  • Posts

    1,993
  • Joined

  • Last visited

Everything posted by MullinRJ

  1. Thanks, @michaelk, I was looking for that earlier and couldn't find it. I would definitely start there first. Much easier than making a PIO event-enabled, but I'd still like to know how kObjXPropTextStyleSupport affects things. Raymond
  2. @Sam Jones, Not sure if this is pertinent, but there is an Object Property for event-enabled PIO's that looks like it might be applicable. I don't have a way to test it now. If @JBenghiat chimes in you may get better advice. const ObjectPropID kObjXPropTextStyleSupport = 42; // NO // Controls whether parametric objects can use class text style attribute and get Text Style on OIP // // Boolean // // Set TRUE if the object supports this // // // e.g. Almost all text-related PIOs set this yes, for support by default. If I guess right, you would put it in event kObjOnInitXProperties {5} along with your other property settings with something like this: case theEvent of ... kObjOnInitXProperties: begin { 5 } result := SetObjPropVS(kObjXPropTextStyleSupport, TRUE); { 42, Controls whether parametric objects can use class text style attribute and get Text Style on OIP. } ... end; { 5 } Please post back if you get it to work, or not. I, for one, would really like to know. Good luck, Raymond
  3. Hi @stevenmorgan94, @Juliensv's method is a sound way to go, but as in all things Vectorscript, there are multiple ways to get to the same place. As luck would have it, I was playing with AddResourceToList() this past weekend, so here are two more ways to get to where you want. The first subroutine, GetSymsInFldr1, uses a WHILE loop to step through the contents of your Symbol Folder. The second subroutine, GetSymsInFldr2, uses ForEachObjectInList() to do the same thing. They are identical in function and nearly identical in size. Use the one that's easiest for you to follow, or try your hand at Julian's method. To run this example, change the value of the constant kSymFldrName to match a Symbol Folder name in your file. PROCEDURE xxx; { Two example subroutines showing how to build a Resource List of Symbol Names in user specified SymFolder. } { 24 Oct 2023 - Raymond J Mullin } CONST kSymFldrName = 'Your Symbol Folder Name'; VAR List16, ListSize :Longint; Function GetSymsInFldr1(FldrNam :String; var NumItems :Longint) :Longint; { Return a Resource List of all SymDefs in symbol folder FldrNam, and return the list size in NumItems. } Const kSymDefType = 16; Var H :Handle; ListID, I :Longint; Begin ListID := BuildResourceListN(kSymDefType, '', NumItems); { empty list of Symbol Defs } H := FInFolder(GetObject(FldrNam)); { first obj in Sym Folder } while (H<>nil) do begin if (GetTypeN(H) = kSymDefType) then I := AddResourceToList(ListID, H); H := NextObj(H); end; { while } NumItems := ResourceListSize(ListID); GetSymsInFldr1 := ListID; End; { GetSymsInFldr1 } Function GetSymsInFldr2(FldrNam :String; var NumItems :Longint) :Longint; { Return a Resource List of all SymDefs in symbol folder FldrNam, and return the list size in NumItems. } Const kSymDefType = 16; Var ListID, I :Longint; Function AddSym2List(H :Handle) :Boolean; { Return a Resource List of all SymDefs in symbol folder FldrNam. } Begin if (GetTypeN(H) = kSymDefType) then I := AddResourceToList(ListID, H); End; { AddSym2List } Begin { GetSymsInFldr2 } ListID := BuildResourceListN(kSymDefType, '', NumItems); { empty list of Symbol Defs } ForEachObjectInList(AddSym2List, 0, 0, FInFolder(GetObject(FldrNam))); { All objects, Shallow } NumItems := ResourceListSize(ListID); GetSymsInFldr2 := ListID; End; { GetSymsInFldr2 } BEGIN { Call first subroutine example and show the results. } List16 := GetSymsInFldr1(kSymFldrName, ListSize); AlrtDialog(concat('List#: ', List16, ' — List Size: ', ListSize)); { Call second subroutine example and show the results. } List16 := GetSymsInFldr2(kSymFldrName, ListSize); AlrtDialog(concat('List#: ', List16, ' — List Size: ', ListSize)); END; Run(xxx); HTH, Raymond
  4. Is it possible the outer PIO (Device) is overwriting the inner PIO (Socket) after the "Socket"."n_circuits" field is written to? If so, I have not been able to see where the previous data is stored. If I place a "Socket" PIO on the Design Layer and run the python script, the value for "n_circuits" is updated to 98. Only when it is embedded in the Device PIO does it not stay updated after the script finishes. Raymond
  5. I launched VW 2009 on an older Mac and confirmed SetAngle() does work, but only on Rectangles and Ovals as far as I could discern. It does not work on Arcs, Lines, Images, Symbols, or PIOs. I then restarted VW 2024, and got the same results. Conclusion: The function SetAngle() is not broken, it is just severely limited in what it will operate upon. For most needs, use HAngle() instead. Raymond
  6. Hi @Marissa Farrell, The Function Reference, HTML and online versions, call for a REAL number input. I haven't tried a VW version earlier than 2015 yet to see if it ever worked, but I'm about to fire up an old computer in a minute to see. More soon. Regardless if it ever worked, it doesn't seem to work now. All the best, Raymond
  7. Hello @Andreas, I tried to use vs.SetAngle() on Lines, Arcs, and Rects to no avail. I tried in VW 2024 and VW 2015 with the same result. I also tried in Python and Pascal, still nothing. It appears the command is not functioning as advertised. There are other ways to set the angle of objects. Here's a short Pascal script that shows the current angle of a Symbol or PIO (which includes the Data Tag), and changes it to the user's value. Here's a short script to show how to set an angle without using vs.SetAngle() import vs # Example script to change the angle of a Symbol or PIO. Ang0 = vs.GetSymRot(vs.FSActLayer()) Ang = vs.RealDialog("Angle: ", vs.Concat(Ang0)) InsPt = vs.GetSymLoc(vs.FSActLayer()) vs.HRotate(vs.FSActLayer(), InsPt, Ang-Ang0) vs.SysBeep() Raymond
  8. @koenr, You're welcome. Here is a very rudimentary Python script to save dialog's position. Lightly tested. Modify it any way you like. kOK = 1 kCancel = 2 kSetupDialogC = 12255 dialogName = "DUMMY DIALOG" scriptName = "myScriptName" def SaveDialogPos(dlogID): (_b, X1, Y1, X2, Y2) = vs.GetLayoutDialogPosition(dlogID) if _b: vs.SetSavedSetting(scriptName, 'PosX', vs.Concat(X1)) vs.SetSavedSetting(scriptName, 'PosY', vs.Concat(Y1)) pass def SetDialogPos(dlogID): (_b, defaultX, defaultY, dummyX, dummyY) = vs.GetLayoutDialogPosition(dlogID) (_b, S) = vs.GetSavedSetting(scriptName, 'PosX') if _b: X = vs.Str2Num(S) (_b, S) = vs.GetSavedSetting(scriptName, 'PosY') if _b: Y = vs.Str2Num(S) _b = vs.SetLayoutDialogPosition(dlogID, X, Y) else: _b = vs.SetLayoutDialogPosition(dlogID, defaultX, defaultY) else: _b = vs.SetLayoutDialogPosition(dlogID, defaultX, defaultY) pass def DialogHandler(item, data): if item == kSetupDialogC: SetDialogPos(dlogID) elif item == kOK: SaveDialogPos(dlogID) elif item == kCancel: SaveDialogPos(dlogID) vs.SysBeep() return item ### MAIN ### dlogID = vs.CreateLayout(dialogName, False, "OK", "Cancel") vs.CreateStaticText(dlogID, 10, 'WUMPUS', 30) vs.SetFirstLayoutItem(dlogID, 10) result = vs.RunLayoutDialog(dlogID, DialogHandler) Raymond
  9. Hello @koenr, It would not be the first time I misread something, and I suspect it will not be the last. Sorry, I thought you wanted to SAVE the dialog's position, not SET its position. My bad! If you do both you can have the dialog open where you left it last time. That is what I typically do. To have persistent parameters, write the positions to an XML file that VW maintains using vs.SetSavedSetting(category, setting, value) and vs.GetSavedSetting(category, setting) return (boolean, value). You create the category and the setting strings as they pertain to your script. You can save lots of things in the saved settings file and the values will persist between open files and even between VW sessions (assuming VW shuts down properly and does not crash.) It is always advised not to store critical data in the settings file as it is meant for convenience, not security. If you are interested in trapping the kSetupDialogC item, use kSetupDialogC=12255 in your constant declarations. This event# is where you want to position your dialog, and it will only happen once, so if you move the dialog it won't jump back with your next key or mouse event. There is another constant but it is little used, kSetdownDialogC=12256 and it will be generated just before the dialog closes. You could put cleanup code there, but I have never found a need to use it. Still, it's nice to know it exists. You are correct, there is no case statement equivalent in Python, so you need to use a series of if statements, as you have done, or if / elif / elif / ... / else. They are functionally the same as the Pascal case statement. You're on the right path. HTH, Raymond
  10. Hello @koenr, I always save my dialog's position when I exit the event loop, either when item==kOK, or when item==kCancel. As long as you are in the dialog the user can move it, so it doesn't make sense to save the position until the dialog handler is done and things are shutting down. As to your second question, "I see a lot about the "kEventDialogPrep" but what item is this?", I have no idea. Where do you typically see this? The value kEventDialogPrep = 9 looks like a user defined dialog item. Raymond
  11. From your description, you will want to create a Plug-in object. There are several levels of complexity, from simple objects or collections of objects, to event-enabled objects. To start, open the Plug-in Manager, Cmd-Shift-Z on Mac, or Ctrl-Shift-Z on PC, or use menu Tools>Plug-ins>Plug-in Manager. There you can create one of the following types. There are three basic types, Menu Commands, Tools, and Objects. Commands (or Menu Commands) are typically procedural scripts and can be used to change VW settings, or operate on existing objects. Their advantage over scripts saved in a script palette is they are stored in the VW program and displayed in a VW menu, so they are available to all open files. Plug-in Tools are interactive and allow you to create or modify objects using the mouse. Plug-in Objects (PIOs) allow you to create custom objects more complex than the basic tools that ship with the software. Not knowing exactly what you want to draw, I will not suggest a PIO type for you at this moment. To become more familiar with how they are structured, create one and look at the interface. Once created, click on the various buttons on the bottom of the Plug-in Manager screen. The Edit Definition... button opens a dialog with 6 panes. You will create your custom variables in the Parameters pane. These parameters are the values that will appear in the OIP when your object is selected. Create some dummy parameters and note how many parameter types there are. Then open all the other panes and look each over. The other button of interest is the Edit Script... button. This is where you place your VectorScript, or Python, code. It's the same window you use when you are editing scripts in a Script Palette. The Parameters pane and and the Script Editor window are where you'll spend most of your time editing. Until you get in a little further, I should probably stop here. Poke around a bit, and send back more questions. The more complicated your Plug-in becomes, the more you will use the other parts of the Plug-in Editor, but for simple PIOs, the Parameters pane and the Script Editor will be mostly what you'll need to use. There's a lot to digest, but luckily there are a lot of people in this community willing to help. Also, if you haven't already, read the first pinned post in the Vectorscript Forum - "What do I do with a Vectorscript, anyway?" by @Pat Stanford where he references the original post by @Robert Anderson which is really hiding in the Archive section of the Forum, under the Resource Share - Vectorscript section, where nobody will ever find it, so thanks to Pat for making it accessible. It's a bit dated, but still relevant. Welcome to VW scripting, Raymond
  12. Hello @Nora, Here is a sample script that shows how to use the GetLine call with a single MouseDown event followed by a subsequent MouseUp event. There is one caveat you will need to understand, if you cancel the GetLine call before it completes, say by hitting the ESC key between MouseDown and MouseUp events, the script will end prematurely and the drawing mode will not be restored. This is only a problem is the original drawing mode was ClickClick to begin with. If this creates a serious problem for you or users of your script, write back. There are ways to mitigate this vulnerability, but more code is needed. PROCEDURE xxx; { Code snippet to test GetLine() procedure. } { If you normally use the Click-Click drawing mode, this code will change the drawing mode to } { Click-Drag for draiwng one Line, then revert back to Click-Click drawing when the script is done. } { If you normally use Click-Click drawing, you will see no change in behavior when drawing the line } { in this script. } { 04 Oct 2023 - Raymond Mullin } VAR Pref0 :Boolean; ptx1, pty1, ptx, pty :Real; BEGIN Pref0 := GetPref(0); { save state of Pref0 - Enable click drag drawing } SetPref(0, True); { set drawing mode to ClickDrag } GetLine(ptx1, pty1, ptx, pty); MoveTo(ptx1, pty1); LineTo(ptx, pty); SetPref(0, Pref0); { restore state of Pref0 - Enable click drag drawing } END; Run(xxx); HTH, Raymond
  13. Do you have more than 500 selected objects? Perhaps you need to create a Dynamic Array to store your handles. It can be as big as 32767 elements. If you need more, then the way the program is written needs to be changed. Add AlrtDialog(concat(NumSelectedObjects)); at the beginning of the script to see how many selected objects you have. Raymond
  14. Hello @Baptiste_02, After rereading my script, I cannot see anything that would cause what you describe. If you relaunch VW, how many times can you run the script before it starts to misbehave? Perhaps you could upload a file where this problem happens. Others may be able to spot something I didn't, but off the top of my head I don't see anything wrong with the script. Also, you should create a signature showing the version of VW you are using, and your computer specs. This saves people from having to ask, and it may also help someone recognize something relevant to your setup. All the best, Raymond
  15. Thank you @Maarten DE, You clarified the use of this command for me. I was assuming it was akin to the menu Modify>Compose which joins two polys to make a longer poly, when it actuality it is akin to the menu Modify>Add Surface. The function's description, or lack thereof, left me hanging once again. Many thanks, Raymond
  16. Has anyone ever gotten this function to work? The function's description in the Script Function Reference and on the Developer's WIKI reads as follows: There is not much else to go on. I've tried it with 2 Polygons, with 2 Polylines, and with a Polygon and Polyline. In all cases, two vertices of each were touching. Reversing directions of one or both Polys did not help. Tried in VW 2024 and in VW 2015 with the same results. Also there is no description for the function of the dFDuzz input, nor is there an expected range of input values. I tried 0, 1, 2, 0.1, 0.5, 0.01, 0.001, 0.0000001, 1.1, 2.5, 8, 10, 100, 1000, 10000000, all to no avail. I even tried negative values – Nada. To answer an obvious question; yes, the handles passed in were tested to be valid, and the handle returned was NIL on every try. Any guidance would be appreciated. Thanks, Raymond
  17. Hi @Jayme McColgan, There are many ways to get to where you want to go. What Tui said is the first step. After that, you can move the text as a 3D object, and/or rotate it in 3D. You can also set a Front or Side view and rotate and move it with 2D commands. Or, you can use the vs.SetEntityMatrix() command which defines a plane's origin and its rotations, then places the text on that plane. There are other ways, but they have oddities that are not worth the effort to go into right now. If you already have an object on a Working Plane, you can get its Planar RefID, and change the text's RefID to match, causing it to jump to that plane. However if you are starting from scratch and defining a plane as you create your text, the methods defined in the first paragraph should get you there. Raymond
  18. Hey @SamIWas, Actually Pen Pat=1 is the background LineStyle (pen pattern) and Pen Pat=2 is the foreground LineStyle (pen pattern). The same is true for the Fill Patterns; Fill Pat=1 is the background fill pattern and Fill Pat=2 is the foreground fill pattern. The colors for foreground and background Pens and Fills track accordingly. The real confusion belongs to VW assigning the default Pen Style as 2 (foreground - which makes sense), BUT the default Fill Pattern is 1 (background - which has been "wrong" for more than 3 decades - IMO.) When you select SOLID from the Attributes Palette for Pens you get the Foreground Pattern - PenPatN(2); but selecting SOLID for Fills, you get FillPat(1). Users don't care, because they assign patterns and colors from the UI palettes and everything works. Programmers are the ones who have to know where the wrinkles are. Welcome to the Wrinkle Conscious Club. I could pontificate more, but we're way past the point of that affecting anything. Raymond
  19. @Marissa Farrell, This is a shot in the dark. Try ResetBBox(). I've had luck with it in the past when RedrawAll didn't work. No guarantees, just a suggestion. Raymond
  20. Hey @Pat Stanford, Yes, I'm always up for a challenge. Buuuuut, this time I think I may not be your best tag-team candidate. First off, you're doing ARCHie stuff. Second, you're dabbling with WALL properties. Both are somewhat out of my wheelhouse. That said, I jumped into the deep end first and attacked the Worksheet function, and the worksheet example in the file @J P posted. If you can imagine the sound of a brick wall being impacted, I made it. Next I simplified, and drew a Wall, selected it and ran a simple script to return its TYPE and its ObjVar value for 1212. I got 68 and '', as I did when I made the brick slamming sound. I then opened the ObjectVariables.h (for VW 2023) file and saw that 1212 was defined as you said it was : const short ovArchStyleFireRating = 1212; // TXString read/write - The fire rating (insertion option) - Public for VS Next, I took my script and Wall back to VW 2020 and tried again. This is where things got squirrelly, even for me. The script result was the same, but I couldn't find anything FIRE related in the OIP like I could in VW 2023; so I opened the SDK file MiniCadCallBacks.h (for VW 2020) and saw the following: const short ovArchStyleMark_OBSOLETE = 1207; // Obsolete const short ovArchStyleDescription_OBSOLETE = 1208; // Obsolete const short ovArchStyleFunction_OBSOLETE = 1209; // Obsolete const short ovArchStyleExterior_OBSOLETE = 1210; // Obsolete const short ovArchStyleLoadBearing_OBSOLETE = 1211; // Obsolete const short ovArchStyleFireRating_OBSOLETE = 1212; // Obsolete const short ovArchStyleCombustibleConstruction_OBSOLETE = 1213; // Obsolete const short ovArchStyleCompartmentation_OBSOLETE = 1214; // Obsolete const short ovArchStyleUValue_OBSOLETE = 1215; // Obsolete const short ovArchStyleRValue_OBSOLETE = 1216; // Obsolete const short ovArchStyleAcousticRating_OBSOLETE = 1217; // Obsolete const short ovArchStyleCostIndexSystem_OBSOLETE = 1218; // Obsolete const short ovArchStyleCostIndexCode_OBSOLETE = 1219; // Obsolete const short ovArchStyleModel_OBSOLETE = 1220; // Obsolete const short ovArchStyleManufacturer_OBSOLETE = 1221; // Obsolete const short ovArchStyleURL_OBSOLETE = 1222; // Obsolete Also obsolete are similar values in the 1118 to 1157 range. In VW 2023, the values 1207 to 1222 have defined values, but in VW 2019 to VW 2022, they are defined as OBSOLETE. I didn't check any earlier. I'm assuming the ObjVars are not returning values in VW 2023. Maybe they should be, but I have no way of knowing. This seems like a factory question, unless @JBenghiat knows off the top of his head. PUNT, the ball is now back in your court. Sorry Pat, that's all I've got. Raymond
  21. Well, with Pat's input, I'll try again. 😉 ************ Short answer, YES. Python uses indentation, even when submitted from Vectorscript. I typically build my Python code in a text block, then execute it all at once. However, in your simple case you can do this, which works. It avoids the need for indentation. Not an answer, but more of a crutch. PROCEDURE test_pythoncontext; CONST Tb = c h r(9); { remove extra spaces before running code } CR = c h r(13); { remove extra spaces before running code } VAR check :BOOLEAN; BEGIN check := true; PythonBeginContext; PythonExecute('import vs'); PythonExecute('check_py = vs.GetVSVar("check")'); PythonExecute('if check_py: check_py = False'); PythonExecute('vs.SetVSVar("check", check_py)'); PythonEndContext; message(check); END; Run(test_pythoncontext); OR, build everything ahead of time, then execute it like this: PROCEDURE test_pythoncontext; CONST Tb = c h r(9); { remove extra spaces before running code } CR = c h r(13); { remove extra spaces before running code } VAR check :BOOLEAN; PyCode :Dynarray of Char; BEGIN check := true; PyCode := concat('import vs', CR); PyCode := concat(PyCode, 'check_py = vs.GetVSVar("check")', CR); PyCode := concat(PyCode, 'if check_py:', CR); PyCode := concat(PyCode, Tb, 'check_py = False', CR); PyCode := concat(PyCode, 'vs.SetVSVar("check", check_py)', CR); PythonBeginContext; PythonExecute(PyCode); PythonEndContext; message(check); END; Run(test_pythoncontext); One benefit of building your python code this way is you can print your PyCode variable to examine it while you are debugging. For short snippets, use: AlrtDialog(PyCode); Or for longer snippets, use: MoveTo(0,0); CreateText(PyCode); When it looks correct, then you can execute it. HTH, Raymond
  22. OK, I can post text, but not code. How long will this last?
  23. @hharker, The reason your import failed is because you saved the file with a ".txt" extension, which tells the Import Script... menu to treat the script as Vectorscript. If you save your file with a ".py" extension, the Import Script... menu will treat it is a Python script. Or you can do as @michaelk suggests above, which is good if you plan to run a script more than once. Sometimes you have to help the machines. They are made in our image and likeness, and therefore suffer the same shortcomings. 😉 Raymond
×
×
  • Create New...