Jump to content

Vectorscript: Move selected to Origin


Recommended Posts

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...

 

Link to comment

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

Link to comment

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. 

 

Link to comment

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.

 

 

 

 

Link to comment

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. 

Link to comment

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 ! :)

 

Link to comment

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 ?

Link to comment

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.

Link to comment
  • 1 year later...

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...