Parse


Description

Populates the shader definition with information from the associated file. This is the second pass at parsing the associated file, since the ParseInfo callback first parses it to compile enough information to register the shader definition and populate the preset manager.

This callback is fired when a shader implemented with this parser's language is instantiated.


Applies To

Custom Shaders


Syntax

public class <plugin-item_name>
{
        public bool Parse( Context in_context )
        {
                ...
        }
}
CStatus <plugin-item_name>_Parse( CRef& in_context ) 
{ 
        ... 
}
function <plugin-item_name>_Parse( in_context ) 
{ 
        ... 
}
def <plugin-item_name>_Parse( in_context ):
        ...
Function <plugin-item_name>_Parse( in_context )
        ...
End Function
sub <plugin-item_name>_Parse 
{ 
        my $in_context = shift; 
}

<plugin-item-name> is the parser name specified in the call to PluginRegistrar.RegisterShaderLanguageParser with any spaces converted to underscores. For example, if you register a parser in a plug-in called "My Parser", the callback function names start with "My_Parser".


Parameters

Parameter Language Type Description
in_context Scripting and C# Context Context.GetAttribute("Definition") returns the ShaderDef.
C++ CRef& Context::GetAttribute("Definition") returns a reference to the ShaderDef.

Context Attributes

Attribute Get/Set Description
Filename Sets a String or CString The full path to the file to pre-parse. ??? What is pre-parsing???
Definition Returns or sets a ShaderDef The shader definition to populate/query.
Errors Returns a String or CString The parser can output parse errors.
Warnings Returns a String or CString The parser can output parse warnings.

Example

SICALLBACK UtShaderLanguageParser_Parse( CRef& in_ctxt  )
{
        XSI::Application app;
        XSI::Factory fact = app.GetFactory();

        /*      For this example, we use a very simple format to define the shader.
                First line represents the prog id.
                Following lines have this format:
                        Type space Input space Texturable space PortName
                        color|float|boolean|integer|vector2|vector3|vector4 in|out on|off $PortName
                Until a line with a single dot is found.
                Then, 2 strings separated by a space give the MR function name and library.                     */
        XSI::Context ctxt(in_ctxt);
        XSI::CString strFilename = ctxt.GetAttribute( L"FileName" );
        XSI::ShaderDef shaderDef = ctxt.GetAttribute( L"Definition" );

        // We'll just check if our user attribute is there
        {
                XSI::CValue valDune;
                valDune = shaderDef.GetAttributes().GetAttribute( L"{F2EF07FE-1B57-4245-BF08-F5556212BFDF}" );
                assert( !valDune.IsEmpty() );
        }

        std::ifstream in( strFilename.GetAsciiString() );
        if(!in) 
        {
                ctxt.PutAttribute( L"Errors", L"Cannot open file: " + strFilename + L"\n" );
                return CStatus::Fail;
        }

        char buf[255];

        // Skip First Line
        in.getline( buf, 255 );

        XSI::ShaderParamDefOptions optTexturableInput = fact.CreateShaderParamDefOptions();
        optTexturableInput.SetTexturable(true);

        // Port Defs 
        XSI::ShaderStructParamDef currentStructDef;
        while( in.getline( buf, 255 ).eof()==false )
        {
                if( strlen( buf ) > 0 )
                {
                        CSIString str(buf);
                        std::vector<CSIString> tokens;
                        str.Split( L" ", tokens );

                        // Strip the enum tokens
                        XSI::CValue valEnumValues;
                        {
                                CSIString strEnumValues;
                                std::vector<CSIString>::iterator itEraseStart = tokens.end();
                                bool bStartedEnum=false;
                                for( std::vector<CSIString>::iterator it=tokens.begin(); it!=tokens.end(); ++it )
                                {
                                        // Skip the enum token
                                        if( *it == L"enum" )
                                        {
                                                
                                                itEraseStart = it;
                                                bStartedEnum = true;
                                        }
                                        // Gather the enum tokens and remove them from the token list
                                        else if( bStartedEnum )
                                        {
                                                
                                                std::vector<CSIString> enumTokens;
                                                it->Split( L"=", enumTokens );
                                                if( enumTokens.size() == 2 )
                                                {
                                                        //Replace '_' by ' '
                                                        for( ULONG i=0; i<enumTokens[0].Length(); ++i )
                                                        {
                                                                if( ((LPCWSTR)enumTokens[0])[i] == L'_' )
                                                                {
                                                                        enumTokens[0].SetAt( i, L' ' );
                                                                }
                                                        }

                                                        strEnumValues += enumTokens[0];
                                                        strEnumValues += L",";
                                                        strEnumValues += enumTokens[1];
                                                        strEnumValues += L";";
                                                }
                                        }
                                }
                        
                                if( bStartedEnum )
                                {
                                        if( itEraseStart!=tokens.end() )
                                                tokens.erase( itEraseStart, tokens.end() );

                                        if( !strEnumValues.IsEmpty() )
                                        {
                                                valEnumValues = (LPCWSTR)strEnumValues;
                                        }
                                }
                        }
                        

                        if( tokens.size()==1  )
                        {
                                if( str==L"." )
                                        break;
                                else if( str==L"endstruct")
                                        currentStructDef=CRef();
                        }
                        else if( tokens.size()==4 )
                        {
                                XSI::CString strParamName = (LPCWSTR)tokens[3];
                                
                                CSIString strType = tokens[0];

                                bool bIsInput= tokens[1]==L"in";
                                bool bTexturable= tokens[2]==L"on";
                                bool bIsArray =false;

                                if( strType.Right(2) == L"[]" )
                                {
                                        bIsArray = true;
                                        strType.TruncateRight(2);
                                }
                                
                                XSI::siShaderParameterType eType = siScalarParameterType;
                                if( strType == L"color"  )
                                        eType = siColorParameterType;
                                if( strType == L"float" )
                                        eType = siScalarParameterType;
                                else if( strType == L"vector2" )
                                        eType = siVector2ParameterType;
                                else if( strType == L"vector3" )
                                        eType = siVectorParameterType;
                                else if( strType == L"vector4" )
                                        eType = siVector4ParameterType;
                                else if( strType == L"boolean" )
                                        eType = siBooleanParameterType;
                                else if( strType == L"integer" )
                                        eType = siIntegerParameterType;
                                else if( strType == L"reference" )
                                        eType = siReferenceParameterType;
                                else if ( strType == L"matrix4")
                                        eType = siMatrixParameterType;
                                else if ( strType == L"matrix3")
                                        eType = siMatrix3ParameterType;
                                else if ( strType == L"string")
                                        eType = siStringParameterType;
                                else if ( strType == L"quaternion")
                                        eType = siQuaternionParameterType;
                                else if ( strType == L"fcurve")
                                        eType = siProfileCurveParameterType;
                                else if ( strType == L"gradient")
                                        eType = siGradientParameterType;
                                else if ( strType == L"texture")
                                        eType = siTextureParameterType;
                                else if ( strType == L"tspace")
                                        eType = siTextureSpaceParameterType;
                                else if ( strType == L"struct" && !currentStructDef.IsValid() )
                                        eType = siStructParameterType;

                                // Now add the port.
                                XSI::ShaderParamDef paramDef;

                                bTexturable &= bIsInput;

                                XSI::ShaderParamDefContainer pdefContainer;
                                if( currentStructDef.IsValid() )
                                        pdefContainer = currentStructDef.GetSubParamDefs();
                                else if( bIsInput )
                                        pdefContainer = shaderDef.GetInputParamDefs();
                                else
                                        pdefContainer = shaderDef.GetOutputParamDefs();


                                if( !bIsArray )
                                {
                                        paramDef = pdefContainer.AddParamDef( strParamName, eType, bTexturable ? optTexturableInput :CRef() );

                                        if( eType == siStructParameterType )
                                        {
                                                currentStructDef = paramDef;
                                        }
                                }
                                else
                                {
                                        paramDef = pdefContainer.AddArrayParamDef( strParamName, eType, bTexturable ? optTexturableInput :CRef() );

                                        XSI::ShaderArrayParamDef arrayDef = paramDef;
                                        
                                        XSI::ShaderParamDef itemDef = arrayDef.GetArrayItemDef();
                                        
                                        if( eType == siStructParameterType )
                                        {
                                                currentStructDef = itemDef;
                                        }
                                }

                                // Set the enum values
                                if( !valEnumValues.IsEmpty() )
                                        paramDef.GetAttributes().SetAttribute( L"PPGPortEnumValues", valEnumValues );
                                
                                // Set tspace filter
                                if( strType==L"tspace" )
                                {
                                        paramDef.GetAttributes().SetAttribute( siPropertyFilterAttribute, (LONG)siUVPropertyFilter );
                                }
                        }
                }
        }

        if( in.getline( buf, 255 ).eof()==true )
        {
                CSIString str(buf);
                std::vector<CSIString> tokens;
                str.Split( L" ", tokens );
                
                // Fill MR MetaShaderDef
                if( tokens.size()==2 || tokens.size()==3 )
                {
                        // Texture type can connect to anything.
                        shaderDef.AddType( L"texture" );

                        XSI::MetaShaderRendererDef rendererDef = shaderDef.AddRendererDef( L"Mental Ray");
                        rendererDef.PutSymbolName( (LPCWSTR)tokens[0] );
                        rendererDef.PutCodePath( (LPCWSTR)tokens[1] );

                        CValue valVersion;

                        if( tokens.size()==2 )
                        {
                                valVersion=(LONG)1;
                        }
                        else
                        {
                                valVersion = (LPCWSTR)tokens[2];
                                valVersion.ChangeType( XSI::CValue::siInt8 );
                        }

                        XSI::AttributeMap rendererOptions = rendererDef.GetRendererOptions();
                        rendererOptions.SetAttribute( L"version", valVersion );

                        // Hardcoded options by shader types.
                        if( tokens[0] == L"sib_uvwgen" )
                        {
                                rendererOptions.SetAttribute( L"derivative1", L"on" );
                                rendererOptions.SetAttribute( L"derivative2", L"on" );
                        }
                }
                else
                {
                        ctxt.PutAttribute( L"Errors", L"Cannot find the DLL Code Section.\n" );
                        in.close();
                        return CStatus::Fail;
                }
        }
        else
        {
                ctxt.PutAttribute( L"Errors", L"Cannot find the DLL Code Section.\n" );
                in.close();
                return CStatus::Fail;
        }
        
        in.close();
        return CStatus::OK;
}

See Also