void ParameterHandler::setKnobProperties( const IECore::Parameter *parameter, DD::Image::Knob_Callback f, DD::Image::Knob *knob ) const
{
	const CompoundObject *userData = parameter->userData();
	const CompoundObject *ui = userData->member<CompoundObject>( "UI" );
	
	int flags = 0;
	if( ui )
	{
		const BoolData *visible = ui->member<BoolData>( "visible" );
		if( visible && !visible->readable() )
		{
			flags |= Knob::INVISIBLE;
		}
	}
	
	SetFlags( f, flags );
	Tooltip( f, parameter->description() );
	
	if( f.makeKnobs() )
	{
		const CompoundObject *nuke = userData->member<CompoundObject>( "nuke" );
		if( nuke )
		{
			const StringData *defaultExpression = nuke->member<StringData>( "defaultExpression" );
			if( defaultExpression )
			{
				if( knob->from_script( defaultExpression->readable().c_str() ) )
				{
					knob->changed();
				}
			}
		}
	}
}
Example #2
0
void VecParameterHandler<T>::knobs( const IECore::Parameter *parameter, const char *knobName, DD::Image::Knob_Callback f )
{
    const T *vecParameter = static_cast<const T *>( parameter );

    if( f.makeKnobs() )
    {
        typename T::ValueType defaultValue = vecParameter->typedDefaultValue();
        for( unsigned i=0; i<T::ValueType::dimensions(); i++ )
        {
            m_storage[i] = defaultValue[i];
        }
    }

    std::string label = knobLabel( parameter );
    if( T::ValueType::dimensions()==2 )
    {
        m_knob = XY_knob( f, m_storage, knobName, label.c_str() );
        SetFlags( f, DD::Image::Knob::NO_PROXYSCALE | DD::Image::Knob::NO_HANDLES );
    }
    else
    {
        assert( T::ValueType::dimensions()==3 );
        m_knob = XYZ_knob( f, m_storage, knobName, label.c_str() );
    }

    setKnobProperties( parameter, f, m_knob );
}
void Color3fParameterHandler::knobs( const IECore::Parameter *parameter, const char *knobName, DD::Image::Knob_Callback f )
{
	const Color3fParameter *color3fParameter = static_cast<const Color3fParameter *>( parameter );

	if( f.makeKnobs() )
	{
		m_storage = color3fParameter->typedDefaultValue();
	}

	std::string label = knobLabel( parameter );
	m_knob = Color_knob( f, &m_storage.x, knobName, label.c_str() );
	setKnobProperties( parameter, f, m_knob );
}
void StringParameterHandler::knobs( const IECore::Parameter *parameter, const char *knobName, DD::Image::Knob_Callback f )
{
	if( f.makeKnobs() )
	{
		m_storage = static_cast<const StringParameter *>( parameter )->typedDefaultValue().c_str();
	}

	m_knob = knob( parameter, knobName, f, &m_storage );
	/// we have a lot of procedurals which do their own variable expansion using a SubstitutedDict,
	/// and the variables in the strings confuse nuke no end, so we're disabling expressions for now.
	/// \todo Can we do better and allow the two to coexist?
	SetFlags( f, DD::Image::Knob::NO_ANIMATION );
	setKnobProperties( parameter, f, m_knob );
}
void FloatParameterHandler::knobs( const IECore::Parameter *parameter, const char *knobName, DD::Image::Knob_Callback f )
{
	const FloatParameter *floatParameter = static_cast<const FloatParameter *>( parameter );

	if( f.makeKnobs() )
	{
		m_storage = floatParameter->numericDefaultValue();
	}

	std::string label = knobLabel( parameter );
	DD::Image::IRange range( floatParameter->minValue(), floatParameter->maxValue() );
	m_knob = Float_knob( f, &m_storage, range, knobName, label.c_str() );
	DD::Image::SetFlags( f, DD::Image::Knob::FORCE_RANGE );
	if( !(floatParameter->hasMinValue() && floatParameter->hasMaxValue()) )
	{
		DD::Image::ClearFlags( f, DD::Image::Knob::SLIDER );
	}
	setKnobProperties( parameter, f, m_knob );
}
void ClassParameterHandler::classChooserKnob( const IECore::Parameter *parameter, const char *knobName, DD::Image::Knob_Callback f )
{

	std::string classChooserName = string( knobName ) + "__classChooser";
	
	static const char *emptyMenu[] = { " ", "", 0 };
	DD::Image::Knob *classChooser = PyPulldown_knob( f, emptyMenu, classChooserName.c_str(), "No class loaded" );
	
	if( !f.makeKnobs() )
	{
		// making the menu is slow, and only needs doing when we're making knobs (not storing for instance),
		// so early out now to avoid massive slowdown.
		return;
	}
	
	vector<string> menuItems;
	menuItems.push_back( " " );
	menuItems.push_back( "" );
	
	std::string label = "No class loaded";
	
	IECorePython::ScopedGILLock gilLock;
	try
	{
		// get current class name, and set label from it
		
		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] )();
		if( className != "" )
		{
			int classVersion = extract<int>( classInfo[2] )();
			label = className + " v" + lexical_cast<string>( classVersion );
		}
		
		// if there is a current class, then add a menu item
		// to allow it to be removed.
		
		std::string parameterPath = knobName + 5; // naughty! we're not meant to know the knob name format
		replace_all( parameterPath, "_", "']['" );		
		boost::format setClassFormat(
			"with IECoreNuke.FnParameterisedHolder( nuke.thisNode() ).parameterModificationContext() as parameters :"
			"	parameters['%s'].setClass( '%s', %d )"
		);
		
		if( className!="" )
		{		
			menuItems.push_back( "Remove" );
			menuItems.push_back( ( setClassFormat % parameterPath % "" % 0 ).str() );
		}
		
		// find alternative classes which could be loaded
		
		std::string classNameFilter = "*";
		const CompoundObject *userData = parameter->userData();
		if( const CompoundObject *ui = userData->member<CompoundObject>( "UI" ) )
		{
			if( const StringData *classNameFilterData = ui->member<StringData>( "classNameFilter" ) )
			{
				classNameFilter = classNameFilterData->readable();
			}
		}
						
		std::string searchPathEnvVar = extract<const char *>( classInfo[3] )();
		object ieCore = import( "IECore" );
		object classLoader = ieCore.attr( "ClassLoader" ).attr( "defaultLoader" )( searchPathEnvVar );
		object classNames = classLoader.attr( "classNames" )( classNameFilter );
		
		// and build menu items to allow each of the alternative classes to be loaded
		
		int numClasses = len( classNames );
		for( int i=0; i<numClasses; i++ )
		{
			string className = extract<string>( classNames[i] )();
			object classVersions = classLoader.attr( "versions" )( object( classNames[i] ) );
			int numVersions = len( classVersions );
			
			for( int j=0; j<numVersions; j++ )
			{
				string versionString = extract<const char *>( classVersions[j].attr( "__str__" )() )();
				if( numVersions > 1 )
				{
					/// \todo We need to make this menu nice and hierarchical.
					/// We need the nuke boys to sort that out though.
					menuItems.push_back( className + " v" + versionString );
				}
				else
				{
					menuItems.push_back( className );
				}
				
				menuItems.push_back( ( setClassFormat % parameterPath % className % versionString ).str() );
			}
		}
		
	}
	catch( boost::python::error_already_set )
	{
		PyErr_Print();
	}
	catch( const std::exception &e )
	{
		msg( Msg::Error, "ClassParameterHandler::classChooserKnob", e.what() );
	}
	
	classChooser->label( label.c_str() );
	classChooser->enumerationKnob()->menu( menuItems );
}