Jump to content
Developer Wiki and Function Reference Links Read more... ×
David Bengali

What PIO State Change on Linear Object Length Adjust / Reshape

Recommended Posts

Hi all,

 

I am creating a Linear plug-in object, and trying to catch and respond to the event where a user changes the LineLength by moving one of the two built in control points of the object. However, I cannot seem to figure  out what event / state change this qualifies as.

 

The vso states I know of are:

vs.kCreatedReset = 0
vs.kMovedReset = 1
vs.kRotatedReset = 2
vs.kParameterChangedReset = 3
vs.kObjectChangedReset = 4
vs.kLayerChangedReset = 5
vs.kExitFromEditGroup = 6
vs.kObjectNameChanged = 7

Below is an example of some code I have used to try to detect this state change.  Alerts appear as expected for move, rotate, attribute change, and parameters changed either in the OIP or by moving an added Conrol Point parameter in the drawing, but when I drag the two points that are actually built in to the PIO, although I do receive 3 for the event, triggering the ResetEventHandler in this case, no alert fires off for any of the checked state changes.  It seems that this state change is not one of those listed above.  I expected it to be a Param change along with possibly a rotation and position change, depending on which of the two points was dragged. Can anyone advise on what state I need to check for, and how I can capture the new and old value for line length, rotation, and position that could have been adjusted by this action?

def execute():
	global objname, oh
	result, objname, oh, rh, wh = vs.GetCustomObjectInfo()

	theEvent, message = None, None
	theEvent, message = vs.vsoGetEventInfo()

	if theEvent == vs.kObjOnInitXProperties: #5
		#enable eventing for this plug-in
		vs.SetPrefInt( vs.kParametricEnableStateEventing, 1 ) #590
		result = vs.SetObjPropVS(vs.kObjXPropAcceptStates, True) #18

	elif theEvent == vs.kObjOnAddState: #44
		message = vs.vsoStateAddCurrent( oh, message )

	elif theEvent == vs.kParametricRecalculate: #3
		ResetEventHandler()

def ResetEventHandler():
	global objname, oh
	if vs.vsoStateGet( oh, vs.kCreatedReset ):
		vs.AlrtDialog("Object Just Created")
	if vs.vsoStateGet( oh, vs.kMovedReset ):
		vs.AlrtDialog("Object Just Moved")
	if vs.vsoStateGet( oh, vs.kRotatedReset ):
		vs.AlrtDialog("Object Just Rotated")
	if vs.vsoStateGet( oh, vs.kParameterChangedReset ):
		vs.AlrtDialog("Parameter Changed")
	if vs.vsoStateGet( oh, vs.kObjectChangedReset ):
		vs.AlrtDialog("Object Changed")


	

 

Share this post


Link to post

I have not used events a lot. It is possible that the events are not powerful enough in VS/Python to give you what you want. Have you read the section on Vectorlab about events?  http://www.vectorlab.info/index.php?title=Events

 

There are things you can't do using events and VS/Python. From the above web page.

 

Quote

The C++ environment is more complicated than VectorScript, but not as complicated as trying to get a limited language like VectorScript to do things for which it was not designed. Besides, these new features in VectorScript were implemented not in an effort to make VectorScript objects as powerful and flexible as SDK objects, but simply to satisfy very specific requirements for specific features under development at NNA. The general public is encouraged to use these features at their own risk, and to not expect the functionality to be rounded out in future releases, the way core functionality is maintained, enhanced, and supported. 

That having been said...

 

My first thought for you wanting to check before and after states is that you will need to use a second set of hidden parameters. At the end of your script copy the actual working state parameters to the "Previous State" parameters. When you modify the object, these would then still contain the previous data and allow you to do whatever comparisons you need. Just don't uses the Previous State parameters anywhere in the script or expose them in the OIP.

 

Based on my understanding either the  ParameterChangedReset or ObjectChangedReset events should get you what you are looking for.

 

HTH

  • Like 1

Share this post


Link to post

Thanks, yes, I am checking both ParameterChangedReset and ObjectChangedReset, and neither one of these seems to be set when the main control points of the Linear PIO are dragged.  Since these are the most basic features of this type of PIO, it seems strange that one would have to resort to the SDK to notice if they have been adjusted, so I assumed I was missing something, but I suppose if Event 3 (parametric recalculate / reset)  gets triggered, and none of the states I am checking are set, then I could assume the only remaining option was a change in those control points, and then check stored hidden variables for position, rotation, and LineLength as you suggest.

 

 

Share this post


Link to post

You should see a param state change.  If I remember correctly, vsoStateGet can clear the state, so you only get the first state message.  Instead, try seeing if vsoStateGetParamChng returns true.

 

-Josh

Share this post


Link to post

Thanks Josh,

 

Strangely enough, I seem to be getting false on vsoStateGetParamChng, even when the last state change really was a change to some parameter in the OIP, but also after dragging one of the end points of the linear PIO.  Wondering if there is anything I am obviously doing wrong here.  

 

Sample code below

 

After a either a linear object reshape, or after a change to a PIO parameter in the OIP, the last alert in the following snippet displays something like

 

didParamChange: False outWidgID: 356515844 OutPrmIdx: -19949 outOldVal: F÷.

 

import vs

# event / state constants
vs.kParametricRecalculate   = 3
vs.kObjOnInitXProperties    = 5
vs.kParametricEnableStateEventing = 590
vs.kObjXPropAcceptStates = 18
vs.kObjOnAddState = 44



vs.kObjectEventHandled      = -8


vs.kCreatedReset = 0
vs.kMovedReset = 1
vs.kRotatedReset = 2
vs.kParameterChangedReset = 3
vs.kObjectChangedReset = 4
vs.kLayerChangedReset = 5
vs.kExitFromEditGroup = 6
vs.kObjectNameChanged = 7




def execute():
    global objname, oh
    result, objname, oh, rh, wh = vs.GetCustomObjectInfo()

    theEvent, message = None, None
    theEvent, message = vs.vsoGetEventInfo()

    if theEvent == vs.kObjOnInitXProperties:
        #enable eventing for this plug-in
        vs.SetPrefInt( vs.kParametricEnableStateEventing, 1 ) #590
        result = vs.SetObjPropVS(vs.kObjXPropAcceptStates, True) #18
    
    
    elif theEvent == vs.kObjOnAddState: #44
        message = vs.vsoStateAddCurrent( oh, message )
    
    elif theEvent == vs.kParametricRecalculate: #3
        ResetEventHandler()

def ResetEventHandler():
    global objname, oh
    if vs.vsoStateGet( oh, vs.kCreatedReset ): #0
        vs.AlrtDialog("Object Just Created")
    if vs.vsoStateGet( oh, vs.kMovedReset ): #1
        vs.AlrtDialog("Object Just Moved")
    if vs.vsoStateGet( oh, vs.kRotatedReset ): #2
        vs.AlrtDialog("Object Just Rotated")
    if vs.vsoStateGet( oh, vs.kParameterChangedReset ): #3
        vs.AlrtDialog("Parameter Changed")
    if vs.vsoStateGet( oh, vs.kObjectChangedReset ): #4
        vs.AlrtDialog("Object Changed")

    didParamChange, outWidgID, outPrmIdx, outOldVal = vs.vsoStateGetParamChng(oh)
    vs.AlrtDialog("didParamChange: " + str(didParamChange) + " outWidgID: " + str(outWidgID) + " outPrmIdx: " + str(outPrmIdx) + " outOldVal: " + str(outOldVal))

 

I also see in the wiki the following:

 

(Orso, 2016.05.08): vsoStateGetParamChng returns false after following modifications:

  • on PIO rec set up
  • on move, rot, path reshape
  • layer scale, height, thickness

Thus there won't be a state parameter change on move, rot or on copy.

  • outWidgID, outPrmIdx return 0 on move, rot, new obj, alt-drag copy

 

 

Of course, I am not seeing 0 for those ID's, rather, something that looks like garbage data.

 

 

Share this post


Link to post

Ah, I now understand what you were saying about the state getting cleared.  If I put the call to vsoStateGetParamChng before the vsoStateGet calls, I do get True and valid other data in the event of changing a parameter in the OIP.

 

However, for dragging one of the ends of the linear PIO, I get false and garbage data, even if vsoStateGetParamChng is called first.

Share this post


Link to post

If you initialize your variables, you won't get garbage data on the false case (I think).

 

The state that you get will depend on which point you move.  One will move the origin of the PIO, as well as affect the rotation and line length.  You won't get a line length param change notification, as the user doesn't directly change this parameter, you'll just have to know it's new.  If the other control point moves, you should get a line length change as well as a rotation.

 

Also, make sure at the end of your reset block you clear state changes.

 

-Josh

Share this post


Link to post

initializing variables doesn't seem to prevent garbage on the False case when the event was triggered by a drag of the built-in control points, but in any case, the solution I have gone with is, as Pat suggested, to use hidden parameters to store the old value of LineLength and rotation, and as Josh suggested, to check if these values have changed if an event is triggered but vsoStateGetParamChng returned False.

 

This works fine for my use case, but I still wonder if there is some undocumented constant that corresponds to the state change reflected by this action.  It is a little too bad that there isn't one single place where all of the arcane constants in vectorscript are documented.  I know there is the appendix of selected tabulated values, but it is incomplete.

Share this post


Link to post

Well in the SDK I think you could catch it with drag events as well, which would even include first and completion click.

Share this post


Link to post

Thanks, it seems like the SDK may eventually be required.  Just curious is there a straightforward way to take a PIO created in python and port it over to the SDK, or even to keep it mostly in python but extend it with the SDK?

Share this post


Link to post

I have no experience with Python. I do know there is a specific SDK call to call all the available Python functions. I'm not sure how flexible it is.

Share this post


Link to post

A few things:

 

- We might benefit in hearing why you need to detect the user drag to set the line length.  Because with the line-type PIO, VW calculates the length for me, I find I don't care how the object length changes, because I'm dealing with a "fresh" LineLength parameter on each regen.  If it's a point or path object simulating a line, that's another story, and in that case there is a control point that prompts a param event change.

 

- Porting from py to the SDK/c++ is not straightforwards, as it's an entirely different API, built around the fact that you pre-compile the plug-in and then register into memory, as opposed to compile at run time.  You can run python from within an SDK plug-in, but it's really just running a script, and exchanging data between the environments is a bit tedious.  That said, you can create an update event manager that is separate from the plug-in, that functions as a sort of control tower for various events.  It's definitely more robust than VS, but I'm not sure it will help you here.

 

- One way the SDK is quite useful is to discover constant values, as those are shared between SDK and vs plug-ins.  In the SDK, look at MiniCadHookIntf.h and MiniCadCallBacks.h.  The latter, for example, will give you all the possible state events:

struct ObjectState : public ObjectEventCall
	// 
	//	Objects with the kObjXPropAcceptStates property have their Object definition procedure called with
	//	the ObjectState::kAction event.  The message parameter is a pointer to this ObjectState structure.  
	//	Use the fSpecifier to determine the type of data in  fData.
	//
{
	enum { kAction = 44 };

	ObjectState() { fAction = ObjectState::kAction; }

	enum EStateType {
		kFirstRegenReset,			// fData => NULL
		kMovedReset,				// fData => (const ObjectStateData_Position*)
		kRotatedReset,				// fData => (const ObjectStateData_Position*)
		kParameterChangedReset,		// fData => (const ObjectStateData_ParamChanged*)
		kObjectChangedReset,		// fData => (const ObjectStateData_ObjectChanged*)
		kLayerChangedReset,			// fData => (const ObjectStateData_LayerChanged*)
		kExitFromEditGroup,			// fData => (const ObjectStateData_ExitFromEditGroup*)
		kNameChanged,				// fData => (const ObjectStateData_ObjectNameChanged*)
		kObjectUndoRestore,			// fData => NULL
		kObjectUndoRemove,			// fData => NULL
		kPlanarRefChanged,			// fData => (const ObjectStateData_ObjectPlanarRefChanged*)
		kBeforeExportReset,			// fData => NULL
		kObjectUndoModify,			// fData => NULL

		// Vectorworks 2012
		kObjectCreated,				// fData => NULL
		kObjectDeleteBefore,		// fData => NULL
		kObjectUngroupBefore,		// fData => NULL

		// Vectorworks 2014
		kObjectExternalReset,		// fData => NULL

		// Vectorworks 2016
		kObjectConnectionsRemapped,	// fData => NULL

		// Vectorworks 2017
		kObjectReshaped,			// fData => NULL
		kObjectLockStatusChanged,	// fData => NULL
		kObjectPathReversed,		// fData => NULL
		kObjectIsGeneratedBy,		// fData => (const ObjectStateData_ObjectIsGeneratedBy*)
	};
};

All these events should register in py except for the undo related events.  One thing you might try is seeing if the reshape event triggers for the end point (if this doesn't, I don't know what will).  If I'm counting correctly, that's 18.

 

HTH,
Josh

  • Like 1

Share this post


Link to post

Thanks Josh for the pointer to those header files; this listing is super helpful!

 

There are certain things I need to do when my object is reshaped but not necessarily when certain other events are triggered, hence my interest in detecting the reshape event unambiguously.  In practice, it has been working fine for me so far to just notice that some reset event occurred, and then see if the length has indeed changed, but it turns out, yes, 18 is the state value that corresponds to this action.  At risk of dropping compatibility for earlier VW versions, I guess.

 

My interest in the SDK's ability to notice drag events is really about added control points, and my wish to possibly keep redrawing part of the object as they are dragged for clearer visual feedback, rather than just when the move is done.  However, it sounds like that is an advanced topic to return to at some later date.

 

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

 

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.

×