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