Skip to content

Commit 355ff7a

Browse files
authored
Merge pull request #1290 from bradleyhenke/vp2_sceneShapeVisibility
IECoreMaya : Fixed various SceneShape drawing bugs.
2 parents 327ae19 + 99159eb commit 355ff7a

File tree

8 files changed

+252
-48
lines changed

8 files changed

+252
-48
lines changed

include/IECoreMaya/LiveScene.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,6 @@ class IECOREMAYA_API LiveScene : public IECoreScene::SceneInterface
7878
/// Name of maya attribute overriding `IECoreScene::SceneInterface::visibilityName`
7979
static IECoreScene::SceneInterface::Name visibilityOverrideName;
8080

81-
/// Returns the MDagPath object to the scene node
82-
MDagPath dagPath() const;
83-
8481
/*
8582
* Bounding box
8683
*/
@@ -188,6 +185,19 @@ class IECOREMAYA_API LiveScene : public IECoreScene::SceneInterface
188185
/// Currently raises an exception
189186
void hash( HashType hashType, double time, IECore::MurmurHash &h ) const override;
190187

188+
/*
189+
* Utility functions
190+
*/
191+
192+
/// Returns the MDagPath object to the scene node
193+
MDagPath dagPath() const;
194+
195+
/// Returns the scene path corresponding to the maya dag path
196+
static void dagPathToPath( MDagPath dagPath, IECoreScene::SceneInterface::Path &path );
197+
198+
/// Returns the maya dag path corresponding to the scene path
199+
static void pathToDagPath( const IECoreScene::SceneInterface::Path &path, MDagPath &dagPath );
200+
191201
/// Translates cortex attribute name to maya attribute name
192202
/// Returns an empty string if there are no valid mappings
193203
static Name toMayaAttributeName( const Name &name );

include/IECoreMaya/SceneShapeInterface.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ class IECOREMAYA_API SceneShapeInterface: public MPxComponentShape
138138
const std::vector< IECore::InternedString > & componentNames() const;
139139
/// Return the value of the time plug for the SceneShape.
140140
double time() const;
141+
/// Determines scene visibility while accounting for ancestral visibility overrides
142+
static bool isVisible( const MDagPath &dagPath );
141143

142144
protected :
143145

src/IECoreMaya/LiveScene.cpp

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -206,20 +206,7 @@ void LiveScene::path( Path &p ) const
206206
throw Exception( "IECoreMaya::LiveScene::path: Dag path no longer exists!" );
207207
}
208208

209-
std::string pathStr( m_dagPath.fullPathName().asChar() );
210-
boost::tokenizer<boost::char_separator<char> > t( pathStr, boost::char_separator<char>( "|" ) );
211-
212-
p.clear();
213-
214-
for (
215-
boost::tokenizer<boost::char_separator<char> >::iterator it = t.begin();
216-
it != t.end();
217-
++it
218-
)
219-
{
220-
p.push_back( Name( *it ) );
221-
}
222-
209+
dagPathToPath( m_dagPath, p );
223210
}
224211

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

1112+
void LiveScene::dagPathToPath( MDagPath dagPath, IECoreScene::SceneInterface::Path &path )
1113+
{
1114+
tbb::recursive_mutex::scoped_lock l( g_mutex );
1115+
path.clear();
1116+
1117+
if( dagPath.isValid() )
1118+
{
1119+
// Only transforms can be part of the path
1120+
if( !dagPath.hasFn( MFn::kTransform ) )
1121+
{
1122+
dagPath.pop();
1123+
}
1124+
1125+
const std::string pathStr( dagPath.fullPathName().asChar() );
1126+
const boost::tokenizer< boost::char_separator<char> > tokens( pathStr, boost::char_separator<char>( "|" ) );
1127+
for ( const auto &token : tokens )
1128+
{
1129+
path.push_back( token );
1130+
}
1131+
1132+
return;
1133+
}
1134+
1135+
throw Exception( "IECoreMaya::LiveScene::dagPathToPath invalid dag path." );
1136+
}
1137+
1138+
void LiveScene::pathToDagPath( const IECoreScene::SceneInterface::Path &path, MDagPath &dagPath )
1139+
{
1140+
tbb::recursive_mutex::scoped_lock l( g_mutex );
1141+
1142+
if( path.empty() )
1143+
{
1144+
MItDag itDag;
1145+
itDag.getPath( dagPath );
1146+
return;
1147+
}
1148+
1149+
std::string dagPathStr;
1150+
for( const auto &name : path )
1151+
{
1152+
dagPathStr += "|";
1153+
dagPathStr += name;
1154+
}
1155+
1156+
MSelectionList sel;
1157+
if( sel.add( dagPathStr.c_str() ) && sel.getDagPath( 0, dagPath ) )
1158+
{
1159+
return;
1160+
}
1161+
1162+
// Invalid dag path
1163+
std::string pathStr;
1164+
IECoreScene::SceneInterface::pathToString( path, pathStr );
1165+
throw Exception(
1166+
boost::str(
1167+
boost::format( "IECoreMaya::LiveScene::pathToDagPath invalid conversion to dag path from \"%1%\"." ) % pathStr
1168+
)
1169+
);
1170+
}
1171+
11251172
void LiveScene::registerCustomObject( HasFn hasFn, ReadFn readFn )
11261173
{
11271174
CustomReader r;

src/IECoreMaya/SceneShapeInterface.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include "IECoreMaya/ToMayaCurveConverter.h"
5858
#include "IECoreMaya/MayaTypeIds.h"
5959
#include "IECoreMaya/PostLoadCallback.h"
60+
#include "IECoreMaya/LiveScene.h"
6061

6162
#include "IECorePython/ScopedGILLock.h"
6263
#include "IECorePython/ScopedGILRelease.h"
@@ -97,6 +98,7 @@
9798
#include "maya/MFnGeometryData.h"
9899
#include "maya/MPlugArray.h"
99100
#include "maya/MFileIO.h"
101+
#include "maya/MAnimControl.h"
100102

101103
#if MAYA_API_VERSION >= 201600
102104

@@ -539,6 +541,38 @@ double SceneShapeInterface::time() const
539541
return time.as( MTime::kSeconds );
540542
}
541543

544+
bool SceneShapeInterface::isVisible( const MDagPath &dagPath )
545+
{
546+
// Let maya check for basic dag visibility
547+
// Maya handles hidden shapes, display layers, render layers, and intermediate objects
548+
if( !dagPath.isVisible() )
549+
{
550+
return false;
551+
}
552+
553+
// Check for ancestral visibility via LiveScene which accounts for visibility overrides which are not exposed to maya
554+
IECoreMaya::ConstLiveScenePtr liveScene = new IECoreMaya::LiveScene();
555+
const double currentTime = MAnimControl::currentTime().as( MTime::kSeconds );
556+
557+
SceneInterface::Path scenePath;
558+
IECoreMaya::LiveScene::dagPathToPath( dagPath, scenePath );
559+
const size_t pathLength = scenePath.size();
560+
for( size_t i = 0; i < pathLength; ++i )
561+
{
562+
ConstSceneInterfacePtr scene = liveScene->scene( scenePath );
563+
ConstBoolDataPtr liveSceneVisibility = runTimeCast<const BoolData>( scene->readAttribute( SceneInterface::visibilityName, currentTime ) );
564+
if( liveSceneVisibility && !liveSceneVisibility->readable() )
565+
{
566+
// Not visible due to a visibility override
567+
return false;
568+
}
569+
570+
scenePath.pop_back();
571+
}
572+
573+
return true;
574+
}
575+
542576
MBoundingBox SceneShapeInterface::boundingBox() const
543577
{
544578
MBoundingBox bound( MPoint( -1, -1, -1 ), MPoint( 1, 1, 1 ) );

src/IECoreMaya/SceneShapeSubSceneOverride.cpp

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,17 +1121,22 @@ bool SceneShapeSubSceneOverride::requiresUpdate(const MSubSceneContainer& contai
11211121
{
11221122
allInvisibleByFilter = true;
11231123

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

1128-
for( size_t i = 0; i < dagPaths.length(); ++i )
1128+
// Create a selection list with all of our dag paths
1129+
MSelectionList dagPathList;
1130+
for( const auto &dagPath : dagPaths )
11291131
{
1130-
if( viewSelectedSet.hasItemPartly( dagPaths[i], component ) )
1131-
{
1132-
allInvisibleByFilter = false;
1133-
break;
1134-
}
1132+
dagPathList.add( dagPath );
1133+
}
1134+
1135+
// Intersect the two lists to determine if any of our dag paths remain unfiltered
1136+
visibleList.intersect( dagPathList, true );
1137+
if( !visibleList.isEmpty() )
1138+
{
1139+
allInvisibleByFilter = false;
11351140
}
11361141
}
11371142

@@ -1360,22 +1365,31 @@ void SceneShapeSubSceneOverride::update( MSubSceneContainer& container, const MF
13601365
M3dView view;
13611366
MString panelName;
13621367
MSelectionList viewSelectedSet;
1363-
MObject component;
13641368
frameContext.renderingDestination( panelName );
13651369
M3dView::getM3dViewFromModelPanel( panelName, view );
13661370
view.filteredObjectList( viewSelectedSet );
13671371

13681372
bool allInvisibleByFilter = false;
1369-
if ( view.viewIsFiltered() )
1373+
if( view.viewIsFiltered() )
13701374
{
13711375
allInvisibleByFilter = true;
1372-
for( auto &instance : m_instances )
1376+
1377+
// Create a selection list of the dagPaths which are visible after the view is filtered
1378+
MSelectionList visibleList;
1379+
view.filteredObjectList( visibleList );
1380+
1381+
// Create a selection list with all of our dag paths
1382+
MSelectionList dagPathList;
1383+
for( const auto &instance : m_instances )
13731384
{
1374-
if ( viewSelectedSet.hasItemPartly( instance.path, component ) )
1375-
{
1376-
allInvisibleByFilter = false;
1377-
break;
1378-
}
1385+
dagPathList.add( instance.path );
1386+
}
1387+
1388+
// Intersect the two lists to determine if any of our dag paths remain unfiltered
1389+
visibleList.intersect( dagPathList, true );
1390+
if( !visibleList.isEmpty() )
1391+
{
1392+
allInvisibleByFilter = false;
13791393
}
13801394
}
13811395

@@ -1404,6 +1418,16 @@ void SceneShapeSubSceneOverride::visitSceneLocations( const SceneInterface *scen
14041418
return;
14051419
}
14061420

1421+
// respect visibility attribute
1422+
if( sceneInterface->hasAttribute( SceneInterface::visibilityName ) )
1423+
{
1424+
ConstBoolDataPtr vis = runTimeCast<const BoolData>( sceneInterface->readAttribute( SceneInterface::visibilityName, m_time ) );
1425+
if( vis && !vis->readable() )
1426+
{
1427+
return;
1428+
}
1429+
}
1430+
14071431
MMatrix accumulatedMatrix;
14081432
if( !isRoot )
14091433
{
@@ -1430,7 +1454,6 @@ void SceneShapeSubSceneOverride::visitSceneLocations( const SceneInterface *scen
14301454
}
14311455

14321456
// Now handle current location.
1433-
14341457
if( isRoot )
14351458
{
14361459
// override relative location for root as it would otherwise be empty
@@ -1469,16 +1492,6 @@ void SceneShapeSubSceneOverride::visitSceneLocations( const SceneInterface *scen
14691492
return;
14701493
}
14711494

1472-
// respect visibility attribute
1473-
if( sceneInterface->hasAttribute( "scene:visible" ) )
1474-
{
1475-
ConstBoolDataPtr vis = runTimeCast<const BoolData>( sceneInterface->readAttribute( "scene:visible", m_time ) );
1476-
if( vis && !vis->readable() )
1477-
{
1478-
return;
1479-
}
1480-
}
1481-
14821495
IECore::ConstObjectPtr object = sceneInterface->readObject( m_time );
14831496
if( !objectCanBeRendered( object ) )
14841497
{
@@ -1924,16 +1937,15 @@ void SceneShapeSubSceneOverride::collectInstances( Instances &instances ) const
19241937
MDagPathArray dagPaths;
19251938
dagNode.getAllPaths(dagPaths);
19261939
size_t numInstances = dagPaths.length();
1927-
19281940
instances.reserve( numInstances );
1941+
19291942
for( size_t pathIndex = 0; pathIndex < numInstances; ++pathIndex )
19301943
{
19311944
MDagPath& path = dagPaths[pathIndex];
19321945
MMatrix matrix = path.inclusiveMatrix();
19331946
bool pathSelected = isPathSelected( selectionList, path );
19341947
bool componentMode = componentsSelectable( path );
1935-
MFnDagNode nodeFn( path );
1936-
bool visible = path.isVisible();
1948+
bool visible = IECoreMaya::SceneShapeInterface::isVisible( path );
19371949

19381950
instances.emplace_back( matrix, pathSelected, componentMode, path, visible );
19391951
}

src/IECoreMaya/SceneShapeUI.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@ void SceneShapeUI::getDrawRequests( const MDrawInfo &info, bool objectAndActiveO
102102
{
103103
return;
104104
}
105+
106+
// make sure we don't have an ancestral visibility override which makes us invisible
107+
if( !SceneShapeInterface::isVisible( info.multiPath() ) )
108+
{
109+
return;
110+
}
111+
105112
// the node we're meant to be drawing
106113
SceneShape *sceneShape = (SceneShape *)surfaceShape();
107114

src/IECoreMaya/bindings/LiveSceneBinding.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,45 @@ void registerCustomAttributes( object namesFn, object readFn, object mightHaveFn
198198
}
199199
}
200200

201+
inline std::string dagPath( object liveSceneObject )
202+
{
203+
const LiveScene &liveScene = extract<const LiveScene&>( liveSceneObject );
204+
return liveScene.dagPath().fullPathName().asChar();
205+
}
206+
207+
inline list dagPathToPath( object dagObj )
208+
{
209+
list pathList;
210+
extract<MDagPath> dagPath( dagObj );
211+
212+
// Return the root path (an empty list) if we are given an empty string
213+
// Maya doesn't really have a "root" dag path, so this is as close as we can get while simultaneously
214+
// ensuring dagPathToPath( pathToDagPath( [] ) ) == []
215+
if( dagPath.check() && len( dagObj ) == 0 )
216+
{
217+
return pathList;
218+
}
219+
220+
// Get the path, or throw if the dag path object is invalid
221+
IECoreScene::SceneInterface::Path path;
222+
LiveScene::dagPathToPath( dagPath(), path );
223+
for(const auto &name : path )
224+
{
225+
pathList.append( name.string() );
226+
}
227+
return pathList;
228+
}
229+
230+
inline std::string pathToDagPath( list pathList )
231+
{
232+
IECoreScene::SceneInterface::Path path;
233+
container_utils::extend_container( path, pathList );
234+
235+
MDagPath dagPath;
236+
LiveScene::pathToDagPath( path, dagPath );
237+
return dagPath.fullPathName().asChar();
238+
}
239+
201240
} // namespace
202241

203242
void IECoreMaya::bindLiveScene()
@@ -206,6 +245,9 @@ void IECoreMaya::bindLiveScene()
206245
.def( init<>() )
207246
.def( "registerCustomTags", registerCustomTags, ( arg_( "hasFn" ), arg_( "readFn" ) ) ).staticmethod( "registerCustomTags" )
208247
.def( "registerCustomAttributes", registerCustomAttributes, ( arg_( "namesFn" ), arg_( "readFn" ), arg_( "mightHaveFn" ) = object() ) ).staticmethod( "registerCustomAttributes" )
248+
.def( "dagPath", ::dagPath )
249+
.def( "dagPathToPath", ::dagPathToPath ).staticmethod( "dagPathToPath" )
250+
.def( "pathToDagPath", ::pathToDagPath ).staticmethod( "pathToDagPath" )
209251
.def( "toMayaAttributeName", LiveScene::toMayaAttributeName ).staticmethod( "toMayaAttributeName" )
210252
.def( "fromMayaAttributeName", LiveScene::fromMayaAttributeName ).staticmethod( "fromMayaAttributeName" )
211253
.def_readonly("visibilityOverrideName", LiveScene::visibilityOverrideName )

0 commit comments

Comments
 (0)