void EditPatchMod::DoVertReset () { ModContextList mcList; INodeTab nodes; TimeValue t = ip->GetTime(); int holdNeeded = 0; BOOL hadSel = FALSE; if (!ip) return; ip->GetModContexts(mcList, nodes); ClearPatchDataFlag(mcList, EPD_BEENDONE); theHold.Begin(); RecordTopologyTags(); for (int i = 0; i < mcList.Count(); i++) { BOOL altered = FALSE; EditPatchData *patchData =(EditPatchData*)mcList[i]->localData; if (!patchData) continue; if (patchData->GetFlag(EPD_BEENDONE)) continue; // If the mesh isn't yet cache, this will cause it to get cached. RPatchMesh *rpatch; PatchMesh *patch = patchData->TempData(this)->GetPatch(t, rpatch); if (!patch) continue; patchData->RecordTopologyTags(patch); // If this is the first edit, then the delta arrays will be allocated patchData->BeginEdit(t); // If any bits are set in the selection set, let's DO IT!! if (patch->vertSel.NumberSet() > 0) { hadSel = TRUE; if (theHold.Holding()) theHold.Put(new PatchRestore(patchData, this, patch, rpatch, "DoVertReset")); // Call the patch weld function ResetVert (patch); patchData->UpdateChanges(patch, rpatch); patchData->TempData(this)->Invalidate(PART_GEOM); /*if (patch->Weld(weldThreshold)) { rpatch->Weld (patch); altered = holdNeeded = TRUE; patchData->UpdateChanges(patch, rpatch); patchData->TempData(this)->Invalidate(PART_TOPO); }*/ } patchData->SetFlag(EPD_BEENDONE, TRUE); } ResolveTopoChanges(); theHold.Accept("Reset Vertex"); /*if (holdNeeded) { ResolveTopoChanges(); theHold.Accept(GetString(IDS_TH_VERTWELD)); } else { if (!hadSel) ip->DisplayTempPrompt(GetString(IDS_TH_NOVERTSSEL), PROMPT_TIME); else ip->DisplayTempPrompt(GetString(IDS_TH_NOWELDPERFORMED), PROMPT_TIME); theHold.End(); }*/ nodes.DisposeTemporary(); ClearPatchDataFlag(mcList, EPD_BEENDONE); NotifyDependents(FOREVER, PART_GEOM, REFMSG_CHANGE); ip->RedrawViews(ip->GetTime(), REDRAW_NORMAL); }
void EditPatchMod::DoRemoveHook() { ModContextList mcList; INodeTab nodes; TimeValue t = ip->GetTime(); BOOL holdNeeded = FALSE; BOOL hadSelected = FALSE; if (!ip) return; ip->GetModContexts(mcList, nodes); ClearPatchDataFlag(mcList, EPD_BEENDONE); theHold.Begin(); RecordTopologyTags(); for (int i = 0; i < mcList.Count(); i++) { BOOL altered = FALSE; EditPatchData *patchData =(EditPatchData*)mcList[i]->localData; if (!patchData) continue; if (patchData->GetFlag(EPD_BEENDONE)) continue; // If the mesh isn't yet cache, this will cause it to get cached. RPatchMesh *rpatch; PatchMesh *patch = patchData->TempData(this)->GetPatch(t, rpatch); if (!patch) continue; patchData->RecordTopologyTags(patch); // If this is the first edit, then the delta arrays will be allocated patchData->BeginEdit(t); // If any bits are set in the selection set, let's DO IT!! if (patch->vertSel.NumberSet()) { altered = holdNeeded = TRUE; if (theHold.Holding()) theHold.Put(new PatchRestore(patchData, this, patch, rpatch)); // Call the vertex type change function // Modif by Hulud //patch->RemoveHook(); rpatch->RemoveHook (*patch); // patch->InvalidateGeomCache(); // InvalidateMesh(); patchData->UpdateChanges(patch, rpatch); patchData->TempData(this)->Invalidate(PART_TOPO); } patchData->SetFlag(EPD_BEENDONE, TRUE); } if (holdNeeded) { ResolveTopoChanges(); theHold.Accept(GetString(IDS_TH_PATCHCHANGE)); } else { ip->DisplayTempPrompt(GetString(IDS_TH_NOPATCHESSEL), PROMPT_TIME); theHold.End(); } nodes.DisposeTemporary(); ClearPatchDataFlag(mcList, EPD_BEENDONE); NotifyDependents(FOREVER, PART_TOPO, REFMSG_CHANGE); ip->RedrawViews(ip->GetTime(), REDRAW_NORMAL); }
int EditPatchMod::DoAttach(INode *node, PatchMesh *attPatch, RPatchMesh *rattPatch, bool & canUndo) { ModContextList mcList; INodeTab nodes; if (!ip) return 0; ip->GetModContexts(mcList, nodes); if (mcList.Count() != 1) { nodes.DisposeTemporary(); return 0; } EditPatchData *patchData =(EditPatchData*)mcList[0]->localData; if (!patchData) { nodes.DisposeTemporary(); return 0; } patchData->BeginEdit(ip->GetTime()); // If the mesh isn't yet cached, this will cause it to get cached. RPatchMesh *rpatch; PatchMesh *patch = patchData->TempData(this)->GetPatch(ip->GetTime(), rpatch); if (!patch) { nodes.DisposeTemporary(); return 0; } patchData->RecordTopologyTags(patch); RecordTopologyTags(); // Transform the shape for attachment: // If reorienting, just translate to align pivots // Otherwise, transform to match our transform Matrix3 attMat(1); if (attachReorient) { Matrix3 thisTM = nodes[0]->GetNodeTM(ip->GetTime()); Matrix3 thisOTMBWSM = nodes[0]->GetObjTMBeforeWSM(ip->GetTime()); Matrix3 thisPivTM = thisTM * Inverse(thisOTMBWSM); Matrix3 otherTM = node->GetNodeTM(ip->GetTime()); Matrix3 otherOTMBWSM = node->GetObjTMBeforeWSM(ip->GetTime()); Matrix3 otherPivTM = otherTM * Inverse(otherOTMBWSM); Point3 otherObjOffset = node->GetObjOffsetPos(); attMat = Inverse(otherPivTM) * thisPivTM; } else { attMat = node->GetObjectTM(ip->GetTime()) * Inverse(nodes[0]->GetObjectTM(ip->GetTime())); } // RB 3-17-96 : Check for mirroring AffineParts parts; decomp_affine(attMat, &parts); if (parts.f < 0.0f) { int v[8], ct, ct2, j; Point3 p[9]; for (int i = 0; i < attPatch->numPatches; i++) { // Re-order rpatch if (attPatch->patches[i].type == PATCH_QUAD) { UI_PATCH rpatch=rattPatch->getUIPatch (i); int ctU=rpatch.NbTilesU<<1; int ctV=rpatch.NbTilesV<<1; int nU; for (nU=0; nU<ctU; nU++) { for (int nV=0; nV<ctV; nV++) { rattPatch->getUIPatch (i).getTileDesc (nU+nV*ctU)=rpatch.getTileDesc (ctU-1-nU+(ctV-1-nV)*ctU); } } for (nU=0; nU<ctU+1; nU++) { for (int nV=0; nV<ctV+1; nV++) { rattPatch->getUIPatch (i).setColor (nU+nV*(ctU+1), rpatch.getColor (ctU-nU+(ctV-nV)*ctU)); } } } // Re-order vertices ct = attPatch->patches[i].type == PATCH_QUAD ? 4 : 3; for (j = 0; j < ct; j++) { v[j] = attPatch->patches[i].v[j]; } for (j = 0; j < ct; j++) { attPatch->patches[i].v[j] = v[ct - j - 1]; } // Re-order vecs ct = attPatch->patches[i].type == PATCH_QUAD ? 8 : 6; ct2 = attPatch->patches[i].type == PATCH_QUAD ? 5 : 3; for (j = 0; j < ct; j++) { v[j] = attPatch->patches[i].vec[j]; } for (j = 0; j < ct; j++, ct2--) { if (ct2 < 0) ct2 = ct - 1; attPatch->patches[i].vec[j] = v[ct2]; } // Re-order enteriors if (attPatch->patches[i].type == PATCH_QUAD) { ct = 4; for (j = 0; j < ct; j++) { v[j] = attPatch->patches[i].interior[j]; } for (j = 0; j < ct; j++) { attPatch->patches[i].interior[j] = v[ct - j - 1]; } } // Re-order aux if (attPatch->patches[i].type == PATCH_TRI) { ct = 9; for (j = 0; j < ct; j++) { p[j] = attPatch->patches[i].aux[j]; } for (j = 0; j < ct; j++) { attPatch->patches[i].aux[j] = p[ct - j - 1]; } } // Re-order TV faces if present for (int chan = 0; chan < patch->getNumMaps(); ++chan) { if (attPatch->tvPatches[chan]) { ct = 4; for (j = 0; j < ct; j++) { v[j] = attPatch->tvPatches[chan][i].tv[j]; } for (j = 0; j < ct; j++) { attPatch->tvPatches[chan][i].tv[j] = v[ct - j - 1]; } } } } } int i; for (i = 0; i < attPatch->numVerts; ++i) attPatch->verts[i].p = attPatch->verts[i].p * attMat; for (i = 0; i < attPatch->numVecs; ++i) attPatch->vecs[i].p = attPatch->vecs[i].p * attMat; attPatch->computeInteriors(); theHold.Begin(); // Combine the materials of the two nodes. int mat2Offset = 0; Mtl *m1 = nodes[0]->GetMtl(); Mtl *m2 = node->GetMtl(); bool condenseMe = FALSE; if (m1 && m2 &&(m1 != m2)) { if (attachMat == ATTACHMAT_IDTOMAT) { int ct = 1; if (m1->IsMultiMtl()) ct = m1->NumSubMtls(); for (int i = 0; i < patch->numPatches; ++i) { int mtid = patch->getPatchMtlIndex(i); if (mtid >= ct) patch->setPatchMtlIndex(i, mtid % ct); } FitPatchIDsToMaterial(*attPatch, m2); if (condenseMat) condenseMe = TRUE; } // the theHold calls here were a vain attempt to make this all undoable. // This should be revisited in the future so we don't have to use the SYSSET_CLEAR_UNDO. theHold.Suspend(); if (attachMat == ATTACHMAT_MATTOID) { m1 = FitMaterialToPatchIDs(*patch, m1); m2 = FitMaterialToPatchIDs(*attPatch, m2); } Mtl *multi = CombineMaterials(m1, m2, mat2Offset); if (attachMat == ATTACHMAT_NEITHER) mat2Offset = 0; theHold.Resume(); // We can't be in face subobject mode, else we screw up the materials: DWORD oldSL = patch->selLevel; DWORD roldSL = patch->selLevel; patch->selLevel = PATCH_OBJECT; rpatch->SetSelLevel (EP_OBJECT); nodes[0]->SetMtl(multi); patch->selLevel = oldSL; rpatch->SetSelLevel (roldSL); m1 = multi; canUndo = FALSE; // Absolutely cannot undo material combinations. } if (!m1 && m2) { // We can't be in face subobject mode, else we screw up the materials: DWORD oldSL = patch->selLevel; DWORD roldSL = rpatch->GetSelLevel(); patch->selLevel = PATCH_OBJECT; rpatch->SetSelLevel (EP_OBJECT); nodes[0]->SetMtl(m2); patch->selLevel = oldSL; rpatch->SetSelLevel (roldSL); m1 = m2; } // Start a restore object... if (theHold.Holding()) theHold.Put(new PatchRestore(patchData, this, patch, rpatch, "DoAttach")); // Do the attach patch->Attach(attPatch, mat2Offset); rpatch->Attach(rattPatch, *patch); patchData->UpdateChanges(patch, rpatch); patchData->TempData(this)->Invalidate(PART_TOPO | PART_GEOM); // Get rid of the original node ip->DeleteNode(node); ResolveTopoChanges(); theHold.Accept(GetString(IDS_TH_ATTACH)); if (m1 && condenseMe) { // Following clears undo stack. patch = patchData->TempData(this)->GetPatch(ip->GetTime(), rpatch); m1 = CondenseMatAssignments(*patch, m1); } nodes.DisposeTemporary(); ClearPatchDataFlag(mcList, EPD_BEENDONE); NotifyDependents(FOREVER, PART_TOPO | PART_GEOM, REFMSG_CHANGE); ip->RedrawViews(ip->GetTime(), REDRAW_NORMAL); return 1; }
// Edger Delete modifier method void EditPatchMod::DoEdgeDelete() { ModContextList mcList; INodeTab nodes; TimeValue t = ip->GetTime(); int holdNeeded = 0; if (!ip) return; ip->GetModContexts(mcList, nodes); ClearPatchDataFlag(mcList, EPD_BEENDONE); theHold.Begin(); RecordTopologyTags(); for (int i = 0; i < mcList.Count(); i++) { int altered = 0; EditPatchData *patchData =(EditPatchData*)mcList[i]->localData; if (!patchData) continue; if (patchData->GetFlag(EPD_BEENDONE)) continue; // If the mesh isn't yet cache, this will cause it to get cached. RPatchMesh *rpatch; PatchMesh *patch = patchData->TempData(this)->GetPatch(t, rpatch); if (!patch) continue; patchData->RecordTopologyTags(patch); // If this is the first edit, then the delta arrays will be allocated patchData->BeginEdit(t); // If any bits are set in the selection set, let's DO IT!! if (patch->edgeSel.NumberSet()) { altered = holdNeeded = 1; if (theHold.Holding()) theHold.Put(new PatchRestore(patchData, this, patch, rpatch, "DoEdgeDelete")); int edges = patch->getNumEdges(); int patches = patch->getNumPatches(); int verts = patch->getNumVerts(); // Tag the patches that are attached to selected edges BitArray delPatches(patches); delPatches.ClearAll(); for (int i = 0; i < edges; ++i) { if (patch->edgeSel[i]) { #if (MAX_RELEASE < 4000) if (patch->edges[i].patch1 >= 0) delPatches.Set(patch->edges[i].patch1); if (patch->edges[i].patch2 >= 0) delPatches.Set(patch->edges[i].patch2); #else // (MAX_RELEASE < 4000) if (patch->edges[i].patches[0] >= 0) delPatches.Set(patch->edges[i].patches[0]); if (patch->edges[i].patches[1] >= 0) delPatches.Set(patch->edges[i].patches[1]); #endif // (MAX_RELEASE < 4000) } } BitArray delVerts(verts); delVerts.ClearAll(); DeletePatchParts(patch, rpatch, delVerts, delPatches); patch->computeInteriors(); patchData->UpdateChanges(patch, rpatch); patchData->TempData(this)->Invalidate(PART_TOPO); } patchData->SetFlag(EPD_BEENDONE, TRUE); } if (holdNeeded) { ResolveTopoChanges(); theHold.Accept(GetString(IDS_TH_EDGEDELETE)); } else { ip->DisplayTempPrompt(GetString(IDS_TH_NOEDGESSEL), PROMPT_TIME); theHold.End(); } nodes.DisposeTemporary(); ClearPatchDataFlag(mcList, EPD_BEENDONE); NotifyDependents(FOREVER, PART_TOPO, REFMSG_CHANGE); ip->RedrawViews(ip->GetTime(), REDRAW_NORMAL); }