// Main selection routine // public override bool select(MSelectInfo selectInfo, MSelectionList selectionList, MPointArray worldSpaceSelectPts) // // Description: // // Main selection routine // // Arguments: // // selectInfo - the selection state information // selectionList - the list of selected items to add to // worldSpaceSelectPts - // { bool selected = false; bool componentSelected = false; bool hilited = false; hilited = (selectInfo.displayStatus == M3dView.DisplayStatus.kHilite); if (hilited) { componentSelected = selectVertices(selectInfo, selectionList, worldSpaceSelectPts); selected = selected || componentSelected; } if (!selected) { apiMesh meshNode = (apiMesh)surfaceShape; // NOTE: If the geometry has an intersect routine it should // be called here with the selection ray to determine if the // the object was selected. selected = true; MSelectionMask priorityMask = new MSelectionMask(MSelectionMask.SelectionType.kSelectNurbsSurfaces); MSelectionList item = new MSelectionList(); item.add(selectInfo.selectPath); MPoint xformedPt = new MPoint(); if (selectInfo.singleSelection) { MPoint center = meshNode.boundingBox().center; xformedPt = center; xformedPt.multiplyEqual(selectInfo.selectPath.inclusiveMatrix); } selectInfo.addSelection(item, xformedPt, selectionList, worldSpaceSelectPts, priorityMask, false); } return(selected); }
// // Description // // Transforms the given components. This method is used by // the move, rotate, and scale tools in component mode when the // tweaks for the shape are stored on a separate tweak node. // The bounding box has to be updated here, so do the normals and // any other attributes that depend on vertex positions. // // Arguments // mat - matrix to transform the components by // componentList - list of components to be transformed, // or an empty list to indicate the whole surface // cachingMode - how to use the supplied pointCache // pointCache - if non-null, save or restore points from this list base // on the cachingMode // handle - handle to the attribute on the tweak node where the // tweaks should be stored // public override void tweakUsing( MMatrix mat, MObjectArray componentList, MVertexCachingMode cachingMode, MPointArray pointCache, MArrayDataHandle handle) { apiMeshGeom geomPtr = meshGeom(); bool savePoints = (cachingMode == MVertexCachingMode.kSavePoints); bool updatePoints = (cachingMode == MVertexCachingMode.kUpdatePoints); MArrayDataBuilder builder = handle.builder(); MPoint delta = new MPoint(); MPoint currPt = new MPoint(); MPoint newPt = new MPoint(); int i=0; uint len = componentList.length; int cacheIndex = 0; uint cacheLen = (null != pointCache) ? pointCache.length : 0; if (cachingMode == MVertexCachingMode.kRestorePoints) { // restore points from the pointCache // if (len > 0) { // traverse the component list // for ( i=0; i<len; i++ ) { MObject comp = componentList[i]; MFnSingleIndexedComponent fnComp = new MFnSingleIndexedComponent( comp ); int elemCount = fnComp.elementCount; for ( int idx=0; idx<elemCount && cacheIndex < cacheLen; idx++, cacheIndex++) { int elemIndex = fnComp.element( idx ); MDataHandle hdl = builder.addElement((uint)elemIndex); double[] pt = hdl.Double3; MPoint cachePt = pointCache[cacheIndex]; pt[0] += cachePt.x; pt[1] += cachePt.y; pt[2] += cachePt.z; hdl.Double3 = pt; } } } else { // if the component list is of zero-length, it indicates that we // should transform the entire surface // len = geomPtr.vertices.length; for ( uint idx = 0; idx < len && idx < cacheLen; ++idx ) { MDataHandle hdl = builder.addElement(idx); double[] pt = hdl.Double3; MPoint cachePt = pointCache[cacheIndex]; pt[0] += cachePt.x; pt[1] += cachePt.y; pt[2] += cachePt.z; hdl.Double3 = pt; } } } else { // Tweak the points. If savePoints is true, also save the tweaks in the // pointCache. If updatePoints is true, add the new tweaks to the existing // data in the pointCache. // if (len > 0) { for ( i=0; i<len; i++ ) { MObject comp = componentList[i]; MFnSingleIndexedComponent fnComp = new MFnSingleIndexedComponent( comp ); int elemCount = fnComp.elementCount; if (savePoints) { pointCache.sizeIncrement = (uint)elemCount; } for ( int idx=0; idx<elemCount; idx++ ) { int elemIndex = fnComp.element( idx ); MDataHandle hdl = builder.addElement((uint)elemIndex); double[] pt = hdl.Double3; currPt = newPt = geomPtr.vertices[elemIndex]; newPt.multiplyEqual( mat ); delta.x = newPt.x - currPt.x; delta.y = newPt.y - currPt.y; delta.z = newPt.z - currPt.z; pt[0] += delta.x; pt[1] += delta.y; pt[2] += delta.z; hdl.Double3 = pt; if (savePoints) { // store the points in the pointCache for undo // pointCache.append(delta*(-1.0)); } else if (updatePoints && cacheIndex < cacheLen) { MPoint cachePt = pointCache[cacheIndex]; cachePt[0] -= delta.x; cachePt[1] -= delta.y; cachePt[2] -= delta.z; cacheIndex++; } } } } else { // if the component list is of zero-length, it indicates that we // should transform the entire surface // len = geomPtr.vertices.length; if (savePoints) { pointCache.sizeIncrement = len; } for ( int idx = 0; idx < len; ++idx ) { MDataHandle hdl = builder.addElement((uint)idx); double[] pt = hdl.Double3; currPt = newPt = geomPtr.vertices[idx]; newPt.multiplyEqual( mat ); delta.x = newPt.x - currPt.x; delta.y = newPt.y - currPt.y; delta.z = newPt.z - currPt.z; pt[0] += delta.x; pt[1] += delta.y; pt[2] += delta.z; hdl.Double3 = pt; if (savePoints) { // store the points in the pointCache for undo // pointCache.append(delta*-1.0); } else if (updatePoints && idx < cacheLen) { MPoint cachePt = pointCache[idx]; cachePt[0] -= delta.x; cachePt[1] -= delta.y; cachePt[2] -= delta.z; } } } } // Set the builder into the handle. // handle.set(builder); // Tell Maya the bounding box for this object has changed // and thus "boundingBox()" needs to be called. // childChanged( MChildChanged.kBoundingBoxChanged ); }
public override void tweakUsing( MMatrix mat, MObjectArray componentList, MVertexCachingMode cachingMode, MPointArray pointCache, MArrayDataHandle handle ) // // Description // // Transforms the given components. This method is used by // the move, rotate, and scale tools in component mode when the // tweaks for the shape are stored on a separate tweak node. // The bounding box has to be updated here, so do the normals and // any other attributes that depend on vertex positions. // // Arguments // mat - matrix to transform the components by // componentList - list of components to be transformed, // or an empty list to indicate the whole surface // cachingMode - how to use the supplied pointCache // pointCache - if non-null, save or restore points from this list base // on the cachingMode // handle - handle to the attribute on the tweak node where the // tweaks should be stored // { apiMeshGeom geomPtr = meshGeom(); bool savePoints = (cachingMode == MVertexCachingMode.kSavePoints); bool updatePoints = (cachingMode == MVertexCachingMode.kUpdatePoints); MArrayDataBuilder builder = handle.builder(); MPoint delta = new MPoint(); MPoint currPt = new MPoint(); MPoint newPt = new MPoint(); int i=0; uint len = componentList.length; int cacheIndex = 0; uint cacheLen = (null != pointCache) ? pointCache.length : 0; if (cachingMode == MVertexCachingMode.kRestorePoints) { // restore points from the pointCache // if (len > 0) { // traverse the component list // for ( i=0; i<len; i++ ) { MObject comp = componentList[i]; MFnSingleIndexedComponent fnComp = new MFnSingleIndexedComponent( comp ); int elemCount = fnComp.elementCount; for ( int idx=0; idx<elemCount && cacheIndex < cacheLen; idx++, cacheIndex++) { int elemIndex = fnComp.element( idx ); MDataHandle hdl = builder.addElement((uint)elemIndex); double[] pt = hdl.Double3; MPoint cachePt = pointCache[cacheIndex]; pt[0] += cachePt.x; pt[1] += cachePt.y; pt[2] += cachePt.z; hdl.Double3 = pt; } } } else { // if the component list is of zero-length, it indicates that we // should transform the entire surface // len = geomPtr.vertices.length; for ( uint idx = 0; idx < len && idx < cacheLen; ++idx ) { MDataHandle hdl = builder.addElement(idx); double[] pt = hdl.Double3; MPoint cachePt = pointCache[cacheIndex]; pt[0] += cachePt.x; pt[1] += cachePt.y; pt[2] += cachePt.z; hdl.Double3 = pt; } } } else { // Tweak the points. If savePoints is true, also save the tweaks in the // pointCache. If updatePoints is true, add the new tweaks to the existing // data in the pointCache. // if (len > 0) { for ( i=0; i<len; i++ ) { MObject comp = componentList[i]; MFnSingleIndexedComponent fnComp = new MFnSingleIndexedComponent( comp ); int elemCount = fnComp.elementCount; if (savePoints) { pointCache.sizeIncrement = (uint)elemCount; } for ( int idx=0; idx<elemCount; idx++ ) { int elemIndex = fnComp.element( idx ); MDataHandle hdl = builder.addElement((uint)elemIndex); double[] pt = hdl.Double3; currPt = newPt = geomPtr.vertices[elemIndex]; newPt.multiplyEqual( mat ); delta.x = newPt.x - currPt.x; delta.y = newPt.y - currPt.y; delta.z = newPt.z - currPt.z; pt[0] += delta.x; pt[1] += delta.y; pt[2] += delta.z; hdl.Double3 = pt; if (savePoints) { // store the points in the pointCache for undo // pointCache.append(delta*(-1.0)); } else if (updatePoints && cacheIndex < cacheLen) { MPoint cachePt = pointCache[cacheIndex]; cachePt[0] -= delta.x; cachePt[1] -= delta.y; cachePt[2] -= delta.z; cacheIndex++; } } } } else { // if the component list is of zero-length, it indicates that we // should transform the entire surface // len = geomPtr.vertices.length; if (savePoints) { pointCache.sizeIncrement = len; } for ( int idx = 0; idx < len; ++idx ) { MDataHandle hdl = builder.addElement((uint)idx); double[] pt = hdl.Double3; currPt = newPt = geomPtr.vertices[idx]; newPt.multiplyEqual( mat ); delta.x = newPt.x - currPt.x; delta.y = newPt.y - currPt.y; delta.z = newPt.z - currPt.z; pt[0] += delta.x; pt[1] += delta.y; pt[2] += delta.z; hdl.Double3 = pt; if (savePoints) { // store the points in the pointCache for undo // pointCache.append(delta*-1.0); } else if (updatePoints && idx < cacheLen) { MPoint cachePt = pointCache[idx]; cachePt[0] -= delta.x; cachePt[1] -= delta.y; cachePt[2] -= delta.z; } } } } // Set the builder into the handle. // handle.set(builder); // Tell Maya the bounding box for this object has changed // and thus "boundingBox()" needs to be called. // childChanged( MChildChanged.kBoundingBoxChanged ); }
// // Description: // // Vertex selection. // // Arguments: // // selectInfo - the selection state information // selectionList - the list of selected items to add to // worldSpaceSelectPts - // public bool selectVertices( MSelectInfo selectInfo, MSelectionList selectionList, MPointArray worldSpaceSelectPts) { bool selected = false; M3dView view = selectInfo.view; MPoint xformedPoint = new MPoint(); MPoint selectionPoint = new MPoint(); double z = 0.0; double previousZ = 0.0; int closestPointVertexIndex = -1; MDagPath path = selectInfo.multiPath; // Create a component that will store the selected vertices // MFnSingleIndexedComponent fnComponent = new MFnSingleIndexedComponent(); MObject surfaceComponent = fnComponent.create( MFn.Type.kMeshVertComponent ); uint vertexIndex; // if the user did a single mouse click and we find > 1 selection // we will use the alignmentMatrix to find out which is the closest // MMatrix alignmentMatrix = new MMatrix(); MPoint singlePoint = new MPoint(); bool singleSelection = selectInfo.singleSelection; if( singleSelection ) { alignmentMatrix = selectInfo.alignmentMatrix; } // Get the geometry information // apiMesh meshNode = (apiMesh)surfaceShape; apiMeshGeom geom = meshNode.meshGeom(); // Loop through all vertices of the mesh and // see if they lie withing the selection area // uint numVertices = geom.vertices.length; for ( vertexIndex=0; vertexIndex<numVertices; vertexIndex++ ) { MPoint currentPoint = geom.vertices[ (int)vertexIndex ]; // Sets OpenGL's render mode to select and stores // selected items in a pick buffer // view.beginSelect(); OpenGL.glBegin(OpenGL.GL_POINTS); OpenGL.glVertex3f((float)currentPoint[0], (float)currentPoint[1], (float)currentPoint[2] ); OpenGL.glEnd(); if ( view.endSelect() > 0 ) // Hit count > 0 { selected = true; if ( singleSelection ) { xformedPoint = currentPoint; xformedPoint.homogenize(); xformedPoint.multiplyEqual( alignmentMatrix ); z = xformedPoint.z; if ( closestPointVertexIndex < 0 || z > previousZ ) { closestPointVertexIndex = (int)vertexIndex; singlePoint = currentPoint; previousZ = z; } } else { // multiple selection, store all elements // fnComponent.addElement( (int)vertexIndex ); } } } // If single selection, insert the closest point into the array // if ( selected && selectInfo.singleSelection ) { fnComponent.addElement(closestPointVertexIndex); // need to get world space position for this vertex // selectionPoint = singlePoint; selectionPoint.multiplyEqual( path.inclusiveMatrix ); } // Add the selected component to the selection list // if ( selected ) { MSelectionList selectionItem = new MSelectionList(); selectionItem.add( path, surfaceComponent ); MSelectionMask mask = new MSelectionMask( MSelectionMask.SelectionType.kSelectComponentsMask ); selectInfo.addSelection( selectionItem, selectionPoint, selectionList, worldSpaceSelectPts, mask, true ); } return selected; }
// // Description: // // Main selection routine // // Arguments: // // selectInfo - the selection state information // selectionList - the list of selected items to add to // worldSpaceSelectPts - // // Main selection routine // public override bool select(MSelectInfo selectInfo, MSelectionList selectionList, MPointArray worldSpaceSelectPts) { bool selected = false; bool componentSelected = false; bool hilited = false; hilited = (selectInfo.displayStatus == M3dView.DisplayStatus.kHilite); if ( hilited ) { componentSelected = selectVertices( selectInfo, selectionList, worldSpaceSelectPts ); selected = selected || componentSelected; } if ( !selected ) { apiMesh meshNode = (apiMesh)surfaceShape; // NOTE: If the geometry has an intersect routine it should // be called here with the selection ray to determine if the // the object was selected. selected = true; MSelectionMask priorityMask = new MSelectionMask( MSelectionMask.SelectionType.kSelectNurbsSurfaces ); MSelectionList item = new MSelectionList(); item.add( selectInfo.selectPath ); MPoint xformedPt = new MPoint(); if ( selectInfo.singleSelection ) { MPoint center = meshNode.boundingBox().center; xformedPt = center; xformedPt.multiplyEqual( selectInfo.selectPath.inclusiveMatrix ); } selectInfo.addSelection( item, xformedPt, selectionList, worldSpaceSelectPts, priorityMask, false ); } return selected; }
public bool selectVertices(MSelectInfo selectInfo, MSelectionList selectionList, MPointArray worldSpaceSelectPts) // // Description: // // Vertex selection. // // Arguments: // // selectInfo - the selection state information // selectionList - the list of selected items to add to // worldSpaceSelectPts - // { bool selected = false; M3dView view = selectInfo.view; MPoint xformedPoint = new MPoint(); MPoint selectionPoint = new MPoint(); double z = 0.0; double previousZ = 0.0; int closestPointVertexIndex = -1; MDagPath path = selectInfo.multiPath; // Create a component that will store the selected vertices // MFnSingleIndexedComponent fnComponent = new MFnSingleIndexedComponent(); MObject surfaceComponent = fnComponent.create(MFn.Type.kMeshVertComponent); uint vertexIndex; // if the user did a single mouse click and we find > 1 selection // we will use the alignmentMatrix to find out which is the closest // MMatrix alignmentMatrix = new MMatrix(); MPoint singlePoint = new MPoint(); bool singleSelection = selectInfo.singleSelection; if (singleSelection) { alignmentMatrix = selectInfo.alignmentMatrix; } // Get the geometry information // apiMesh meshNode = (apiMesh)surfaceShape; apiMeshGeom geom = meshNode.meshGeom(); // Loop through all vertices of the mesh and // see if they lie withing the selection area // uint numVertices = geom.vertices.length; for (vertexIndex = 0; vertexIndex < numVertices; vertexIndex++) { MPoint currentPoint = geom.vertices[(int)vertexIndex]; // Sets OpenGL's render mode to select and stores // selected items in a pick buffer // view.beginSelect(); OpenGL.glBegin(OpenGL.GL_POINTS); OpenGL.glVertex3f((float)currentPoint[0], (float)currentPoint[1], (float)currentPoint[2]); OpenGL.glEnd(); if (view.endSelect() > 0) // Hit count > 0 { selected = true; if (singleSelection) { xformedPoint = currentPoint; xformedPoint.homogenize(); xformedPoint.multiplyEqual(alignmentMatrix); z = xformedPoint.z; if (closestPointVertexIndex < 0 || z > previousZ) { closestPointVertexIndex = (int)vertexIndex; singlePoint = currentPoint; previousZ = z; } } else { // multiple selection, store all elements // fnComponent.addElement((int)vertexIndex); } } } // If single selection, insert the closest point into the array // if (selected && selectInfo.singleSelection) { fnComponent.addElement(closestPointVertexIndex); // need to get world space position for this vertex // selectionPoint = singlePoint; selectionPoint.multiplyEqual(path.inclusiveMatrix); } // Add the selected component to the selection list // if (selected) { MSelectionList selectionItem = new MSelectionList(); selectionItem.add(path, surfaceComponent); MSelectionMask mask = new MSelectionMask(MSelectionMask.SelectionType.kSelectComponentsMask); selectInfo.addSelection( selectionItem, selectionPoint, selectionList, worldSpaceSelectPts, mask, true); } return(selected); }