The Function Publishing System, introduced with 3ds Max version 4, is a system that allows plug-ins to publish their major functions and operations in such a way that code outside the plug-in can discover and make inquiries about these functions and is thus able to call them though a common calling mechanism. The whole system is very similar to Window’s COM and OLE Automation systems and share many similar concepts in the architecture. However, the Function Publishing System is not based on COM and OLE but instead is a custom architecture more suited and optimized for 3ds Max. The Function Publishing API serves a number of purposes, which allow third-party developers to open up important portions of their plug-ins for use by external sources, allowing for users to extend and control these directly.
Some of the purposes of the Function Publishing System are:
Modularizing plugin code into various "engines" that are able to supply services to other parts of 3ds Max and other third party plug-ins and can be delivered to the user through various different user-interfaces.
Providing automatic scriptability by exposing the published functions directly to MAXScript.
Providing alternate means of invoking plugin functions in the UI, such as via the manipulator system, scripted menus, quad menus, keyboard shortcuts, macroScripts, toolbar buttons, etc.
Allowing the MAXScript Macro Recorder to automatically generate calls to the published functions, in the event that these are invoked by the expanded ParamMap2 system or other UI mechanisms such as keyboard shortcuts or menu items.
Interfaces
Functions are published in one or more Interfaces by a plug-in. Action functions must be published in their own set of interfaces. Each interface is represented by an instance of a class derived from the base class FPInterface. An external system can find out about the interfaces published by calling various query methods on ClassDesc that access these interface definition objects. As well as these inquiry or 'reflection' methods, an FPInterface also has the calling methods for actually invoking a particular function in the interface, so that if something has hold of one of your interfaces, it can call any of its published functions.
Action Interfaces
A special kind of interface is the Action Interface. These interfaces only contain UI Action Functions that provide a programmatic way of "pressing" buttons and keys in the UI for a plug-in.
Direct dot-notation properties
MAXScript exposes properties defined in this way as direct dot-notation properties on the interface. So, were before the Get/SetRadius in the example cylinder mixin would have been accessed as functions
EXAMPLE
r = $cyl01.cylMixin.getRadius() $cyl01.cylMixin.setRadius 23
you now can use:
r = $cyl01.cylMixin.radius $cyl01.cylMixin.radius = 23
This is true for all the types of Function Published Interfaces that exist in MAXScript-static, Mixin and Core. As a further optimization, MAXScript effectively promotes all interface methods and properties to the level of the interface, so if individual methods and properties have unique names within all the interfaces of an object or class, you can omit the interface name.
The above examples could be written as
EXAMPLE
r = $cyl01.getRadius() $cyl01.setRadius 23
and
r = $cyl01.radius $cyl01.radius = 23
If there is a naming conflict, you can always include the interface name level to resolve this.
MAXScript automatically provides access to all functions published by a plug-in via the Function Publishing system. Each plug-in class appears in MAXScript as a MAX class object, which can be used to construct instances of the plug-in, do class tests, etc. If a plug-in publishes interfaces, they are visible in MAXScript as properties on this class object. The internal name for the interface is used as the property name. All the functions in the interface are accessible as named properties on the interface. So, if the above example interfaces were published by EditMesh, the following script fragments would work
EXAMPLE
EditMesh.faceOps.extrude $foo.mesh #{1,2,3} 10
The above script calls the Extrude function in the FaceOps interface on $foo
's mesh, faces 1, 2 and 3, amount 10 units.
EditMesh.actions
Retrieves and displays the action functions. Each interface is stored as a struct definition in the class object.
EditMesh.actions.create()
Starts (or stops) the create mode. This would have the side-effect of highlighting/unhighlighting the Create button in the EditMesh rollups. Calls to Action functions in MAXScript return true if the function returns FPS_OK and false otherwise.
if EditMesh.actions.create.isChecked() then ...
The predicate functions for an Action Function are available as properties on the action function object itself, as shown. You can determine if a predicate is supplied by asking:
if EditMesh.actions.create.isChecked != undefined
Two Ways of Accessing the Interface
There are two ways to access the interface - as a standalone interface and as an interface on a particular object. If you access the interface directly, you need to pass to it the object to work on.
EXAMPLE
m = Bitmaptexture fileName:"L:\\mypath\\scenes\\2500hicon.JPG" bitmapTex.viewImage m -- direct interface access, need to pass object m.viewImage() -- accessing interface on object, object internally passed as arg 1.
Associated Method:
getCoreInterfaces()
Returns an array of core interface values.
EXAMPLE
The following will list all of the core interfaces:
core_interfaces = getcoreinterfaces() for i in core_interfaces do (showinterface i; format"\n")