Jump to content

MullinRJ

Member
  • Posts

    1,990
  • Joined

  • Last visited

Everything posted by MullinRJ

  1. Hello @unearthed, I thought you would have had an answer by now. Since that didn't happen, I cobbled together a script that will split lines into text blocks. It could have more refinements, but I assume that is not necessary. Let me know if this works for you. And if you want the original text block to disappear after it is split, uncomment line 46 near the bottom. (See comments.) PROCEDURE SplitTextToLines; { Split selected text block into individual lines at each Carriage Return. Each line becomes its own text block. } { Original text block gets deleted if user uncomments the DelObject() line at the end of the script. } { 06 Mar 2023 - Raymond J Mullin } { NO WARRANTY EXPRESSED OR IMPLIED. } { USE AT YOUR OWN RISK. USE ON A COPY OF YOUR DATA FIRST. } CONST CR = chr(13); VAR H :Handle; Mirrored :Boolean; X, Y, Ang, LineSpc :Real; S, T :Dynarray of Char; BEGIN PushAttrs; H := FSActLayer; { create new text with these attributes. } TextVerticalAlign(2); { top baseline } TextJust(1); { left justified } TextSize(GetTextSize(H, 0)); { get the text, its insertion point, and the line spacing } S := GetText(H); GetTextOrientation(H, X, Y, Ang, Mirrored); LineSpc := GetTextSize(H, 0)/72; { approximate } { make sure text ends with a carriage return. } if (S[len(S)] <> CR) then S := concat(S, CR); { split lines here } while (len(S) > 0) do begin T := copy(S, 1, pos(CR, S)-1); delete(S, 1, pos(CR, S)); if (len(T) > 0) then begin MoveTo(X, Y); CreateText(T); end; Y := Y - LineSpc; end; { while } { **** Uncomment following line if you wish to delete the original text when done. **** } {DelObject(H); } PopAttrs; SysBeep; END; Run(SplitTextToLines); Raymond
  2. Hello @spettitt, There are some syntax errors in your script (missing ";" after DSelectAll), and some logic errors (procedure Execute never executes). Rather than massage your script, I'm posting a script that I think does what you want. If it is what you want, use it as a template to create similar scripts, or modify it further as you deem fit. If you want something different, please explain further. PROCEDURE SelPosFix; { Select all Lighting Devices that match the Position and Instrument Type of the selected LD. } CONST RecName = 'Lighting Device'; Fld1 = 'Position'; Fld2 = 'Inst Type'; VAR Hd0 :HANDLE; Pos0, Typ0 :STRING; BEGIN Hd0 := FSActLayer; if (Hd0 <> nil) then begin { save values of selected object } Pos0 := GetRField(Hd0, RecName, Fld1); { Lighting Device . Position } Typ0 := GetRField(Hd0, RecName, Fld2); { Lighting Device . Inst Type } DSelectAll; { select all objects matching the original selected object. } SelectObj(INSYMBOL & INVIEWPORT & (R In [RecName]) & (RecName.Fld1 = Pos0) & (RecName.Fld2 = Typ0) ); SysBeep; { make noise when done } end { if } else AlrtDialog('Select an object and rerun script.'); END; Run(SelPosFix); One note of caution, in your original script you used the variable "Pos", which you can legally do, but "Pos" is a VS function name that returns the position of a substring from a target string. If you don't expect to use that function, no foul, but if you try do use both in the same script there could be some confusion headed your way. In the example above, I added a "0" to the global variable Pos0, and a "1" to the local variable Pos1. This will avoid all future conflict with predefined terms. HTH, Raymond
  3. Peter, Did you select Python Script in the popup menu at the top of the Script Editor? If it's set to VectorScript it will definitely error. Raymond
  4. @Chris Burton, 1) Check out this link and read what Robert Anderson wrote several years ago. I think most of it is still relevant. 2) Open the Plug-In Manager and create a new plug-in – type Command, it's the top choice. Give it a name, and click Enter. 3) Next, click the Edit Script... button and paste your script code here. Select Vectorscript or Python and click OK. 4) Next, click the Edit Definition... button and select the Properties tab. Here you and add a Tool Tip to describe your command when you hover over it with the cursor, and set any restriction on how it executes. Mostly, NONE is acceptable, unless something needs to be selected. 5) Click OK, then click Close. 6) Wash – Rinse – Repeat for each script you want to immortalize. Are you familiar with the Workspace Editor? If not, write back if you need help to add your new commands to a menu. Raymond
  5. You can save your master file as a template (.sta) and when you open new files using that template your scripts will be included. Use menu File > Save As Template... OR You can create Menu Command plug-ins from your scripts with the Plug-in Manager (Shift-Cmd-Z), which are subsequently added to the VW interface with the Workspace Editor (Option-Shift-Cmd-W). Hot keys can be assigned to your scripts in the Workspace editor so you can quickly access them, too. This is the more tedious route, but the more flexible one If you need help with either of these options, please write back. Raymond
  6. @pfalvi, I'm going to describe the manual way first. 1) Create your symbol with geometry AND a text field. The text can have anything in it as it's just a place holder at this point. 2) Create a Record Format with one field (type text). The default you type in for the record will be the default text you see when the symbol is placed in the drawing. It can be blank. 3) Edit the symbol and select the Text object. Select menu item Modify > Link text to record... Choose the new record format and the field and click the OK button. 4) Exit the symbol. 5) With the symbol selected, open the DATA pane of the OIP. Select the record format (if there are more records attached to your symbol), and change the text to the right of the field name below. You may have to adjust the pane dividers to see everything. Press ENTER and your new text will display next to your symbol. You can now change the text in the OIP for each symbol in your drawing without affecting previously placed symbols. Putting these steps into a script can be done, but it is more difficult. Off the top of my head I don't remember exactly how it's done, but I've done it before, so I know it's possible. Write back with more questions. Raymond
  7. The same applies for =T, for the column header. CSG and Generic Solids will both show as CSG Solids.
  8. The object type is the same for CSG and Generic Solids (84). I doubt worksheets can see the difference if they are just sorting by Object Type. @Pat Stanford may know better, so wait for his answer. After some quick testing, if your column header in a database row is =ObjectTypeName, you will see things like Extrude, Solid Addition, CSG Solid, etc. It appears the label CSG Solid refers to Generic Solids, while solid objects that have an editable history will be labeled by the outermost solids operation. if you just use =ObjectType for the column header, then you will see "84" for CSG Solids and Generic Solids. Other solids like Extrudes (24) and Sweeps (34) will show their respective object type numbers. HTH, Raymond
  9. Hi Peter, As I understand it, CSG Solids contain history, while Generic Solids do not. CSG stands for Constructive Solids Geometry, which implies it is made from operations with other Solids. With the solid's history, you can enter a CSG Solid and see what composes it, like Solid Addition / Subtraction operations, and/or Filleting / Chamfering operations. Each of those can subsequently be entered and edited. Then you can back out to see the result. With Generic Solids you cannot enter them to perform any edits. You can only scale, and rotate them. I assume the memory requirements are much less for Generic Solids, though I've never compared them. HTH, Raymond PS - I just tried this to confirm – you can use Generic Solids in subsequent Solid Operations. So, a CSG Solid can contain solid primitives (like extrudes, etc.), other CSG solids, and Generic Solids.
  10. @BillW, I see what you mean by your code not working when a design layer has a z-offset. I have written a utility plug-in, Reshaper, that gets and sets object parameters. My Reshaper code and your code and the OIP agree when objects are placed on layers without a z-offset. Reshaper and your code also equally disagree withe the OIP when there is a layer offset, so you're basically doing things correctly. There may be a bug that needs to be exposed, but a workaround would be more useful. I have not tested my Reshaper code under these conditions, but I'm about to start. I'll keep you posted as I learn what's really going on, assuming I do. Raymond
  11. @Sam Jones, Do you need to ungroup it? You can scale symbols now, too. SetObjectVariableInt(Obj, 101, 2); { ScaleMode: 1=None, 2=Symmetric, 3=Asymmetric } SetObjectVariableReal(Obj, 102, 0.2); { X scale factor } SetObjectVariableReal(Obj, 103, 0.2); { Y scale factor } SetObjectVariableReal(Obj, 104, 0.2); { Z scale factor } Symbols will scale around the Insertion Point. If you are only scaling symmetrically (ObjVar_101 = 2), you only need to set ObjVar_102 (X Scale Factor), as all symbol axes will use that value. If you do need to ungroup it —> What@Pat Stanford said. Raymond
  12. @BillW, Welcome to the world of 3D programming in VW. I'm guessing it's not what you were hoping for. In looking at your file, code, and the numbers you've posted, I can tell you many of them, if not most of them, are right. Since I have to get up early tomorrow, I don't have the luxury of really digging into your code. I think you're close, but you have to move very carefully, as you've already figured out, because small changes can have profound effects on the numbers presented. Also, you have to test every one of you assumptions carefully. If you still haven't resolved this by tomorrow when I get back, I'll jump back in. I spent the better part of a summer decoding the way the Entity Matrix was constructed for 2D shapes. I've tried to forget, but that hasn't happened completely yet. I can tell you the EM is employed the same for all 2D objects, EXCEPT for Symbols and Bitmap Images – and possibly PIOs (that part's foggy). Nice job so far, Raymond
  13. Glad to hear. It's probably not worth the effort to figure that out.
  14. FWIW, my code runs in a Tool (.vst) and it's not Event Enabled.
  15. Hi Pat, I found my code { build object in a symbol } BeginSym(kImgSym); PushAttrs; { create object here } PopAttrs; EndSym; { object symbol } { make image from symbol } H := CreateImgFromSymbolN(kImgSym, 692, 792, 0, 0, 2, 1); { 692 & 792 are pixels of image} DelObject(GetObject(kImgSym)); { delete object symbol } { recreate the same symbol, now with dummy locus... } BeginSym(kImgSym); { create empty symbol } Locus(0, 0); { dummy locus } EndSym; { ...then with image of the object } B := SetParent(H, LNewObj); { move image into symbol } GetBBox(H, P1.x, P1.y, P2.x, P2.y); { P1 & P2 are vectors } P1 := -(P1 + P2) / 2; hMove(H, P1.x, P1.y); { center image in symbol } DelObject(FIn3D(LNewObj)); { remove dummy locus } ResetBBox(LNewObj); { reset symbol's BBox - very necessary } I use the same symbol name for the object and the image. After I create the bitmap, I delete the symbol then recreate it with a Locus as a place holder. Then I move the image into the symbol and remove the Locus. If you already have the object before this point, you should be able to move it into the symbol instead of create it there, and proceed as outlined above. If this works for you, meet me in Albuquerque and you can buy me a beer. 😉 Raymond
  16. Hi Pat, I think I've done something similar recently, where I needed a Bitmap in a Symbol, to show in a WS. I was able to create the object, convert it to a Bitmap, then move the Bitmap into a newly created symbol – all in one script. No Event-Enabled anything. Is that close to what you are looking to do? If so, I'll dig up the code for you. Raymond
  17. Hi Sean, Sadly, Saved Views cannot be Copy/Paste from one file to another; nor can they be Imported. With a bit of work, it is possible that most information from a Saved View could be "gathered" in one file, saved to a neutral domain, then recreated in a second file, utilizing two scripts. I don't know if anyone has published a solution over the years, so hopefully if it has been done, someone will chime in. This has been requested many times over the years, but never implemented. I've thought of doing it several times over the past decades, but my need has never been great enough to justify the time spent. How many files do you need to update? If it's in the dozens or more and you can't find an existing solution, you might consider contracting the job out. But if you have a LOT of time on your hands, you could learn some seriously good scripting skills in the effort. Before you go any further, have you searched this Forum for this topic. I know it has come up several times, but I don't remember if any solutions were put forward. @Pat Stanford, have you any recollection of a prior solution? Raymond
  18. Hi Sean, It's a simple one-line script. It could be more complicated if you want, but if you have already saved a view by name, this one-line script will recall it. Since there are no variable names, the script does not need a PROCEDURE name; / BEGIN / END; / Run(name); structure. VRestore('Your Saved View Name Here'); HTH, Raymond
  19. Hello David, That's interesting, fearing the same thing you just stated, I tried my code in 2D & 3D and it seems to work just fine. If I click near a window or a door it gets selected. If I click on the wall away from inserted objects, it selects the wall – again in both 2D & 3D. I reread your signature and notice you are using VW 2018. Is that still the case? I wrote the code using VW 2023. When I try it in VW 2018, it still works in 3D, but the selection is VERY picky and more often than not the inserted object does not get selected. This is the case with OpenGL rendering. When I change to Wireframe, it works as expected. Also, when I try it in VW 2020, it works about 50% of the time in OpenGL, which is better than VW 2018, but it works best in Wireframe. VW 2019 seems to work the same as VW 2018. The performance in VW 2023 is still better in rendered views and best in Wireframe. Let us know what you find. Raymond
  20. Hello Peter, Try this script – but only on copies of your files before you are sure it does what you want. This will convert ALL Extrudes in your Symbol Definition Library to Generic Solids. PROCEDURE Extr2Solids; { Convert all Extrudes in symbol library to Generic Solids. } { VERY LIGHTLY TESTED - BACKUP WORK BEFORE USING, and USE ON A COPY FIRST. } { 13 Feb 2023 - R. Mullin } function ConvertIt(H :Handle) :Boolean; Var OT :Integer; Begin OT := GetTypeN(H); if (OT = 24) then { 24 = Extrudes } H := CnvrtToGenericSolid(H); End; { ConvertIt } BEGIN ForEachObjectInList(ConvertIt, 0, 2, FSymDef); SysBeep; { make a noise when done } END; Run(Extr2Solids); Raymond
  21. Hi Peter, Asked for many times, never developed. The only way to peek under the hood, is to draw something, then "Export Script..." under the File menu. It does not give you the progression of steps you are looking for, but only a static snapshot of the drawing state at the time of export. There is a lot of clutter that you can ignore at the top and bottom of the file. I typically search for "CreateLayer(" and look for the layer name you expect to find your object(s) of interest. If your file is complicated with many objects, and/or many layers, copy your object(s) of interest to a blank file and Paste_In_Place, then Export Script from that file. It will make finding your target code a lot easier. Not sure if this helps, Raymond
  22. You’re welcome. But I think my day ran a few hours later. I’m just now getting up. 😫 😶 ☀️
  23. I figured it out. When I tried to manually select a window and then the wall, VW popped a message at the bottom of the drawing window saying: the wall object could not be selected if an in-wall object is selected. So, selecting the wall AND the inserted PIO with a script results in ONLY the PIO being selected. The order of selection is not important. I learn something new every day, even when I don't want to. Raymond
  24. @Pat Stanford, Try this. It works, but I don't know why. This is using your variable names. SetSelect(H1); { Wall handle } SetSelect(H2); { handle to sub_object in Wall } And so does this: SetSelect(H2); { handle to sub_object in Wall } SetSelect(H1); { Wall handle } Go figure!?! Raymond
  25. Hello, David. HINT: Pat's second suggestion is what you need. Try this code snippet. No error checking is done, so you'll have to add your own. PROCEDURE xxx; { Report the type and the PIO Name of a selected wall item. } VAR H, subH :Handle; B :Boolean; I :Integer; P :Vector; BEGIN GetPt(P.x, P.y); B := GetPickObjectInfo(P.x, P.y, H, subH, I); message(GetTypeN(subH), ' ', GetName(GetParametricRecord(SubH))); SysBeep; END; Run(xxx); HTH, Raymond
×
×
  • Create New...