Selection Operation - Automatic implementation

From The Foundry MODO SDK wiki
Revision as of 12:43, 31 August 2016 by Mattcox (Talk | contribs) (Created page with "__TOC__ Selection Operations integrate into the procedural system by writing an ILxSelectionOperation server to a channel, which is evaluated by the procedural modelling syst...")

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Selection Operations integrate into the procedural system by writing an ILxSelectionOperation server to a channel, which is evaluated by the procedural modelling system. This ILxSelectionOperation has functions for testing individual elements on the mesh to determine whether they should be selected or not.

For the majority of Selection Operations, the item and modifier code is boiler plate and completely generic. Therefore, we provide a simplified path that automatically generates an Selection Operation item from an ILxSelectionOperation server.

Applying the following server tag to an ILxSelectionOperation interface, will automatically create a selection operation item and a modifier. The modifier will write the ILxSelectionOperation server into a channel, so that it can be evaluated as part of the procedural system. The ILxSelectionOperation should also implement an Attributes interface, that will allow attributes to converted into channels on the newly created item. The value of this tag doesn't matter, as the presence of the server tag alone is enough to automatically create a selection operation item. The name of the selection operation item, will be the name of selection operation server, with ".item" appended at the end.

#define LXsSELOP_PMODEL                "pmodel.selectionop"

Sample Code

The following sample code implements a very basic selection operation that selects all elements within a particular index range. The start and end attributes are converted into channels that can be manipulated or animated by the user.

C++
class SelectionOperation : public CLxImpl_SelectionOperation, public CLxDynamicAttributes
{
	public:
		SelectionOperation ()
		{
			dyna_Add ("start", LXsTYPE_INTEGER);
			attr_SetInt (0, 0);
 
			dyna_Add ("end", LXsTYPE_INTEGER);
			attr_SetInt (1, 100);
		}
 
			LxResult
		selop_SetMesh (
			ILxUnknownID		 mesh)		LXx_OVERRIDE
		{
			/*
			 *	Cache the mesh COM object. This is need to spawn the accessors
			 *	in the Test functions.
			 */
 
			if (_mesh.set (mesh))
				return LXe_OK;
 
			return LXe_FAILED;
		}
 
			bool
		IsIndexInRange (
			unsigned int		 index)
		{
			int			 start = 0, end = 100;
 
			/*
			 *	Get the start and end attributes and ensure that start < end.
			 */
 
			start = dyna_Int (0, 0);
			end = dyna_Int (0, 100);
 
			if (start > end)
				std::swap (start, end);
 
			/*
			 *	Test if the provided index is within range.
			 */
 
			return (index <= end && index >= start);
		}
 
			LxResult
		selop_TestPoint (
			LXtPointID		 point)		LXx_OVERRIDE
		{
			CLxUser_Point		 accessor;
			unsigned int		 index = 0;
 
			/*
			 *	Select the provided point in the accessor and test it's index
			 *	against the range.
			 */
 
			if (_mesh.test () && accessor.fromMesh (_mesh))
			{
				if (LXx_OK (accessor.Select (point)))
				{
					accessor.Index (&index);
					if (IsIndexInRange (index))
						return LXe_TRUE;
				}
			}
 
			return LXe_FALSE;
		}
 
			LxResult
		selop_TestEdge (
			LXtEdgeID		 edge)		LXx_OVERRIDE
		{
			CLxUser_Edge		 accessor;
			unsigned int		 index = 0;
 
			/*
			 *	Select the provided point in the accessor and test it's index
			 *	against the range.
			 */
 
			if (_mesh.test () && accessor.fromMesh (_mesh))
			{
				if (LXx_OK (accessor.Select (edge)))
				{
					accessor.Index (&index);
					if (IsIndexInRange (index))
						return LXe_TRUE;
				}
			}
 
			return LXe_FALSE;
		}
 
			LxResult
		selop_TestPolygon (
			LXtPolygonID		 polygon)	LXx_OVERRIDE
		{
			CLxUser_Polygon		 accessor;
			unsigned int		 index = 0;
 
			/*
			 *	Select the provided point in the accessor and test it's index
			 *	against the range.
			 */
 
			if (_mesh.test () && accessor.fromMesh (_mesh))
			{
				if (LXx_OK (accessor.Select (polygon)))
				{
					accessor.Index (&index);
					if (IsIndexInRange (index))
						return LXe_TRUE;
				}
			}
 
			return LXe_FALSE;
		}
 
		CLxUser_Mesh		 _mesh;
 
		static LXtTagInfoDesc	 descInfo[];
};
 
LXtTagInfoDesc SelectionOperation::descInfo[] =
{
	{ LXsSELOP_PMODEL,		"." },
	{ 0 }
};
 
void initialize ()
{
	CLxGenericPolymorph	*srv = NULL;
 
	srv = new CLxPolymorph						<SelectionOperation>;
	srv->AddInterface		(new CLxIfc_SelectionOperation	<SelectionOperation>);
	srv->AddInterface		(new CLxIfc_Attributes		<SelectionOperation>);
	srv->AddInterface		(new CLxIfc_StaticDesc		<SelectionOperation>);
 
	lx::AddServer ("select.inRange", srv);
}