Jump to content


  • Posts

  • Joined

  • Last visited

Everything posted by MullinRJ

  1. Hi Pat, I never use Dialog Builder as I find it much easier to build them by hand. Usually dialogs are pretty simple in structure so hand coding is pretty straight forward. If ever you are interested, I can elaborate, but that seems to be beyond the scope of your questions here. If my script is really short and the dialog small (<100 lines total) I will usually make the dialog code a procedure and leave it at the top of the program. For larger scripts, I will make the dialog code a procedure/function and place it in its own $INCLUDE file. For the Dialog Procedure/Function, I structure it as follows: { In the MyDialog1 file... } Function MyDialog1 :Longint; Const Var Dialog :Longint; Function CreateDialogItems(DialogName :String) :Longint; { Create all the elements that are, or may be, displayed in the dialog box. } { Return the DialogID when done. } Procedure PositionDialogItems(DialogID :Longint); { Define the Control Tree (i.e., positions) of the dialog box elements relative to each other. } Procedure AlignDialogItems(DialogID :Longint); { Define the alignment of the dialog box items. } { This section is OPTIONAL, and often not needed. } Procedure SetDialogHelpItems(dlogID :Longint; DialogName :String); { Lastly, define the Help Strings that describe each dialog box item. } Procedure DialogEventLoop(var item :Longint; data :Longint); { Contains a CASE statement to process events for each editable or control ITEM in the dialog. } BEGIN { MyDialog1 } DialogID := CreateDialogItems(DialogName); PositionDialogItems(DialogID); AlignDialogItems(DialogID); SetDialogHelpItems(dlogID, DialogName); if VerifyLayout(DialogID) then MyDialog1 := RunLayoutDialog(DialogID, DialogEventLoop); END; { MyDialog1 } **************************************** { In the MAIN program file... } ... {$INCLUDE \File Path\MyDialog1.px } BEGIN { main program } ... if (MyDialog1 = 1) then { User pressed OK button } begin { continue with your program } end; { if MyDialog1 } ... END; { main program } Raymond
  2. I would imagine the four SavedSettings files work the same way. SavedSettings.xml SavedSettingsDialog.xml SavedSettingsRsrcMgr.xml SavedSettingsUser.xml And I just noticed "IFC_DM3_DefaultMapping.xml" is in the same User Settings folder, so I imagine it may be rewritten at closing, too; as well as the XML files in the DWG_DXF and DWF folders. Raymond
  3. That's what I like about you @Pat Stanford, you always show me something I wasn't expecting. After looking at it your way, I'd agree — it's a BUG. It should be returning a very small integer. Raymond
  4. Hey @Pat Stanford, Did you use GetObjectVariableInt(H, 101), not GetObjectVariableReal(H, 101)? I use it in Reshaper and it's worked for years. I didn't test today, but Reshaper is still working for symbols so I assume these commands are still working as advertised. All the best, Raymond
  5. To add to @Pat Stanford's reply, ObjVar 101 has an integer value of 1=None, 2=Symmetric, or 3=Asymmetric. ObjVars 102-104 are the XY&Z scaling factors (Real). If ObjVar 101 = 1 (None) then the XY&Z scaling factors = 1. If ObjVar 101 = 2 (Symmetric) then the Y&Z scaling factors = the X Scaling factor. Only when ObjVar 101 = 3 (Asymmetric) do you need to read all two, or three, scaling factors. (X&Y for 2D Symbols, and XY&Z for 3D symbols). Raymond
  6. David (@The Hamma), I was not able to get your script to work, and even tried it on a lone extrude without the first "vs.FIn3D()" and the "if vs.Random()" lines. If it's working for you then ignore the following. Cut & Paste works on the entire selection and probably won't work the way you've structured your script. By making some assumptions, I was able to get this version to work, but it assumes you are only working on one group at a time. A selection of multiple groups will get merged into one (not ideal). Again, if you got your script to work, please ignore the following. def FlipIt(h): if vs.GetTypeN(h) == 24: h2 = vs.FIn3D(h) if vs.GetTypeN(h2) == 5: if vs.Random() > 0.5: vs.Mirror(h2, False, (0,0), (5,0)) vs.Ungroup() vs.ForEachObjectInLayer(FlipIt, 2, 2, 0) vs.DoMenuTextByName('Cut', 0) vs.DoMenuTextByName('Paste In Place', 0) vs.Group() vs.SysBeep() Raymond
  7. Hello David, Okay, this works, but it is like throwing a hand grenade over the wall. Using Pat's script as a starting point I tried the not so obvious as it's something that's worked for me in the past. CUT & PASTE. Since you're working in 3D, I assume the final stacking order is not critical. The result in the script below will end up on the top of the stack. If it is critical, you can save the extrude's original position using NextObj() or PrevObj(), and use hMoveBackward() on your flipped extrude to reposition it to its original neighbors. More lines of code, but doable. After you get your script running, you should still file a bug. PROCEDURE Test; VAR H1,H2 :Handle; P1,P2 :Point; BEGIN P1.x := 1; P1.y := 0; P2.x := 2; P2.y := 0; H1 := FinGroup( FSActLayer ); { the Poly profile } H2 := Mirror( H1, False, P1, P2 ); DoMenuTextByName( 'Cut', 0 ); DoMenuTextByName( 'Paste In Place', 0 ); H2 := LActLayer; { for future reference } SysBeep; { make noise when done } END; Run(Test); HTH, Raymond
  8. @Pat Stanford, While I was admiring your Python Date function I noticed you are using an IF/ELSE to assign your boolean, which can be simplified by making the assignment directly. It's not much different, but it saves one line of code. S0:=Concat('import vs',CR, 'from datetime import date',CR, 'mybool = date(', Year,', ', Month,', ', Day,') > date.today()',CR, 'vs.Rpstr_SetValueBool(',SQ,'WSSplit_DateLimit',SQ,', mybool)',CR); Thanks for posting. Raymond
  9. @Pat Stanford, Are you still looking for a VS only solution? Raymond
  10. @Sam Jones, Use LActLayer, or a Waldo that places a locus and retrieves the PrevObj(LNewObj), were LNewObj is now the Locus. Delete when done. Raymond
  11. @MarcelP102, Long ago I felt that this article would survive better on my hard drive than in the ether. You've proved my supposition correct. Yes, it's one you only need rarely, but it's invaluable when it is needed. I tried to attach the file directly to this post, but the forum does not accept the .webarchive file extension. Let me know if the attached ZIP file opens and you can read it. If not, I'll send it to you offline. Are you using a Mac, or a PC? [ Upload Deleted ] Raymond
  12. @Sam Jones, What about __LeaderEndX and __LeaderEndY? They are relative to the insertion point of the Data Tag, but you can figure out their values from real drawing coordinates using Vectors, or at least I've been told that is possible. 😉 Raymond
  13. @hollister design Studio, I hope what I am about to say doesn't sound too negative toward your idea. On the surface it does sound reasonable and somewhat simple, but in reality it is a big ask. Both @Pat Stanford, and @Sam Jones, are right in their reasoning about the difficulty of implementing Layer History for grouped objects, but here's the simple truth about wanting VW to add a new feature — if the new feature can be accomplished via a user script, and in this case a very simple script, then it is not worth the engineering effort, or risk, to change the main program. To everyone's benefit, a script solution is effectively an instant solution, compared to the time one would have to wait for a feature change to be reviewed, accepted, and implemented by the engineering team. The process could take years. This is one scenario where the KISS philosophy is perfectly apropos. Respectfully, Raymond Mullin
  14. To test for Top/Plan before you use SetView(), check that Projection = 6. IsView2D := GetProjection(ActLayer) = 6; { TRUE if view is TopPlan } To reset TopPlan after messing with SetView(), use: if IsView2D then begin SetView (0,0,0, 0,0,0); { Top view } Projection(6, 0, 10, -2, -2, 2, 2); { TopPlan } end; Raymond
  15. @Bruce Kieffer, I don’t believe that is native VW functionality. However, it can be done with a script, actually two scripts. The first script would add a record to each object and store its layer name before grouping. The second would ungroup, then shuffle the objects back to their original layers. Finished scripts can be added to your workspace and assigned hot keys, making them appear like native functions or tools. It would not be a very difficult task for someone familiar with Vectorscript, but it might be for a novice scripter. Query the VS forum for help. Raymond
  16. @MarcelP102, You can also use the Pos() function to test the string. I'm not sure which one is faster. If you have enough records to delete you can test the two commands against each other and see if there is a noticeable difference. But if your list of records is small, it doesn't matter which way you go; they'll both be fast enough. The benefit is you'll know which function to use if you know you have a large set of records to process someday. My guess is Pos() will be faster than SubString(), but by how much 🤔 ?!? If (SubString(S1, '_', 1) = 'ESRI') then DelObject(GetResourceFromList(L1, L3)); vs. If (Pos('ESRI_', S1) = 1) then DelObject(GetResourceFromList(L1, L3)); You only need to check if you are interested. But if you do check, I'd love to hear your result. Raymond
  17. That is an incredible feeling, I agree. Glad to help. Raymond
  18. @MarcelP102, Try this instead. IF (Pos( 'voet', GetRField(h, 'ESRI_BGT - wegdeel', 'functie' )) > 0) THEN SetClass( h, '94 terreinafwerkingen-verharding-trottoir' ); For any occurrence of a substring IN a target_string - (eg. - '*voet*'): POS (substring, target_string) > 0 For any occurrence of a substring at the BEGINNING of a target_string - (eg. - 'voet*'): POS (substring, target_string) = 1 For any occurrence of a substring at the END of a target_string - (eg. - '*voet'): POS (substring, target_string) = (len(target_string) - len(substring) + 1 ) In the last example, make sure the length of the target string is equal to, or longer than, the substring or you could get some false positives. Raymond
  19. As usual, @Pat Stanfordbeat me to the punch 😉 Check out this example for reference. PROCEDURE xxx; VAR H, H1 :Handle; I :Integer; B :Boolean; BEGIN H := FSActLayer; { H is a handle to a Polyline } B := GetNumHoles(H, I); { I has the # of holes in the Polyline; and B is TRUE if (H<>nil) - Not very useful. } while (I > 0) do begin { loop through the holes } B := GetHole(H, I, H1); { H1 now has a handle to one of the hole objects } I := I - 1; end; { while } SysBeep; END; Run(xxx); Raymond
  20. @Sam Jones, You have to have VW PREF - Show other objects while in editing mode turned ON before the Greying option will work. It is VW Pref# 14. So you need a toggle for SetPref(14, not GetPref(14)); { toggle Show others while editing } and one for SetPref(1055, not GetPref(1055)); { toggle Grey others while editing } Raymond
  21. Hi @leisure, In your example above, your first two lines appear to be syntactically correct, but the rest are not. Originally, I think you had the first two correct. vs.GetObject('Test_2') hDataTag = vs.LNewObj() should still be: hDataTag = vs.GetObject('Test_2') but this assumes there is a Data Tag on the drawing with the name 'Test_2'. If 'Test_2' is a name to another VW object, you'll get a handle to some other object type. You might want to test the handle you get to ensure it is a PIO instance (type = 86), and that the name of the PIO your handle points to is 'Data Tag'. But, if you are wanting to PLACE a Data Tag, then you need to use: hDataTag = vs.CreateCustomObject('Data Tag', X, Y, 0) Note vs.CreateCustomObject() returns a handle so you do not need to use vs.LNewObj(). and the 5th line returns a boolean, so you might write it like: if vs.DT_AssociateWithObj(hDataTag, rec): hDataTag.SetParameter("Roomnumber", "101.01") # Fill custom object parameters assuming the hDataTag.SetParameter() line is syntactically correct, but I doubt Handles have the attribute "SetParameter". If I were to guess, I think you have to access the PIO's record with SetRField() and access the right parameter, but I'm guessing here as I've never played with Data Tags. HTH, Raymond
  22. Hi @leisure, I don't think there was any command in VW 2019 of a similar nature. It is not a command I have ever used, so I don't know if there is another way to make the association. If it is possible, hopefully someone else will chime in with their insight. Or, you could contact Tech Support to see if you can get an answer from VW Engineering. Yes, there is an online Script Reference at Script Function Reference. It is organized by category (list shown on the right sided of the page), so if you don't know the category of your command, use the Search field at the top of the page to locate it. Also, there is a similar HTML copy that ships with your software, but it is limited to the calls found in you version and older. You can find it in the VW Application folder under /VWHelp/Script Reference/ScriptFunctionReference.html. I usually use the HTML version first, then if I can't find the function, or I think there may be more information available, I check the online version. At the top of each command in the HTML version, the "Born On Date" is listed to the right of the command name. In the online version, it is listed at the bottom, under the section titled Version. If the function has been deprecated, that "date" is also listed. By "date" I mean VW version. HTH, Raymond
  23. @chrisgeorge292, If you are waiting for a specific occurrence in a loop, you can always nest the vs.AlrtDialog() call in an "if" statement. You can wait for the loop counter to reach a certain point, say 70: for X in range [1, 81]: if X >= 70: vs.AlrtDialog(vs.Concat("I'm here: X= ", X)) or, an object to reach a certain type: Hnd = vs.FSActLayer() while Hnd != 0: if vs.GetType(Hnd) == 10: # Text object vs.AlrtDialog(vs.GetText(Hnd)) Hnd = vs.NextObj(Hnd) There are endless ways to configure a test for your stopping point. The filter condition can be simple, or complicated. Often the time you spend crafting a filter will save you stepping through a lot of unnecessary steps, especially if you have to run the code more than once. If it doesn't save you time, then don't do it. HTH, Raymond
  24. Sam, The number you're getting is correct, you just have to change the units — from mm to points, AND correct for the layer scale. I thought everybody knew this. 😜 Try: LyrScale := GetLScale(GetLayer(PIO_Hand)); PtSize := GetPrefReal(57)/LyrScale*72/25.4; { convert doc text size from mm to points } Raymond
  • Create New...