halfcoupler Posted April 29, 2017 Share Posted April 29, 2017 Hi , I'm just messing a bit around with Vectorscript.( I'm completely new to this, and try to do my first steps...) As a start I wanted to create a script that moves all selected items to the origin, but Im not very sucsessful in this. Here is whatI have so far: PROCEDURE MoveZero; VAR h : HANDLE; BEGIN h:= FSActLayer; HMove(h, 0, 0); END; Run(MoveZero); My questions: 1.) FSActLayer chooses only the first object on the active layer, how do I choose all selected objects? 2.) HMove(x,x,x ) moves only relative to the current location, what is the command to move to a certain point ? Thanks for help... Quote Link to comment
MullinRJ Posted April 29, 2017 Share Posted April 29, 2017 This topic should have been started in the Vectorscript forum, but I'll let the powers that be move it if they deem fit. To operate on multiple objects you can use a WHILE loop, such as this: h := FSActLayer; WHILE (h <> nil) do begin { hmove your stuff here } H := NextSObj(H); { get handle to next selected object } end; { WHILE } or use ForEachObject(), which uses a procedure to perform a small task on each object, like this: PROCEDURE MoveToOrigin; { move all Selected objects on the Active Layer to the origin } VAR LyrName :String; procedure DoThis(h :Handle); Var x, y :Real; Begin HCenter(h, x, y); HMove(h, -x, -y); End; { DoThis } BEGIN LyrName := GetLName(ActLayer); { name of active layer } ForEachObject(DoThis, SEL & (L=LyrName) ); SysBeep; END; Run(MoveToOrigin); Of course, with a script like this, all selected objects will be stacked on top of each other at the drawing origin. If you want to keep them in their relative position after they are moved, you might try grouping them first, moving the Group, then ungrouping them. Then you won't need ForEachObject() and FSActLayer will return a handle to the Group. HTH, Raymond Quote Link to comment
Pat Stanford Posted April 29, 2017 Share Posted April 29, 2017 Hi, My name is Pat and I am a Vectorscripter. (Hi, Pat) Welcome to the club. Lots of friendly scripter here, so just keep asking. We will be glad to share what we know. This answer is probably going to be longer than either you or I expect it to be. You have asked some great questions to allow for a general explanation of VS. First, the simple answer. Nothing moved because you didn't tell it to move. HMove moves objects by an offset, not to an absolute point. So you moved the object by zero in the X direction and zero in the Y direction. Second, there are three main ways of operating on objects in VS. The first is by Handle. This is basically what you have done with FSActLayer. Now, this description is incomplete (intentionally), so don't treat this as absolute, but it will give you the basics of using Document List Handling (the sub category the routines are listed in in the Vectorscript Function Reference). The way I think about it, VS internally keeps a big "list" of objects and there are procedures to allow you to get a handle to an object in the list. You can get: Selected object on the active layer (FSActLayer, LSActLayer) Any object on the active layer (FActLayer, LActLayer) Selected object on any layer (FSObject) Any object on any layer (FObject, LObject) You can then move between objects using the versions of Next and Previous. NextObj, PrevObj Item below or above in the list NextSObj PrevSObj Selected item below or above in the list NextDObj, PrevDObj Deselected item below or above in the list Using any of the Next/Previous routines will only return objects that are on the same layer as the first object when you got into the list. You can then use a loop (For, While, Repeat - See the Vectorscript Language Guide for the differences) to step through and process each object in the list and do whatever you need. The second way to deal with object is to use Criteria. Criteria can be generated by hand or by the Criteria... menu item in the Script Editor. Criteria are just a way of specifying what objects you want and letting VS get them all for you. Examples could be: All Rectangles ((T=Rect)) Text on Layer-1 ((T=Text) & (L='Layer-1')) Red Ovals ((T=Arc) & (PF=1272)) [PF stands for PenFore See the Vectorscript Appendix for object types and selection criteria] There are lots of functions that can be passes a criteria and will perform the same action on every object that meets that criteria. The ForEachObject function mentioned by Raymond lets you process objects that meet the criteria individually. Most of the commands that process object based on criteria tend to return data on the objects rather than change them graphically and are listed in the Criteria section of the VS Function Reference [view by Class to see the sections] Finally, there are a number of routines that will process objects based on their being selected. Examples are Duplicate, DeleteObjs. And finally, there is a kind of hybrid for what you are doing. The MoveObjs has options that allow you to determine if you are going to move selected object or all objects and only the active layer or objects on all layers. Since you say you want all the objects moved to the origin, you will need to use something like Raymond suggested to get the location of each object and then move it the correct distance to sit at the origin. I hope this actually helps and does not cause more confusion. Quote Link to comment
halfcoupler Posted April 30, 2017 Author Share Posted April 30, 2017 Thanks much Raymond and Pat, yes, I want a couple of selected symbols stacked at the origin above each other. The script is almost what I want, exept that the move should be in 3D, and the symbols should be moved by their insertion point. So tried this: PROCEDURE MoveToOrigin; { move all Selected objects on the Active Layer to the origin } VAR LyrName :String; procedure DoThis(h :Handle); Var x, y, z :Real; Begin x := XCoordinate (h); y := YCoordinate (h); z := ZCoordinate (h); Move3DObj(h, -x, -y, -z); End; { DoThis } BEGIN LyrName := GetLName(ActLayer); { name of active layer } ForEachObject(DoThis, SEL & (L=LyrName) ); SysBeep; END; Run(MoveToOrigin); But it does not work... sorry for placing this topic in the wrong forum. Quote Link to comment
Pat Stanford Posted April 30, 2017 Share Posted April 30, 2017 The coordinate calls do not take a Handle, they need a criteria. Try using Get3DCntr(h, x,y,z); instead. Also, I have gotten bitten a number of times over the years with variable names that happen to be the same a criteria. I have since taken up using variable names of at least two characters, usually with one of them being a number. So I would have written the above line as: Get3DCntr(H1, X1, Y1, Z1); Especially for short test scripts I tend to use the variable type and a number to specify what they are, unless it is points in which can I use X, Y, Z. so: R1: Real; S1: String; B1: Boolean; L1: LongInt; N1: Integer; (this one is different because I find it to hard to differentiate between a upper case I and a lower case L in sans serif fonts. Quote Link to comment
halfcoupler Posted April 30, 2017 Author Share Posted April 30, 2017 works perfect! ... hm, almost.... Get3DCntr(H1, X1, Y1, Z1) returns the center point of the object,- what I need is the insertion point of the symbols. Is there a function for this or do I have to calculate this via Get3DInfo() ? Quote Link to comment
halfcoupler Posted April 30, 2017 Author Share Posted April 30, 2017 this seems to work: PROCEDURE MoveToOrigin; { move all Selected objects on the Active Layer to the origin } VAR LyrName :String; procedure DoThis(H1 :Handle); Var X1, Y1, Z1 :Real; U1, V1, W1 :Real; Begin Get3DCntr(H1, X1, Y1, Z1); Get3DInfo(H1, U1, V1, W1); Move3DObj(H1, -X1+U1/2, -Y1+V1/2, -Z1+W1/2); End; { DoThis } BEGIN LyrName := GetLName(ActLayer); { name of active layer } ForEachObject(DoThis, SEL & (L=LyrName) ); SysBeep; END; Run(MoveToOrigin); YEAH ! Quote Link to comment
Pat Stanford Posted April 30, 2017 Share Posted April 30, 2017 Might be slightly easier with: PROCEDURE GetSymLoc3D ( objectHandle :HANDLE; VAR x :REAL; VAR y :REAL; VAR z :REAL ) ; Determines the location of a specified symbol or plug-in object in 3D space. Quote Link to comment
halfcoupler Posted May 1, 2017 Author Share Posted May 1, 2017 yes, this one is perfect: PROCEDURE MoveToOrigin; { move all Selected objects on the Active Layer to the origin } VAR LyrName :String; procedure DoThis(H1 :Handle); Var X1, Y1, Z1 :Real; Begin GetSymLoc3D (H1,X1,Y1,Z1); Move3DObj(H1, -X1, -Y1, -Z1); End; { DoThis } BEGIN LyrName := GetLName(ActLayer); { name of active layer } ForEachObject(DoThis, SEL & (L=LyrName) ); SysBeep; END; Run(MoveToOrigin); one last thing, can I have this embedded in a menue bar of the workspace, or have a keyboard shortcut for this ? Quote Link to comment
Pat Stanford Posted May 1, 2017 Share Posted May 1, 2017 To do that you have to make it a Plugin Command. Copy the script. Go to Tools:Plugins:Plugin Manager. Create a new Command and Name it. Click the Edit Script button and paste the script in. Click OK and Close the Plugin Manager. Go to Tools:Workspaces:Edit Current Workspace. Add the new Command to a menu and give it a keyboard shortcut. You used to have to restart VW to get the new Plugin to show up. I am not certain if that is still the case or not. If it does not work after editing the workspace, restart before you panic. Easier to do that to describe, but there are lots of options in both the Plugin Manager and the Workspace editor, so if you have not used them, it will probably take some time to get it all right. Quote Link to comment
halfcoupler Posted May 2, 2017 Author Share Posted May 2, 2017 (edited) Works fine ! Thanks much ! Guess I will become a script kiddie now, despite my age.. Edited May 2, 2017 by halfcouple Quote Link to comment
Alinoz Posted July 21, 2018 Share Posted July 21, 2018 Thanks so much for this!!! I'm new to Vectorworks and this has been invaluable. Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.