IECore::ConstCompoundObjectPtr DeleteGlobals::computeProcessedGlobals( const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputGlobals ) const { if( inputGlobals->members().empty() ) { return inputGlobals; } const std::string names = namesPlug()->getValue(); const bool invert = invertNamesPlug()->getValue(); if( !invert && !names.size() ) { return inputGlobals; } const std::string prefix = namePrefix(); IECore::CompoundObjectPtr result = new IECore::CompoundObject; for( IECore::CompoundObject::ObjectMap::const_iterator it = inputGlobals->members().begin(), eIt = inputGlobals->members().end(); it != eIt; ++it ) { bool keep = true; if( boost::starts_with( it->first.c_str(), prefix ) ) { if( matchMultiple( it->first.c_str() + prefix.size(), names.c_str() ) != invert ) { keep = false; } } if( keep ) { result->members()[it->first] = it->second; } } return result; }
IECore::ConstCompoundObjectPtr AttributeProcessor::computeProcessedAttributes( const ScenePath &path, const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputAttributes ) const { if( inputAttributes->members().empty() ) { return inputAttributes; } const std::string names = namesPlug()->getValue(); const bool invert = invertNamesPlug()->getValue(); CompoundObjectPtr result = new CompoundObject; for( CompoundObject::ObjectMap::const_iterator it = inputAttributes->members().begin(), eIt = inputAttributes->members().end(); it != eIt; ++it ) { ConstObjectPtr attribute = it->second; if( matchMultiple( it->first, names ) != invert ) { attribute = processAttribute( path, context, it->first, attribute.get() ); } if( attribute ) { result->members().insert( CompoundObject::ObjectMap::value_type( it->first, // cast is ok - result is const immediately on // returning from this function, and attribute will // therefore not be modified. boost::const_pointer_cast<Object>( attribute ) ) ); } } return result; }
IECore::CompoundObjectPtr ScenePlug::fullAttributes( const ScenePath &scenePath ) const { ContextPtr tmpContext = new Context( *Context::current(), Context::Borrowed ); Context::Scope scopedContext( tmpContext.get() ); IECore::CompoundObjectPtr result = new IECore::CompoundObject; IECore::CompoundObject::ObjectMap &resultMembers = result->members(); ScenePath path( scenePath ); while( path.size() ) { tmpContext->set( scenePathContextName, path ); IECore::ConstCompoundObjectPtr a = attributesPlug()->getValue(); const IECore::CompoundObject::ObjectMap &aMembers = a->members(); for( IECore::CompoundObject::ObjectMap::const_iterator it = aMembers.begin(), eIt = aMembers.end(); it != eIt; it++ ) { if( resultMembers.find( it->first ) == resultMembers.end() ) { resultMembers.insert( *it ); } } path.pop_back(); } return result; }
void InteractiveRender::updateLights() { if( !m_lightsDirty || !updateLightsPlug()->getValue() ) { return; } IECore::ConstCompoundObjectPtr globals = inPlug()->globalsPlug()->getValue(); outputLightsInternal( globals.get(), /* editing = */ true ); m_lightsDirty = false; }
void InteractiveRender::updateCamera() { if( !m_cameraDirty || !updateCameraPlug()->getValue() ) { return; } IECore::ConstCompoundObjectPtr globals = inPlug()->globalsPlug()->getValue(); { EditBlock edit( m_renderer.get(), "option", CompoundDataMap() ); outputCamera( inPlug(), globals.get(), m_renderer.get() ); } m_cameraDirty = false; }
void InteractiveRender::updateCoordinateSystems() { if( !m_coordinateSystemsDirty || !updateCoordinateSystemsPlug()->getValue() ) { return; } IECore::ConstCompoundObjectPtr globals = inPlug()->globalsPlug()->getValue(); { EditBlock edit( m_renderer.get(), "attribute", CompoundDataMap() ); outputCoordinateSystems( inPlug(), globals.get(), m_renderer.get() ); } m_coordinateSystemsDirty = false; }
IECore::ConstCompoundObjectPtr Options::computeProcessedGlobals( const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputGlobals ) const { const CompoundDataPlug *p = optionsPlug(); if( !p->children().size() ) { return inputGlobals; } IECore::CompoundObjectPtr result = new IECore::CompoundObject; // Since we're not going to modify any existing members (only add new ones), // and our result becomes const on returning it, we can directly reference // the input members in our result without copying. Be careful not to modify // them though! result->members() = inputGlobals->members(); const std::string prefix = computePrefix( context ); std::string name; for( NameValuePlugIterator it( p ); !it.done(); ++it ) { IECore::DataPtr d = p->memberDataAndName( it->get(), name ); if( d ) { result->members()[prefix + name] = d; } } return result; }
IECore::ConstCompoundObjectPtr Displays::computeProcessedGlobals( const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputGlobals ) const { const CompoundPlug *dsp = displaysPlug(); if( !dsp->children().size() ) { return inputGlobals; } CompoundObjectPtr result = inputGlobals->copy(); // add our displays to the result for( InputCompoundPlugIterator it( dsp ); it != it.end(); it++ ) { const CompoundPlug *displayPlug = *it; if( displayPlug->getChild<BoolPlug>( "active" )->getValue() ) { std::string name = displayPlug->getChild<StringPlug>( "name" )->getValue(); std::string type = displayPlug->getChild<StringPlug>( "type" )->getValue(); std::string data = displayPlug->getChild<StringPlug>( "data" )->getValue(); if( name.size() && type.size() && data.size() ) { DisplayPtr d = new Display( name, type, data ); displayPlug->getChild<CompoundDataPlug>( "parameters" )->fillCompoundData( d->parameters() ); result->members()["display:" + name] = d; } } } return result; }
IECore::ConstCompoundObjectPtr Set::computeProcessedGlobals( const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputGlobals ) const { std::string name = namePlug()->getValue(); if( !name.size() ) { return inputGlobals; } IECore::CompoundObjectPtr result = new IECore::CompoundObject; // Since we're not going to modify any existing members other than the sets, // and our result becomes const on returning it, we can directly reference // the input members in our result without copying. We have to be careful not // to modify the input sets though. result->members() = inputGlobals->members(); CompoundDataPtr sets = new CompoundData; if( const CompoundData *inputSets = inputGlobals->member<CompoundData>( "gaffer:sets" ) ) { sets->writable() = inputSets->readable(); } result->members()["gaffer:sets"] = sets; ConstObjectPtr set = pathMatcherPlug()->getValue(); // const cast is acceptable because we're just using it to place a const object into a // container that will be treated as const everywhere immediately after return from this method. sets->writable()[name] = const_cast<Data *>( static_cast<const Data *>( set.get() ) ); return result; }
IECore::ConstCompoundObjectPtr Attributes::computeProcessedAttributes( const ScenePath &path, const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputAttributes ) const { const CompoundDataPlug *ap = attributesPlug(); if( !ap->children().size() ) { return inputAttributes; } /// \todo You might think that we wouldn't have to check this again /// because the base class would have used processesAttributes() /// to avoid even calling this function. But that isn't the case for /// some reason. if( globalPlug()->getValue() ) { return inputAttributes; } CompoundObjectPtr result = new CompoundObject; // Since we're not going to modify any existing members (only add new ones), // and our result becomes const on returning it, we can directly reference // the input members in our result without copying. Be careful not to modify // them though! result->members() = inputAttributes->members(); ap->fillCompoundObject( result->members() ); return result; }
IECore::ConstCompoundObjectPtr AttributeProcessor::computeProcessedAttributes( const ScenePath &path, const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputAttributes ) const { if( inputAttributes->members().empty() ) { return inputAttributes; } /// \todo See todos about name matching in PrimitiveVariableProcessor. typedef boost::tokenizer<boost::char_separator<char> > Tokenizer; std::string namesValue = namesPlug()->getValue(); Tokenizer names( namesValue, boost::char_separator<char>( " " ) ); bool invert = invertNamesPlug()->getValue(); CompoundObjectPtr result = new CompoundObject; IECore::PrimitiveVariableMap::iterator next; for( CompoundObject::ObjectMap::const_iterator it = inputAttributes->members().begin(), eIt = inputAttributes->members().end(); it != eIt; ++it ) { ConstObjectPtr attribute = it->second; bool found = std::find( names.begin(), names.end(), it->first.string() ) != names.end(); if( found != invert ) { attribute = processAttribute( path, context, it->first, attribute.get() ); } if( attribute ) { result->members().insert( CompoundObject::ObjectMap::value_type( it->first, // cast is ok - result is const immediately on // returning from this function, and attribute will // therefore not be modified. constPointerCast<Object>( attribute ) ) ); } } return result; }
IECore::ConstCompoundObjectPtr Outputs::computeProcessedGlobals( const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputGlobals ) const { const CompoundPlug *dsp = outputsPlug(); if( !dsp->children().size() ) { return inputGlobals; } IECore::CompoundObjectPtr result = new IECore::CompoundObject; // Since we're not going to modify any existing members (only add new ones), // and our result becomes const on returning it, we can directly reference // the input members in our result without copying. Be careful not to modify // them though! result->members() = inputGlobals->members(); // add our outputs to the result for( InputCompoundPlugIterator it( dsp ); it != it.end(); it++ ) { const CompoundPlug *outputPlug = it->get(); if( outputPlug->getChild<BoolPlug>( "active" )->getValue() ) { // backwards compatibility with old plug layout const StringPlug *namePlug = outputPlug->getChild<StringPlug>( "label" ); if( !namePlug ) { namePlug = outputPlug->getChild<StringPlug>( "name" ); } const std::string name = namePlug->getValue(); const StringPlug *fileNamePlug = outputPlug->getChild<StringPlug>( "fileName" ); if( !fileNamePlug ) { // backwards compatibility with old plug layout fileNamePlug = outputPlug->getChild<StringPlug>( "name" ); } const std::string fileName = fileNamePlug->getValue(); const std::string type = outputPlug->getChild<StringPlug>( "type" )->getValue(); const std::string data = outputPlug->getChild<StringPlug>( "data" )->getValue(); if( name.size() && fileName.size() && type.size() && data.size() ) { DisplayPtr d = new Display( fileName, type, data ); outputPlug->getChild<CompoundDataPlug>( "parameters" )->fillCompoundData( d->parameters() ); result->members()["output:" + name] = d; } } } return result; }
IECore::ConstCompoundObjectPtr Options::computeProcessedGlobals( const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputGlobals ) const { IECore::CompoundObjectPtr result = inputGlobals->copy(); const CompoundDataPlug *p = optionsPlug(); std::string name; for( CompoundDataPlug::MemberPlugIterator it( p ); it != it.end(); ++it ) { IECore::DataPtr d = p->memberDataAndName( it->get(), name ); if( d ) { result->members()["option:" + name] = d; } } return result; }
IECore::ConstCompoundObjectPtr ShaderAssignment::computeProcessedAttributes( const ScenePath &path, const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputAttributes ) const { CompoundObjectPtr result = inputAttributes->copy(); const Shader *shader = shaderPlug()->source<Plug>()->ancestor<Shader>(); if( shader ) { // Shader::state() returns a const object, so that in the future it may // come from a cached value. we're putting it into our result which, once // returned, will also be treated as const and cached. for that reason the // temporary const_cast needed to put it into the result is justified - // we never change the object and nor can anyone after it is returned. ObjectVectorPtr state = boost::const_pointer_cast<ObjectVector>( shader->state() ); if( state->members().size() ) { result->members()["shader"] = state; } } return result; }
IECore::ConstCompoundObjectPtr AttributeVisualiser::computeProcessedAttributes( const ScenePath &path, const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputAttributes ) const { const std::string attributeName = attributeNamePlug()->getValue(); if( !attributeName.size() ) { return inputAttributes; } const std::string shaderType = shaderTypePlug()->getValue(); if( !shaderType.size() ) { return inputAttributes; } const Object *attribute = inputAttributes->member<Object>( attributeName ); if( !attribute ) { if( !inputAttributes->member<Object>( shaderType ) ) { return inputAttributes; } } CompoundObjectPtr result = new CompoundObject; // Since we're not going to modify any existing members (only add a new one), // and our result becomes const on returning it, we can directly reference // the input members in our result without copying. Be careful not to modify // them though! result->members() = inputAttributes->members(); if( !attribute ) { result->members().erase( shaderType ); return result; } // Compute our colour. Color3f color( 0.0f ); const Mode mode = (Mode)modePlug()->getValue(); if( mode == Random ) { Rand32 r( tbb_hasher( attribute->hash() ) ); for( int i = 0; i < 3; ++i ) { color[i] = r.nextf(); } } else if( mode == ShaderNodeColor ) { const Shader *shader = runTimeCast<const Shader>( attribute ); if( !shader ) { if( const ShaderNetwork *network = runTimeCast<const ShaderNetwork>( attribute ) ) { shader = network->outputShader(); } } if( shader ) { const Color3fData *colorData = shader->blindData()->member<const Color3fData>( "gaffer:nodeColor" ); if( colorData ) { color = colorData->readable(); } } } else { // Color or FalseColor switch( attribute->typeId() ) { case FloatDataTypeId : color = Color3f( static_cast<const FloatData *>( attribute )->readable() ); break; case DoubleDataTypeId : color = Color3f( static_cast<const DoubleData *>( attribute )->readable() ); break; case IntDataTypeId : color = Color3f( static_cast<const IntData *>( attribute )->readable() ); break; case BoolDataTypeId : color = Color3f( static_cast<const BoolData *>( attribute )->readable() ); break; case Color3fDataTypeId : color = static_cast<const Color3fData *>( attribute )->readable(); break; default : throw IECore::Exception( boost::str( boost::format( "Unsupported attribute data type \"%s\"" ) % attribute->typeName() ) ); } const Color3f min( minPlug()->getValue() ); const Color3f max( maxPlug()->getValue() ); color = ( color - min ) / ( max - min ); if( mode == FalseColor ) { const SplinefColor3f ramp = rampPlug()->getValue().spline(); color = ramp( color[0] ); } } // Apply the colour using a shader. ShaderPtr shader = new Shader( shaderNamePlug()->getValue(), shaderType ); shader->parameters()[shaderParameterPlug()->getValue()] = new Color3fData( color ); ShaderNetworkPtr shaderNetwork = new ShaderNetwork; const InternedString handle = shaderNetwork->addShader( "surface", std::move( shader ) ); shaderNetwork->setOutput( handle ); result->members()[shaderType] = shaderNetwork; return result; }
virtual task *execute() { ScenePlug::PathScope pathScope( m_sceneGadget->m_context.get(), m_scenePath ); // Update attributes, and compute visibility. const bool previouslyVisible = m_sceneGraph->m_visible; if( m_dirtyFlags & AttributesDirty ) { const IECore::MurmurHash attributesHash = m_sceneGadget->m_scene->attributesPlug()->hash(); if( attributesHash != m_sceneGraph->m_attributesHash ) { IECore::ConstCompoundObjectPtr attributes = m_sceneGadget->m_scene->attributesPlug()->getValue( &attributesHash ); const IECore::BoolData *visibilityData = attributes->member<IECore::BoolData>( "scene:visible" ); m_sceneGraph->m_visible = visibilityData ? visibilityData->readable() : true; IECore::ConstRunTimeTypedPtr glStateCachedTyped = IECoreGL::CachedConverter::defaultCachedConverter()->convert( attributes.get() ); IECoreGL::ConstStatePtr glStateCached = IECore::runTimeCast<const IECoreGL::State>( glStateCachedTyped ); IECoreGL::ConstStatePtr visState = NULL; deferReferenceRemoval( m_sceneGraph->m_attributesRenderable ); m_sceneGraph->m_attributesRenderable = AttributeVisualiser::allVisualisations( attributes.get(), visState ); deferReferenceRemoval( m_sceneGraph->m_state ); if( visState ) { IECoreGL::StatePtr glState = new IECoreGL::State( *glStateCached ); glState->add( const_cast< IECoreGL::State* >( visState.get() ) ); m_sceneGraph->m_state = glState; } else { m_sceneGraph->m_state = glStateCached; } m_sceneGraph->m_attributesHash = attributesHash; } } if( !m_sceneGraph->m_visible ) { // No need to update further since we're not visible. return NULL; } else if( !previouslyVisible ) { // We didn't perform any updates when we were invisible, // so we need to update everything now. m_dirtyFlags = AllDirty; } // Update the object - converting it into an IECoreGL::Renderable if( m_dirtyFlags & ObjectDirty ) { const IECore::MurmurHash objectHash = m_sceneGadget->m_scene->objectPlug()->hash(); if( objectHash != m_sceneGraph->m_objectHash ) { IECore::ConstObjectPtr object = m_sceneGadget->m_scene->objectPlug()->getValue( &objectHash ); deferReferenceRemoval( m_sceneGraph->m_renderable ); if( !object->isInstanceOf( IECore::NullObjectTypeId ) ) { m_sceneGraph->m_renderable = objectToRenderable( object.get() ); } m_sceneGraph->m_objectHash = objectHash; } } // Update the transform and bound if( m_dirtyFlags & TransformDirty ) { m_sceneGraph->m_transform = m_sceneGadget->m_scene->transformPlug()->getValue(); } m_sceneGraph->m_bound = m_sceneGraph->m_renderable ? m_sceneGraph->m_renderable->bound() : Box3f(); // Update the expansion state const bool previouslyExpanded = m_sceneGraph->m_expanded; if( m_dirtyFlags & ExpansionDirty ) { m_sceneGraph->m_expanded = m_sceneGadget->m_minimumExpansionDepth >= m_scenePath.size(); if( !m_sceneGraph->m_expanded ) { m_sceneGraph->m_expanded = m_sceneGadget->m_expandedPaths->readable().match( m_scenePath ) & Filter::ExactMatch; } } // If we're not expanded, then we can early out after creating a bounding box. deferReferenceRemoval( m_sceneGraph->m_boundRenderable ); if( !m_sceneGraph->m_expanded ) { // We're not expanded, so we early out before updating the children. // We do however need to see if we have any children, and arrange to // draw their bounding box if we do. bool haveChildren = m_sceneGraph->m_children.size(); if( m_dirtyFlags & ChildNamesDirty || !previouslyExpanded ) { IECore::ConstInternedStringVectorDataPtr childNamesData = m_sceneGadget->m_scene->childNamesPlug()->getValue(); haveChildren = childNamesData->readable().size(); } m_sceneGraph->clearChildren(); m_sceneGraph->m_bound.extendBy( m_sceneGadget->m_scene->boundPlug()->getValue() ); if( haveChildren ) { IECore::CurvesPrimitivePtr curvesBound = IECore::CurvesPrimitive::createBox( m_sceneGraph->m_bound ); m_sceneGraph->m_boundRenderable = boost::static_pointer_cast<const IECoreGL::Renderable>( IECoreGL::CachedConverter::defaultCachedConverter()->convert( curvesBound.get() ) ); } return NULL; } // We are expanded, so we need to visit all the children // and update those too. if( !previouslyExpanded ) { m_dirtyFlags = AllDirty; } // Make sure we have a child for each child name if( m_dirtyFlags & ChildNamesDirty ) { IECore::ConstInternedStringVectorDataPtr childNamesData = m_sceneGadget->m_scene->childNamesPlug()->getValue(); const std::vector<IECore::InternedString> &childNames = childNamesData->readable(); if( !existingChildNamesValid( childNames ) ) { m_sceneGraph->clearChildren(); for( std::vector<IECore::InternedString>::const_iterator it = childNames.begin(), eIt = childNames.end(); it != eIt; ++it ) { SceneGraph *child = new SceneGraph(); child->m_name = *it; m_sceneGraph->m_children.push_back( child ); } m_dirtyFlags = AllDirty; // We've made brand new children, so they need a full update. } } // And then update each child if( m_sceneGraph->m_children.size() ) { set_ref_count( 1 + m_sceneGraph->m_children.size() ); ScenePlug::ScenePath childPath = m_scenePath; childPath.push_back( IECore::InternedString() ); // space for the child name for( std::vector<SceneGraph *>::const_iterator it = m_sceneGraph->m_children.begin(), eIt = m_sceneGraph->m_children.end(); it != eIt; ++it ) { childPath.back() = (*it)->m_name; UpdateTask *t = new( allocate_child() ) UpdateTask( m_sceneGadget, *it, m_dirtyFlags, childPath ); spawn( *t ); } wait_for_all(); } // Finally compute our bound from the child bounds. for( std::vector<SceneGraph *>::const_iterator it = m_sceneGraph->m_children.begin(), eIt = m_sceneGraph->m_children.end(); it != eIt; ++it ) { const Box3f childBound = transform( (*it)->m_bound, (*it)->m_transform ); m_sceneGraph->m_bound.extendBy( childBound ); } return NULL; }
Implementation( ShaderLoaderPtr shaderLoader, TextureLoaderPtr textureLoader, const std::string &vertexSource, const std::string &geometrySource, const std::string &fragmentSource, IECore::ConstCompoundObjectPtr parameterValues ) : m_shaderLoader( shaderLoader ), m_textureLoader( textureLoader ), m_fragmentSource( fragmentSource ), m_geometrySource( geometrySource ), m_vertexSource( vertexSource ), m_parameterMap( parameterValues->copy() ), m_shaderSetup( 0 ) { }