Handling Requests for Interfaces

As mentioned in the Interface Querying topic, incorrect implementation of InterfaceServer::GetInterface() might lead to incorrect display of the plug-in in the Nitrous viewport.

 BaseInterface*
InterfaceServer::GetInterface(Interface_ID iid);

Often a plug-in class inherits from multiple base classes, some of which are mixin interfaces while others are base classes representing the plug-ins main type (class SimpleObject, class Modifier, etc). The plug-in's implementation of InterfaceServer::GetInterface() needs to allow for correct handling of requests for:

A couple of examples of incorrect but typical implementations of InterfaceServer::GetInterface() are provided below:

// A mixin interface
#define IID_SOME_MIXIN_INTERFACE Interface_ID (0x627c2f9c, 0x52671832)
class SomeMixinInterface : public FPMixinInterface  
{ 
	// Does not implement GetInterface(Interface_ID iid)	
	// Details elided for brevity 
}

// A plugin class that derives from a non-mixin class and a mixin interface class
class MyPlugin : public SimpleObject, public SomeMixinInterface  
{
	// details elided for brevity 
}

// Incorrect GetInterface() implementation - does not handle requests for base mixin interfaces
BaseInterface* MyPlugin::GetInterface(Interface_ID iid)
{
	if (iid == IID_SOME_MIXIN_INTERFACE) return (SomeMixinInterface*)this;
	return SimpleObject::GetInterface(iid);
}

// Incorrect GetInterface() implementation - does not handle requests for 
// base mixin interfaces supported by the main parent class SimpleObject
BaseInterface* MyPlugin::GetInterface(Interface_ID iid)
{
	if (iid == IID_SOME_MIXIN_INTERFACE) return (SomeMixinInterface*)this;
	return FPMixinInterface::GetInterface(iid);
}

A correct implementation of the plug-in's implementations of InterfaceServer::GetInterface() would look like this:

// Correct GetInterface() implementation 
BaseInterface* MyPlugin::GetInterface(Interface_ID iid)
{
	// Handle request for specific mixin interface
	if (iid == IID_SOME_MIXIN_INTERFACE) return (SomeMixinInterface*)this;
	else 
	{
		// Handle requests for base mixin interfaces
		BaseInterface* baseIfc = FPMixinInterface::GetInterface(iid);
		if (baseIfc) return intf;
	}
	// Handle requests for mixin interfaces supported by main base class
	return SimpleObject::GetInterface(iid);
}

How to Test for Correct Handling of Interface Requests

A simple test can be written in MAXScript to ensure that the plug-in overriding of InterfaceServer::GetInterface() is correct. The test works by querying a plug-in instance for a specific interface. The following MAXScript code shows the test for ensuring that requests for interface IObjectDislay identified by interface id IOBJECT_DISPLAY_INTERFACE_ID are serviced correctly by the Box plug-in:

-- create an instance of a box
boxInstance = Box -- "Box" is the name of the class of the box plug-in object
-- define the value of the interface id to query; see maxsdk\include\graphics\IObjectDisplay.h
IOBJECT_DISPLAY_INTERFACE_ID = #(0x39820fa0,0x6311340d) 
-- query the box instance for IOBJECT_DISPLAY_INTERFACE_ID
res = getInterface boxInstance IOBJECT_DISPLAY_INTERFACE_ID
-- Use the MAXScript assertion mechanism to signal a test failure
assert_true (res) message: ("Box failed to handle requests for IOBJECT_DISPLAY_INTERFACE_ID")
-- Print all assertion messages
for msg in AssertReporter.GetMessages() do print msg

The test uses an undocumented feature of the getInterface MAXScript method which interprets an array of two integers as an Interface_ID value and call the plug-in's override of InterfaceServer::GetInterface(Interface_ID) with it. It returns true if the plug-in returns a valid (non-NULL) pointer, false otherwise.