Here's an untested example for both poly attach and poly detach. Make sure to have a look at the documentation of classes PolyObject and MNMesh. I don't actually know if this keeps maps and UVWs intact. But it should give you a decent starting point.
The polyAttach function takes a node that must reference an poly object and an INodeTab containing nodes that should be attached to the node. All attached nodes are then deleted.
bool polyAttach(INode* targetNode, const INodeTab& sourceNodes)
{
if (!targetNode || sourceNodes.Count() == 0)
return false;
// make sure we have a valid poly object
auto targetObj = targetNode->GetObjectRef();
if (!targetObj || targetObj->SuperClassID() != GEOMOBJECT_CLASS_ID || targetObj->ClassID() != Class_ID(POLYOBJ_CLASS_ID, 0))
return false;
// cast the object to a poly object
auto targetPolyObj = static_cast<PolyObject*>(targetObj);
// get the poly mesh we want the other poly meshes to attach to
auto targetPolyMesh = &targetPolyObj->GetMesh();
// iterate all source nodes
for (auto i = 0; i < sourceNodes.Count(); ++i)
{
auto sourceNode = sourceNodes[i];
if (!sourceNode)
continue;
// get and check if the object can be converted to a poly object
auto sourceObj = sourceNode->EvalWorldState(0).obj;
if (!sourceObj || sourceObj->SuperClassID() != GEOMOBJECT_CLASS_ID || !sourceObj->CanConvertToType(Class_ID(POLYOBJ_CLASS_ID, 0)))
continue;
// convert the object to a poly object
auto sourcePolyObj = static_cast<PolyObject*>(sourceObj->ConvertToType(GetCOREInterface()->GetTime(), Class_ID(POLYOBJ_CLASS_ID, 0)));
if (!sourcePolyObj)
continue;
// get the mesh and attach it to the target mesh
auto sourcePolyMesh = &sourcePolyObj->GetMesh();
*targetPolyMesh += *sourcePolyMesh;
// delete the temporary source poly object (only if ConvertToType() created a new object)
if (sourcePolyObj != sourceObj)
sourcePolyObj->DeleteThis();
// finally delete the node we took the mesh from as we usually don't need it anymore
sourceNode->DeleteMe();
}
return true;
}
The polyDetach function takes a node which must reference a poly object. It then detaches the currently selected element to a new node.
bool polyDetach(INode* node)
{
if (!node)
return false;
// make sure we have a valid (poly) object
auto obj = node->GetObjectRef();
if (!obj || obj->SuperClassID() != GEOMOBJECT_CLASS_ID || obj->ClassID() != Class_ID(POLYOBJ_CLASS_ID, 0))
return false;
// cast the object to a poly object
auto polyObj = static_cast<PolyObject*>(obj);
// create a new poly object that will hold the detached mesh
auto detachedPolyObj = static_cast<PolyObject*>(CreateInstance(GEOMOBJECT_CLASS_ID, Class_ID(POLYOBJ_CLASS_ID, 0)));
if (!detachedPolyObj)
return false;
// detach the SELECTED element to the new poly object's mesh (see class MNMesh)
if (!polyObj->GetMesh().DetachElementToObject(detachedPolyObj->GetMesh()))
{
detachedPolyObj->DeleteThis();
return false;
}
// create a new node referencing the detached poly object
auto newNode = GetCOREInterface()->CreateObjectNode(detachedPolyObj);
if (!newNode)
{
detachedPolyObj->DeleteThis();
return false;
}
return true;
}