User:CBM-c-/Plug-in with widget basic example: Difference between revisions

From Vectorworks Developer
Jump to navigation Jump to search
(Transfer plug-in example from the Techboard for easier correction and maintenance)
 
No edit summary
Line 3: Line 3:
</div>
</div>


The present article was originally published on the Techboard (2021.03.27): see the thread ''81852-python-plug-in-with-widgets-basic-example''
The present article was originally published on the Techboard (2021.03.27): see the thread ''python-plug-in-with-widgets-basic-example''.
 
I transfer it to the present wiki for fixing some mistakes and easier later maintenance. --[[User:CBM-c-|_c_]] ([[User talk:CBM-c-|talk]]) 05:35, 1 January 2022 (EST)
I transfer it in the present wiki for fixing some mistake and later easier maintenance.





Revision as of 10:35, 1 January 2022

The present article was originally published on the Techboard (2021.03.27): see the thread python-plug-in-with-widgets-basic-example. I transfer it to the present wiki for fixing some mistakes and easier later maintenance. --_c_ (talk) 05:35, 1 January 2022 (EST)


Plug-in with widgets, basic example (Python)

There was a question on the German VW forum about plug-ins with dividers and buttons. An ever recurring topic. I am [ever] switching to Python, and I though that it could be a nice exercise for me to try it pythonically.

Please download the test files and expand them into your User's plug-in folder (there is no installer here):

File:Test PioWithWidgetsBasic.zip

The Test PIO _c_ plug-in:

  • uses an external file source (you don't need to script in the Plug-in Editor)
  • is event enabled
  • has a button triggering a script
  • has dividers
  • turns the dividers into expandable group widgets
  • doesn't resolve text alignments, so that will take the active document's settings

I am new to Python and am sure that this can be done more efficiently, just take it as exercise.


Imports

Anything you do in Python from within Vectorworks, it implies importing the file "VS.py", which you can find in the SDK. This makes the odd 3000 Vectorscript routines usable.

Important, if you work on Python coding in external files - vs. inside the plug-in editor - you will need to import these files into the plug-in somehow and the plug-in (as .vst, .vso. or .vsm object) needs to reload the code every time, so you must turn off caching during development, or the code won't execute properly. In Vectorscript Pascal the imports are called includes.


Events

The plug-in needs to be event enabled: you do this in the Options tab of the Plug-in editor:


There are bucketloads of events, you'll find them in the SDK, MiniCadHookIntf.h and it does take a lot of time to be comfortable with their usage. Some of them I have really no idea what they do, and believe me, I did spend an inordinate amount of time on them. The two major files you might want to study are these below, but there is far more (the SDK version is here just irrelevant):


Below I break down the events employed in this test plug-in. Important: The code runs a number of times (and double as much if the developer mode is on), VS:GetCustomObjectInfo is compulsory for fetching the needed basic variables and make thus possible to run the code over the right objects.

(ok, gPio_N, gPio_H, gPioRec_H, gWall_H) = vs.GetCustomObjectInfo()


Every time the code runs, you must fetch the type of event and run the right code during the right event. VS:vsoGetEventInfo is compulsory for fetching event info:

(theEvent, theButton) = vs.vsoGetEventInfo()
# whereby theButton is a generic message, not necessarily a button

(theEvent, aMessage) = vs.vsoGetEventInfo()


Events: Init properties

During the init event (5) you set up the Object Info Palette behaviour and other things:

if theEvent == kObjOnInitXProperties: # event 5


If you want to use buttons and/or Custom pull-down menus you need to turn on UIoverride:

ok = vs.SetObjPropVS( kObjXPropHasUIOverride, True )


IF, and only IF, you also want to use custom pull-down menus loading custom values, you will also need to enable custom widget visibilities. If you do this, you cannot use VS:SetParameterVisibility or VS:EnableParameter, which use parameter names, you can only use VS:vsoWidgetSetVisible and VS:vsoWidgetSetEnable. These need parameter indexes, so you must keep track of the parameter indexes and store them somehow as file. This does add complexity (I have a sub auto-filling a list as text into the right place):

  • not used in the test example:
vs.SetObjPropVS(kObjXHasCustWidgetVisibilities, True); 
  • only needed for custom pull-down menus with special lists of values
  • after enabling this prop you need to set visibilities during event kObjOnWidgetPrep

To have the lovely widget groups in expanded/collapsed state you must

  • enable them with ok = vs.SetObjPropCharVS( kWidgetGroupMode, vs.Chr(kWidgetGroupAutomatic), True )
  • add widget groups
  • add parameters as static text
  • turn the static text into separators


Mind that the routine VS:vsoInsertWidget takes a string and places it in the Object Info Palette. You can use the localised parameter name. Since the function

(boo, locParmName) = vs.GetLocalizedPluginParameter(pioRecName, univParmName) 


returns two vars, it cannot be used directly, so I created one simple sub named 'O_GetLocParmName' which returns only a string:

ok = vs.vsoInsertWidget( cP___div0 -1, kWidgetSeparator, cP___div0, 'parameter name', empty);


We use the localized parameter name. O_GetLocParmName is a subroutine that fetches only the string, dropping the boolean, so I can use it directly in VS:vsoInsertWidget

ok = vs.vsoInsertWidget( cP___div0 -1, kWidgetSeparator, cP___div0, O_GetLocParmName(gPio_N, '__div0'), empty);
def O_GetLocParmName(pioRecName, univParmName):
	(boo, locParmName) = vs.GetLocalizedPluginParameter(pioRecName, univParmName)
	return locParmName


We add indenting levels in a loop using VS:vsoWidgetSetIndLv. This turns the widgets into expandable widgets.

Important
Don't omit to set the 0-levels, or things are going to mess up:
titles = [cP___div0, cP___div1, cP___div2]
for i in range(vs.NumFields(gPioRec_H) +1):
	if (i in titles): 
		vs.vsoWidgetSetIndLvl(i, 0)
	else:
		vs.vsoWidgetSetIndLvl(i, 1)


Warning: you will need to close and re-open your document to see widget groups display properly EVERY time you change something in the parameter index list (add, delete parameters)


Text Alignment

You can set a plug-in object to respond to font and text size using

vs.SetObjectVariableBoolean(gPio_H, 800, True) 

but all other text properties, such as horizontal and vertical alignment, etc. must be coded and driven by parameters.