Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions include/IECoreMaya/LiveScene.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,6 @@ class IECOREMAYA_API LiveScene : public IECoreScene::SceneInterface
/// Name of maya attribute overriding `IECoreScene::SceneInterface::visibilityName`
static IECoreScene::SceneInterface::Name visibilityOverrideName;

/// Returns the MDagPath object to the scene node
MDagPath dagPath() const;

/*
* Bounding box
*/
Expand Down Expand Up @@ -188,6 +185,19 @@ class IECOREMAYA_API LiveScene : public IECoreScene::SceneInterface
/// Currently raises an exception
void hash( HashType hashType, double time, IECore::MurmurHash &h ) const override;

/*
* Utility functions
*/

/// Returns the MDagPath object to the scene node
MDagPath dagPath() const;

/// Returns the scene path corresponding to the maya dag path
static void dagPathToPath( MDagPath dagPath, IECoreScene::SceneInterface::Path &path );

/// Returns the maya dag path corresponding to the scene path
static void pathToDagPath( const IECoreScene::SceneInterface::Path &path, MDagPath &dagPath );

/// Translates cortex attribute name to maya attribute name
/// Returns an empty string if there are no valid mappings
static Name toMayaAttributeName( const Name &name );
Expand Down
2 changes: 2 additions & 0 deletions include/IECoreMaya/SceneShapeInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ class IECOREMAYA_API SceneShapeInterface: public MPxComponentShape
const std::vector< IECore::InternedString > & componentNames() const;
/// Return the value of the time plug for the SceneShape.
double time() const;
/// Determines scene visibility while accounting for ancestral visibility overrides
static bool isVisible( const MDagPath &dagPath );

protected :

Expand Down
75 changes: 61 additions & 14 deletions src/IECoreMaya/LiveScene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,20 +206,7 @@ void LiveScene::path( Path &p ) const
throw Exception( "IECoreMaya::LiveScene::path: Dag path no longer exists!" );
}

std::string pathStr( m_dagPath.fullPathName().asChar() );
boost::tokenizer<boost::char_separator<char> > t( pathStr, boost::char_separator<char>( "|" ) );

p.clear();

for (
boost::tokenizer<boost::char_separator<char> >::iterator it = t.begin();
it != t.end();
++it
)
{
p.push_back( Name( *it ) );
}

dagPathToPath( m_dagPath, p );
}

Imath::Box3d LiveScene::readBound( double time ) const
Expand Down Expand Up @@ -1122,6 +1109,66 @@ void LiveScene::hash( HashType hashType, double time, MurmurHash &h ) const
throw Exception( "Hashes currently not supported in IECoreMaya::LiveScene objects." );
}

void LiveScene::dagPathToPath( MDagPath dagPath, IECoreScene::SceneInterface::Path &path )
{
tbb::recursive_mutex::scoped_lock l( g_mutex );
path.clear();

if( dagPath.isValid() )
{
// Only transforms can be part of the path
if( !dagPath.hasFn( MFn::kTransform ) )
{
dagPath.pop();
}

const std::string pathStr( dagPath.fullPathName().asChar() );
const boost::tokenizer< boost::char_separator<char> > tokens( pathStr, boost::char_separator<char>( "|" ) );
for ( const auto &token : tokens )
{
path.push_back( token );
}

return;
}

throw Exception( "IECoreMaya::LiveScene::dagPathToPath invalid dag path." );
}

void LiveScene::pathToDagPath( const IECoreScene::SceneInterface::Path &path, MDagPath &dagPath )
{
tbb::recursive_mutex::scoped_lock l( g_mutex );

if( path.empty() )
{
MItDag itDag;
itDag.getPath( dagPath );
return;
}

std::string dagPathStr;
for( const auto &name : path )
{
dagPathStr += "|";
dagPathStr += name;
}

MSelectionList sel;
if( sel.add( dagPathStr.c_str() ) && sel.getDagPath( 0, dagPath ) )
{
return;
}

// Invalid dag path
std::string pathStr;
IECoreScene::SceneInterface::pathToString( path, pathStr );
throw Exception(
boost::str(
boost::format( "IECoreMaya::LiveScene::pathToDagPath invalid conversion to dag path from \"%1%\"." ) % pathStr
)
);
}

void LiveScene::registerCustomObject( HasFn hasFn, ReadFn readFn )
{
CustomReader r;
Expand Down
34 changes: 34 additions & 0 deletions src/IECoreMaya/SceneShapeInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#include "IECoreMaya/ToMayaCurveConverter.h"
#include "IECoreMaya/MayaTypeIds.h"
#include "IECoreMaya/PostLoadCallback.h"
#include "IECoreMaya/LiveScene.h"

#include "IECorePython/ScopedGILLock.h"
#include "IECorePython/ScopedGILRelease.h"
Expand Down Expand Up @@ -97,6 +98,7 @@
#include "maya/MFnGeometryData.h"
#include "maya/MPlugArray.h"
#include "maya/MFileIO.h"
#include "maya/MAnimControl.h"

#if MAYA_API_VERSION >= 201600

Expand Down Expand Up @@ -539,6 +541,38 @@ double SceneShapeInterface::time() const
return time.as( MTime::kSeconds );
}

bool SceneShapeInterface::isVisible( const MDagPath &dagPath )
{
// Let maya check for basic dag visibility
// Maya handles hidden shapes, display layers, render layers, and intermediate objects
if( !dagPath.isVisible() )
{
return false;
}

// Check for ancestral visibility via LiveScene which accounts for visibility overrides which are not exposed to maya
IECoreMaya::ConstLiveScenePtr liveScene = new IECoreMaya::LiveScene();
const double currentTime = MAnimControl::currentTime().as( MTime::kSeconds );

SceneInterface::Path scenePath;
IECoreMaya::LiveScene::dagPathToPath( dagPath, scenePath );
const size_t pathLength = scenePath.size();
for( size_t i = 0; i < pathLength; ++i )
{
ConstSceneInterfacePtr scene = liveScene->scene( scenePath );
ConstBoolDataPtr liveSceneVisibility = runTimeCast<const BoolData>( scene->readAttribute( SceneInterface::visibilityName, currentTime ) );
if( liveSceneVisibility && !liveSceneVisibility->readable() )
{
// Not visible due to a visibility override
return false;
}

scenePath.pop_back();
}

return true;
}

MBoundingBox SceneShapeInterface::boundingBox() const
{
MBoundingBox bound( MPoint( -1, -1, -1 ), MPoint( 1, 1, 1 ) );
Expand Down
74 changes: 43 additions & 31 deletions src/IECoreMaya/SceneShapeSubSceneOverride.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1121,17 +1121,22 @@ bool SceneShapeSubSceneOverride::requiresUpdate(const MSubSceneContainer& contai
{
allInvisibleByFilter = true;

MObject component;
MSelectionList viewSelectedSet;
view.filteredObjectList( viewSelectedSet );
// Create a selection list of the dagPaths which are visible after the view is filtered
MSelectionList visibleList;
view.filteredObjectList( visibleList );

for( size_t i = 0; i < dagPaths.length(); ++i )
// Create a selection list with all of our dag paths
MSelectionList dagPathList;
for( const auto &dagPath : dagPaths )
{
if( viewSelectedSet.hasItemPartly( dagPaths[i], component ) )
{
allInvisibleByFilter = false;
break;
}
dagPathList.add( dagPath );
}

// Intersect the two lists to determine if any of our dag paths remain unfiltered
visibleList.intersect( dagPathList, true );
if( !visibleList.isEmpty() )
{
allInvisibleByFilter = false;
}
}

Expand Down Expand Up @@ -1360,22 +1365,31 @@ void SceneShapeSubSceneOverride::update( MSubSceneContainer& container, const MF
M3dView view;
MString panelName;
MSelectionList viewSelectedSet;
MObject component;
frameContext.renderingDestination( panelName );
M3dView::getM3dViewFromModelPanel( panelName, view );
view.filteredObjectList( viewSelectedSet );

bool allInvisibleByFilter = false;
if ( view.viewIsFiltered() )
if( view.viewIsFiltered() )
{
allInvisibleByFilter = true;
for( auto &instance : m_instances )

// Create a selection list of the dagPaths which are visible after the view is filtered
MSelectionList visibleList;
view.filteredObjectList( visibleList );

// Create a selection list with all of our dag paths
MSelectionList dagPathList;
for( const auto &instance : m_instances )
{
if ( viewSelectedSet.hasItemPartly( instance.path, component ) )
{
allInvisibleByFilter = false;
break;
}
dagPathList.add( instance.path );
}

// Intersect the two lists to determine if any of our dag paths remain unfiltered
visibleList.intersect( dagPathList, true );
if( !visibleList.isEmpty() )
{
allInvisibleByFilter = false;
}
}

Expand Down Expand Up @@ -1404,6 +1418,16 @@ void SceneShapeSubSceneOverride::visitSceneLocations( const SceneInterface *scen
return;
}

// respect visibility attribute
if( sceneInterface->hasAttribute( SceneInterface::visibilityName ) )
{
ConstBoolDataPtr vis = runTimeCast<const BoolData>( sceneInterface->readAttribute( SceneInterface::visibilityName, m_time ) );
if( vis && !vis->readable() )
{
return;
}
}

MMatrix accumulatedMatrix;
if( !isRoot )
{
Expand All @@ -1430,7 +1454,6 @@ void SceneShapeSubSceneOverride::visitSceneLocations( const SceneInterface *scen
}

// Now handle current location.

if( isRoot )
{
// override relative location for root as it would otherwise be empty
Expand Down Expand Up @@ -1469,16 +1492,6 @@ void SceneShapeSubSceneOverride::visitSceneLocations( const SceneInterface *scen
return;
}

// respect visibility attribute
if( sceneInterface->hasAttribute( "scene:visible" ) )
{
ConstBoolDataPtr vis = runTimeCast<const BoolData>( sceneInterface->readAttribute( "scene:visible", m_time ) );
if( vis && !vis->readable() )
{
return;
}
}

IECore::ConstObjectPtr object = sceneInterface->readObject( m_time );
if( !objectCanBeRendered( object ) )
{
Expand Down Expand Up @@ -1924,16 +1937,15 @@ void SceneShapeSubSceneOverride::collectInstances( Instances &instances ) const
MDagPathArray dagPaths;
dagNode.getAllPaths(dagPaths);
size_t numInstances = dagPaths.length();

instances.reserve( numInstances );

for( size_t pathIndex = 0; pathIndex < numInstances; ++pathIndex )
{
MDagPath& path = dagPaths[pathIndex];
MMatrix matrix = path.inclusiveMatrix();
bool pathSelected = isPathSelected( selectionList, path );
bool componentMode = componentsSelectable( path );
MFnDagNode nodeFn( path );
bool visible = path.isVisible();
bool visible = IECoreMaya::SceneShapeInterface::isVisible( path );

instances.emplace_back( matrix, pathSelected, componentMode, path, visible );
}
Expand Down
7 changes: 7 additions & 0 deletions src/IECoreMaya/SceneShapeUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@ void SceneShapeUI::getDrawRequests( const MDrawInfo &info, bool objectAndActiveO
{
return;
}

// make sure we don't have an ancestral visibility override which makes us invisible
if( !SceneShapeInterface::isVisible( info.multiPath() ) )
{
return;
}

// the node we're meant to be drawing
SceneShape *sceneShape = (SceneShape *)surfaceShape();

Expand Down
42 changes: 42 additions & 0 deletions src/IECoreMaya/bindings/LiveSceneBinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,45 @@ void registerCustomAttributes( object namesFn, object readFn, object mightHaveFn
}
}

inline std::string dagPath( object liveSceneObject )
{
const LiveScene &liveScene = extract<const LiveScene&>( liveSceneObject );
return liveScene.dagPath().fullPathName().asChar();
}

inline list dagPathToPath( object dagObj )
{
list pathList;
extract<MDagPath> dagPath( dagObj );

// Return the root path (an empty list) if we are given an empty string
// Maya doesn't really have a "root" dag path, so this is as close as we can get while simultaneously
// ensuring dagPathToPath( pathToDagPath( [] ) ) == []
if( dagPath.check() && len( dagObj ) == 0 )
{
return pathList;
}

// Get the path, or throw if the dag path object is invalid
IECoreScene::SceneInterface::Path path;
LiveScene::dagPathToPath( dagPath(), path );
for(const auto &name : path )
{
pathList.append( name.string() );
}
return pathList;
}

inline std::string pathToDagPath( list pathList )
{
IECoreScene::SceneInterface::Path path;
container_utils::extend_container( path, pathList );

MDagPath dagPath;
LiveScene::pathToDagPath( path, dagPath );
return dagPath.fullPathName().asChar();
}

} // namespace

void IECoreMaya::bindLiveScene()
Expand All @@ -206,6 +245,9 @@ void IECoreMaya::bindLiveScene()
.def( init<>() )
.def( "registerCustomTags", registerCustomTags, ( arg_( "hasFn" ), arg_( "readFn" ) ) ).staticmethod( "registerCustomTags" )
.def( "registerCustomAttributes", registerCustomAttributes, ( arg_( "namesFn" ), arg_( "readFn" ), arg_( "mightHaveFn" ) = object() ) ).staticmethod( "registerCustomAttributes" )
.def( "dagPath", ::dagPath )
.def( "dagPathToPath", ::dagPathToPath ).staticmethod( "dagPathToPath" )
.def( "pathToDagPath", ::pathToDagPath ).staticmethod( "pathToDagPath" )
.def( "toMayaAttributeName", LiveScene::toMayaAttributeName ).staticmethod( "toMayaAttributeName" )
.def( "fromMayaAttributeName", LiveScene::fromMayaAttributeName ).staticmethod( "fromMayaAttributeName" )
.def_readonly("visibilityOverrideName", LiveScene::visibilityOverrideName )
Expand Down
Loading