David Bengali Posted June 21, 2017 Share Posted June 21, 2017 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") Quote Link to comment
Pat Stanford Posted June 21, 2017 Share Posted June 21, 2017 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 1 Quote Link to comment
David Bengali Posted June 21, 2017 Author Share Posted June 21, 2017 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. Quote Link to comment
JBenghiat Posted June 21, 2017 Share Posted June 21, 2017 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 Quote Link to comment
David Bengali Posted June 21, 2017 Author Share Posted June 21, 2017 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. Quote Link to comment
David Bengali Posted June 21, 2017 Author Share Posted June 21, 2017 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. Quote Link to comment
JBenghiat Posted June 21, 2017 Share Posted June 21, 2017 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 Quote Link to comment
David Bengali Posted June 23, 2017 Author Share Posted June 23, 2017 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. Quote Link to comment
Hippocode Posted June 23, 2017 Share Posted June 23, 2017 Well in the SDK I think you could catch it with drag events as well, which would even include first and completion click. Quote Link to comment
David Bengali Posted June 23, 2017 Author Share Posted June 23, 2017 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? Quote Link to comment
Hippocode Posted June 23, 2017 Share Posted June 23, 2017 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. Quote Link to comment
JBenghiat Posted June 23, 2017 Share Posted June 23, 2017 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 1 Quote Link to comment
David Bengali Posted June 29, 2017 Author Share Posted June 29, 2017 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. Quote Link to comment
Recommended Posts
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.