IECore::ObjectPtr CompoundParameterHandler::getState( const IECore::Parameter *parameter ) { const CompoundParameter *compoundParameter = static_cast<const CompoundParameter *>( parameter ); CompoundObjectPtr result = new CompoundObject; const CompoundParameter::ParameterVector &childParameters = compoundParameter->orderedParameters(); for( CompoundParameter::ParameterVector::const_iterator cIt=childParameters.begin(); cIt!=childParameters.end(); cIt++ ) { ParameterHandlerPtr h = handler( *cIt, true ); if( h ) { ObjectPtr childState = h->getState( *cIt ); if( childState ) { result->members()[(*cIt)->name()] = childState; } } } if( result->members().size() ) { return result; } return 0; }
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::ObjectPtr ClassParameterHandler::getState( const IECore::Parameter *parameter ) { CompoundObjectPtr result = staticPointerCast<CompoundObject>( CompoundParameterHandler::getState( parameter ) ); if( !result ) { result = new CompoundObject; } IECorePython::ScopedGILLock gilLock; try { boost::python::object pythonParameter( ParameterPtr( const_cast<Parameter *>( parameter ) ) ); boost::python::tuple classInfo = extract<boost::python::tuple>( pythonParameter.attr( "getClass" )( true ) ); std::string className = extract<const char *>( classInfo[1] )(); int classVersion = extract<int>( classInfo[2] )(); std::string searchPathEnvVar = extract<const char *>( classInfo[3] )(); result->members()["__className"] = new IECore::StringData( className ); result->members()["__classVersion"] = new IECore::IntData( classVersion ); result->members()["__searchPathEnvVar"] = new IECore::StringData( searchPathEnvVar ); } catch( boost::python::error_already_set ) { PyErr_Print(); } catch( const std::exception &e ) { msg( Msg::Error, "ClassParameterHandler::getState", e.what() ); } return result; }
static void userHeaderGenerator( CompoundObjectPtr header ) { uid_t uid = getuid(); struct passwd *st = getpwuid( uid ); if ( st ) { header->members()["userName"] = new StringData( st->pw_name ); } else { header->members()["userID"] = new IntData( uid ); } }
IECore::ConstCompoundObjectPtr SceneReader::computeAttributes( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { std::string fileName = fileNamePlug()->getValue(); if( !fileName.size() ) { return parent->attributesPlug()->defaultValue(); } ConstSceneInterfacePtr s = SharedSceneInterfaces::get( fileName ); s = s->scene( path ); // read attributes SceneInterface::NameList nameList; s->attributeNames( nameList ); CompoundObjectPtr result = new CompoundObject; for( SceneInterface::NameList::iterator it = nameList.begin(); it != nameList.end(); ++it ) { // these internal attributes should be ignored: if( *it == SceneCache::animatedObjectTopologyAttribute ) { continue; } if( *it == SceneCache::animatedObjectPrimVarsAttribute ) { continue; } // the const cast is ok, because we're only using it to put the object into a CompoundObject that will // be treated as forever const after being returned from this function. result->members()[ std::string( *it ) ] = constPointerCast<Object>( s->readAttribute( *it, context->getFrame() / g_frameRate ) ); } // read tags and turn them into attributes of the form "user:tag:tagName" nameList.clear(); s->readTags( nameList, IECore::SceneInterface::LocalTag ); for( SceneInterface::NameList::const_iterator it = nameList.begin(); it != nameList.end(); ++it ) { if( it->string().compare( 0, 11, "ObjectType:" ) == 0 ) { continue; } result->members()["user:tag:"+it->string()] = g_trueBoolData; } return result; }
IECore::ConstCompoundObjectPtr ArnoldDisplacement::attributes() const { CompoundObjectPtr result = new CompoundObject; if( !enabledPlug()->getValue() ) { return result; } CompoundObject::ObjectMap &m = result->members(); m = mapPlug()->attributes()->members(); for( InternedString *n = g_mapInputAttributeNames; *n != InternedString(); ++n ) { CompoundObject::ObjectMap::iterator it = m.find( *n ); if( it != m.end() ) { m[g_mapAttributeName] = it->second; m.erase( it ); break; } } m[g_heightAttributeName] = new FloatData( heightPlug()->getValue() ); m[g_paddingAttributeName] = new FloatData( paddingPlug()->getValue() ); m[g_zeroValueAttributeName] = new FloatData( zeroValuePlug()->getValue() ); m[g_autoBumpAttributeName] = new BoolData( autoBumpPlug()->getValue() ); return result; }
void ObjectWriter::doWrite( const CompoundObject *operands ) { IndexedIOPtr io = new FileIndexedIO( fileName(), IndexedIO::rootPath, IndexedIO::Exclusive | IndexedIO::Write); /// \todo Establish why we only accept CompoundData / Data here when HeaderGenerator::header(), for example, /// returns a CompoundObject // write the header CompoundDataPtr header = boost::static_pointer_cast<CompoundData>( m_headerParameter->getValue()->copy() ); header->writable()["typeName"] = new StringData( object()->typeName() ); if( const VisibleRenderable* visibleRenderable = runTimeCast<const VisibleRenderable>(object()) ) { header->writable()["bound"] = new Box3fData( visibleRenderable->bound() ); } CompoundObjectPtr genericHeader = HeaderGenerator::header(); for ( CompoundObject::ObjectMap::const_iterator it = genericHeader->members().begin(); it != genericHeader->members().end(); it++ ) { assert( it->second ); if ( it->second->isInstanceOf( Data::staticTypeId() ) ) { header->writable()[ it->first ] = boost::static_pointer_cast< Data >( it->second ); } } ((ObjectPtr)header)->save( io, "header" ); // write the object object()->save( io, "object" ); }
AttributeCache::AttributeCache( const std::string &filename, IndexedIO::OpenMode mode ) { IndexedIOPtr io = IndexedIO::create(filename, IndexedIO::rootPath, mode ); if ( mode == IndexedIO::Write || mode == IndexedIO::Append ) { m_headersIO = io->subdirectory("headers", IndexedIO::CreateIfMissing ); m_objectsIO = io->subdirectory("objects", IndexedIO::CreateIfMissing ); CompoundObjectPtr header = HeaderGenerator::header(); for ( CompoundObject::ObjectMap::const_iterator it = header->members().begin(); it != header->members().end(); it++ ) { writeHeader( it->first, it->second.get() ); } } if ( mode == IndexedIO::Read ) { try { m_headersIO = io->subdirectory("headers"); m_objectsIO = io->subdirectory("objects"); } catch (IECore::Exception &e) { throw Exception("Not an AttributeCache file."); } } }
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 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; }
SceneGadget::SceneGadget() : Gadget( defaultName<SceneGadget>() ), m_paused( false ), m_renderer( IECoreScenePreview::Renderer::create( "OpenGL", IECoreScenePreview::Renderer::Interactive ) ), m_controller( nullptr, nullptr, m_renderer ), m_updateErrored( false ), m_renderRequestPending( false ) { typedef CompoundObject::ObjectMap::value_type Option; CompoundObjectPtr openGLOptions = new CompoundObject; openGLOptions->members().insert( { Option( "gl:primitive:wireframeColor", new Color4fData( Color4f( 0.2f, 0.2f, 0.2f, 1.0f ) ) ), Option( "gl:primitive:pointColor", new Color4fData( Color4f( 0.9f, 0.9f, 0.9f, 1.0f ) ) ), Option( "gl:primitive:pointWidth", new FloatData( 2.0f ) ) } ); setOpenGLOptions( openGLOptions.get() ); m_controller.updateRequiredSignal().connect( boost::bind( &SceneGadget::requestRender, this ) ); visibilityChangedSignal().connect( boost::bind( &SceneGadget::visibilityChanged, this ) ); setContext( new Context ); }
IECore::ConstCompoundObjectPtr SceneReader::computeAttributes( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { ConstSceneInterfacePtr s = scene( path ); if( !s ) { return parent->attributesPlug()->defaultValue(); } // read attributes SceneInterface::NameList nameList; s->attributeNames( nameList ); CompoundObjectPtr result = new CompoundObject; for( SceneInterface::NameList::iterator it = nameList.begin(); it != nameList.end(); ++it ) { // these internal attributes should be ignored: if( *it == SceneCache::animatedObjectTopologyAttribute ) { continue; } if( *it == SceneCache::animatedObjectPrimVarsAttribute ) { continue; } // the const cast is ok, because we're only using it to put the object into a CompoundObject that will // be treated as forever const after being returned from this function. result->members()[ std::string( *it ) ] = boost::const_pointer_cast<Object>( s->readAttribute( *it, context->getTime() ) ); } return result; }
ConstCompoundObjectPtr SetVisualiser::computeProcessedAttributes( const ScenePath &path, const Gaffer::Context *context, ConstCompoundObjectPtr inputAttributes ) const { 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(); ConstCompoundDataPtr outSetsData = outSetsPlug()->getValue(); const InternedStringVectorData *setNamesData = outSetsData->member<InternedStringVectorData>( "names" ); const Color3fVectorData *setColorsData = outSetsData->member<Color3fVectorData>( "colors" ); int matchResult = PathMatcher::ExactMatch; if( includeInheritedPlug()->getValue() ) { matchResult |= PathMatcher::AncestorMatch; } ConstCompoundDataPtr targetSets = SceneAlgo::sets( inPlug(), setNamesData->readable() ); std::vector<Color3f> shaderColors; size_t index = 0; for( auto &setName : setNamesData->readable() ) { const PathMatcherData *pathMatchData = targetSets->member<const PathMatcherData>( setName ); if( pathMatchData->readable().match( path ) & matchResult ) { shaderColors.push_back( setColorsData->readable()[ index ] ); } // We need to pass our colors to the shader as a fixed size array if( shaderColors.size() == g_maxShaderColors ) { break; } ++index; } // Avoids shader compilation errors as its expecting g_maxShaderColors elements const size_t numColorsUsed = shaderColors.size(); shaderColors.resize( g_maxShaderColors ); result->members()["gl:surface"] = stripeShader( stripeWidthPlug()->getValue(), numColorsUsed, shaderColors ); return result; }
void CopyChannels::compute( Gaffer::ValuePlug *output, const Gaffer::Context *context ) const { if( output == mappingPlug() ) { const string channelMatchPatterns = channelsPlug()->getValue(); CompoundObjectPtr result = new CompoundObject(); StringVectorDataPtr channelNamesData = new StringVectorData; result->members()["__channelNames"] = channelNamesData; vector<string> &channelNames = channelNamesData->writable(); size_t i = 0; for( ImagePlugIterator it( inPlugs() ); !it.done(); ++i, ++it ) { /// \todo We need this check because an unconnected input /// has a default channelNames value of [ "R", "G", "B" ], /// when it should have an empty default instead. Fix /// the ImagePlug constructor and remove the check. if( !(*it)->getInput<Plug>() ) { continue; } ConstStringVectorDataPtr inputChannelNamesData = (*it)->channelNamesPlug()->getValue(); const vector<string> &inputChannelNames = inputChannelNamesData->readable(); for( vector<string>::const_iterator cIt = inputChannelNames.begin(), ceIt = inputChannelNames.end(); cIt != ceIt; ++cIt ) { if( i > 0 && !StringAlgo::matchMultiple( *cIt, channelMatchPatterns ) ) { continue; } if( find( channelNames.begin(), channelNames.end(), *cIt ) == channelNames.end() ) { channelNames.push_back( *cIt ); } result->members()[*cIt] = new IntData( i ); } } static_cast<CompoundObjectPlug *>( output )->setValue( result ); return; } ImageProcessor::compute( output, context ); }
IECore::ConstCompoundObjectPtr SubTree::computeGlobals( const Gaffer::Context *context, const ScenePlug *parent ) const { ConstCompoundObjectPtr inputGlobals = inPlug()->globalsPlug()->getValue(); const CompoundData *inputSets = inputGlobals->member<CompoundData>( "gaffer:sets" ); if( !inputSets ) { return inputGlobals; } CompoundObjectPtr outputGlobals = inputGlobals->copy(); CompoundDataPtr outputSets = new CompoundData; outputGlobals->members()["gaffer:sets"] = outputSets; std::string root = rootPlug()->getValue(); if( !root.size() || root[root.size()-1] != '/' ) { root += "/"; } size_t prefixSize = root.size() - 1; // number of characters to remove from front of each declaration if( includeRootPlug()->getValue() && prefixSize ) { size_t lastSlashButOne = root.rfind( "/", prefixSize-1 ); if( lastSlashButOne != string::npos ) { prefixSize = lastSlashButOne; } } for( CompoundDataMap::const_iterator it = inputSets->readable().begin(), eIt = inputSets->readable().end(); it != eIt; ++it ) { /// \todo This could be more efficient if PathMatcher exposed the internal nodes, /// and allowed sharing between matchers. Then we could just pick the subtree within /// the matcher that we wanted. const PathMatcher &inputSet = static_cast<const PathMatcherData *>( it->second.get() )->readable(); PathMatcher &outputSet = outputSets->member<PathMatcherData>( it->first, /* throwExceptions = */ false, /* createIfMissing = */ true )->writable(); vector<string> inputPaths; inputSet.paths( inputPaths ); for( vector<string>::const_iterator pIt = inputPaths.begin(), peIt = inputPaths.end(); pIt != peIt; ++pIt ) { const string &inputPath = *pIt; if( inputPath.compare( 0, root.size(), root ) == 0 ) { std::string outputPath( inputPath, prefixSize ); outputSet.addPath( outputPath ); } } } return outputGlobals; }
IECore::ConstCompoundObjectPtr Grid::computeAttributes( const SceneNode::ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { if( path.size() == 1 ) { CompoundObjectPtr result = new CompoundObject; result->members()["gl:curvesPrimitive:useGLLines"] = new BoolData( true ); result->members()["gl:smoothing:lines"] = new BoolData( true ); ShaderPtr shader = new Shader( "Constant", "gl:surface" ); shader->parameters()["Cs"] = new Color3fData( Color3f( 1 ) ); result->members()["gl:surface"] = shader; return result; } else if( path.size() == 2 ) { float pixelWidth = 1.0f; if( path.back() == g_gridLinesName ) { pixelWidth = gridPixelWidthPlug()->getValue(); } else if( path.back() == g_centerLinesName ) { pixelWidth = centerPixelWidthPlug()->getValue(); } else if( path.back() == g_borderLinesName ) { pixelWidth = borderPixelWidthPlug()->getValue(); } CompoundObjectPtr result = new CompoundObject; result->members()["gl:curvesPrimitive:glLineWidth"] = new FloatData( pixelWidth ); return result; } return outPlug()->attributesPlug()->defaultValue(); }
CompoundObjectPtr AttributeCache::readHeader( ) { CompoundObjectPtr dict = new CompoundObject(); IndexedIO::EntryIDList directories; m_headersIO->entryIds( directories, IndexedIO::Directory ); for (IndexedIO::EntryIDList::const_iterator it = directories.begin(); it != directories.end(); ++it) { ObjectPtr data = Object::load( m_headersIO, *it ); dict->members()[ *it ] = data; } return dict; }
static void unameHeaderGenerator( CompoundObjectPtr header ) { struct utsname name; if ( !uname( &name ) ) { CompoundDataPtr compound = new CompoundData(); compound->writable()["systemName"] = new StringData( name.sysname ); compound->writable()["nodeName"] = new StringData( name.nodename ); compound->writable()["systemRelease"] = new StringData( name.release ); compound->writable()["systemVersion"] = new StringData( name.version ); compound->writable()["machineName"] = new StringData( name.machine ); header->members()["host"] = compound; } }
CompoundObjectPtr AttributeCache::read( const ObjectHandle &obj ) { CompoundObjectPtr dict = new CompoundObject(); IndexedIO::EntryIDList directories; IndexedIOPtr object = m_objectsIO->subdirectory( obj ); object->entryIds( directories, IndexedIO::Directory ); for (IndexedIO::EntryIDList::const_iterator it = directories.begin(); it != directories.end(); ++it) { ObjectPtr data = Object::load( object, *it ); dict->members()[ *it ] = data; } return dict; }
static void timeStampHeaderGenerator( CompoundObjectPtr header ) { time_t tm; time( &tm ); /// ctime_r manpage suggest that 26 characters should be enough in all cases char buf[27]; std::string strTime ( ctime_r( &tm, &buf[0] ) ); assert( strTime.length() <= 26 ); /// Remove the newline at the end boost::algorithm::trim_right( strTime ); header->members()["timeStamp"] = new StringData( strTime ); }
IECore::ConstCompoundObjectPtr Prune::computeGlobals( const Gaffer::Context *context, const ScenePlug *parent ) const { ConstCompoundObjectPtr inputGlobals = inPlug()->globalsPlug()->getValue(); const CompoundData *inputSets = inputGlobals->member<CompoundData>( "gaffer:sets" ); if( !inputSets ) { return inputGlobals; } CompoundObjectPtr outputGlobals = inputGlobals->copy(); CompoundDataPtr outputSets = new CompoundData; outputGlobals->members()["gaffer:sets"] = outputSets; ContextPtr tmpContext = new Context( *Context::current() ); Context::Scope scopedContext( tmpContext ); ScenePath path; for( CompoundDataMap::const_iterator it = inputSets->readable().begin(), eIt = inputSets->readable().end(); it != eIt; ++it ) { /// \todo This could be more efficient if PathMatcher exposed the internal nodes, /// and allowed sharing between matchers. Then we could do a really lightweight copy /// and just trim out the nodes we didn't want. const PathMatcher &inputSet = static_cast<const PathMatcherData *>( it->second.get() )->readable(); PathMatcher &outputSet = outputSets->member<PathMatcherData>( it->first, /* throwExceptions = */ false, /* createIfMissing = */ true )->writable(); vector<string> inputPaths; inputSet.paths( inputPaths ); for( vector<string>::const_iterator pIt = inputPaths.begin(), peIt = inputPaths.end(); pIt != peIt; ++pIt ) { path.clear(); ScenePlug::stringToPath( *pIt, path ); tmpContext->set( ScenePlug::scenePathContextName, path ); if( !(filterPlug()->getValue() & ( Filter::ExactMatch | Filter::AncestorMatch ) ) ) { outputSet.addPath( *pIt ); } } } return outputGlobals; }
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 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 GafferScene::SceneAlgo::globalAttributes( const IECore::CompoundObject *globals ) { static const std::string prefix( "attribute:" ); CompoundObjectPtr result = new CompoundObject; CompoundObject::ObjectMap::const_iterator it, eIt; for( it = globals->members().begin(), eIt = globals->members().end(); it != eIt; ++it ) { if( !boost::starts_with( it->first.c_str(), "attribute:" ) ) { continue; } // Cast is justified because we don't modify the data, and will return it // as const from this function. result->members()[it->first.string().substr( prefix.size() )] = boost::const_pointer_cast<Object>( it->second ); } return result; }
IECore::ConstCompoundObjectPtr AppleseedShaderAdaptor::computeAttributes( const ScenePath &path, const Gaffer::Context *context, const GafferScene::ScenePlug *parent ) const { ConstCompoundObjectPtr inputAttributes = inPlug()->attributesPlug()->getValue(); /// \todo Drop support for "osl:shader" assignments. They were never desirable, and the ShaderAssignment node /// no longer makes them. const ShaderNetwork *shaderNetwork = inputAttributes->member<const ShaderNetwork>( g_oslShaderAttributeName ); if( !shaderNetwork ) { shaderNetwork = inputAttributes->member<const ShaderNetwork>( g_oslSurfaceAttributeName ); } if( !shaderNetwork ) { return inputAttributes; } const Shader *outputShader = shaderNetwork->outputShader(); if( !outputShader ) { return inputAttributes; } OSLQuery::Parameter *firstOutput = firstOutputParameter( outputShader->getName() ); // Build an adaptor network ShaderNetworkPtr adaptedNetwork; if( firstOutput && firstOutput->isclosure ) { adaptedNetwork = shaderNetwork->copy(); ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); InternedString materialHandle = adaptedNetwork->addShader( "material", std::move( material ) ); adaptedNetwork->addConnection( { { adaptedNetwork->getOutput().shader, firstOutput->name.string() }, { materialHandle, g_bsdfParameterName } } ); adaptedNetwork->setOutput( materialHandle ); } else if( firstOutput && firstOutput->type == TypeDesc::TypeColor ) { adaptedNetwork = shaderNetwork->copy(); ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" ); InternedString emissionHandle = adaptedNetwork->addShader( "emission", std::move( emission ) ); adaptedNetwork->addConnection( { { adaptedNetwork->getOutput().shader, firstOutput->name.string() }, { emissionHandle, "Color" } } ); ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); InternedString materialHandle = adaptedNetwork->addShader( "material", std::move( material ) ); adaptedNetwork->addConnection( { { emissionHandle, "BSDF" }, { materialHandle, "BSDF" } } ); adaptedNetwork->setOutput( materialHandle ); } else if( firstOutput && ( firstOutput->type == TypeDesc::TypeFloat || firstOutput->type == TypeDesc::TypeInt ) ) { adaptedNetwork = shaderNetwork->copy(); ShaderPtr colorBuild = new Shader( "color/as_color_build", "osl:shader" ); InternedString colorBuildHandle = adaptedNetwork->addShader( "colorBuild", std::move( colorBuild ) ); for( const auto &channel : { "R", "G", "B" } ) { adaptedNetwork->addConnection( { { adaptedNetwork->getOutput().shader, firstOutput->name.string() }, { colorBuildHandle, channel } } ); } ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" ); InternedString emissionHandle = adaptedNetwork->addShader( "emission", std::move( emission ) ); adaptedNetwork->addConnection( { { colorBuildHandle, "ColorOut" }, { emissionHandle, "Color" } } ); ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); InternedString materialHandle = adaptedNetwork->addShader( "material", std::move( material ) ); adaptedNetwork->addConnection( { { emissionHandle, "BSDF" }, { materialHandle, "BSDF" } } ); adaptedNetwork->setOutput( materialHandle ); } else if( firstOutput && firstOutput->type == TypeDesc::TypeVector ) { adaptedNetwork = shaderNetwork->copy(); ShaderPtr vectorSplit = new Shader( "vector/as_vector_split", "osl:shader" ); InternedString vectorSplitHandle = adaptedNetwork->addShader( "vectorSplit", std::move( vectorSplit ) ); adaptedNetwork->addConnection( { { adaptedNetwork->getOutput().shader, firstOutput->name.string() }, { vectorSplitHandle, "Vector" } } ); ShaderPtr colorBuild = new Shader( "color/as_color_build", "osl:shader" ); InternedString colorBuildHandle = adaptedNetwork->addShader( "colorBuild", std::move( colorBuild ) ); for( const auto &c : { make_pair( "X", "R" ), make_pair( "Y", "G" ), make_pair( "Z", "B" ) } ) { adaptedNetwork->addConnection( { { vectorSplitHandle, c.first }, { colorBuildHandle, c.second } } ); } ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" ); InternedString emissionHandle = adaptedNetwork->addShader( "emission", std::move( emission ) ); adaptedNetwork->addConnection( { { colorBuildHandle, "ColorOut" }, { emissionHandle, "Color" } } ); ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); InternedString materialHandle = adaptedNetwork->addShader( "material", std::move( material ) ); adaptedNetwork->addConnection( { { emissionHandle, "BSDF" }, { materialHandle, "BSDF" } } ); adaptedNetwork->setOutput( materialHandle ); } else { // Shader has no output, or an output we can't map sensibly. // Make an "error" shader. adaptedNetwork = new ShaderNetwork; ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" ); emission->parameters()["Color"] = new Color3fData( Imath::Color3f( 1, 0, 0 ) ); InternedString emissionHandle = adaptedNetwork->addShader( "emission", std::move( emission ) ); ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); InternedString materialHandle = adaptedNetwork->addShader( "material", std::move( material ) ); adaptedNetwork->addConnection( { { emissionHandle, "BSDF" }, { materialHandle, "BSDF" } } ); adaptedNetwork->setOutput( materialHandle ); } // Place the new network into the "osl:surface" attribute // and remove the "osl:shader" attribute. CompoundObjectPtr outputAttributes = new CompoundObject; outputAttributes->members() = inputAttributes->members(); // Shallow copy for speed - do not modify in place! outputAttributes->members()[g_oslSurfaceAttributeName] = adaptedNetwork; outputAttributes->members().erase( g_oslShaderAttributeName ); return outputAttributes; }
IECore::ConstCompoundObjectPtr AppleseedShaderAdaptor::computeAttributes( const ScenePath &path, const Gaffer::Context *context, const GafferScene::ScenePlug *parent ) const { ConstCompoundObjectPtr inputAttributes = inPlug()->attributesPlug()->getValue(); const ObjectVector *shaderNetwork = inputAttributes->member<const ObjectVector>( g_oslShaderAttributeName ); if( !shaderNetwork || shaderNetwork->members().empty() ) { return inputAttributes; } const Shader *rootShader = runTimeCast<const Shader>( shaderNetwork->members().back().get() ); if( !rootShader ) { return inputAttributes; } OSLQuery::Parameter *firstOutput = firstOutputParameter( rootShader->getName() ); // Build an adapter network if we can. bool prependInputNetwork = true; vector<ShaderPtr> adapters; if( firstOutput && firstOutput->isclosure ) { ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); material->parameters()[g_bsdfParameterName] = new StringData( "link:adapterInputHandle." + firstOutput->name.string() ); adapters.push_back( material ); } else if( firstOutput && firstOutput->type == TypeDesc::TypeColor ) { ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" ); emission->parameters()["Color"] = new StringData( "link:adapterInputHandle." + firstOutput->name.string() ); emission->parameters()[g_handleParameterName] = new StringData( "adapterEmissionHandle" ); ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); material->parameters()[g_bsdfParameterName] = new StringData( "link:adapterEmissionHandle.BSDF" ); adapters.push_back( emission ); adapters.push_back( material ); } else if( firstOutput && ( firstOutput->type == TypeDesc::TypeFloat || firstOutput->type == TypeDesc::TypeInt ) ) { ShaderPtr colorBuild = new Shader( "color/as_color_build", "osl:shader" ); StringDataPtr colorLink = new StringData( "link:adapterInputHandle." + firstOutput->name.string() ); colorBuild->parameters()["R"] = colorLink; colorBuild->parameters()["G"] = colorLink; colorBuild->parameters()["B"] = colorLink; colorBuild->parameters()[g_handleParameterName] = new StringData( "adapterColorBuildHandle" ); ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" ); emission->parameters()["Color"] = new StringData( "link:adapterColorBuildHandle.ColorOut" ); emission->parameters()[g_handleParameterName] = new StringData( "adapterEmissionHandle" ); ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); material->parameters()[g_bsdfParameterName] = new StringData( "link:adapterEmissionHandle.BSDF" ); adapters.push_back( colorBuild ); adapters.push_back( emission ); adapters.push_back( material ); } else if( firstOutput && firstOutput->type == TypeDesc::TypeVector ) { ShaderPtr vectorSplit = new Shader( "vector/as_vector_split", "osl:shader" ); vectorSplit->parameters()["Vector"] = new StringData( "link:adapterInputHandle." + firstOutput->name.string() ); vectorSplit->parameters()[g_handleParameterName] = new StringData( "adapterVectorSplit" ); ShaderPtr colorBuild = new Shader( "color/as_color_build", "osl:shader" ); colorBuild->parameters()["R"] = new StringData( "link:adapterVectorSplit.X" ); colorBuild->parameters()["G"] = new StringData( "link:adapterVectorSplit.Y" ); colorBuild->parameters()["B"] = new StringData( "link:adapterVectorSplit.Z" ); colorBuild->parameters()[g_handleParameterName] = new StringData( "adapterColorBuildHandle" ); ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" ); emission->parameters()["Color"] = new StringData( "link:adapterColorBuildHandle.ColorOut" ); emission->parameters()[g_handleParameterName] = new StringData( "adapterEmissionHandle" ); ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); material->parameters()[g_bsdfParameterName] = new StringData( "link:adapterEmissionHandle.BSDF" ); adapters.push_back( vectorSplit ); adapters.push_back( colorBuild ); adapters.push_back( emission ); adapters.push_back( material ); } else { // Shader has no output, or an output we can't map sensibly. // Make an "error" shader. ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" ); emission->parameters()["Color"] = new Color3fData( Imath::Color3f( 1, 0, 0 ) ); emission->parameters()[g_handleParameterName] = new StringData( "adapterEmissionHandle" ); ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); material->parameters()[g_bsdfParameterName] = new StringData( "link:adapterEmissionHandle.BSDF" ); adapters.push_back( emission ); adapters.push_back( material ); prependInputNetwork = false; // We don't need the original shaders at all } // Make a new network with the adapter network // appended onto the input network ObjectVectorPtr adaptedNetwork = new ObjectVector(); if( prependInputNetwork ) { adaptedNetwork->members() = shaderNetwork->members(); // Shallow copy for speed - do not modify in place! ShaderPtr rootShaderCopy = rootShader->copy(); rootShaderCopy->parameters()[g_handleParameterName] = new StringData( "adapterInputHandle" );; adaptedNetwork->members().back() = rootShaderCopy; } std::copy( adapters.begin(), adapters.end(), back_inserter( adaptedNetwork->members() ) ); // Place the new network into the "osl:surface" attribute // and remove the "osl:shader" attribute. CompoundObjectPtr outputAttributes = new CompoundObject; outputAttributes->members() = inputAttributes->members(); // Shallow copy for speed - do not modify in place! outputAttributes->members()[g_oslSurfaceAttributeName] = adaptedNetwork; outputAttributes->members().erase( g_oslShaderAttributeName ); return outputAttributes; }
ObjectPtr EnvMapSampler::doOperation( const CompoundObject * operands ) { ImagePrimitivePtr image = static_cast<ImagePrimitive *>( imageParameter()->getValue() )->copy(); Box2i dataWindow = image->getDataWindow(); // find the rgb channels ConstFloatVectorDataPtr redData = image->getChannel<float>( "R" ); ConstFloatVectorDataPtr greenData = image->getChannel<float>( "G" ); ConstFloatVectorDataPtr blueData = image->getChannel<float>( "B" ); if( !(redData && greenData && blueData) ) { throw Exception( "Image does not contain valid RGB float channels." ); } const vector<float> &red = redData->readable(); const vector<float> &green = greenData->readable(); const vector<float> &blue = blueData->readable(); // get a luminance channel LuminanceOpPtr luminanceOp = new LuminanceOp(); luminanceOp->inputParameter()->setValue( image ); luminanceOp->copyParameter()->getTypedValue() = false; luminanceOp->removeColorPrimVarsParameter()->getTypedValue() = false; luminanceOp->operate(); // do the median cut thing to get some samples MedianCutSamplerPtr sampler = new MedianCutSampler; sampler->imageParameter()->setValue( image ); sampler->subdivisionDepthParameter()->setNumericValue( subdivisionDepthParameter()->getNumericValue() ); ConstCompoundObjectPtr samples = boost::static_pointer_cast<CompoundObject>( sampler->operate() ); const vector<V2f> ¢roids = boost::static_pointer_cast<V2fVectorData>( samples->members().find( "centroids" )->second )->readable(); const vector<Box2i> &areas = boost::static_pointer_cast<Box2iVectorData>( samples->members().find( "areas" )->second )->readable(); // get light directions and colors from the samples V3fVectorDataPtr directionsData = new V3fVectorData; Color3fVectorDataPtr colorsData = new Color3fVectorData; vector<V3f> &directions = directionsData->writable(); vector<Color3f> &colors = colorsData->writable(); float radiansPerPixel = M_PI / (dataWindow.size().y + 1); float angleAtTop = ( M_PI - radiansPerPixel ) / 2.0f; for( unsigned i=0; i<centroids.size(); i++ ) { const Box2i &area = areas[i]; Color3f color( 0 ); for( int y=area.min.y; y<=area.max.y; y++ ) { int yRel = y - dataWindow.min.y; float angle = angleAtTop - yRel * radiansPerPixel; float weight = cosf( angle ); int index = (area.min.x - dataWindow.min.x) + (dataWindow.size().x + 1 ) * yRel; for( int x=area.min.x; x<=area.max.x; x++ ) { color[0] += weight * red[index]; color[1] += weight * green[index]; color[2] += weight * blue[index]; index++; } } color /= red.size(); colors.push_back( color ); float phi = angleAtTop - (centroids[i].y - dataWindow.min.y) * radiansPerPixel; V3f direction; direction.y = sinf( phi ); float r = cosf( phi ); float theta = 2 * M_PI * lerpfactor( (float)centroids[i].x, (float)dataWindow.min.x, (float)dataWindow.max.x ); direction.x = r * cosf( theta ); direction.z = r * sinf( theta ); directions.push_back( -direction ); // negated so we output the direction the light shines in } // return the result CompoundObjectPtr result = new CompoundObject; result->members()["directions"] = directionsData; result->members()["colors"] = colorsData; return result; }
int ParameterisedHolder<BaseType>::knob_changed( DD::Image::Knob *knob ) { if( knob==m_classSpecifierKnob || knob==m_classReloadKnob ) { // reload the class, or load a new class updateParameterised( knob==m_classReloadKnob ); // regenerate the knobs used to represent the parameters replaceKnobs(); // update the version menu updateVersionChooser(); return 1; } else if( knob==m_getParameterisedKnob ) { // this is triggered by the FnParameterisedHolder.getParameterised implementation. // currently there's no way to get an Op * and call a method on it from // python, so we use the knob_changed() mechanism to simulate a function call by // shoving the result into g_getParameterisedResult for subsequent retrieval. g_getParameterisedResult = loadClass( false ); if( g_getParameterisedResult ) { ParameterisedInterface *parameterisedInterface = dynamic_cast<ParameterisedInterface *>( g_getParameterisedResult.get() ); // apply current state ConstCompoundObjectPtr classSpecifier = runTimeCast<const CompoundObject>( m_classSpecifierKnob->getValue() ); ConstObjectPtr handlerState = classSpecifier->member<Object>( "handlerState" ); if( handlerState ) { m_parameterHandler->setState( parameterisedInterface->parameters(), handlerState ); } // get values directly from knobs as they haven't been stored at this point m_parameterHandler->setParameterValue( parameterisedInterface->parameters(), ParameterHandler::Knob ); } return 1; } else if( knob==m_modifiedParametersKnob ) { // this is triggered by the FnParameterisedHolder.classModificationContext() implementation. // as above, we use this method in lieu of being able to call a method on this class. // get the new handler state and store it so we have it for save/load copy/paste etc //////////////////////////////////////////////////////////////////////////////////// ParameterisedInterface *inputParameterisedInterface = dynamic_cast<ParameterisedInterface *>( g_modifiedParametersInput.get() ); ObjectPtr handlerState = m_parameterHandler->getState( inputParameterisedInterface->parameters() ); CompoundObjectPtr classSpecifier = runTimeCast<CompoundObject>( m_classSpecifierKnob->getValue()->copy() ); if( handlerState ) { classSpecifier->members()["handlerState"] = handlerState; } else { classSpecifier->members().erase( "handlerState" ); } // it seems that setting the value from inside knob_changed() doesn't emit a new knob_changed(), which // is fortunately what we want. m_classSpecifierKnob->setValue( classSpecifier ); // apply the new state to the current parameterised object //////////////////////////////////////////////////////////////////////////////////// ParameterisedInterface *parameterisedInterface = dynamic_cast<ParameterisedInterface *>( m_parameterised.get() ); if( handlerState ) { m_parameterHandler->setState( parameterisedInterface->parameters(), handlerState ); } parameterisedInterface->parameters()->setValue( inputParameterisedInterface->parameters()->getValue() ); // update the knobs using our newly updated parameterised object //////////////////////////////////////////////////////////////////////////////////// replaceKnobs(); setKnobValues(); // forget the input g_modifiedParametersInput = 0; return 1; } return BaseType::knob_changed( knob ); }
static void ieCoreHeaderGenerator( CompoundObjectPtr header ) { header->members()["ieCoreVersion"] = new StringData( versionString() ); }
IECore::ObjectPtr Group::computeMapping( const Gaffer::Context *context ) const { /// \todo It might be more optimal to make our own Object subclass better tailored /// for passing the information we want. CompoundObjectPtr result = new CompoundObject(); InternedStringVectorDataPtr childNamesData = new InternedStringVectorData(); vector<InternedString> &childNames = childNamesData->writable(); result->members()["__GroupChildNames"] = childNamesData; ObjectVectorPtr forwardMappings = new ObjectVector; result->members()["__GroupForwardMappings"] = forwardMappings; boost::regex namePrefixSuffixRegex( "^(.*[^0-9]+)([0-9]+)$" ); boost::format namePrefixSuffixFormatter( "%s%d" ); set<InternedString> allNames; for( ScenePlugIterator it( inPlugs() ); it != it.end(); ++it ) { ConstInternedStringVectorDataPtr inChildNamesData = (*it)->childNames( ScenePath() ); CompoundDataPtr forwardMapping = new CompoundData; forwardMappings->members().push_back( forwardMapping ); const vector<InternedString> &inChildNames = inChildNamesData->readable(); for( vector<InternedString>::const_iterator cIt = inChildNames.begin(), ceIt = inChildNames.end(); cIt!=ceIt; cIt++ ) { InternedString name = *cIt; if( allNames.find( name ) != allNames.end() ) { // uniqueify the name /// \todo This code is almost identical to code in GraphComponent::setName(), /// is there a sensible place it can be shared? The primary obstacle is that /// each use has a different method of storing the existing names. string prefix = name; int suffix = 1; boost::cmatch match; if( regex_match( name.value().c_str(), match, namePrefixSuffixRegex ) ) { prefix = match[1]; suffix = boost::lexical_cast<int>( match[2] ); } do { name = boost::str( namePrefixSuffixFormatter % prefix % suffix ); suffix++; } while( allNames.find( name ) != allNames.end() ); } allNames.insert( name ); childNames.push_back( name ); forwardMapping->writable()[*cIt] = new InternedStringData( name ); CompoundObjectPtr entry = new CompoundObject; entry->members()["n"] = new InternedStringData( *cIt ); entry->members()["i"] = new IntData( it.base() - inPlugs()->children().begin() ); result->members()[name] = entry; } } return result; }