Jump to content

MullinRJ

Member
  • Posts

    2,007
  • Joined

  • Last visited

Everything posted by MullinRJ

  1. @The Hamma, Out of curiosity, how many scripts is too many? Ball park. I assume the limit depends on how many total items are in a workspace, but knowing how many scripts you added would be interesting to know. Also, were your scripts Menu Items, or Palette Scripts? Thanks, Raymond
  2. Sam, in my experience, whenever you pick an upper limit for a data structure, you can count on a user going right past it. Just sayin'. Raymond
  3. @DomC, That's one of the more creative suggestions I've ever heard. 🤣🤣🤣 Raymond
  4. I just modified the third script above so that it only acts on selected text blocks. I changed <T=Text> to <Sel & (T=Text)>. Now the three scripts should be functionally equivalent. A little sleep does wonders to clear the brain. Raymond
  5. I believe @anthonydcobb is looking for a way to loop through a list of selected text objects to increase or decrease their sizes. In Pascal you can use a for, while, or repeat/until loop, or you can use one of the built-in functions in the ForEachObject function family (there are 5). Here are three examples that essentially do the same thing: This one uses a while loop. PROCEDURE xxx; { Increase the text size of all selected text objects on the active layer by 1 point. } { Assumes all characters in a text block have uniform size. } { Uses a WHILE loop to examine the list of selected objects. } CONST TextSzInc = 1; VAR H :Handle; BEGIN H := FSActLayer; while (H <> nil) do begin if (GetTypeN(H) = 10) then { 10 is object type for TEXT objects. } SetTextSize(H, 0, GetTextLength(H), GetTextSize(H, 0)+TextSzInc); H := NextSObj(H); end; SysBeep; END; Run(xxx); This one uses ForEachObjectInList(). PROCEDURE yyy; { Decrement the text size of all selected text objects on the active layer by 1 point. } { Assumes all characters in a text block have uniform size. } { Uses ForEachObjectInList to control the loop. Only looks at Selected objects, and does not enter Groups. } CONST TextSzInc = -1; function IncPtSz(H :Handle) :Boolean; Begin if (GetTypeN(H) = 10) then SetTextSize(H, 0, GetTextLength(H), GetTextSize(H, 0)+TextSzInc); End; { IncPtSz } BEGIN ForEachObjectInList(IncPtSz, 2, 0, FSActLayer); { 2 = Selected objects, 0 = Shallow } SysBeep; END; Run(yyy); And lastly, this one uses ForEachObject(), which is a CRITERIA based call. PROCEDURE zzz; { Increment the text size of all selected text objects on the active layer by 2 points. } { Assumes all characters in a text block have uniform size. } { Uses ForEachObject() to control the loop, which filters objects by <criteria>. } CONST TextSzInc = 2; procedure IncPtSz(H :Handle); Begin SetTextSize(H, 0, GetTextLength(H), GetTextSize(H, 0)+TextSzInc); End; { IncPtSz } BEGIN ForEachObject(IncPtSz, Sel & (T=Text)); { where "Text" = 10 } SysBeep; END; Run(zzz); You can Pythonize these pascal scripts as is and they will work, or you can use more conventional ways of building a python list of selected text handles and iterate over that list. I will let you decide which way to go. Hopefully this will get you started. Raymond
  6. Try using: vs.Move3DObj(vs.LNewObj(), 0, 0, AOD) instead. This moves the symbol by referencing its handle, and vs.LNewObj() returns a handle to the last object created in the drawing – "usually". Raymond PS - After actually reading your code, move the "move symbol" line after you assign variable h2. Then it should look like this: h2 = vs.LNewObj() vs.Move3DObj(h2, 0, 0, AOD) vs.SetObjectVariableInt(h2, 101, 3) #Set symbol scaling to assymetric ...
  7. You can use the GetPt(X, Y) function, then count the vertices in a loop until the XY values match. It's kind of a brute force method but it will get you there. One way to test the points' proximity is to store both points in vector variables, one for the GetPt value in P1, and the other for the vertex values in P2. Then use this line in your loop to decide: IF (Norm(P2-P1) < Tol) THEN {points match} Set the value of Tol to a number significantly smaller than the distance between your vertices, for example: Tol := 1e-6; { or some relevantly small number } The NORM() function returns the length of a vector, in this case, NORM(P2-P1), or NORM(P1-P2), is the distance between the two points, and it's always non-negative. Also, make sure Snap to Points is turned ON when your script runs. HTH, Raymond
  8. Yes, all objects inside the outer rectangle have the record attached, using a Mac. I select the outer rectangle and run your script. When I select the wall object, I see this in the OIP. When I first click on the wall, the IFC record is selected, but when I click on the "Format-1" record above it I see the field "fld" at the bottom with dummy data "abc", so the record is definitely attached. Raymond
  9. It seems to be working on my VW 2022. When I first select the wall after the script is run, the OIP Data pane has the <Default IfcWallStandateCase> record format selected. If I change the record selection to "MyRecord> (with the wall selected) I see the proper fields show up below. Is this what you are seeing? Raymond
  10. @elepp, Unlike my fellow scriptographers, except for the simplest of cases, I spend too much time trying to get <criteria> to work cleanly, so I usually take a more blunt approach. Here is a Vectorscript that looks at the Name List, which includes worksheet names, and decides which names are Worksheets, then tests if the name matches a predefined pattern, namely, it starts with N-characters in common. I know you are working in Python, but it's late, I'm tired, so I'll let you pythonize it. PROCEDURE xxx; { Script to recalculate all worksheets whose names start with the string in WSName. } { 25 Feb 2022 - R. Mullin } CONST WSName = 'TAB_WE_H'; WSType = 18; VAR ObjH :Handle; I, J, NameCnt :Longint; aName :String; BEGIN J := 0; NameCnt := NameNum; for I:=1 to NameCnt do begin aName := Index2Name(I); ObjH := GetObject(aName); if (GetTypeN(ObjH) = WSType) & (pos(WSName, aName) = 1) then begin RecalculateWS(ObjH); J := J + 1; end; { if } end; { for } Message(J, ' worksheets recalculated.'); END; Run(xxx); Raymond PS - Feel free to beat on the <criteria> beast if you so choose. PPS - I think the problem with using ForEachObject to test for worksheet names is that worksheets are not ON the drawing, and I think ForEachObject only tests objects that exist on Design Layers, Sheet Layers, in Viewports, and inside Symbols. @Pat Stanford, @JBenghiat, please verify.
  11. In Vectorscript there is a 32K limit to the amount of text the Script Editor can hold for scripts stored in a Script Palette. One way around it is to use an $INCLUDE statement in the script's main text body to reference the script's external location for the Pascal compiler. The compiler can handle much more than 32K bytes. It may be that you've run into the same text size limit in your Python script. Using an external editor check the size of your 810 lines to see if this is true. If it is, you will have to break you script into smaller chunks and import them into the main script. Raymond
  12. VW is not set up to run scripts on OPEN or CLOSE file events, but it is very doable to replace the "Open..." and "Close..." menus with custom menu scripts that run your commands after or before the respective Open(filename) or Close(filename) commands. Of course, you would have to edit the workspace on each computer you support to swap out the existing menu commands and reassign keyboard shortcuts to the new ones. But since there are multiple ways to open a file in VW – Open... command, drag and drop file on the Dock app icon, double click on a file in the Finder – you cannot add a script to each of these methods, only to the menu command. I'm not sure if this helps. Raymond
  13. @Jiajing, My apologies. I didn't read your code example before I answered. What I said above is still true, you can set the "item" variable to 1 at any point in your dialog handler, BUT what I didn't say and should have, you must return that value at the end of the DialogHandler proc. The second part is always needed, since the handler uses the value of "item" on exit to determine whether to stop or continue. I modified your example slightly to demonstrate a little better. Note that now when you click on your "None" pushbutton, "item" is set to 1 and the dialog closes without any fanfare, but hey, it's just an example. Also note, there are two constants that run just before the dialog starts and just after the dialog stops – kSetUpDialogC & kSetDownDialogC. I only included the first one in the DialogHandler definition below. The second one is rarely used, but it's included if you need it. In Python you have to define them, but in VectorScript they are predefined. import vs # control IDs kOK = 1 kCancel = 2 kUnnamed1 = 5 kTextbox = 7 kCpop = 8 kC2 = 9 kSetUpDialogC = 12255 # predefined dialog event constant used for setup BEFORE dialog runs kSetDownDialogC = 12256 # predefined dialog event constant used for setup AFTER dialog runs def CreateDialog(): # Alignment constants kRight = 1 kBottom = 2 kLeft = 3 kColumn = 4 kResize = 0 kShift = 1 def GetPluginString(ndx): # Static Text if ndx == 1001: return 'OK' elif ndx == 1002: return 'Cancel' elif ndx == 1003: return 'Dialog' elif ndx == 1005: return 'None' elif ndx == 1007: return '' elif ndx == 1008: return '' elif ndx == 1009: return '' # Help Text elif ndx == 2001: return 'Accepts the dialog data.' elif ndx == 2002: return 'Cancels the dialog data.' elif ndx == 2005: return 'Help text.' elif ndx == 2007: return 'Help text.' elif ndx == 2008: return 'Help text.' elif ndx == 2009: return 'Help text.' return '' def GetStr(ndx): result = GetPluginString( ndx + 1000 ) return result def GetHelpStr(ndx): result = GetPluginString( ndx + 2000 ) return result dialog = vs.CreateLayout( GetStr(3), True, GetStr(kOK), GetStr(kCancel) ) # create controls vs.CreateEditText( dialog, kTextbox, GetStr(kTextbox), 16 ) vs.CreateColorPopup( dialog, kCpop, 16 ) vs.CreateEditReal( dialog, kC2, 1, 0.0, 16 ) vs.CreatePushButton( dialog, kUnnamed1, GetStr(kUnnamed1) ) # set relations vs.SetFirstLayoutItem( dialog, kTextbox ) vs.SetBelowItem( dialog, kTextbox, kCpop, 0, 0 ) vs.SetBelowItem( dialog, kCpop, kC2, 0, 0 ) vs.SetBelowItem( dialog, kC2, kUnnamed1, 0, 0 ) # set alignments # set help strings cnt = 1 while ( cnt <= 9 ): vs.SetHelpText( dialog, cnt, GetHelpStr(cnt) ) cnt += 1 return dialog # Sample dialog handler # Uncomment this code if you want to display the dialog def DialogHandler(item, data): if (item == kSetupDialogC): # 12255 pass elif (item == kOK): # 1 pass elif (item == kCancel): # 2 pass elif (item == kUnnamed1): # 5 item = 1 # change "item" from 5 to 1 after pushing button elif (item == kTextbox): # 7 pass elif (item == kCpop): # 8 pass elif (item == kC2): # 9 pass return item dlg = CreateDialog() result = vs.RunLayoutDialog( dlg, DialogHandler ) # use "result" if you want to process # things after the dialog closes Raymond
  14. Just assign the variable to be 1.
  15. @Jiajing, Assuming you are referring to a custom dialog, a dialog will close when the ITEM variable, defined in the Dialog_Event_Handler routine, is equal to 1, or 2. Clicking on the CANCEL button (if you have one) will set ITEM=2. Usually when the ITEM variable equals 2, the dialog will dismiss (i.e., Cancel) with no changes, but that depends on what you write for the ITEM=2 case of your dialog event handler. Clicking on the OK button will set ITEM=1. With ITEM=1 the dialog will also dismiss, and it should accept all changes to the dialog, but that, too, depends on what you write in the ITEM=1 case of your dialog event handler. At any time in your dialog event handler, you can force the ITEM variable to be either 1 or 2 to close the dialog. When the event loop ends, if the ITEM variable =1 or =2, the dialog handler will stop, and the dialog will close. HTH, Raymond
  16. @Alexander Zemtsov, Pwidth, Pdepth, and Pheight are programmer defined parameters in the Plug-in object. The are displayed in the OIP at runtime (without the leading "P") and you use them to change the shape of the Plug-in object on the drawing. You can see all of the plug-in's "P" parameters by using the Plug-In Editor. In the code, they are effectively constants that are loaded before the code runs. HTH, Raymond
  17. @lucioing, GetWSFromImage(FSActLayer); { will return a handle to the WS Resource, when FSActLayer points to a worksheet image on the drawing. } GetName(GetWSFromImage(FSActLayer)); { will return the name of the WS resource, when FSActLayer points to a worksheet image on the drawing. } HTH, Raymond
  18. This is actually quite moot, but there are 3 dashes that are able to be typed from a Mac keyboard: 1) the hyphen, or minus-sign: "-" 2) the n-dash (Option-hyphen*): "–" 3) the m-dash (Shift-Option-hyphen*): "—" * on the Mac Keyboard I'm sure you can get there from a Windows keyboard, but I don't know the escape codes off the top of my head. Okay, I looked them up: type "Alt 0150" for an n-dash and "Alt 0151" for an m-dash. Nit–pickily yours, Raymond
  19. I believe that exceeds the scope of your original question. More programming will be required. Much more. Raymond
  20. @SamIWas, After a little playing, I found one way to populate a Symbol Popup Menu: index := InsertImagePopupObjectItem(dialogid, menuID, SymNam); And it appears you can also use: index := InsertImagePopupResource(dialogID, kImagePopupID, listID, index); where you use one of the BuildResourceList commands to build a list of symbol definition names, though I haven't tried this explicitly. Have fun, Raymond
  21. Hello @SamIWas, For your symbol popup item, look at: CreateThumbnailPopup(dialogID, item_number); Sorry, I don't have any example code to populate it. I assume your LayerName popup menu is already populated, but if not, use: GetChoiceCount(dialogID, menuID, Cnt); AddChoice(dialogID, menuID, 'menu item text', Cnt); in a loop to add items to the end of the menu. This code would go in the SetupDialogC section of the dialog handler. To select an existing menu item to be the chosen item, use: SelectChoice(dialogID, menuID, menuPos, TRUE); where menuPos is the position of the Active Layer Name in your list. I believe counting in SelectChoice is 1-based, but if I'm wrong, it's 0-based. Easy enough to test. This code also goes in the SetupDialogC section of the dialog handler. HTH, Raymond
  22. Second thought, if you use the Reshape Tool and draw a marquee around the ends to be moved, can you resize multiple PIOs then? One is scaling, while the other is moving, so they're not the same but it might be useful. Raymond
  23. @VectorGeek, How is your Interactive Mode set? If it's not on the 3rd position, as shown here , then you cannot scale multiple objects at the same time. Use the U key to move positions when the Selection Tool is active. If that doesn't help, wait for @PatStanford's answer. 😉 HTH, Raymond
  24. Here's a very useful script you'll have a hard time ferreting out of the Script Documentation. Sorry, it's in Pascal, so you'll have to Pythonize it. Like you, it's bed time. I assume you can build your list from this. Good luck, good night. PROCEDURE xxx; { Show the name of each symbol definition that has the record name 'Bob' attached to it. } CONST RecName = 'Bob'; function DoIt2It(H :Handle) :Boolean; Begin if (Eval(H, (R IN [RecName])) = 1) then AlrtDialog(GetName(H)); { show Symbol Name } End; { DoIt2It } BEGIN ForEachObjectInList(DoIt2It, 0, 0, FSymDef); END; Run(xxx); Raymond
×
×
  • Create New...