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.
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".
| 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. |
| 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. |
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;
}
|