SDK - PolyObject modify verts not undoable


#1

Hello,

I have written a function in the Max SDK that takes a delta offset and applies it to all verts in the given editable poly.
It works as expected, however the action is not undoable, which is confusing as if I use a function that manipulates a TriMesh rather than a MNMesh it is undoable.
I cannot use the TriMesh function as it causes any custom attributes on my editable poly object to be lost as it is converting the object to an Editable Mesh.

I am not sure what I could be missing, other than TriMesh has undo functionality included and MNMesh does not.

Here is the function that modifies the MNMesh:

PolyObject* GetPolyObjectFromNode(INode* inNode, TimeValue inTime, bool& deleteIt)
{
	Object* object = inNode->GetObjectRef();
	if (object->CanConvertToType(Class_ID(POLYOBJ_CLASS_ID, 0)))
	{
		PolyObject* polyObject = (PolyObject*)object->ConvertToType(inTime, Class_ID(POLYOBJ_CLASS_ID, 0));
		// Note that the polyObject should only be deleted
		// if the pointer to it is not equal to the object

		// pointer that called ConvertToType()
		if (object != polyObject) deleteIt = true;
		return polyObject;
	}
	else
	{
		return NULL;
	}
}

static bool applyOffsetToVertices(INode* inNode, Point3 inOffset)
{
	static bool success = false;
	bool deleteIt = false;
	bool polyDeleteIt = false;
	Interface* coreInterface = GetCOREInterface();
	PolyObject* polyObject = GetPolyObjectFromNode(inNode, coreInterface->GetTime(), deleteIt);
	if (polyObject)
	{
		MNMesh& mesh = polyObject->GetMesh();
		for (int vertIndex = 0; vertIndex < mesh.VNum(); vertIndex++)
		{
			MNVert* vert = mesh.V(vertIndex);
			vert->p += inOffset;
		}
		inNode->SetObjectRef(polyObject);
		polyObject->FreeCaches();
		polyObject->NotifyDependents(FOREVER, OBJ_CHANNELS, REFMSG_CHANGE);
		coreInterface->RedrawViews(coreInterface->GetTime());
		success = true;
	}
	return success;
}

and here is the function that modifies the TriMesh:

TriObject* GetTriObjectFromNode(INode* inNode, TimeValue inTime, bool& deleteIt)
{
	deleteIt = false;
	Object* obj = inNode->EvalWorldState(inTime).obj;
	if (obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0)))
	{
		TriObject* triObject = (TriObject*)obj->ConvertToType(inTime, Class_ID(TRIOBJ_CLASS_ID, 0));
		// Note that the TriObject should only be deleted
		// if the pointer to it is not equal to the object

		// pointer that called ConvertToType()
		if (obj != triObject) deleteIt = true;
		return triObject;
	}
	else
	{
		return NULL;
	}
}
static bool applyOffsetToVertices(INode* inNode, Point3 inOffset)
{
	static bool success = false;
	bool deleteIt = false;
	TriObject* triObject = GetTriObjectFromNode(inNode, GetCOREInterface()->GetTime(), deleteIt);
	if (triObject)
	{
		Mesh& mesh = triObject->GetMesh();
		for (int vertIndex = 0; vertIndex < mesh.getNumVerts(); vertIndex++)
		{
			Point3 position = mesh.getVert(vertIndex);
			mesh.setVert(vertIndex, position + inOffset);
		}
		mesh.InvalidateGeomCache();
		mesh.InvalidateTopologyCache();
		inNode->SetObjectRef(triObject);
		triObject->NotifyDependents(FOREVER, OBJ_CHANNELS, REFMSG_CHANGE);
		Interface* coreInterface = GetCOREInterface();
		coreInterface->RedrawViews(coreInterface->GetTime());
		success = true;
	}
	return success;
}

#2

You’ll have to add your modification to the undo stack manually if it doesn’t do it internally. Look at the docs for “theHold”.


#3

This is what I thought, I just wanted to make sure before I implemented undo logic myself.


#4

use EPoly ApplyDelta… it’s undoable