Jump to content
Developer Wiki and Function Reference Links ×

Selection within a Symbol Definition?


SamIWas

Recommended Posts

I can't believe I've never run into this before...

 

Write a small script to change text to poly line, then apply the correct attributes, because I'm doing it hundreds of times through a ton of symbols.   Finally got everything working correctly, then went to do it inside the symbol definition, and it does nothing.  FSActLayer doesn't seem to work inside symbols. FSObject doesn't seem to work because it still has to reference a layer.  FInSymDef doesn't appear to apply to current selection  Is there another one I'm missing here?

Link to comment

Have you ever heard of WALDO?

 

 

No, you are not missing anything in the VS API. There is no command to get a handle to any object when you are inside a container object (SymDef, Group, Sweep, etc.)

But there is WALDO. He's very useful when you want to run a script and you are editing inside a container object.

 

WALDO works like this:

1) Drop a 2D Locus anywhere  –  (0,0) is as good a place as any.

2) Get a handle to the Locus with  H := LNewObj;

3a) Get a handle to the previous object with H1 := PrevObj(H), or H1 := PrevSObj(H). Now you are at the top of the stacking order.

or

3b) Move the Locus all the way to the back and get a handle to the next object with H1 := NextObj(H) or H1 := NextSObj(H). Now you are at the bottom of the stacking order.

4) Delete the Locus with DelObject(H).

 

WALDO (if you make it a function) returns H1. Your scripts can now run INSIDE container objects if you use WALDO instead of FActLayer, or FSActLayer, or LActLayer, or LSActLayer. Waldo works on Design Layers, too, so you don't have to worry about where you are when you run a script.

 

Welcome to Waldo World,

Raymond

  • Like 4
Link to comment
On 12/9/2022 at 2:21 AM, MullinRJ said:

Have you ever heard of WALDO?

 

 

No, you are not missing anything in the VS API. There is no command to get a handle to any object when you are inside a container object (SymDef, Group, Sweep, etc.)

But there is WALDO. He's very useful when you want to run a script and you are editing inside a container object.

 

WALDO works like this:

1) Drop a 2D Locus anywhere  –  (0,0) is as good a place as any.

2) Get a handle to the Locus with  H := LNewObj;

3a) Get a handle to the previous object with H1 := PrevObj(H), or H1 := PrevSObj(H). Now you are at the top of the stacking order.

or

3b) Move the Locus all the way to the back and get a handle to the next object with H1 := NextObj(H) or H1 := NextSObj(H). Now you are at the bottom of the stacking order.

4) Delete the Locus with DelObject(H).

 

WALDO (if you make it a function) returns H1. Your scripts can now run INSIDE container objects if you use WALDO instead of FActLayer, or FSActLayer, or LActLayer, or LSActLayer. Waldo works on Design Layers, too, so you don't have to worry about where you are when you run a script.

 

Welcome to Waldo World,

Raymond

I kind of get what you're saying, but can't for the life of me get it to work.  I'm sure there's some stickler in the call to the function.  I know the function runs because it drops the locus.  But nothing happens past that.  The locus won't delete, either.  So it seems that the handles aren't being assigned.  I'm just going to keep doing this manually for now.  Spending more time trying to get the script to work than just manually doing the actions!

Link to comment
2 hours ago, Pat Stanford said:

Post the script and we can help you get it working.

Ha...good idea.   This is probably terrible code.  Not being really familiar with function calls, it's probably not written right at all.  Well, obviously it's not because it doesn't work! 😄

 

The general idea is that I select a piece of text inside a symbol, and the script changes that text to the correct font and correct justification, then changes it to a poly line and applies the correct attributes.

 

PROCEDURE Convert;
VAR

h,hp,ht : HANDLE;

ti : LONGINT;

FUNCTION GetTextBlock(h:HANDLE):HANDLE;
	BEGIN
		Locus(0,0);
		h:=LNewObj;
		
		ht:=PrevObj(h);
		SelectObj(ht);
		DelObject(h);
		END; {gettextblock}



BEGIN

	ht:=GetTextBlock(h);

	{----change font attributes of existing text----}
	SetTextVertAlignN(ht,3);
	SetTextJustN(ht,2);
	SetTextFont(ht,0,20,GetFontID('Avenir Next Medium'));
	
	ti:=TrueTypetoPoly(ht,hp);
	
	{----Set class and attributes of new group----}
	SetClass(hp,'Lighting-Label-Degree#');
	SetFPat(hp,1);
	SetFillColorByClass(hp);
	SetLSN(hp,0);
	
END;

Run(Convert);

 

Link to comment

@SamIWas,   This first code snippet is an annotated, verbose version of Waldo, as a function. It returns a handle to the FIRST SELECTED OBJECT in your current editing window so that your scripts will work even when you are not editing on a Design Layer. To use, place a copy of the Waldo function at the top of your code and replace H := FSActLayer; with H := FSWaldo; in your code. Modify this function as needed to achieve your desired functionality.

 

Function FSWaldo :Handle;
{ Return a handle to the first selected object in the present context of the drawing window. }
Var
	H, H1 :Handle;
Begin
	Locus(0, 0);		{ drop a breadcrumb, a Locus }  
	H := LNewObj;		{ H now contains a handle to the Locus }
	hMoveBackward(H, True);	{ move it to the bottom of the stacking order, but stay within the current container } 
	H1 := NextSObj(H);	{ get the handle to the next selected object above your locus, or NIL if there are none }
	DelObject(H);		{ discard the locus }
	FSWaldo := H1;		{ return the handle in H1 }
End;		{ FSWaldo }

 

 

   Here are two streamlined versions of Waldo to replace the FSActLayer and LSActLayer functions. These WALDOs will enable your scripts to work in any window you can open in Vectorworks.

 

Function FSWaldo :Handle;
Begin
	Locus(0, 0);
	hMoveBackward(LNewObj, True);
	FSWaldo := NextSObj(LNewObj);
	DelObject(LNewObj);
End;		{ FSWaldo }


Function LSWaldo :Handle;
Begin
	Locus(0, 0);
	LSWaldo := PrevSObj(LNewObj);
	DelObject(LNewObj);
End;		{ LSWaldo }

 

@SamIWas, if you would, please describe where you got confused in your previous implementation. It may help me describe this more clearly in the future.

 

HTH,

Raymond

 

  • Like 1
Link to comment
14 minutes ago, SamIWas said:
FUNCTION GetTextBlock(h:HANDLE):HANDLE;
	BEGIN
		Locus(0,0);
		h:=LNewObj;
		
		ht:=PrevObj(h);
		SelectObj(ht);
		DelObject(h);
		END; {gettextblock}

 

 

 You were very close. The only thing missing is the last line. You need to tell the function to return its answer with:

GetTextBlock := ht;

 

I assume ht is a global variable? For transportability, you should make ht a local variable like this:

FUNCTION GetTextBlock(h:HANDLE):HANDLE;
	VAR
		ht :Handle;
	BEGIN
		Locus(0,0);
		h:=LNewObj;
		
		ht:=PrevObj(h);
		SelectObj(ht);
		DelObject(h);
		GetTextBlock := ht;
	END; {gettextblock}

 

As you've written your code, do not delete ht from your global variables. ht can be both a local and global variable, as long as it doesn't confuse you.

 

So with the above modified function, you will still write:

        ht:=GetTextBlock(h);

 

in your main code.

 

Raymond

 

Edited by MullinRJ
additional comment
  • Like 1
Link to comment

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