JBenghiat 333 Posted May 20, 2020 The button ID is a unique identifier, like with dialog items. It can be anything, but can’t overlap with the automatically generated IDs of your parameters, which start at 1. To make things easy, I just start my first custom widget at 9000, so I know it’s out of the way. Appending a widget always puts it at the end of the list. Inserting a widget will place it in with the other widgets, but that is a longer conversation when you are ready. The last value was reserved for future use but never implemented. I defined a variable called ThisDoesNothing that I use so it’s clear. I suspect your issue is setting the button ID to 1, which overlaps with your parameter widgets, but in case I need to state the obvious, also make sure you select Event Enabled in the last pane of options in the Plug-in Manager. Quote Share this post Link to post
michaelk 467 Posted May 20, 2020 Thanks, Josh. A higher number for the button id fixed it. Quote Share this post Link to post
JBenghiat 333 Posted May 20, 2020 Here's my python templates. I have a pio class, which has all of the constants stored as well as class pio: def __init__(self): self.PIName = '' self.PIHan = 0 self.PIRecHan = 0 self.PIWallHan = 0 self.x, self.y, self.z, self.rot = 0.0, 0.0, 0.0, 0.0 boo, self.PIName, self.PIHan, self.PIRecHan, self.PIWallHan = vs.GetCustomObjectInfo() if self.PIHan != 0: self.rot = vs.GetSymRot(self.PIHan) self.x, self.y, self.z = vs.GetSymLoc3D(self.PIHan) And here is the overall base code import vs #vs.SetPref(412, True) #Turns off include caching # import pydevd # pydevd.settrace(suspend=False) from jbld.piolib import pio PIO = pio() #=============================================================================== # Initialize and event handler #=============================================================================== def execute(): global PIO theEvent, eventMessage = None, None theEvent, eventMessage = vs.vsoGetEventInfo(theEvent, eventMessage) if theEvent == PIO.kObjOnInitXProperties: InitPIO() elif theEvent == PIO.kObjOnWidgetPrep: WidgetPrep() elif theEvent == PIO.kObjOnAddState: GetStateChange(eventMessage) elif theEvent == PIO.kObjOnObjectUIButtonHit: ButtonHandler(eventMessage) elif theEvent == PIO.kObjOnSpecialEditID: SpecialEdit() elif theEvent == PIO.kParametricPreference: SpecialPreferences() elif theEvent == PIO.kResetEventID: ResetEventHandler() #=============================================================================== # this funciton is executed once and # it defines the shape pane of the parametric object # # The shape pane is composed of widgets # it is a widget connected to a parameter or it is a button widget #=============================================================================== def InitPIO(): # Enable custom shape pane ok = vs.SetObjPropVS(PIO.kObjXPropHasUIOverride, True) ok = vs.SetObjPropVS(PIO.kObjXHasCustomWidgetVisibilities, True) vs.SetPrefInt(PIO.kParametricEnableStateEventing, 1 ); ok = vs.SetObjPropVS(PIO.kObjXPropAcceptStates, True); ok = vs.vsoInsertAllParams() # Insert buttons thisDoesNothing = 0 ok = vs.vsoAppendWidget(PIO.kWidgetButton, PIO.buttonID_1, 'Button_Name', thisDoesNothing) #============================================================================== # this function updates the visibility or enable/disable state of the widgets # note: keep this one fast, it is called often #============================================================================== def WidgetPrep(): # if vs.vsoPrmName2WidgetID('', 'Param_Name', widgID): # vs.vsoWidgetSetVisible( widgID, True ) # if vs.vsoPrmName2WidgetID('', 'Param_Name', widgID): # vs.vsoWidgetSetEnable( widgID, True ) # this is very important! this is how the system knows we've handled this vs.vsoSetEventResult(PIO.kObjectEventHandled) #============================================================================== # Stores regen events to memory #============================================================================== def GetStateChange(eventMessage): eventMessage = vs.vsoStateAddCurrent(PIO.PIHan, eventMessage) #============================================================================== # this function handles button clicks from the shape pane #============================================================================== def ButtonHandler(theButton): # def ResetAll(h): # vs.ResetObject(h) if theButton == PIO.buttonID_1: # vs.ForEachObjectInList( ResetAll(), 2, 0, PIO.PIHan ) vs.AlrtDialog("You pressed a button!") #=============================================================================== # Handle special edit behavior #=============================================================================== def SpecialEdit(): pass #=============================================================================== # Handle custom preferences dialog #=============================================================================== def SpecialPreferences(): if PIO.PIHan == 0: PIO.PIHan = vs.GetObject(PIO.PIName) #============================================================================== # Main reset event #============================================================================== def ResetEventHandler(): # Parameter => vs.PParameterName vs.Locus(0, 0) Quote Share this post Link to post
michaelk 467 Posted May 20, 2020 9 hours ago, JBenghiat said: Appending a widget always puts it at the end of the list. Inserting a widget will place it in with the other widgets, but that is a longer conversation when you are ready. Starting the longer conversation: From experimenting with vsoAddWidget(#,kWidgetType,locName); I'm assuming that the number in the first argument is the number of the parameter in the definition. But the values aren't appearing in the OIP. Is there a different SetObjPropVS that is needed when using only vsoAddWidget? Widget type makes sense. If I use '' as the locName it inserts nothing and a colon. I thought from the function reference that if locName is '' then it uses the alternate name of the parameter? It seems like some changes in the OIP don't take effect until I open a new document. Is there a way to "reset" the OIP in the current document? Procedure Test; {Badly Scripted by Michael Klaers.} CONST kCR = CHR(13); kObjOnInitXProperties = 5; kObjOnWidgetPrep = 41; kObjOnAddState = 44; kObjOnObjectUIButtonHit = 35; kResetEventID = 3; kObjXPropHasUIOverride = 8; kParametricEnableStateEventing = 590; kObjXPropAcceptStates = 18; ButtonID_1 = 9001; kFieldLongInt = 1; kFieldBoolean = 2; kFieldReal = 3; kFieldText = 4; kFieldCalculation = 5; kFieldHandle = 6; kFieldCoordDisp = 7; {dimension} kFieldPopUp = 8; kFieldRadio = 9; kFieldCoordLocX = 10; kFieldCoordLocY = 11; kWidgetButton = 12; kWidgetStaticText = 13; kWidgetDisclosure = 14; {not implemented?} VAR PIHan, PIRecHan, PIWallHan : HANDLE; resultStatus, result : BOOLEAN; PIName : STRING; eventMessage,theEvent : LONGINT; {---------------------------------------------------------------------} PROCEDURE InitPIO; BEGIN {This tells VW to let the object decide what goes onto the Object Info palette.} result:= SetObjPropVS(kObjXPropHasUIOverride, TRUE); result := SetObjPropVS(12, TRUE); {kObjXHasCustomWidgetVisibilities} SetPrefInt(kParametricEnableStateEventing, 1 ); result := SetObjPropVS(kObjXPropAcceptStates, TRUE); {Now we manually add the "normal" parameters...} {One way is to use this single call to add all of the existing parameters.} {result:= vsoInsertAllParams;} result := vsoAddWidget(1,kFieldCoordDisp,'Blah Width'); result := vsoAddWidget(2,kFieldCoordDisp,'Blah Height'); result := vsoAddWidget(3,kFieldCoordDisp,'Blah Extrusion'); result := vsoAddWidget(1,kFieldText,''); {Finally, we add the button.} result:= vsoAppendWidget(kWidgetButton, ButtonID_1, 'Do Something', 1); END; {---------------------------------------------------------------------} PROCEDURE WidgetPrep; BEGIN vsoSetEventResult( -8 {kObjectEventHandled} ); END; {---------------------------------------------------------------------} PROCEDURE GetStateChange; BEGIN eventMessage := vsoStateAddCurrent(PIHan, eventMessage); END; {---------------------------------------------------------------------} PROCEDURE ButtonHandler; BEGIN CASE eventMessage OF ButtonID_1: BEGIN Message('Stop Pressing That Button'); Sysbeep; Wait(3); ClrMessage; END; END; {CASE} END; {---------------------------------------------------------------------} PROCEDURE Main; BEGIN BeginXtrd(0,pExtrusion); RectangleN(0, 0, 1, 0, pWidth, pHeight); EndXtrd; {Message( 'pWidth: ',pWidth,kCR, 'pHeight: ',pHeight,kCR, 'pExtrusion: ',pExtrusion ); } END; {---------------------------------------------------------------------} BEGIN resultStatus := GetCustomObjectInfo(PIName, PIHan, PIRecHan, PIWallHan); vsoGetEventInfo(theEvent, eventMessage); CASE theEvent OF {User has single-clicked the object's icon.} kObjOnInitXProperties: InitPIO; kObjOnWidgetPrep: WidgetPrep; kObjOnAddState: GetStateChange; {User has clicked a button in the Object Info palette.} kObjOnObjectUIButtonHit: ButtonHandler; {Object reset has been called.} kResetEventID: Main; END; {Event case} END; RUN(Test); Quote Share this post Link to post
MullinRJ 203 Posted May 20, 2020 Michael, Use vsoAppendWidget() { adds widget to the end of the list } or vsoInsertWidget() { adds widget before "paramID" } Raymond Quote Share this post Link to post
michaelk 467 Posted May 21, 2020 So funny you should say that. I've been wondering what the difference is between vsoInsertWidget and vsoAddWidget. So I tried it out. There must be a setting somewhere I don't quite get yet. Procedure Test; {Badly Scripted by Michael Klaers.} CONST kCR = CHR(13); kObjOnInitXProperties = 5; kObjOnWidgetPrep = 41; kObjOnAddState = 44; kObjOnObjectUIButtonHit = 35; kResetEventID = 3; kObjXPropHasUIOverride = 8; kParametricEnableStateEventing = 590; kObjXPropAcceptStates = 18; ButtonID_1 = 9001; kWidgetLongInt = 1; kWidgetBoolean = 2; kWidgetReal = 3; kWidgetText = 4; kWidgetCalculation = 5; kWidgetHandle = 6; kWidgetCoordDisp = 7; kWidgetPopUp = 8; kWidgetRadio = 9; kWidgetCoordLocX = 10; kWidgetCoordLocY = 11; kWidgetButton = 12; kWidgetStaticText = 13; kWidgetStaticTextParam = 14; kWidgetDisclosure = 14; {not implemented?} kWidgetDimStdPopUp = 16; kWidgetPrecisionPopUp = 17; kWidgetClassesPopup = 18; kWidgetLayersPopup = 19; kWidgetAngleDisp = 20; kWidgetAreaDisp = 21; kWidgetVolumeDisp = 22; kWidgetSeparator = 100; kWidgetSubSelection = 101; kWidgetBoundPopup = 102; kWidgetBoundOffset = 103; kWidgetSliderWithEdit = 104; kWidgetButtonResourcePopup= 105; kWidgetBoxPosition = 106; kWidgetResourcePopup = 107; kWidgetSearchablePopup = 108; kDeadData = 0; VAR PIHan, PIRecHan, PIWallHan : HANDLE; resultStatus, result : BOOLEAN; PIName : STRING; eventMessage,theEvent : LONGINT; {---------------------------------------------------------------------} PROCEDURE InitPIO; BEGIN {This tells VW to let the object decide what goes onto the Object Info palette.} result:= SetObjPropVS(kObjXPropHasUIOverride, TRUE); result := SetObjPropVS(12, TRUE); {kObjXHasCustomWidgetVisibilities} SetPrefInt(kParametricEnableStateEventing, 1 ); result := SetObjPropVS(kObjXPropAcceptStates, TRUE); {Now we manually add the "normal" parameters...} {One way is to use this single call to add all of the existing parameters.} {result:= vsoInsertAllParams;} result := vsoInsertWidget(1,kWidgetCoordDisp,1,'',kDeadData); result := vsoInsertWidget(2,kWidgetCoordDisp,2,'',kDeadData); result := vsoInsertWidget(3,kWidgetCoordDisp,3,'',kDeadData); vsoWidgetSetIndLvl(3,1); result := vsoInsertWidget(4,kWidgetSeparator,0,'',kDeadData); result := vsoInsertWidget(5,kWidgetText,4,'',kDeadData); {Finally, we add the button.} result:= vsoAppendWidget(kWidgetButton, ButtonID_1, 'Do Something', 1); END; {---------------------------------------------------------------------} PROCEDURE WidgetPrep; BEGIN vsoSetEventResult( -8 {kObjectEventHandled} ); END; {---------------------------------------------------------------------} PROCEDURE GetStateChange; BEGIN eventMessage := vsoStateAddCurrent(PIHan, eventMessage); END; {---------------------------------------------------------------------} PROCEDURE ButtonHandler; BEGIN CASE eventMessage OF ButtonID_1: BEGIN Message('Stop Pressing That Button'); Sysbeep; Wait(3); ClrMessage; END; END; {CASE} END; {---------------------------------------------------------------------} PROCEDURE Main; BEGIN BeginXtrd(0,pExtrusion); RectangleN(0, 0, 1, 0, pWidth, pHeight); EndXtrd; {Message( 'pWidth: ',pWidth,kCR, 'pHeight: ',pHeight,kCR, 'pExtrusion: ',pExtrusion ); } END; {---------------------------------------------------------------------} BEGIN resultStatus := GetCustomObjectInfo(PIName, PIHan, PIRecHan, PIWallHan); vsoGetEventInfo(theEvent, eventMessage); CASE theEvent OF {User has single-clicked the object's icon.} kObjOnInitXProperties: InitPIO; kObjOnWidgetPrep: WidgetPrep; kObjOnAddState: GetStateChange; {User has clicked a button in the Object Info palette.} kObjOnObjectUIButtonHit: ButtonHandler; {Object reset has been called.} kResetEventID: Main; END; {Event case} END; RUN(Test); Quote Share this post Link to post
JBenghiat 333 Posted May 21, 2020 LocName is the "localized name." It's meant for adapting to language translations, but you can think of it as the display name. This must have a value here. Here's a few excerpts from a dialog with Sam Quote Is the “paramID” the param before the button position, after the button positions, the desired button position, or something else? This is the ID where you want the widget to insert before. I recommend using vsoPrmName2WidgetID to get the location of the item ahead of where you want it and add 1: result:=vsoPrmName2WidgetID('', 'LXMarkers', widgID); result:= vsoInsertWidget(widgID+1, kWidgetButton, buttonID_6, GetPluginString( kStr_ButtonMarker ), thisDoesNothing); I do find that inserting widgets can change the widget ID’s that automatically assign to parameters. For that reason, I tend to insert widgets from the bottom up, so that I’m never affecting anything upstream in the index. It’s possible that vsoPrmName2WidgetID() makes this moot, and honestly I haven’t tested in a while, but I definitely found that working from the bottom up prevented a number of headaches. (And this may very well be due to my preference to identify the widget ID after which I want to insert my widget) Quote Does this have any effect on the parameter indexes that I reference in the Reset Event. No — if with vsoStateGetParamChng( PIHan, widgID, prmIndex, oldValue ) you look at prmIndex, as that refers to the parameters, not the widgets. You can think of the parameters as the field indices for the PIO’s data record. The widget ID’s are each item in the OIP, identified by an integer UID. If you act on widgID, then you would need to take those into account. Quote Share this post Link to post