bool MannequinMoveManipulator::intersectManip(MPxManipulatorNode* manip) const { M3dView view = M3dView::active3dView(); float size = _manipScale * MFnManip3D::globalSize(); MPoint xEnd = _origin + (_x * size); MPoint yEnd = _origin + (_y * size); MPoint zEnd = _origin + (_z * size); short mx, my; manip->mousePosition(mx, my); short ox, oy, xx, xy, yx, yy, zx, zy; view.worldToView(_origin, ox, oy); view.worldToView(xEnd, xx, xy); view.worldToView(yEnd, yx, yy); view.worldToView(zEnd, zx, zy); // Calculate approximate handle size in view space. float viewLength = 0.0f; viewLength = std::max(viewLength, sqrtf(pow(float(xx) - float(ox), 2) + pow(float(xy) - float(oy), 2))); viewLength = std::max(viewLength, sqrtf(pow(float(yx) - float(ox), 2) + pow(float(yy) - float(oy), 2))); viewLength = std::max(viewLength, sqrtf(pow(float(zx) - float(ox), 2) + pow(float(zy) - float(oy), 2))); float handleSize = MFnManip3D::handleSize() / 100.0f; // Probably on [0, 100]. float handleHeight = viewLength * handleSize * 0.5f; float handleRadius = std::max(handleHeight * 0.3f, 4.0f); // Note: slightly exaggerated; normally handleHeight * 0.25f. // Determine if we're in range to any of the lines. float curDist, t; curDist = Util::distanceToLine(ox, oy, xx, xy, mx, my, &t); if (curDist < handleRadius && t >= 0.0f && t <= 1.0f) { return true; } curDist = Util::distanceToLine(ox, oy, yx, yy, mx, my, &t); if (curDist < handleRadius && t >= 0.0f && t <= 1.0f) { return true; } curDist = Util::distanceToLine(ox, oy, zx, zy, mx, my, &t); if (curDist < handleRadius && t >= 0.0f && t <= 1.0f) { return true; } return false; }
MStatus MannequinMoveManipulator::doPress(M3dView& view) { getPointValue(_translateIndex, false, _opValueBegin); GLuint activeAxis; glActiveName(activeAxis); if (activeAxis == _glPickableItem + 0) { _opAxis = _x; _opAxisIndex = 0; } else if (activeAxis == _glPickableItem + 1) { _opAxis = _y; _opAxisIndex = 1; } else if (activeAxis == _glPickableItem + 2) { _opAxis = _z; _opAxisIndex = 2; } else { _opAxis = MVector::zero; _opValid = false; return MS::kUnknownParameter; } _opOrigin = _origin; // Determine the translation "plane"; it is orthogonal to the axis and faces // the view as best as possible. short originX, originY; view.worldToView(_opOrigin, originX, originY); MPoint rayNear; MVector dirToOrigin; view.viewToWorld(originX, originY, rayNear, dirToOrigin); MVector dirInPlane = dirToOrigin ^ _opAxis; _opPlaneNormal = dirInPlane ^ _opAxis; // Determine where the current mouse ray hits the plane. MPoint rayOrigin; MVector rayDirection; mouseRayWorld(rayOrigin, rayDirection); MPoint isect; bool didIsect = Util::rayPlaneIntersection(rayOrigin, rayDirection, _opOrigin, _opPlaneNormal, &isect); if (!didIsect) { _opValid = false; return MS::kUnknownParameter; } _opHitBegin = isect; _opValid = true; // We need to calculate the handle directions in parent space. This is // because the handle positions align with the child pivot rotation, so they // DO NOT correspond to the child's X, Y, and Z-position, which are // indicated in terms of the parent's coordinate space. MMatrix parentInverse = _parentXform.asMatrixInverse(); _xInParentSpace = _x * parentInverse; _yInParentSpace = _y * parentInverse; _zInParentSpace = _z * parentInverse; return MS::kSuccess; }
MStatus lassoTool::doRelease( MEvent & /*event*/ ) // Selects objects within the lasso { MStatus stat; MSelectionList incomingList, boundingBoxList, newList; if (!firstDraw) { // Redraw the lasso to clear it. view.beginXorDrawing(true, true, 1.0f, M3dView::kStippleDashed); draw_lasso(); view.endXorDrawing(); } // We have a non-zero sized lasso. Close the lasso, and sort // all the points on it. append_lasso(lasso[0].h, lasso[0].v); qsort( &(lasso[0]), num_points, sizeof( coord ), (int (*)(const void *, const void *))xycompare); // Save the state of the current selections. The "selectFromSceen" // below will alter the active list, and we have to be able to put // it back. MGlobal::getActiveSelectionList(incomingList); // As a first approximation to the lasso, select all components with // the bounding box that just contains the lasso. MGlobal::selectFromScreen( min.h, min.v, max.h, max.v, MGlobal::kReplaceList ); // Get the list of selected items from within the bounding box // and create a iterator for them. MGlobal::getActiveSelectionList(boundingBoxList); // Restore the active selection list to what it was before we // the "selectFromScreen" MGlobal::setActiveSelectionList(incomingList, MGlobal::kReplaceList); // Iterate over the objects within the bounding box, extract the // ones that are within the lasso, and add those to newList. MItSelectionList iter(boundingBoxList); newList.clear(); bool foundEntireObjects = false; bool foundComponents = false; for ( ; !iter.isDone(); iter.next() ) { MDagPath dagPath; MObject component; MPoint point; coord pt; MObject singleComponent; iter.getDagPath( dagPath, component ); if (component.isNull()) { foundEntireObjects = true; continue; // not a component } foundComponents = true; switch (component.apiType()) { case MFn::kCurveCVComponent: { MItCurveCV curveCVIter( dagPath, component, &stat ); for ( ; !curveCVIter.isDone(); curveCVIter.next() ) { point = curveCVIter.position(MSpace::kWorld, &stat ); view.worldToView( point, pt.h, pt.v, &stat ); if (!stat) { stat.perror("Could not get position"); continue; } if ( point_in_lasso( pt ) ) { singleComponent = curveCVIter.cv(); newList.add (dagPath, singleComponent); } } break; } case MFn::kSurfaceCVComponent: { MItSurfaceCV surfCVIter( dagPath, component, true, &stat ); for ( ; !surfCVIter.isDone(); surfCVIter.next() ) { point = surfCVIter.position(MSpace::kWorld, &stat ); view.worldToView( point, pt.h, pt.v, &stat ); if (!stat) { stat.perror("Could not get position"); continue; } if ( point_in_lasso( pt ) ) { singleComponent = surfCVIter.cv(); newList.add (dagPath, singleComponent); } } break; } case MFn::kMeshVertComponent: { MItMeshVertex vertexIter( dagPath, component, &stat ); for ( ; !vertexIter.isDone(); vertexIter.next() ) { point = vertexIter.position(MSpace::kWorld, &stat ); view.worldToView( point, pt.h, pt.v, &stat ); if (!stat) { stat.perror("Could not get position"); continue; } if ( point_in_lasso( pt ) ) { singleComponent = vertexIter.vertex(); newList.add (dagPath, singleComponent); } } break; } case MFn::kMeshEdgeComponent: { MItMeshEdge edgeIter( dagPath, component, &stat ); for ( ; !edgeIter.isDone(); edgeIter.next() ) { point = edgeIter.center(MSpace::kWorld, &stat ); view.worldToView( point, pt.h, pt.v, &stat ); if (!stat) { stat.perror("Could not get position"); continue; } if ( point_in_lasso( pt ) ) { singleComponent = edgeIter.edge(); newList.add (dagPath, singleComponent); } } break; } case MFn::kMeshPolygonComponent: { MItMeshPolygon polygonIter( dagPath, component, &stat ); for ( ; !polygonIter.isDone(); polygonIter.next() ) { point = polygonIter.center(MSpace::kWorld, &stat ); view.worldToView( point, pt.h, pt.v, &stat ); if (!stat) { stat.perror("Could not get position"); continue; } if ( point_in_lasso( pt ) ) { singleComponent = polygonIter.polygon(); newList.add (dagPath, singleComponent); } } break; } default: #ifdef DEBUG cerr << "Selected unsupported type: (" << component.apiType() << "): " << component.apiTypeStr() << endl; #endif /* DEBUG */ continue; } } // Warn user if zie is trying to select objects rather than components. if (foundEntireObjects && !foundComponents) { MGlobal::displayWarning("lassoTool can only select components, not entire objects."); } // Update the selection list as indicated by the modifier keys. MGlobal::selectCommand(newList, listAdjustment); // Free the memory that held our lasso points. free(lasso); lasso = (coord*) 0; maxSize = 0; num_points = 0; return MS::kSuccess; }