// general cortex render function, takes a gu_detail and uses the NodePassData attribute // to call the required render method void GR_Cortex::render( GU_Detail *gdp, const IECoreGL::State *displayState ) { // gl scene from a parameterised procedural const GA_ROAttributeRef attrRef = gdp->findAttribute( GA_ATTRIB_DETAIL, GA_SCOPE_PRIVATE, "IECoreHoudiniNodePassData" ); if ( attrRef.isInvalid() ) { return; } const GA_Attribute *attr = attrRef.getAttribute(); const GA_AIFBlindData *blindData = attr->getAIFBlindData(); const NodePassData passData = blindData->getValue<NodePassData>( attr, 0 ); switch( passData.type() ) { case IECoreHoudini::NodePassData::CORTEX_OPHOLDER : { SOP_OpHolder *sop = dynamic_cast<SOP_OpHolder*>( const_cast<OP_Node*>( passData.nodePtr() ) ); if ( !sop ) { return; } IECore::OpPtr op = IECore::runTimeCast<IECore::Op>( sop->getParameterised() ); if ( !op ) { return; } const IECore::Parameter *result_parameter = op->resultParameter(); const IECore::Object *result_object = result_parameter->getValue(); renderObject( result_object, displayState ); break; } case IECoreHoudini::NodePassData::CORTEX_PROCEDURALHOLDER : { SOP_ProceduralHolder *sop = dynamic_cast<SOP_ProceduralHolder*>( const_cast<OP_Node*>( passData.nodePtr() ) ); if ( !sop ) { return; } IECoreGL::ConstScenePtr scene = sop->scene(); if ( !scene ) { return; } scene->render( const_cast<IECoreGL::State *>( displayState ) ); break; } default : { break; } } }
void DrawableHolderUI::draw( const MDrawRequest &request, M3dView &view ) const { MDrawData drawData = request.drawData(); DrawableHolder *drawableHolder = (DrawableHolder *)drawData.geometry(); assert( drawableHolder ); IECoreGL::ConstScenePtr s = drawableHolder->scene(); if( !s ) { return; } view.beginGL(); // maya can sometimes leave an error from it's own code, // and we don't want that to confuse us in our drawing code. while( glGetError()!=GL_NO_ERROR ) { } // if we're being drawn as part of a selection operation we need // to make sure there's a name on the name stack, as the IECoreGL::NameStateComponent // expects to be able to load a name into it (it fails with an invalid operation if // there's no name slot to load into). if( view.selectMode() ) { view.pushName( 0 ); } try { // do the main render s->render( m_displayStyle.baseState( request.displayStyle() ) ); // do a wireframe render over the top if we're selected and we just did a solid // draw. bool selected = request.displayStatus()==M3dView::kActive || request.displayStatus()==M3dView::kLead; bool solid = request.displayStyle()==M3dView::kFlatShaded || request.displayStyle()==M3dView::kGouraudShaded; if( selected && solid ) { s->render( m_displayStyle.baseState( M3dView::kWireFrame ) ); } } catch( std::exception &e ) { IECore::msg( IECore::Msg::Error, "DrawableHolderUI::draw", e.what() ); } view.endGL(); }
bool DrawableHolderUI::select( MSelectInfo &selectInfo, MSelectionList &selectionList, MPointArray &worldSpaceSelectPts ) const { MStatus s; // early out if we're not selectable. we always allow components to be selected if we're highlighted, // but we don't allow ourselves to be selected as a whole unless meshes are in the selection mask. // it's not ideal that we act like a mesh, but it's at least consistent with the drawing mask we use. if( selectInfo.displayStatus() != M3dView::kHilite ) { MSelectionMask meshMask( MSelectionMask::kSelectMeshes ); if( !selectInfo.selectable( meshMask ) ) { return false; } } // early out if we have no scene to draw DrawableHolder *drawableHolder = static_cast<DrawableHolder *>( surfaceShape() ); IECoreGL::ConstScenePtr scene = drawableHolder->scene(); if( !scene ) { return false; } // we want to perform the selection using an IECoreGL::Selector, so we // can avoid the performance penalty associated with using GL_SELECT mode. // that means we don't really want to call view.beginSelect(), but we have to // call it just to get the projection matrix for our own selection, because as far // as i can tell, there is no other way of getting it reliably. M3dView view = selectInfo.view(); view.beginSelect(); Imath::M44d projectionMatrix; glGetDoublev( GL_PROJECTION_MATRIX, projectionMatrix.getValue() ); view.endSelect(); view.beginGL(); glMatrixMode( GL_PROJECTION ); glLoadMatrixd( projectionMatrix.getValue() ); IECoreGL::Selector::Mode selectionMode = IECoreGL::Selector::IDRender; if( selectInfo.displayStatus() == M3dView::kHilite && !selectInfo.singleSelection() ) { selectionMode = IECoreGL::Selector::OcclusionQuery; } std::vector<IECoreGL::HitRecord> hits; { IECoreGL::Selector selector( Imath::Box2f( Imath::V2f( 0 ), Imath::V2f( 1 ) ), selectionMode, hits ); IECoreGL::State::bindBaseState(); selector.baseState()->bind(); scene->render( selector.baseState() ); } view.endGL(); if( !hits.size() ) { return false; } // find the depth of the closest hit: MIntArray componentIndices; float depthMin = std::numeric_limits<float>::max(); for( int i=0, e = hits.size(); i < e; i++ ) { if( hits[i].depthMin < depthMin ) { depthMin = hits[i].depthMin; } } // figure out the world space location of the closest hit MDagPath camera; view.getCamera( camera ); MFnCamera fnCamera( camera.node() ); float near = fnCamera.nearClippingPlane(); float far = fnCamera.farClippingPlane(); float z = -1; if( fnCamera.isOrtho() ) { z = Imath::lerp( near, far, depthMin ); } else { // perspective camera - depth isn't linear so linearise to get z float a = far / ( far - near ); float b = far * near / ( near - far ); z = b / ( depthMin - a ); } MPoint localRayOrigin; MVector localRayDirection; selectInfo.getLocalRay( localRayOrigin, localRayDirection ); MMatrix localToCamera = selectInfo.selectPath().inclusiveMatrix() * camera.inclusiveMatrix().inverse(); MPoint cameraRayOrigin = localRayOrigin * localToCamera; MVector cameraRayDirection = localRayDirection * localToCamera; MPoint cameraIntersectionPoint = cameraRayOrigin + cameraRayDirection * ( -( z - near ) / cameraRayDirection.z ); MPoint worldIntersectionPoint = cameraIntersectionPoint * camera.inclusiveMatrix(); MSelectionList item; item.add( selectInfo.selectPath() ); selectInfo.addSelection( item, worldIntersectionPoint, selectionList, worldSpaceSelectPts, MSelectionMask::kSelectMeshes, false ); return true; }
bool ProceduralHolderUI::select( MSelectInfo &selectInfo, MSelectionList &selectionList, MPointArray &worldSpaceSelectPts ) const { MStatus s; // early out if we're not selectable. we always allow components to be selected if we're highlighted, // but we don't allow ourselves to be selected as a whole unless meshes are in the selection mask. // it's not ideal that we act like a mesh, but it's at least consistent with the drawing mask we use. if( selectInfo.displayStatus() != M3dView::kHilite ) { MSelectionMask meshMask( MSelectionMask::kSelectMeshes ); if( !selectInfo.selectable( meshMask ) ) { return false; } } // early out if we have no scene to draw ProceduralHolder *proceduralHolder = static_cast<ProceduralHolder *>( surfaceShape() ); IECoreGL::ConstScenePtr scene = proceduralHolder->scene(); if( !scene ) { return false; } // we want to perform the selection using an IECoreGL::Selector, so we // can avoid the performance penalty associated with using GL_SELECT mode. // that means we don't really want to call view.beginSelect(), but we have to // call it just to get the projection matrix for our own selection, because as far // as i can tell, there is no other way of getting it reliably. M3dView view = selectInfo.view(); view.beginSelect(); Imath::M44d projectionMatrix; glGetDoublev( GL_PROJECTION_MATRIX, projectionMatrix.getValue() ); view.endSelect(); view.beginGL(); glMatrixMode( GL_PROJECTION ); glLoadMatrixd( projectionMatrix.getValue() ); IECoreGL::Selector::Mode selectionMode = IECoreGL::Selector::IDRender; if( selectInfo.displayStatus() == M3dView::kHilite && !selectInfo.singleSelection() ) { selectionMode = IECoreGL::Selector::OcclusionQuery; } std::vector<IECoreGL::HitRecord> hits; { IECoreGL::Selector selector( Imath::Box2f( Imath::V2f( 0 ), Imath::V2f( 1 ) ), selectionMode, hits ); IECoreGL::State::bindBaseState(); selector.baseState()->bind(); scene->render( selector.baseState() ); if( selectInfo.displayStatus() != M3dView::kHilite ) { // we're not in component selection mode. we'd like to be able to select the procedural // object using the bounding box so we draw it too. MPlug pDrawBound( proceduralHolder->thisMObject(), ProceduralHolder::aDrawBound ); bool drawBound = true; pDrawBound.getValue( drawBound ); if( drawBound ) { IECoreGL::BoxPrimitive::renderWireframe( IECore::convert<Imath::Box3f>( proceduralHolder->boundingBox() ) ); } } } view.endGL(); if( !hits.size() ) { return false; } // iterate over the hits, converting them into components and also finding // the closest one. MIntArray componentIndices; float depthMin = std::numeric_limits<float>::max(); int depthMinIndex = -1; for( int i=0, e = hits.size(); i < e; i++ ) { if( hits[i].depthMin < depthMin ) { depthMin = hits[i].depthMin; depthMinIndex = componentIndices.length(); } ProceduralHolder::ComponentsMap::const_iterator compIt = proceduralHolder->m_componentsMap.find( hits[i].name.value() ); assert( compIt != proceduralHolder->m_componentsMap.end() ); componentIndices.append( compIt->second.first ); } assert( depthMinIndex >= 0 ); // figure out the world space location of the closest hit MDagPath camera; view.getCamera( camera ); MFnCamera fnCamera( camera.node() ); float near = fnCamera.nearClippingPlane(); float far = fnCamera.farClippingPlane(); float z = -1; if( fnCamera.isOrtho() ) { z = Imath::lerp( near, far, depthMin ); } else { // perspective camera - depth isn't linear so linearise to get z float a = far / ( far - near ); float b = far * near / ( near - far ); z = b / ( depthMin - a ); } MPoint localRayOrigin; MVector localRayDirection; selectInfo.getLocalRay( localRayOrigin, localRayDirection ); MMatrix localToCamera = selectInfo.selectPath().inclusiveMatrix() * camera.inclusiveMatrix().inverse(); MPoint cameraRayOrigin = localRayOrigin * localToCamera; MVector cameraRayDirection = localRayDirection * localToCamera; MPoint cameraIntersectionPoint = cameraRayOrigin + cameraRayDirection * ( -( z - near ) / cameraRayDirection.z ); MPoint worldIntersectionPoint = cameraIntersectionPoint * camera.inclusiveMatrix(); // turn the processed hits into appropriate changes to the current selection if( selectInfo.displayStatus() == M3dView::kHilite ) { // selecting components MFnSingleIndexedComponent fnComponent; MObject component = fnComponent.create( MFn::kMeshPolygonComponent, &s ); assert( s ); if( selectInfo.singleSelection() ) { fnComponent.addElement( componentIndices[depthMinIndex] ); } else { fnComponent.addElements( componentIndices ); } MSelectionList items; items.add( selectInfo.multiPath(), component ); selectInfo.addSelection( items, worldIntersectionPoint, selectionList, worldSpaceSelectPts, MSelectionMask::kSelectMeshFaces, true ); } else { // selecting objects MSelectionList item; item.add( selectInfo.selectPath() ); selectInfo.addSelection( item, worldIntersectionPoint, selectionList, worldSpaceSelectPts, MSelectionMask::kSelectMeshes, false ); } return true; }
void ProceduralHolderUI::draw( const MDrawRequest &request, M3dView &view ) const { MStatus s; MDrawData drawData = request.drawData(); ProceduralHolder *proceduralHolder = (ProceduralHolder *)drawData.geometry(); assert( proceduralHolder ); view.beginGL(); LightingState lightingState; bool restoreLightState = cleanupLights( request, view, &lightingState ); // maya can sometimes leave an error from it's own code, // and we don't want that to confuse us in our drawing code. while( glGetError()!=GL_NO_ERROR ) { } try { // draw the bound if asked if( request.token()==BoundDrawMode ) { IECoreGL::BoxPrimitive::renderWireframe( IECore::convert<Imath::Box3f>( proceduralHolder->boundingBox() ) ); } // draw the scene if asked if( request.token()==SceneDrawMode ) { resetHilites(); IECoreGL::ConstScenePtr scene = proceduralHolder->scene(); if( scene ) { IECoreGL::State *displayState = m_displayStyle.baseState( (M3dView::DisplayStyle)request.displayStyle() ); if ( request.component() != MObject::kNullObj ) { MDoubleArray col; s = MGlobal::executeCommand( "colorIndex -q 21", col ); assert( s ); IECoreGL::WireframeColorStateComponentPtr hilite = new IECoreGL::WireframeColorStateComponent( Imath::Color4f( col[0], col[1], col[2], 1.0f ) ); MFnSingleIndexedComponent fnComp( request.component(), &s ); assert( s ); int len = fnComp.elementCount( &s ); assert( s ); for ( int j = 0; j < len; j++ ) { int compId = fnComp.element(j); assert( proceduralHolder->m_componentToGroupMap.find( compId ) != proceduralHolder->m_componentToGroupMap.end() ); hiliteGroups( proceduralHolder->m_componentToGroupMap[compId], hilite, const_cast<IECoreGL::WireframeColorStateComponent *>( displayState->get< IECoreGL::WireframeColorStateComponent >() ) ); } } scene->render( displayState ); } } } catch( const IECoreGL::Exception &e ) { // much better to catch and report this than to let the application die IECore::msg( IECore::Msg::Error, "ProceduralHolderUI::draw", boost::format( "IECoreGL Exception : %s" ) % e.what() ); } if( restoreLightState ) { restoreLights( &lightingState ); } view.endGL(); }
bool SceneShapeUI::select( MSelectInfo &selectInfo, MSelectionList &selectionList, MPointArray &worldSpaceSelectPts ) const { MStatus s; // early out if we're not selectable. we always allow components to be selected if we're highlighted, // but we don't allow ourselves to be selected as a whole unless meshes are in the selection mask. // it's not ideal that we act like a mesh, but it's at least consistent with the drawing mask we use. if( selectInfo.displayStatus() != M3dView::kHilite ) { MSelectionMask meshMask( MSelectionMask::kSelectMeshes ); // Apparently selectInfo.selectable() still returns true when meshes are not // displayed by the M3dView, so we are also testing the objectDisplay status. // This was last confirmed in Maya 2014, and is presumably a Maya bug. if( !selectInfo.selectable( meshMask ) || !selectInfo.objectDisplayStatus( M3dView::kDisplayMeshes ) ) { return false; } } // early out if we have no scene to draw SceneShape *sceneShape = static_cast<SceneShape *>( surfaceShape() ); if( !sceneShape->getSceneInterface() ) { return false; } IECoreGL::ConstScenePtr scene = sceneShape->glScene(); if( !scene ) { return false; } // we want to perform the selection using an IECoreGL::Selector, so we // can avoid the performance penalty associated with using GL_SELECT mode. // that means we don't really want to call view.beginSelect(), but we have to // call it just to get the projection matrix for our own selection, because as far // as I can tell, there is no other way of getting it reliably. M3dView view = selectInfo.view(); view.beginSelect(); Imath::M44d projectionMatrix; glGetDoublev( GL_PROJECTION_MATRIX, projectionMatrix.getValue() ); view.endSelect(); view.beginGL(); glMatrixMode( GL_PROJECTION ); glLoadMatrixd( projectionMatrix.getValue() ); IECoreGL::Selector::Mode selectionMode = IECoreGL::Selector::IDRender; if( selectInfo.displayStatus() == M3dView::kHilite && !selectInfo.singleSelection() ) { selectionMode = IECoreGL::Selector::OcclusionQuery; } std::vector<IECoreGL::HitRecord> hits; { IECoreGL::Selector selector( Imath::Box2f( Imath::V2f( 0 ), Imath::V2f( 1 ) ), selectionMode, hits ); IECoreGL::State::bindBaseState(); selector.baseState()->bind(); scene->render( selector.baseState() ); if( selectInfo.displayStatus() != M3dView::kHilite ) { // We're not in component selection mode. We'd like to be able to select the scene shape // using the bounding box so we draw it too but only if it is visible MPlug pDrawBound( sceneShape->thisMObject(), SceneShape::aDrawRootBound ); bool drawBound; pDrawBound.getValue( drawBound ); if( drawBound ) { IECoreGL::BoxPrimitive::renderWireframe( IECore::convert<Imath::Box3f>( sceneShape->boundingBox() ) ); } } } view.endGL(); if( hits.empty() ) { return false; } // iterate over the hits, converting them into components and also finding // the closest one. MIntArray componentIndices; float depthMin = std::numeric_limits<float>::max(); int depthMinIndex = -1; for( unsigned int i=0, e = hits.size(); i < e; i++ ) { if( hits[i].depthMin < depthMin ) { depthMin = hits[i].depthMin; depthMinIndex = componentIndices.length(); } int index = sceneShape->selectionIndex( IECoreGL::NameStateComponent::nameFromGLName( hits[i].name ) ); componentIndices.append( index ); } assert( depthMinIndex >= 0 ); // figure out the world space location of the closest hit MDagPath camera; view.getCamera( camera ); MPoint worldIntersectionPoint; selectionRayToWorldSpacePoint( camera, selectInfo, depthMin, worldIntersectionPoint ); // turn the processed hits into appropriate changes to the current selection if( selectInfo.displayStatus() == M3dView::kHilite ) { // selecting components MFnSingleIndexedComponent fnComponent; MObject component = fnComponent.create( MFn::kMeshPolygonComponent, &s ); assert( s ); if( selectInfo.singleSelection() ) { fnComponent.addElement( componentIndices[depthMinIndex] ); } else { fnComponent.addElements( componentIndices ); } MSelectionList items; items.add( selectInfo.multiPath(), component ); MDagPath path = selectInfo.multiPath(); selectInfo.addSelection( items, worldIntersectionPoint, selectionList, worldSpaceSelectPts, MSelectionMask::kSelectMeshFaces, true ); } else { // Check if we should be able to select that object MPlug pObjectOnly( sceneShape->thisMObject(), SceneShape::aObjectOnly ); bool objectOnly; pObjectOnly.getValue( objectOnly ); if( objectOnly && !sceneShape->getSceneInterface()->hasObject() ) { return true; } // selecting objects MSelectionList item; item.add( selectInfo.selectPath() ); selectInfo.addSelection( item, worldIntersectionPoint, selectionList, worldSpaceSelectPts, MSelectionMask::kSelectMeshes, false ); } return true; }
bool SceneShapeUI::snap( MSelectInfo &snapInfo ) const { MStatus s; if( snapInfo.displayStatus() != M3dView::kHilite ) { MSelectionMask meshMask( MSelectionMask::kSelectMeshes ); if( !snapInfo.selectable( meshMask ) ) { return false; } } // early out if we have no scene to draw SceneShape *sceneShape = static_cast<SceneShape *>( surfaceShape() ); const IECore::SceneInterface *sceneInterface = sceneShape->getSceneInterface().get(); if( !sceneInterface ) { return false; } IECoreGL::ConstScenePtr scene = sceneShape->glScene(); if( !scene ) { return false; } // Get the viewport that the snapping operation is taking place in. M3dView view = snapInfo.view(); // Use an IECoreGL::Selector to find the point in world space that we wish to snap to. // We do this by first getting the origin of the selection ray and transforming it into // NDC space using the OpenGL projection and transformation matrices. Once we have the // point in NDC we can use it to define the viewport that the IECoreGL::Selector will use. MPoint localRayOrigin; MVector localRayDirection; snapInfo.getLocalRay( localRayOrigin, localRayDirection ); Imath::V3d org( localRayOrigin[0], localRayOrigin[1], localRayOrigin[2] ); MDagPath camera; view.getCamera( camera ); MMatrix localToCamera = snapInfo.selectPath().inclusiveMatrix() * camera.inclusiveMatrix().inverse(); view.beginSelect(); Imath::M44d projectionMatrix; glGetDoublev( GL_PROJECTION_MATRIX, projectionMatrix.getValue() ); view.endSelect(); double v[4][4]; localToCamera.get( v ); Imath::M44d cam( v ); Imath::V3d ndcPt3d = ( (org * cam ) * projectionMatrix + Imath::V3d( 1. ) ) * Imath::V3d( .5 ); Imath::V2d ndcPt( std::max( std::min( ndcPt3d[0], 1. ), 0. ), 1. - std::max( std::min( ndcPt3d[1], 1. ), 0. ) ); view.beginGL(); glMatrixMode( GL_PROJECTION ); glLoadMatrixd( projectionMatrix.getValue() ); float radius = .001; // The radius of the selection area in NDC. double aspect = double( view.portWidth() ) / view.portHeight(); Imath::V2f selectionWH( radius, radius * aspect ); std::vector<IECoreGL::HitRecord> hits; { IECoreGL::Selector selector( Imath::Box2f( ndcPt - selectionWH, ndcPt + selectionWH ), IECoreGL::Selector::IDRender, hits ); IECoreGL::State::bindBaseState(); selector.baseState()->bind(); scene->render( selector.baseState() ); } view.endGL(); if( hits.empty() ) { return false; } // Get the closest mesh hit. float depthMin = std::numeric_limits<float>::max(); int depthMinIndex = -1; for( unsigned int i=0, e = hits.size(); i < e; i++ ) { if( hits[i].depthMin < depthMin ) { depthMin = hits[i].depthMin; depthMinIndex = i; } } // Get the absolute path of the hit object. IECore::SceneInterface::Path objPath; std::string objPathStr; sceneInterface->path( objPath ); IECore::SceneInterface::pathToString( objPath, objPathStr ); objPathStr += IECoreGL::NameStateComponent::nameFromGLName( hits[depthMinIndex].name ); IECore::SceneInterface::stringToPath( objPathStr, objPath ); // Validate the hit selection. IECore::ConstSceneInterfacePtr childInterface; try { childInterface = sceneInterface->scene( objPath ); } catch(...) { return false; } if( !childInterface ) { return false; } if( !childInterface->hasObject() ) { return false; } // Get the mesh primitive so that we can query it's vertices. double time = sceneShape->time(); IECore::ConstObjectPtr object = childInterface->readObject( time ); IECore::ConstMeshPrimitivePtr meshPtr = IECore::runTimeCast<const IECore::MeshPrimitive>( object.get() ); if ( !meshPtr ) { return false; } // Calculate the snap point in object space. MPoint worldIntersectionPoint; selectionRayToWorldSpacePoint( camera, snapInfo, depthMin, worldIntersectionPoint ); Imath::V3f pt( worldIntersectionPoint[0], worldIntersectionPoint[1], worldIntersectionPoint[2] ); Imath::M44f objToWorld( worldTransform( childInterface.get(), time ) ); pt = pt * objToWorld.inverse(); // Get the list of vertices in the mesh. IECore::V3fVectorData::ConstPtr pointData( meshPtr->variableData<IECore::V3fVectorData>( "P", IECore::PrimitiveVariable::Vertex ) ); const std::vector<Imath::V3f> &vertices( pointData->readable() ); // Find the vertex that is closest to the snap point. Imath::V3d closestVertex; float closestDistance = std::numeric_limits<float>::max(); for( std::vector<Imath::V3f>::const_iterator it( vertices.begin() ); it != vertices.end(); ++it ) { Imath::V3d vert( *it ); float d( ( pt - vert ).length() ); // Calculate the distance between the vertex and the snap point. if( d < closestDistance ) { closestDistance = d; closestVertex = vert; } } // Snap to the vertex. closestVertex *= objToWorld; snapInfo.setSnapPoint( MPoint( closestVertex[0], closestVertex[1], closestVertex[2] ) ); return true; }
void SceneShapeUI::draw( const MDrawRequest &request, M3dView &view ) const { MStatus s; MDrawData drawData = request.drawData(); SceneShape *sceneShape = (SceneShape *)drawData.geometry(); assert( sceneShape ); view.beginGL(); M3dView::LightingMode lightingMode; view.getLightingMode( lightingMode ); LightingState lightingState; bool restoreLightState = cleanupLights( request, view, &lightingState ); // maya can sometimes leave an error from it's own code, // and we don't want that to confuse us in our drawing code. while( glGetError()!=GL_NO_ERROR ) { } try { // draw the bound if asked if( request.token()==BoundDrawMode ) { IECoreGL::BoxPrimitive::renderWireframe( IECore::convert<Imath::Box3f>( sceneShape->boundingBox() ) ); } // draw the scene if asked if( request.token()==SceneDrawMode ) { resetHilites(); IECoreGL::ConstScenePtr scene = sceneShape->glScene(); if( scene ) { IECoreGL::State *displayState = m_displayStyle.baseState( (M3dView::DisplayStyle)request.displayStyle(), lightingMode ); if ( request.component() != MObject::kNullObj ) { MDoubleArray col; s = MGlobal::executeCommand( "colorIndex -q 21", col ); assert( s ); IECoreGL::WireframeColorStateComponentPtr hilite = new IECoreGL::WireframeColorStateComponent( Imath::Color4f( col[0], col[1], col[2], 1.0f ) ); MFnSingleIndexedComponent fnComp( request.component(), &s ); assert( s ); int len = fnComp.elementCount( &s ); assert( s ); std::vector<IECore::InternedString> groupNames; for ( int j = 0; j < len; j++ ) { int index = fnComp.element(j); groupNames.push_back( sceneShape->selectionName( index ) ); } // Sort by name to make sure we don't unhilite selected items that are further down the hierarchy std::sort( groupNames.begin(), groupNames.end() ); for ( std::vector<IECore::InternedString>::iterator it = groupNames.begin(); it!= groupNames.end(); ++it) { IECoreGL::GroupPtr group = sceneShape->glGroup( *it ); hiliteGroups( group, hilite, const_cast<IECoreGL::WireframeColorStateComponent *>( displayState->get< IECoreGL::WireframeColorStateComponent >() ) ); } } scene->render( displayState ); } } } catch( const IECoreGL::Exception &e ) { // much better to catch and report this than to let the application die IECore::msg( IECore::Msg::Error, "SceneShapeUI::draw", boost::format( "IECoreGL Exception : %s" ) % e.what() ); } if( restoreLightState ) { restoreLights( &lightingState ); } view.endGL(); }