Jump to content
DeSignature

Empty Record Fields in PIO

Recommended Posts

How come, if I call my PIO a first time in a drawing that all PIO record fields - since all the respective text items that are created in that PIO are blanc - appear to be empty?

If I delete that PIO en recall the same PIO, all the text items are displayed as I intended them to be displayed.

 

When I insert the PIO in a new drawing, there is no PIO record in the new drawing, I guess when I reinsert the PIO, the PIO can get it's values from the record created by the first call.

Is there a standard procedure to avoid this behavior?

Share this post


Link to post

I'm not completely sure I understand the question: are you placing a PIO via script and immediately trying to access its data?

 

You can run https://developer.vectorworks.net/index.php/VS:DefineCustomObj to create the record first (you can get a handle to the PIO's record by its name and check for nil). Otherwise, the PIO doesn't actually create it's record until after the vs runs.

Share this post


Link to post
Posted (edited)

The PIO is not being placed via a script, I just click a button in a tool palette and place the corresponding (custom) object somewhere on a sheet layer.

For now, I'll check out the DefineCustomObj function.

Thanks.

 

Edited by DeSignature

Share this post


Link to post

What you are seeing is not expected behavior, then. You should see PIO defaults on the first insertion. Is your PIO event enabled? If so, you may have code allocated to the wrong events.

Share this post


Link to post

The difference is that the first time you place a PIO in a specific document there Plug-in Parameter Record does not yet exist. When you place the PIO it is created.  When you delete the PIO the Parameter Record is not deleted, so the next time you place the same PIO the Parameter Record with the default data is still there to be used.

 

You should be able to set reasonable default values in the Plug-in Editor so that on first insertion you get something reasonable. And these should be editable if you click the Preferences setting of the insertion tool (Pencil/wrench icon) to be used as the defaults for future insertions.

 

Share this post


Link to post

Is there a function or a procedure that can check whether or not a record already exists in a drawing?

 

Apparently, if I replace the variable strings ( GetRField (PIO_H, PIO_R, StrVar) ) in the linked text items by constant strings ( 'Some Text' ), then the text items get displayed at the first insertion of the PIO.

So, I guess I could write a code that checks if the record is already present in the current drawing,

if not then the text items should use constant strings, if so then the text items should use variable strings.

Share this post


Link to post
Posted (edited)

The function Count (R IN [PIO_N]) helped me out here, but I could not find a the criteria to see if a record already exists in a drawing.

Since the function above checks if there exists an object with the referenced record attached to it in the drawing, it still doesn't check if a certain record exists in the drawing.

If I insert the PIO in a drawing for the first time the Count will return 0, once I've inserted 1 PIO, the count will return 1, but if I delete the PIO the count would return 0 again - which would be correct, but the PIO did create a record and if I delete the PIO, the record would still exist in the drawing.

 

EDIT:

This function only helped me out to display the text objects at the insertion of the PIO, since the created texts were constant strings ('Some Text'), they couldn't be edited anymore, so ...: back to the drawing board.

Edited by DeSignature

Share this post


Link to post
On 3/26/2020 at 6:17 AM, DeSignature said:

Is there a function or a procedure that can check whether or not a record already exists in a drawing?

I alluded to this in my first post. To get a handle to the plug-in’s record, use GetObject(plug-in_name). If the handle equals NIL, it doesn’t exist. 
 

But I would still revisit your issue in general. Plug-in objects shouldn’t need any special handling to display their default values on the first insertion. Something is either wrong with the structure of your code or the way you are retrieving parameters. 
 

Can you post some sample code?

Share this post


Link to post

Well I'll definitely will have to give that a try, but something tells me that this function will look for inserted PIO's and not for (hidden) PIO records ...

Anyway, I have simplified the actual code and tested the result, the result is the same, the variable strings are not being displayed at the moment of insertion,

they get displayed when the 'Edit Subgeometry' dialog gets confirmed or when the PIO is being reinserted.

Really looking forward to your findings, just hoping it won't be something too obvious ...

Dimitri.

PROCEDURE Simple;
VAR
	PIO_N			: STRING;
	PIO_H, PIO_R, PIO_W	: HANDLE;
	EventId, EventResult	: LONGINT;
	DialogId, DialogResult	: LONGINT;
	Result			: BOOLEAN;
	Txt			: STRING;

	PROCEDURE Geometry;
		PROCEDURE Define_Size;
		BEGIN
		END;

		PROCEDURE Draw_Geometry;
		BEGIN;
			RectangleN (-30, -15, 1, 0, 60, 30);
		END;

		PROCEDURE Insert_Subgeometry;
			PROCEDURE Draw_Subgeometry;
			BEGIN
				MoveTo (-30, 10);
				LineTo (60, #0);
				MoveTo (0, -15);
				LineTo (30, #90);
			END;

			PROCEDURE Insert_Text_Items;
				PROCEDURE Insert_Text_Items_A (x, y: REAL; T: STRING);
				BEGIN
					TextSize (8);
					MoveTo (x, y);
					CreateText (T);
				END;

				PROCEDURE Insert_Text_Items_B (x, y, StrS: REAL; T: STRING);
				BEGIN
					TextSize (StrS);
					MoveTo (x, y);
					CreateText (T);
				END;

			BEGIN
				Insert_Text_Items_A (-15, 12.5, 'Text A:');
				Insert_Text_Items_A (15, 12.5, 'Text B:');
				{ ... }

				Insert_Text_Items_B (-15, 0, 12, GetRField (PIO_H, PIO_N, 'RecordField A'));
				LinkText (LNewObj, PIO_N, GetRField (PIO_H, PIO_N, 'RecordField A'));
				Insert_Text_Items_B (15, 0, 12, GetRField (PIO_H, PIO_N, 'RecordField B'));
				LinkText (LNewObj, PIO_N, GetRField (PIO_H, PIO_N, 'RecordField B'));
				{ ... }
			END;
		BEGIN
			Draw_Subgeometry;
			Insert_Text_Items;
		END;
	BEGIN
		Define_Size;
		Draw_Geometry;
		Insert_Subgeometry;
	END;

	PROCEDURE EditSubgeometry;
		PROCEDURE Records;
		BEGIN
			NewField (PIO_N, 'RecordField A', 'TEXT A', 4, 1);
			NewField (PIO_N, 'RecordField B', 'TEXT B', 4, 1);
			{ ... }
		END;

		PROCEDURE Apply2All (ObjH: HANDLE);
		BEGIN
			GetItemText (DialogID, 161, Txt);
			SetRField (ObjH, PIO_N, 'RecordField A', Txt);
			{ ... }
			ResetObject (ObjH);
		END;

		PROCEDURE DialogLayout;
		BEGIN
			DialogId := CreateLayout ('Dialog A', FALSE, 'OK', 'Cancel');

			CreateGroupBox			(DialogId, 100, 'Tab A', FALSE);
			CreateRightStaticText	(DialogId, 110, 'Text A:', 20);
			CreateEditText			(DialogId, 111, 'TEXT A', 41);
			{ ... }
			CreateCheckBox			(DialogId, 120, 'Apply To All');
				SetFirstGroupItem	(DialogId, 100, 110);
				SetRightItem		(DialogId, 110, 111, 0, 0);
				SetBelowItem		(DialogId, 110, 120, 0, 0);
				{ ... }

			CreateGroupBox			(DialogId, 200, 'Tab B', FALSE);
			CreateRightStaticText	(DialogId, 210, 'Text B:', 20);
			CreateEditText			(DialogId, 211, 'Text B', 41);
			{ ... }
				SetFirstGroupItem	(DialogId, 200, 210);
				SetRightItem		(DialogId, 210, 211, 0, 0);
				{ ... }

			CreateTabControl		(DialogId, 10);
			SetFirstLayoutItem		(DialogId, 10);
			CreateTabPane			(DialogId, 10, 100);
			CreateTabPane			(DialogId, 10, 200);
		END;

		PROCEDURE DialogEvents (VAR Item, Data: LONGINT);			
			PROCEDURE DialogSettings;
			BEGIN
				SetItemText (DialogID, 111, GetRField (PIO_H, PIO_N, 'RecordField A'));
				{ ... }

				SetItemText (DialogID, 211, GetRField (PIO_H, PIO_N, 'RecordField B'));
				{ ... }
			END;

			PROCEDURE ConfirmDialog;
			BEGIN
				GetItemText (DialogId, 111, Txt); SetRField (PIO_H, PIO_N, 'RecordField A', Txt);
				{ ... }
				
				GetItemText (DialogId, 211, Txt); SetRField (PIO_H, PIO_N, 'RecordField B', Txt);
				{ ... }
				
				GetBooleanItem (DialogID, 120, Result);
				IF Result = TRUE THEN ForEachObject (Apply2All, PON = PIO_N);

				ResetObject (PIO_H);
			END;
			
			PROCEDURE CancelDialog;
			BEGIN
			END;
		BEGIN
			IF GetCustomObjectInfo (PIO_N, PIO_H, PIO_R, PIO_W) THEN
			CASE Item OF
				SetupDialogC	:	DialogSettings;
				1		:	ConfirmDialog;
				2		:	CancelDialog;
			END;
		END;
	BEGIN
		Records;
		DialogLayout;
		IF VerifyLayout (DialogID) THEN DialogResult := RunLayoutDialog (DialogID, DialogEvents);
	END;

	PROCEDURE Button_B;
	BEGIN
	END;

	PROCEDURE Button_C;
	BEGIN
	END;

	PROCEDURE Button_D;
	BEGIN
	END;

	PROCEDURE AutoEdit;
	VAR
		AutoTxt		: STRING;
	BEGIN
		AutoTxt		:= GetFName;

		IF GetCustomObjectInfo (PIO_N, PIO_H, PIO_R, PIO_W) THEN
		BEGIN
			SetRField (PIO_H, PIO_N, 'RecordField A', AutoTxt);
			{ ... }
		END;
		ResetObject (PIO_H);
	END;
BEGIN
	vsoGetEventInfo (EventId, EventResult);
	CASE EventId OF
		03:
		IF GetCustomObjectInfo (PIO_N, PIO_H, PIO_R, PIO_W) THEN
		BEGIN
			PushAttrs;
				Geometry;
			PopAttrs;
		END;	

		05:
		BEGIN
			Result	:= SetObjPropVS (08, TRUE);
			Result	:= vsoInsertAllParams;
			Result	:= vsoAppendWidget (12, 100, 'Edit Subgeometry', 0);
			Result	:= vsoAppendWidget (12, 200, 'Button B', 0);
			Result	:= vsoAppendWidget (12, 300, 'Button C', 0);
			Result	:= vsoAppendWidget (12, 400, 'Button D', 0);
			Result	:= vsoAppendWidget (12, 500, 'Auto Edit', 0);
		END;

		35:
		IF GetCustomObjectInfo (PIO_N, PIO_H, PIO_R, PIO_W) THEN CASE EventResult OF
			100:	EditSubgeometry;
			200:	Button_B;
			300:	Button_C;
			400:	Button_D;
			500:	AutoEdit;
		END;
	END;
END;
RUN (Simple);

 

Share this post


Link to post

DeSignature,

 

43 minutes ago, DeSignature said:

Well I'll definitely will have to give that a try, but something tells me that this function will look for inserted PIO's and not for (hidden) PIO records ...

 

Josh is one of the most knowledgeable (THE most knowledgeable in many areas) and most generous with sharing his knowledge. Your putting yourself at risk by putting out your opinion that something won't work with his statement that that is the way to do it.

 

By the way, I agree with him, but I tested it with the following single line script:

 

AlrtDialog(Concat(GetObject('Door')));

 

I ran it in a new document which did not have a door and I got a return of 0 meaning a nil handle. Placed a door and ran it. Got a 16 digit number which is the handle. Deleted the door and ran it again and got the same  16 digit number. That shows that it is the handle to the Record Definition, not the Door object in the drawing.

 

And remember, in VW, only a single object in the drawing can have a name. If you draw a rectangle, go to the OIP and set the Name field to Door, you will not be able to add a door object to the drawing as the name has already been taken. Similarly, if a door has ever been placed in the drawing the Door Record now exists and you will never be able to name an object in the drawing Door.

Share this post


Link to post

It's just that GetObject(plug-in_name) contained 'plug-in_name' and not 'plug-in_handle', but I really do agree it would have been much wiser to check the function reference before putting out my opinion and I will keep your advise in mind.

Hoping I didn't offend anybody in any way,

Dimitri.

Share this post


Link to post

I’m not nearly as generous with my time as @PatStanford, but I do know the ins and outs of vs fairly well. 🙂
 

GetObject() will return a handle to the object with the name you pass to it. Every PIO has a record format with the same name as the PIO. In terms of object type, it is exactly the same as a data record format. VW creates the format when you first insert the PIO or open its default settings in the mode bar. 
 

In your case, you have an issue with the code, though. You are calling LinkText() which is for creating symbols with text linked to record fields. You do not need this for PIOs, and in fact the use here is causing the text to always be one step behind. The PIO will completely redraw it’s contents any time you change a parameter, so simply creating the text is enough. 
 

If you are setting the parameter via another script, call ResetObj() to get the values to update.

 

You also don’t need to use GetRField to get the parameter value, unless the text is more than 255 characters or you use SetRField elsewhere in the script. Usually you can just use PParameterName, which is essentially a constant at run time with a type matching the parameter type. 

Share this post


Link to post

Following your remarks, I have deleted the LinkText() calls,

I tried to include the GetObject function in about every part of the script,

I tried to include the DefineCustomObj function in about every part of the script - every part but the correct one, I guess - using the 3 possible preference settings,

I did not delete or replace the GetRField function since I do use the SetRField function in the script.

but still, in every case the texts do not get displayed at insertion of the PIO.

 

As far as I can understand, I have to try to create the records before anything else happens in the script, so I guess I I'm creating the records at the wrong time in the script.

As I have mentioned above, the DefineCustomObj function did not help out on this one, where should I call this function?

Share this post


Link to post

Just adding DefineCustomObj() everywhere may be doing more harm than good. You should not need this anywhere in the code — my suggestion was based on the assumption you were placing custom objects via scripts, which is when the call is needed. 
 

As far as I can tell, you are only using SetRField in a button event. You can view the scope of each event running separately. 

I also noticed EditSubGeometry calls NewField() on the plug-in record. You should never modify the plug-in record via VectorScript, so that could be causing issues. Only use the Plug-in Manager to edit the parameter format. 

 

I would recommend stripping the code down to only the reset event to troubleshoot, and getting rid of all your DefineCustomObj calls for now. One of my initial suspicions is that your code isn’t handling events correctly. 
 

You may also want to restructure your code a bit to make it easier to troubleshoot. In some cases, you seem to be using subprocedures in lieu of commented code blocks, which could be causing scope issues. In contrast, one place where I do recommend subprocedures is for each event type (currently they are all inline in the case statement), which lets you write a simple main function with an event handler and clarifies that each handler should have its own scope. 

Share this post


Link to post

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.


 

7150 Riverwood Drive, Columbia, Maryland 21046, USA   |   Contact Us:   410-290-5114

 

© 2018 Vectorworks, Inc. All Rights Reserved. Vectorworks, Inc. is part of the Nemetschek Group.

×
×
  • Create New...