Jump to content
Developer Wiki and Function Reference Links ×

Pickup Object via Button on OIP


twk

Recommended Posts

Greetings all,

Anyone know how, if possible, to script in a way to get a handle to an external object via a button on the Object Info Pallette(OIP)??

So far my experimenting has utilised

- Event Enabled PIO

- Placing in the Button Event loop, the GetPt(px,py) and h:=PickObject(px, py)

- and then SetRField the Area of picked object onto Parameter Field

Im trying to have a static txt parameter display area for certain type of objects on layer (via a critera, same pen/fill/class/etc).

the result from the PickObj method semi works, but it doesnt store the value in the parameter field. and sometimes it causes VW to go haywire. (Menu Items greyed out etc).

Does anyone know if Im way off track or a bit close?

Thanks in advance

Tui W K

Link to comment

Sounds like you are on the right track.

SetRField should only be in the button event.

What does your SetRField look like? Does your call work from the main reset part of the script if you use a test string?

A button event won't reset the object to display the new data. Add a ResetObject() call to cause the PIO to regenerate.

-Josh

Link to comment

Hi Josh,

Yes, setrfield works from main reset procedure test.

Below is full testing code.

Procedure EventStamp;
CONST
	kObjOnInitXProp = 5;
	kResetEventID = 3;
	kObjXPropHasUIOverride = 8;
	kWidgetButton = 12;
	ButtonID_1 = 1331;
	ButtonID_2 = 1332;
	kButtonOIPHit = 35;
VAR
	theEvent, theButton : LONGINT;
	result, bCustomObjInfo, bPIOisNEW : BOOLEAN;
	PIONameh :STRING; hParm, hParmRecord, hWall : HANDLE;
	iNothing : LONGINT;
	hPick : HANDLE; px, py : REAL;

	p1x, p1y, vAREA : REAL;
	bPick : BOOLEAN;

PROCEDURE ResetEvent;
	{$INCLUDE \Vectorscript Scripts\PIO Codes\trigFunctions.vss}
	{$INCLUDE \Vectorscript Scripts\PIO Codes\CustRect01.vss}
	BEGIN
		IF bCustomObjInfo THEN 
			BEGIN
				CustomRect(5mm, 5mm, -5mm/2,-5mm/2);
				Locus(0,0);
				{ResetObject(hParm);}
			END;
	END;

BEGIN
	bCustomObjInfo := GetCustomObjectInfo(PIONameh, hParm, hParmRecord, hWall) & (hParm <> Nil);
	bPIOisNEW := IsNewCustomObject(PIONameh);

	vsoGetEventInfo(theEvent, theButton);
	CASE theEvent OF
		kObjOnInitXProp :
			BEGIN
				result := SetObjPropVS(kObjXPropHasUIOverride, TRUE);
				result := vsoInsertAllParams;
				result := vsoAppendWidget(kWidgetButton, ButtonID_1, 'Pick Object', iNothing);
				result := vsoAppendWidget(kWidgetButton, ButtonID_2, 'Pick Object v2', iNothing);
			END;

		kButtonOIPHit :
			BEGIN
				CASE theButton OF
					ButtonID_1 :
						BEGIN
							GetPt(p1x, p1y);
							hPick := PickObject(p1x, p1y);
						END;
					{ButtonID_2 :
						AlrtDialog('You Hit Button 02');}
				END;

				IF (bCustomObjInfo) & (hPick<>NIL) THEN
					BEGIN
						vAREA := ObjAreaN(hpick);
						SetRField(hParm,PioNameH,'Area',Concat(vAREA));
						ResetObject(hParm);
					END;
			END;

		kResetEventID :
			ResetEvent;
	END;
END;
Run(EventStamp);

Edited by TuiWalker
Link to comment

Furthermore, all works well

- button works

- able to pick object

- able to pass Area to Parameter and store it

except

- the initial PickObject UI cursor comes up

- im able to select an object and store its area

- however if i click on an empty space on the page it resets to the previous value in the Parameter

- to keep the value store I have to click on the button again and select the same object (making it work by selecting same object two times)

Link to comment

Your script works for me. The only think I can think of is that the main name of your parameter should be "area" and not your alternate name.

I would also recommend placing your set field section in the button 1 case.

Delete the ResetObject call in your main code. If uncommented, this could cause an endless loop.

Link to comment

Hmm, I've relocated the SetRFiled call, but still no luck..and removed the ResetObject call as well.

What do you mean by main name of parameter? I havent set any alternate names yet.. Unless I'm misreading something.

Thanks for the help though..

Here's a screencap video of whats happening..

https://vimeo.com/135019482

Link to comment

I think I know what is wrong. Your event is running twice because you don't clear your state info on resetting. You can test this easily to assign an alertbox in your event and see how much times it pops up.

Add this as an theEvent case:

3:	BEGIN
			result:= GetCustomObjectInfo(objName,objHd,objrecHd,wHd);
			vsoStateClear(objHd);
END;

Edited by hippothamus
Link to comment

Hi Josh, tried adding that to the end of the ResetID, still no luck. I think it's got somehting to do with the Picking Object procedure.. still testing

Below is code so far

Procedure EventStamp;
CONST
	kObjOnInitXProp = 5;
	kResetEventID = 3;
	kObjXPropHasUIOverride = 8;
	kWidgetButton = 12;
	ButtonID_1 = 1331;
	kButtonOIPHit = 35;
VAR
	theEvent, theButton : LONGINT;
	result, bCustomObjInfo, bPIOisNEW : BOOLEAN;
	PIONameh :STRING; hParm, hParmRecord, hWall : HANDLE;
	iNothing : LONGINT;
	hPick : HANDLE; px, py : REAL;

	p1x, p1y, vAREA : REAL;
	bPick : BOOLEAN;

PROCEDURE ResetEvent;
	{$INCLUDE \Vectorscript Scripts\PIO Codes\trigFunctions.vss}
	{$INCLUDE \Vectorscript Scripts\PIO Codes\CustRect01.vss}
	BEGIN
		IF bCustomObjInfo THEN 
			BEGIN
				CustomRect(5mm, 5mm, -5mm/2,-5mm/2);
				Locus(0,0);
				{ResetObject(hParm);}
			END;
	END;

BEGIN
	bCustomObjInfo := GetCustomObjectInfo(PIONameh, hParm, hParmRecord, hWall) & (hParm <> Nil);

	vsoGetEventInfo(theEvent, theButton);
	CASE theEvent OF
		kObjOnInitXProp :
			BEGIN
				result := SetObjPropVS(kObjXPropHasUIOverride, TRUE);
				result := vsoInsertAllParams;
				result := vsoAppendWidget(kWidgetButton, ButtonID_1, 'Pick Object', iNothing);
			END;

		kButtonOIPHit :
			BEGIN
				CASE theButton OF
					ButtonID_1 :
						BEGIN
							GetPt(p1x, p1y);
							hPick := PickObject(p1x, p1y);

							IF (bCustomObjInfo) & (hPick<>NIL) THEN
								BEGIN
									vAREA := ObjAreaN(hpick);
									SetRField(hParm,PioNameH,'Area',Concat(vAREA));
									ResetObject(hParm);
								END;
						END;
				END;

			END;

		kResetEventID :
			BEGIN
				ResetEvent;
				IF bCustomObjInfo THEN
					vsoStateClear(hParm);
			END;
	END;
END;
Run(EventStamp);

Link to comment

Try rewriting it in a while loop so until the user succeeds selecting a point it will keep requesting one. Maybe that "ends" the function in a better way.

This will also make sure it will only copy the area if it has a valid object. Clicking in white space would not reset the values even if the GetPt was triggered again for some reason.

Edited by hippothamus
Link to comment

Hmm, ok so changing the Button_ID1 Call to this

kButtonOIPHit :
BEGIN
	CASE theButton OF
		ButtonID_1 :
			BEGIN
				GetPt(p1x, p1y);
				hPick := PickObject(p1x, p1y);

				WHILE hPick = NIL DO
					BEGIN
						GetPt(p1x, p1y);
					END;

				IF (bCustomObjInfo) & (hPick<>NIL) THEN
					BEGIN
						vAREA := ObjAreaN(hpick);
						SetRField(hParm,PioNameH,'Area',Concat(vAREA));
						ResetObject(hParm);
					END;
			END;
	END;

END;

Still no luck.. on a side note, my lack of understanding of getting While loops to work in my favor may be a cause as well.

Thanks in advance .. again

Edited by TuiWalker
Link to comment

Thanks Hippothamus,

I'm at a loss, its still getting reset if I select in an empty space.

Here is the full code, and atached is the VSO file if that helps.

Parameters are:

nObjFound : STATIC TEXT

sArea : STATIC TEXT

sCriteria : STATIC TEXT

PROCEDURE Take2;
CONST
	kObjOnInitXProp = 5;
	kResetEventID = 3;
	kObjXPropHasUIOverride = 8;
	kWidgetButton = 12;
	ButtonID_1 = 1331;
	kButtonOIPHit = 35;
VAR
	theEvent, evResult : LONGINT;
	result, bCustomObjInfo, bPIOisNEW : BOOLEAN;
	PIONameh :STRING; hParm, hParmRecord, hWall : HANDLE;
	iNothing : LONGINT;
	hPick : HANDLE; p1x, p1y : REAL; PickCriteria : DYNARRAY[] OF CHAR;
PROCEDURE ResetEvent;
	VAR
		vsqrDim : REAL;
		bAttr : BOOLEAN;
	BEGIN
		IF bCustomObjInfo THEN 
			BEGIN
				TextJust(1);
				CreateText(Concat(PsArea, GetPrefString(178)));
				Locus(0,0);
				SetObjectVariableBoolean (hParm,800,TRUE);
				{ResetObject(hParm);}
			END;
	END;

BEGIN
bCustomObjInfo := GetCustomObjectInfo(PIONameh, hParm, hParmRecord, hWall) & (hParm <> Nil);
vsoGetEventInfo(theEvent, evResult);
	CASE theEvent OF
		kObjOnInitXProp :
			BEGIN
				result := SetObjPropVS(kObjXPropHasUIOverride, TRUE);
				result := vsoInsertAllParams;
				result := vsoAppendWidget(kWidgetButton, ButtonID_1, 'Pick Object', iNothing);
			END;
		kButtonOIPHit :
			BEGIN
				CASE evResult OF
					ButtonID_1 :
						BEGIN
							IF bCustomObjInfo THEN
								BEGIN
									hPick := NIL;
									WHILE hPick = NIL DO
										BEGIN
											GetPT(p1x, p1y);
											hPick := PickObject(p1x, p1y);
											Message(GetTypeN(hPick));
											PickCriteria := Concat('T=',GetTypeN(hPick));
											SetRField(hParm, PIONameh, 'sCriteria', PickCriteria);
											SetRField(hParm,PioNameH,'sArea',Concat(AreaN(PickCriteria)));
										END;
									ResetObject(hParm);
								END;
						END;
				END;
			END;
		kResetEventID :
			BEGIN
				ResetEvent;
				IF bCustomObjInfo THEN
				    vsoStateClear(hParm);       
			END;
	END;
END;
Run(Take2);

The Stored parameter fields get reset if I select an empty space directly after selecting an object to query. Maybe its a bug of the PickObj function??

If someone can replicate this and let me know if it's just my machine or if they're getting the same results as I am, it would be much appreciated.

Also, the VWDeveloper Wiki explains the Gtpt function like this:

Procedure GetPt switches the cursor to selection mode and allows the user to select a point in a VectorWorks document. This cannot be used if there is a function anywhere in the calling chain.

What does the last part mean? Have I got a function somewhere in the ?calling chain?..

Thanks in Advance

Tui

Edited by TuiWalker
Link to comment

..and I present to you the culprit..

Vectorworks Preferences>>

Session Tab>>

'Run scripts in Developer Mode'

Turning that checkbox off made it work!

After all that and it was a simple check box!!

Thanks sooo much hippothamus and Josh for putting up with this roundabout exercise.

Tui

Link to comment

There is no reason that turning off developer mode should cause your issue, unless your case statement isn't set up right.

I tried your vso, and it worked fine for me even in developer mode, except that the object would occasionally crash VW.

A few suggestions:

You shouldn't need vsoState clear, as you haven't set up your object to accept states.

Before CreateText, check that Len( text ) > 0

I recommend against testing for HParm = NIL. There are some cases where you want the NIL case to be handled, like inserting the object.

My guess is your issue lies with the PickObject call -- it's fairly old and may be causing a memory leak. Try the FindObjAtPt commands, which might be more stable.

-Josh

Link to comment

Thanks for the tips Josh.. Unfortunately I am very new to implementing events.

FYI, im using this method for picking object attributes (hatch/fill/etc) and getting areas based on these. It's been working for the past couple of days with no crashes, all with Developer mode off.

That being said, I'd really like to set this up correctly so I don't hit any problems down the road.

You mentioned I don't need vsoState clear as I haven't set up my object to accept states.

So do I need to remove vsoState clear? or Make my object accept states?

With regards to the hParm<>NIL, I've used that with all my PIO's, is this incorrect? I can't recall where I picked up this step, must've been during my early days of learning VS, and I've never checked or thought it was incorrect. Thanks for the info.

Will be trying the FindObjAtPt command and see how that fares.

Thanks again

Tui

Link to comment
Thanks for the tips Josh.. Unfortunately I am very new to implementing events.

FYI, im using this method for picking object attributes (hatch/fill/etc) and getting areas based on these. It's been working for the past couple of days with no crashes, all with Developer mode off.

Don't spend too much time on perfection, then. I do, however, find small imperfections can suddenly make a script crash in future versions.

That being said, I'd really like to set this up correctly so I don't hit any problems down the road.

You mentioned I don't need vsoState clear as I haven't set up my object to accept states.

So do I need to remove vsoState clear? or Make my object accept states?

States will tell you why a plugin is regenerating -- move, parameter change, layer change, etc. I don't think you need any special handling in your resource event, so it's not necessary. If you were to want the object to be state aware, you would set some options in the init event and add the addState event to you event cases.

With regards to the hParm<>NIL, I've used that with all my PIO's, is this incorrect? I can't recall where I picked up this step, must've been during my early days of learning VS, and I've never checked or thought it was incorrect. Thanks for the info.

There are a few instances where the handle will be nil. Off the top of my head, clicking on the preferences icon in the mode bar is one of them.

-Josh

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