/// <see cref="Translator.Translate"/> public override void Translate( ScriptCompiler compiler, AbstractNode node ) { var obj = (ObjectAbstractNode)node; // Must have a type as the first value if ( obj.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, obj.File, obj.Line ); return; } var type = string.Empty; if ( !getString( obj.Values[ 0 ], out type ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, obj.File, obj.Line ); return; } var system = (ParticleSystem)obj.Parent.Context; this._Emitter = system.AddEmitter( type ); foreach ( var i in obj.Children ) { if ( i is PropertyAbstractNode ) { var prop = (PropertyAbstractNode)i; var value = string.Empty; // Glob the values together foreach ( var it in prop.Values ) { if ( it is AtomAbstractNode ) { if ( string.IsNullOrEmpty( value ) ) { value = ( (AtomAbstractNode)it ).Value; } else { value = value + " " + ( (AtomAbstractNode)it ).Value; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); break; } } if ( !this._Emitter.SetParam( prop.Name, value ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } else { processNode( compiler, i ); } } }
public override void Translate( ScriptCompiler compiler, AbstractNode node ) { var obj = (ObjectAbstractNode)node; if ( obj != null ) { if ( string.IsNullOrEmpty( obj.Name ) ) { compiler.AddError( CompileErrorCode.ObjectNameExpected, obj.File, obj.Line, "gpu program object must have names" ); return; } } else { compiler.AddError( CompileErrorCode.ObjectNameExpected, obj.File, obj.Line, "gpu program object must have names" ); return; } // Must have a language type if ( obj.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, obj.File, obj.Line, "gpu program object require language declarations" ); return; } // Get the language string language; if ( !getString( obj.Values[ 0 ], out language ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, obj.File, obj.Line ); return; } if ( language == "asm" ) { _translateGpuProgram( compiler, obj ); } else if ( language == "unified" ) { _translateUnifiedGpuProgram( compiler, obj ); } else { _translateHighLevelGpuProgram( compiler, obj ); } }
/// <see cref="Translator.Translate"/> public override void Translate( ScriptCompiler compiler, AbstractNode node ) { ObjectAbstractNode obj = (ObjectAbstractNode)node; Compositor compositor = (Compositor)obj.Parent.Context; _Technique = compositor.CreateTechnique(); obj.Context = _Technique; foreach ( AbstractNode i in obj.Children ) { if ( i is ObjectAbstractNode ) { _processNode( compiler, i ); } else if ( i is PropertyAbstractNode ) { PropertyAbstractNode prop = (PropertyAbstractNode)i; switch ( (Keywords)prop.Id ) { #region ID_TEXTURE case Keywords.ID_TEXTURE: { int atomIndex = 1; AbstractNode it = getNodeAt( prop.Values, 0 ); if ( it is AtomAbstractNode ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); return; } // Save the first atom, should be name AtomAbstractNode atom0 = (AtomAbstractNode)it; int width = 0, height = 0; float widthFactor = 1.0f, heightFactor = 1.0f; bool widthSet = false, heightSet = false, formatSet = false; bool pooled = false; bool hwGammaWrite = false; bool fsaa = true; CompositionTechnique.TextureScope scope = CompositionTechnique.TextureScope.Local; List<PixelFormat> formats = new List<PixelFormat>(); while ( atomIndex < prop.Values.Count ) { it = getNodeAt( prop.Values, atomIndex++ ); if ( !(it is AtomAbstractNode) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); return; } AtomAbstractNode atom = (AtomAbstractNode)it; switch ( (Keywords)atom.Id ) { case Keywords.ID_TARGET_WIDTH: width = 0; widthSet = true; break; case Keywords.ID_TARGET_HEIGHT: height = 0; heightSet = true; break; case Keywords.ID_TARGET_WIDTH_SCALED: case Keywords.ID_TARGET_HEIGHT_SCALED: { bool pSetFlag = false; int pSize = 0; float pFactor = 0; if ( atom.Id == (uint)Keywords.ID_TARGET_WIDTH_SCALED ) { pSetFlag = widthSet; pSize = width; pFactor = widthFactor; } else { pSetFlag = heightSet; pSize = height; pFactor = heightFactor; } // advance to next to get scaling it = getNodeAt( prop.Values, atomIndex++ ); if ( it == null || !(it is AtomAbstractNode) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); return; } atom = (AtomAbstractNode)it; if ( !atom.IsNumber ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); return; } pSize = 0; pFactor = atom.Number; pSetFlag = true; } break; case Keywords.ID_POOLED: pooled = true; break; case Keywords.ID_SCOPE_LOCAL: scope = CompositionTechnique.TextureScope.Local; break; case Keywords.ID_SCOPE_CHAIN: scope = CompositionTechnique.TextureScope.Chain; break; case Keywords.ID_SCOPE_GLOBAL: scope = CompositionTechnique.TextureScope.Global; break; case Keywords.ID_GAMMA: hwGammaWrite = true; break; case Keywords.ID_NO_FSAA: fsaa = false; break; default: if ( atom.IsNumber ) { if ( atomIndex == 2 ) { width = (int)atom.Number; widthSet = true; } else if ( atomIndex == 3 ) { height = (int)atom.Number; heightSet = true; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); return; } } else { // pixel format? PixelFormat format = PixelUtil.GetFormatFromName( atom.Value, true ); if ( format == PixelFormat.Unknown ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); return; } formats.Add( format ); formatSet = true; } break; } } if ( !widthSet || !heightSet || !formatSet ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } // No errors, create CompositionTechnique.TextureDefinition def = _Technique.CreateTextureDefinition( atom0.Value ); def.Width = width; def.Height = height; def.WidthFactor = widthFactor; def.HeightFactor = heightFactor; def.PixelFormats = formats; def.HwGammaWrite = hwGammaWrite; def.Fsaa = fsaa; def.Pooled = pooled; def.Scope = scope; } break; #endregion ID_TEXTURE #region ID_TEXTURE_REF case Keywords.ID_TEXTURE_REF: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count != 3 ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "texture_ref only supports 3 argument" ); } else { string texName = string.Empty, refCompName = string.Empty, refTexName = string.Empty; AbstractNode it = getNodeAt( prop.Values, 0 ); if ( !getString( it, out texName ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "texture_ref must have 3 string arguments" ); } it = getNodeAt( prop.Values, 1 ); if ( !getString( it, out refCompName ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "texture_ref must have 3 string arguments" ); } it = getNodeAt( prop.Values, 2 ); if ( !getString( it, out refTexName ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "texture_ref must have 3 string arguments" ); } CompositionTechnique.TextureDefinition refTexDef = _Technique.CreateTextureDefinition( texName ); refTexDef.ReferenceCompositorName = refCompName; refTexDef.ReferenceTextureName = refTexName; } break; #endregion ID_TEXTURE_REF #region ID_SCHEME case Keywords.ID_SCHEME: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "scheme only supports 1 argument" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ); string scheme = string.Empty; if ( getString( i0, out scheme ) ) _Technique.SchemeName = scheme; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "scheme must have 1 string argument" ); } break; #endregion ID_SCHEME #region ID_COMPOSITOR_LOGIC case Keywords.ID_COMPOSITOR_LOGIC: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "compositor logic only supports 1 argument" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ); string logicName = string.Empty; if ( getString( i0, out logicName ) ) _Technique.CompositorLogicName = logicName; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "compositor logic must have 1 string argument" ); } break; #endregion ID_COMPOSITOR_LOGIC default: compiler.AddError( CompileErrorCode.UnexpectedToken, prop.File, prop.Line, "token \"" + prop.Name + "\" is not recognized" ); break; } } } }
/// <see cref="Translator.Translate"/> public override void Translate( ScriptCompiler compiler, AbstractNode node ) { ObjectAbstractNode obj = (ObjectAbstractNode)node; Pass pass = (Pass)obj.Parent.Context; _textureunit = pass.CreateTextureUnitState(); obj.Context = _textureunit; // Get the name of the technique if ( !string.IsNullOrEmpty( obj.Name ) ) _textureunit.Name = obj.Name; // Set the properties for the material foreach ( AbstractNode i in obj.Children ) { if ( i is PropertyAbstractNode ) { PropertyAbstractNode prop = (PropertyAbstractNode)i; switch ( (Keywords)prop.Id ) { #region ID_TEXTURE_ALIAS case Keywords.ID_TEXTURE_ALIAS: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "texture_alias must have at most 1 argument" ); } else { string val; if ( getString( prop.Values[ 0 ], out val ) ) _textureunit.TextureNameAlias = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid texture alias" ); } break; #endregion ID_TEXTURE_ALIAS #region ID_TEXTURE case Keywords.ID_TEXTURE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 5 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "texture must have at most 5 arguments" ); } else { AbstractNode j = getNodeAt( prop.Values, 0 ); int index = 1; string val; if ( getString( j, out val ) ) { TextureType texType = TextureType.TwoD; bool isAlpha = false; bool sRGBRead = false; PixelFormat format = PixelFormat.Unknown; int mipmaps = -1;//MIP_DEFAULT; while ( j != null ) { if ( j is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)j; switch ( (Keywords)atom.Id ) { case Keywords.ID_1D: texType = TextureType.OneD; break; case Keywords.ID_2D: texType = TextureType.TwoD; break; case Keywords.ID_3D: texType = TextureType.ThreeD; break; case Keywords.ID_CUBIC: texType = TextureType.CubeMap; break; case Keywords.ID_UNLIMITED: mipmaps = 0x7FFFFFFF;//MIP_UNLIMITED; break; case Keywords.ID_ALPHA: isAlpha = true; break; case Keywords.ID_GAMMA: sRGBRead = true; break; default: if ( atom.IsNumber ) mipmaps = (int)atom.Number; else format = PixelUtil.GetFormatFromName( atom.Value, true ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, j.Value + " is not a supported argument to the texture property" ); } j = getNodeAt( prop.Values, index++ ); } ScriptCompilerEvent evt = new ProcessResourceNameScriptCompilerEvent( ProcessResourceNameScriptCompilerEvent.ResourceType.Texture, val ); compiler._fireEvent( ref evt ); string textureName = ( (ProcessResourceNameScriptCompilerEvent)evt ).Name; _textureunit.SetTextureName( textureName, texType ); _textureunit.DesiredFormat = format; _textureunit.IsAlpha = isAlpha; _textureunit.MipmapCount = mipmaps; _textureunit.IsHardwareGammaEnabled = sRGBRead; } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, j.Value + " is not a valid texture name" ); } break; #endregion ID_TEXTURE #region ID_ANIM_TEXTURE case Keywords.ID_ANIM_TEXTURE: if ( prop.Values.Count < 3 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else { AbstractNode i1 = getNodeAt( prop.Values, 1 ); if ( i1 is AtomAbstractNode && ( (AtomAbstractNode)i ).IsNumber ) { // Short form AbstractNode i0 = getNodeAt( prop.Values, 0 ), i2 = getNodeAt( prop.Values, 2 ); if ( i0 is AtomAbstractNode ) { string val0; int val1; Real val2; if ( getString( i0, out val0 ) && getInt( i1, out val1 ) && getReal( i2, out val2 ) ) { ScriptCompilerEvent evt = new ProcessResourceNameScriptCompilerEvent( ProcessResourceNameScriptCompilerEvent.ResourceType.Texture, val0 ); compiler._fireEvent( ref evt ); string evtName = ( (ProcessResourceNameScriptCompilerEvent)evt ).Name; _textureunit.SetAnimatedTextureName( evtName, val1, val2 ); } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "anim_texture short form requires a texture name, number of frames, and animation duration" ); } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "anim_texture short form requires a texture name, number of frames, and animation duration" ); } } else { // Long form has n number of frames Real duration = 0; AbstractNode inNode = getNodeAt( prop.Values, prop.Values.Count - 1 ); if ( getReal( inNode, out duration ) ) { string[] names = new string[ prop.Values.Count - 1 ]; int n = 0; AbstractNode j = prop.Values[ 0 ]; int index = 0; while ( j != inNode ) { if ( j is AtomAbstractNode ) { string name = ( (AtomAbstractNode)j ).Value; #warning check this if statement // Run the name through the listener if ( compiler.Listener != null ) { ScriptCompilerEvent evt = new ProcessResourceNameScriptCompilerEvent( ProcessResourceNameScriptCompilerEvent.ResourceType.Texture, name ); compiler._fireEvent( ref evt ); names[ n++ ] = ( (ProcessResourceNameScriptCompilerEvent)evt ).Name; } else { names[ n++ ] = name; } } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, j.Value + " is not supported as a texture name" ); ++index; j = prop.Values[ index ]; } _textureunit.SetAnimatedTextureName( names, n, duration ); } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, inNode.Value + " is not supported for the duration argument" ); } } } break; #endregion ID_ANIM_TEXTURE #region ID_CUBIC_TEXTURE case Keywords.ID_CUBIC_TEXTURE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count == 2 ) { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); if ( i0 is AtomAbstractNode && i1 is AtomAbstractNode ) { AtomAbstractNode atom0 = (AtomAbstractNode)i0, atom1 = (AtomAbstractNode)i1; ScriptCompilerEvent evt = new ProcessResourceNameScriptCompilerEvent( ProcessResourceNameScriptCompilerEvent.ResourceType.Texture, atom0.Value ); compiler._fireEvent( ref evt ); string evtName = ( (ProcessResourceNameScriptCompilerEvent)evt ).Name; _textureunit.SetCubicTextureName( evtName, atom1.Id == (uint)Keywords.ID_COMBINED_UVW ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } else if ( prop.Values.Count == 7 ) { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ), i3 = getNodeAt( prop.Values, 3 ), i4 = getNodeAt( prop.Values, 4 ), i5 = getNodeAt( prop.Values, 5 ), i6 = getNodeAt( prop.Values, 6 ); if ( i0 is AtomAbstractNode && i1 is AtomAbstractNode && i2 is AtomAbstractNode && i3 is AtomAbstractNode && i4 is AtomAbstractNode && i5 is AtomAbstractNode && i6 is AtomAbstractNode ) { AtomAbstractNode atom0 = (AtomAbstractNode)i0, atom1 = (AtomAbstractNode)i1, atom2 = (AtomAbstractNode)i2, atom3 = (AtomAbstractNode)i3, atom4 = (AtomAbstractNode)i4, atom5 = (AtomAbstractNode)i5, atom6 = (AtomAbstractNode)i6; string[] names = new string[ 6 ]; names[ 0 ] = atom0.Value; names[ 1 ] = atom1.Value; names[ 2 ] = atom2.Value; names[ 3 ] = atom3.Value; names[ 4 ] = atom4.Value; names[ 5 ] = atom5.Value; if ( compiler.Listener != null ) { // Run each name through the listener for ( int j = 0; j < 6; ++j ) { ScriptCompilerEvent evt = new ProcessResourceNameScriptCompilerEvent( ProcessResourceNameScriptCompilerEvent.ResourceType.Texture, names[ j ] ); compiler._fireEvent( ref evt ); names[ j ] = ( (ProcessResourceNameScriptCompilerEvent)evt ).Name; } } _textureunit.SetCubicTextureName( names, atom6.Id == (uint)Keywords.ID_COMBINED_UVW ); } } else { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "cubic_texture must have at most 7 arguments" ); } break; #endregion ID_CUBIC_TEXTURE #region ID_TEX_COORD_SET case Keywords.ID_TEX_COORD_SET: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "tex_coord_set must have at most 1 argument" ); } else { int val = 0; if ( getInt( prop.Values[ 0 ], out val ) ) _textureunit.TextureCoordSet = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not supported as an integer argument" ); } break; #endregion ID_TEX_COORD_SET #region ID_TEX_ADDRESS_MODE case Keywords.ID_TEX_ADDRESS_MODE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ); UVWAddressing mode = new UVWAddressing( TextureAddressing.Wrap ); if ( i0 != null && i0 is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)i0; switch ( (Keywords)atom.Id ) { case Keywords.ID_WRAP: mode.U = TextureAddressing.Wrap; break; case Keywords.ID_CLAMP: mode.U = TextureAddressing.Clamp; break; case Keywords.ID_MIRROR: mode.U = TextureAddressing.Mirror; break; case Keywords.ID_BORDER: mode.U = TextureAddressing.Border; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " not supported as first argument (must be \"wrap\", \"clamp\", \"mirror\", or \"border\")" ); break; } } mode.V = mode.U; mode.W = mode.U; if ( i1 != null && i1 is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)i1; switch ( (Keywords)atom.Id ) { case Keywords.ID_WRAP: mode.V = TextureAddressing.Wrap; break; case Keywords.ID_CLAMP: mode.V = TextureAddressing.Clamp; break; case Keywords.ID_MIRROR: mode.V = TextureAddressing.Mirror; break; case Keywords.ID_BORDER: mode.V = TextureAddressing.Border; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " not supported as second argument (must be \"wrap\", \"clamp\", \"mirror\", or \"border\")" ); break; } } if ( i2 != null && i2 is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)i2; switch ( (Keywords)atom.Id ) { case Keywords.ID_WRAP: mode.W = TextureAddressing.Wrap; break; case Keywords.ID_CLAMP: mode.W = TextureAddressing.Clamp; break; case Keywords.ID_MIRROR: mode.W = TextureAddressing.Mirror; break; case Keywords.ID_BORDER: mode.W = TextureAddressing.Border; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " not supported as third argument (must be \"wrap\", \"clamp\", \"mirror\", or \"border\")" ); break; } } _textureunit.SetTextureAddressingMode( mode ); } break; #endregion ID_TEX_ADDRESS_MODE #region ID_TEX_BORDER_COLOUR case Keywords.ID_TEX_BORDER_COLOUR: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else { ColorEx val; if ( getColor( prop.Values, 0, out val ) ) _textureunit.TextureBorderColor = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "tex_border_colour only accepts a colour argument" ); } break; #endregion ID_TEX_BORDER_COLOUR #region ID_FILTERING case Keywords.ID_FILTERING: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count == 1 ) { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_NONE: _textureunit.SetTextureFiltering( TextureFiltering.None ); break; case Keywords.ID_BILINEAR: _textureunit.SetTextureFiltering( TextureFiltering.Bilinear ); break; case Keywords.ID_TRILINEAR: _textureunit.SetTextureFiltering( TextureFiltering.Trilinear ); break; case Keywords.ID_ANISOTROPIC: _textureunit.SetTextureFiltering( TextureFiltering.Anisotropic ); break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " not supported as first argument (must be \"none\", \"bilinear\", \"trilinear\", or \"anisotropic\")" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " not supported as first argument (must be \"none\", \"bilinear\", \"trilinear\", or \"anisotropic\")" ); } } else if ( prop.Values.Count == 3 ) { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ); if ( i0 is AtomAbstractNode && i1 is AtomAbstractNode && i2 is AtomAbstractNode ) { AtomAbstractNode atom0 = (AtomAbstractNode)i0, atom1 = (AtomAbstractNode)i1, atom2 = (AtomAbstractNode)i2; FilterOptions tmin = FilterOptions.None, tmax = FilterOptions.None, tmip = FilterOptions.None; switch ( (Keywords)atom0.Id ) { case Keywords.ID_NONE: tmin = FilterOptions.None; break; case Keywords.ID_POINT: tmin = FilterOptions.Point; break; case Keywords.ID_LINEAR: tmin = FilterOptions.Linear; break; case Keywords.ID_ANISOTROPIC: tmin = FilterOptions.Anisotropic; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " not supported as first argument (must be \"none\", \"point\", \"linear\", or \"anisotropic\")" ); break; } switch ( (Keywords)atom1.Id ) { case Keywords.ID_NONE: tmax = FilterOptions.None; break; case Keywords.ID_POINT: tmax = FilterOptions.Point; break; case Keywords.ID_LINEAR: tmax = FilterOptions.Linear; break; case Keywords.ID_ANISOTROPIC: tmax = FilterOptions.Anisotropic; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " not supported as second argument (must be \"none\", \"point\", \"linear\", or \"anisotropic\")" ); break; } switch ( (Keywords)atom2.Id ) { case Keywords.ID_NONE: tmip = FilterOptions.None; break; case Keywords.ID_POINT: tmip = FilterOptions.Point; break; case Keywords.ID_LINEAR: tmip = FilterOptions.Linear; break; case Keywords.ID_ANISOTROPIC: tmip = FilterOptions.Anisotropic; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " not supported as third argument (must be \"none\", \"point\", \"linear\", or \"anisotropic\")" ); break; } _textureunit.SetTextureFiltering( tmin, tmax, tmip ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } else { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "filtering must have either 1 or 3 arguments" ); } break; #endregion ID_FILTERING #region ID_MAX_ANISOTROPY case Keywords.ID_MAX_ANISOTROPY: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "max_anisotropy must have at most 1 argument" ); } else { int val = 0; if ( getInt( prop.Values[ 0 ], out val ) ) _textureunit.TextureAnisotropy = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid integer argument" ); } break; #endregion ID_MAX_ANISOTROPY #region ID_MIPMAP_BIAS case Keywords.ID_MIPMAP_BIAS: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "mipmap_bias must have at most 1 argument" ); } else { throw new NotImplementedException(); #if UNREACHABLE_CODE Real val = 0.0f; if ( getReal( prop.Values[ 0 ], out val ) ) { /*mUnit->setTextureMipmapBias(val);*/ } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid number argument" ); #endif } break; #endregion ID_MIPMAP_BIAS #region ID_COLOUR_OP case Keywords.ID_COLOUR_OP: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "colour_op must have at most 1 argument" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_REPLACE: _textureunit.ColorOperation = LayerBlendOperation.Replace; break; case Keywords.ID_ADD: _textureunit.ColorOperation = LayerBlendOperation.Add; break; case Keywords.ID_MODULATE: _textureunit.ColorOperation = LayerBlendOperation.Modulate; break; case Keywords.ID_ALPHA_BLEND: _textureunit.ColorOperation = LayerBlendOperation.AlphaBlend; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid argument (must be \"replace\", \"add\", \"modulate\", or \"alpha_blend\")" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid argument (must be \"replace\", \"add\", \"modulate\", or \"alpha_blend\")" ); } } break; #endregion ID_COLOUR_OP #region ID_COLOUR_OP_EX case Keywords.ID_COLOUR_OP_EX: if ( prop.Values.Count < 3 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line, "colour_op_ex must have at least 3 arguments" ); } else if ( prop.Values.Count > 10 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "colour_op_ex must have at most 10 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ); if ( i0 is AtomAbstractNode && i1 is AtomAbstractNode && i2 is AtomAbstractNode ) { AtomAbstractNode atom0 = (AtomAbstractNode)i0, atom1 = (AtomAbstractNode)i1, atom2 = (AtomAbstractNode)i2; LayerBlendOperationEx op = LayerBlendOperationEx.Add; LayerBlendSource source1 = LayerBlendSource.Current, source2 = LayerBlendSource.Texture; ColorEx arg1 = ColorEx.White, arg2 = ColorEx.White; Real manualBlend = 0.0f; switch ( (Keywords)atom0.Id ) { case Keywords.ID_SOURCE1: op = LayerBlendOperationEx.Source1; break; case Keywords.ID_SOURCE2: op = LayerBlendOperationEx.Source2; break; case Keywords.ID_MODULATE: op = LayerBlendOperationEx.Modulate; break; case Keywords.ID_MODULATE_X2: op = LayerBlendOperationEx.ModulateX2; break; case Keywords.ID_MODULATE_X4: op = LayerBlendOperationEx.ModulateX4; break; case Keywords.ID_ADD: op = LayerBlendOperationEx.Add; break; case Keywords.ID_ADD_SIGNED: op = LayerBlendOperationEx.AddSigned; break; case Keywords.ID_ADD_SMOOTH: op = LayerBlendOperationEx.AddSmooth; break; case Keywords.ID_SUBTRACT: op = LayerBlendOperationEx.Subtract; break; case Keywords.ID_BLEND_DIFFUSE_ALPHA: op = LayerBlendOperationEx.BlendDiffuseAlpha; break; case Keywords.ID_BLEND_TEXTURE_ALPHA: op = LayerBlendOperationEx.BlendTextureAlpha; break; case Keywords.ID_BLEND_CURRENT_ALPHA: op = LayerBlendOperationEx.BlendCurrentAlpha; break; case Keywords.ID_BLEND_MANUAL: op = LayerBlendOperationEx.BlendManual; break; case Keywords.ID_DOT_PRODUCT: op = LayerBlendOperationEx.DotProduct; break; case Keywords.ID_BLEND_DIFFUSE_COLOUR: op = LayerBlendOperationEx.BlendDiffuseColor; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " is not a valid first argument (must be \"source1\", \"source2\", \"modulate\", \"modulate_x2\", \"modulate_x4\", \"add\", \"add_signed\", \"add_smooth\", \"subtract\", \"blend_diffuse_alpha\", \"blend_texture_alpha\", \"blend_current_alpha\", \"blend_manual\", \"dot_product\", or \"blend_diffuse_colour\")" ); break; } switch ( (Keywords)atom1.Id ) { case Keywords.ID_SRC_CURRENT: source1 = LayerBlendSource.Current; break; case Keywords.ID_SRC_TEXTURE: source1 = LayerBlendSource.Texture; break; case Keywords.ID_SRC_DIFFUSE: source1 = LayerBlendSource.Diffuse; break; case Keywords.ID_SRC_SPECULAR: source1 = LayerBlendSource.Specular; break; case Keywords.ID_SRC_MANUAL: source1 = LayerBlendSource.Manual; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i1.Value + " is not a valid second argument (must be \"src_current\", \"src_texture\", \"src_diffuse\", \"src_specular\", or \"src_manual\")" ); break; } switch ( (Keywords)atom2.Id ) { case Keywords.ID_SRC_CURRENT: source2 = LayerBlendSource.Current; break; case Keywords.ID_SRC_TEXTURE: source2 = LayerBlendSource.Texture; break; case Keywords.ID_SRC_DIFFUSE: source2 = LayerBlendSource.Diffuse; break; case Keywords.ID_SRC_SPECULAR: source2 = LayerBlendSource.Specular; break; case Keywords.ID_SRC_MANUAL: source2 = LayerBlendSource.Manual; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i2.Value + " is not a valid third argument (must be \"src_current\", \"src_texture\", \"src_diffuse\", \"src_specular\", or \"src_manual\")" ); break; } if ( op == LayerBlendOperationEx.BlendManual ) { AbstractNode i3 = getNodeAt( prop.Values, 3 ); if ( i3 != null ) { if ( !getReal( i3, out manualBlend ) ) compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i3.Value + " is not a valid number argument" ); } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "fourth argument expected when blend_manual is used" ); } } AbstractNode j = getNodeAt( prop.Values, 3 ); int index = 3; if ( op == LayerBlendOperationEx.BlendManual ) j = getNodeAt( prop.Values, ++index ); if ( source1 == LayerBlendSource.Manual ) { if ( j != null ) { if ( !getColor( prop.Values, 3, out arg1, 3 ) ) compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "valid colour expected when src_manual is used" ); } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "valid colour expected when src_manual is used" ); } } if ( source2 == LayerBlendSource.Manual ) { if ( j != null ) { if ( !getColor( prop.Values, 3, out arg2, 3 ) ) compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "valid colour expected when src_manual is used" ); } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "valid colour expected when src_manual is used" ); } } _textureunit.SetColorOperationEx( op, source1, source2, arg1, arg2, manualBlend ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_COLOUR_OP_EX #region ID_COLOUR_OP_MULTIPASS_FALLBACK case Keywords.ID_COLOUR_OP_MULTIPASS_FALLBACK: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 2 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "colour_op_multiplass_fallback must have at most 2 arguments" ); } else if ( prop.Values.Count == 1 ) { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_ADD: _textureunit.SetColorOpMultipassFallback( SceneBlendFactor.One, SceneBlendFactor.One ); break; case Keywords.ID_MODULATE: _textureunit.SetColorOpMultipassFallback( SceneBlendFactor.DestColor, SceneBlendFactor.Zero ); break; case Keywords.ID_COLOUR_BLEND: _textureunit.SetColorOpMultipassFallback( SceneBlendFactor.SourceColor, SceneBlendFactor.OneMinusSourceColor ); break; case Keywords.ID_ALPHA_BLEND: _textureunit.SetColorOpMultipassFallback( SceneBlendFactor.SourceAlpha, SceneBlendFactor.OneMinusSourceAlpha ); break; case Keywords.ID_REPLACE: _textureunit.SetColorOpMultipassFallback( SceneBlendFactor.One, SceneBlendFactor.Zero ); break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "argument must be a valid scene blend type (add, modulate, colour_blend, alpha_blend, or replace)" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "argument must be a valid scene blend type (add, modulate, colour_blend, alpha_blend, or replace)" ); } } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); SceneBlendFactor sbf0, sbf1; if ( getEnumeration<SceneBlendFactor>( i0, compiler, out sbf0 ) && getEnumeration<SceneBlendFactor>( i1, compiler, out sbf1 ) ) _textureunit.SetColorOpMultipassFallback( sbf0, sbf1 ); else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "arguments must be valid scene blend factors" ); } break; #endregion ID_COLOUR_OP_MULTIPASS_FALLBACK #region ID_ALPHA_OP_EX case Keywords.ID_ALPHA_OP_EX: if ( prop.Values.Count < 3 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line, "alpha_op_ex must have at least 3 arguments" ); } else if ( prop.Values.Count > 6 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "alpha_op_ex must have at most 6 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ); if ( i0 is AtomAbstractNode && i1 is AtomAbstractNode && i2 is AtomAbstractNode ) { AtomAbstractNode atom0 = (AtomAbstractNode)i0, atom1 = (AtomAbstractNode)i1, atom2 = (AtomAbstractNode)i2; LayerBlendOperationEx op = LayerBlendOperationEx.Add; LayerBlendSource source1 = LayerBlendSource.Current, source2 = LayerBlendSource.Texture; Real arg1 = 0.0f, arg2 = 0.0f; Real manualBlend = 0.0f; switch ( (Keywords)atom0.Id ) { case Keywords.ID_SOURCE1: op = LayerBlendOperationEx.Source1; break; case Keywords.ID_SOURCE2: op = LayerBlendOperationEx.Source2; break; case Keywords.ID_MODULATE: op = LayerBlendOperationEx.Modulate; break; case Keywords.ID_MODULATE_X2: op = LayerBlendOperationEx.ModulateX2; break; case Keywords.ID_MODULATE_X4: op = LayerBlendOperationEx.ModulateX4; break; case Keywords.ID_ADD: op = LayerBlendOperationEx.Add; break; case Keywords.ID_ADD_SIGNED: op = LayerBlendOperationEx.AddSigned; break; case Keywords.ID_ADD_SMOOTH: op = LayerBlendOperationEx.AddSmooth; break; case Keywords.ID_SUBTRACT: op = LayerBlendOperationEx.Subtract; break; case Keywords.ID_BLEND_DIFFUSE_ALPHA: op = LayerBlendOperationEx.BlendDiffuseAlpha; break; case Keywords.ID_BLEND_TEXTURE_ALPHA: op = LayerBlendOperationEx.BlendTextureAlpha; break; case Keywords.ID_BLEND_CURRENT_ALPHA: op = LayerBlendOperationEx.BlendCurrentAlpha; break; case Keywords.ID_BLEND_MANUAL: op = LayerBlendOperationEx.BlendManual; break; case Keywords.ID_DOT_PRODUCT: op = LayerBlendOperationEx.DotProduct; break; case Keywords.ID_BLEND_DIFFUSE_COLOUR: op = LayerBlendOperationEx.BlendDiffuseColor; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " is not a valid first argument (must be \"source1\", \"source2\", \"modulate\", \"modulate_x2\", \"modulate_x4\", \"add\", \"add_signed\", \"add_smooth\", \"subtract\", \"blend_diffuse_alpha\", \"blend_texture_alpha\", \"blend_current_alpha\", \"blend_manual\", \"dot_product\", or \"blend_diffuse_colour\")" ); break; } switch ( (Keywords)atom1.Id ) { case Keywords.ID_SRC_CURRENT: source1 = LayerBlendSource.Current; break; case Keywords.ID_SRC_TEXTURE: source1 = LayerBlendSource.Texture; break; case Keywords.ID_SRC_DIFFUSE: source1 = LayerBlendSource.Diffuse; break; case Keywords.ID_SRC_SPECULAR: source1 = LayerBlendSource.Specular; break; case Keywords.ID_SRC_MANUAL: source1 = LayerBlendSource.Manual; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i1.Value + " is not a valid second argument (must be \"src_current\", \"src_texture\", \"src_diffuse\", \"src_specular\", or \"src_manual\")" ); break; } switch ( (Keywords)atom2.Id ) { case Keywords.ID_SRC_CURRENT: source2 = LayerBlendSource.Current; break; case Keywords.ID_SRC_TEXTURE: source2 = LayerBlendSource.Texture; break; case Keywords.ID_SRC_DIFFUSE: source2 = LayerBlendSource.Diffuse; break; case Keywords.ID_SRC_SPECULAR: source2 = LayerBlendSource.Specular; break; case Keywords.ID_SRC_MANUAL: source2 = LayerBlendSource.Manual; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i2.Value + " is not a valid third argument (must be \"src_current\", \"src_texture\", \"src_diffuse\", \"src_specular\", or \"src_manual\")" ); break; } if ( op == LayerBlendOperationEx.BlendManual ) { AbstractNode i3 = getNodeAt( prop.Values, 3 ); if ( i3 != null ) { if ( !getReal( i3, out manualBlend ) ) compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "valid number expected when blend_manual is used" ); } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "valid number expected when blend_manual is used" ); } } AbstractNode j = getNodeAt( prop.Values, 3 ); int index = 3; if ( op == LayerBlendOperationEx.BlendManual ) j = getNodeAt( prop.Values, ++index ); if ( source1 == LayerBlendSource.Manual ) { if ( j != null ) { if ( !getReal( j, out arg1 ) ) compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "valid colour expected when src_manual is used" ); else j = getNodeAt( prop.Values, ++index ); } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "valid colour expected when src_manual is used" ); } } if ( source2 == LayerBlendSource.Manual ) { if ( j != null ) { if ( !getReal( j, out arg2 ) ) compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "valid colour expected when src_manual is used" ); } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "valid colour expected when src_manual is used" ); } } _textureunit.SetAlphaOperation( op, source1, source2, arg1, arg2, manualBlend ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_ALPHA_OP_EX #region ID_ENV_MAP case Keywords.ID_ENV_MAP: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "env_map must have at most 1 argument" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( atom.Id ) { case (uint)BuiltIn.ID_OFF: _textureunit.SetEnvironmentMap( false ); break; case (uint)Keywords.ID_SPHERICAL: _textureunit.SetEnvironmentMap( true, EnvironmentMap.Curved ); break; case (uint)Keywords.ID_PLANAR: _textureunit.SetEnvironmentMap( true, EnvironmentMap.Planar ); break; case (uint)Keywords.ID_CUBIC_REFLECTION: _textureunit.SetEnvironmentMap( true, EnvironmentMap.Reflection ); break; case (uint)Keywords.ID_CUBIC_NORMAL: _textureunit.SetEnvironmentMap( true, EnvironmentMap.Normal ); break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid argument (must be \"off\", \"spherical\", \"planar\", \"cubic_reflection\", or \"cubic_normal\")" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid argument (must be \"off\", \"spherical\", \"planar\", \"cubic_reflection\", or \"cubic_normal\")" ); } } break; #endregion ID_ENV_MAP #region ID_SCROLL case Keywords.ID_SCROLL: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 2 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "scroll must have at most 2 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); Real x, y; if ( getReal( i0, out x ) && getReal( i1, out y ) ) _textureunit.SetTextureScroll( x, y ); else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " and/or " + i1.Value + " is invalid; both must be numbers" ); } break; #endregion ID_SCROLL #region ID_SCROLL_ANIM case Keywords.ID_SCROLL_ANIM: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 2 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "scroll_anim must have at most 2 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); Real x, y; if ( getReal( i0, out x ) && getReal( i1, out y ) ) _textureunit.SetScrollAnimation( x, y ); else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " and/or " + i1.Value + " is invalid; both must be numbers" ); } break; #endregion ID_SCROLL_ANIM #region ID_ROTATE case Keywords.ID_ROTATE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "rotate must have at most 1 argument" ); } else { Real angle; if ( getReal( prop.Values[ 0 ], out angle ) ) #warning check this statement //mUnit->setTextureRotate(Degree(angle)); _textureunit.SetTextureRotate( angle ); else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid number value" ); } break; #endregion ID_ROTATE #region ID_ROTATE_ANIM case Keywords.ID_ROTATE_ANIM: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "rotate_anim must have at most 1 argument" ); } else { Real angle; if ( getReal( prop.Values[ 0 ], out angle ) ) _textureunit.SetRotateAnimation( angle ); else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid number value" ); } break; #endregion ID_ROTATE_ANIM #region ID_SCALE case Keywords.ID_SCALE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 2 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "scale must have at most 2 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); Real x, y; if ( getReal( i0, out x ) && getReal( i1, out y ) ) _textureunit.SetTextureScale( x, y ); else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "first and second arguments must both be valid number values (received " + i0.Value + ", " + i1.Value + ")" ); } break; #endregion ID_SCALE #region ID_WAVE_XFORM case Keywords.ID_WAVE_XFORM: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 6 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "wave_xform must have at most 6 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ), i3 = getNodeAt( prop.Values, 3 ), i4 = getNodeAt( prop.Values, 4 ), i5 = getNodeAt( prop.Values, 5 ); if ( i0 is AtomAbstractNode && i1 is AtomAbstractNode && i2 is AtomAbstractNode && i3 is AtomAbstractNode && i4 is AtomAbstractNode && i5 is AtomAbstractNode ) { AtomAbstractNode atom0 = (AtomAbstractNode)i0, atom1 = (AtomAbstractNode)i1; TextureTransform type = TextureTransform.Rotate; WaveformType wave = WaveformType.Sine; Real baseVal = 0.0f, freq = 0.0f, phase = 0.0f, amp = 0.0f; switch ( (Keywords)atom0.Id ) { case Keywords.ID_SCROLL_X: type = TextureTransform.TranslateU; break; case Keywords.ID_SCROLL_Y: type = TextureTransform.TranslateV; break; case Keywords.ID_SCALE_X: type = TextureTransform.ScaleU; break; case Keywords.ID_SCALE_Y: type = TextureTransform.ScaleV; break; case Keywords.ID_ROTATE: type = TextureTransform.Rotate; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, atom0.Value + " is not a valid transform type (must be \"scroll_x\", \"scroll_y\", \"scale_x\", \"scale_y\", or \"rotate\")" ); break; } switch ( (Keywords)atom1.Id ) { case Keywords.ID_SINE: wave = WaveformType.Sine; break; case Keywords.ID_TRIANGLE: wave = WaveformType.Triangle; break; case Keywords.ID_SQUARE: wave = WaveformType.Square; break; case Keywords.ID_SAWTOOTH: wave = WaveformType.Sawtooth; break; case Keywords.ID_INVERSE_SAWTOOTH: wave = WaveformType.InverseSawtooth; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, atom1.Value + " is not a valid waveform type (must be \"sine\", \"triangle\", \"square\", \"sawtooth\", or \"inverse_sawtooth\")" ); break; } if ( !getReal( i2, out baseVal ) || !getReal( i3, out freq ) || !getReal( i4, out phase ) || !getReal( i5, out amp ) ) compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "arguments 3, 4, 5, and 6 must be valid numbers; received " + i2.Value + ", " + i3.Value + ", " + i4.Value + ", " + i5.Value ); _textureunit.SetTransformAnimation( type, wave, baseVal, freq, phase, amp ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_WAVE_XFORM #region ID_TRANSFORM case Keywords.ID_TRANSFORM: { throw new NotImplementedException(); #if UNREACHABLE_CODE Matrix4 m; if ( getMatrix4( prop.Values, 0, out m ) ) { /*mUnit->setTextureTransform(m);*/ } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } break; #else } #endif #endregion ID_TRANSFORM #region ID_BINDING_TYPE case Keywords.ID_BINDING_TYPE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "binding_type must have at most 1 argument" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_VERTEX: _textureunit.BindingType = TextureBindingType.Vertex; break; case Keywords.ID_FRAGMENT: _textureunit.BindingType = TextureBindingType.Fragment; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, atom.Value + " is not a valid binding type (must be \"vertex\" or \"fragment\")" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid binding type" ); } } break; #endregion ID_BINDING_TYPE #region ID_CONTENT_TYPE case Keywords.ID_CONTENT_TYPE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 4 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "content_type must have at most 4 arguments" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { throw new NotImplementedException(); #if UNREACHABLE_CODE AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_NAMED: //mUnit->setContentType(TextureUnitState::CONTENT_NAMED); break; case Keywords.ID_SHADOW: //mUnit->setContentType(TextureUnitState::CONTENT_SHADOW); break; case Keywords.ID_COMPOSITOR: //mUnit->setContentType(TextureUnitState::CONTENT_COMPOSITOR); if ( prop.Values.Count >= 3 ) { string compositorName; getString( getNodeAt( prop.Values, 1 ), out compositorName ); string textureName; getString( getNodeAt( prop.Values, 2 ), out textureName ); if ( prop.Values.Count == 4 ) { uint mrtIndex; getUInt( getNodeAt( prop.Values, 3 ), out mrtIndex ); //mUnit->setCompositorReference(compositorName, textureName, mrtIndex); } else { //mUnit->setCompositorReference(compositorName, textureName); } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "content_type compositor must have an additional 2 or 3 parameters" ); } break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, atom.Value + " is not a valid content type (must be \"named\" or \"shadow\" or \"compositor\")" ); break; } #endif } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid content type" ); } } break;
/// <see cref="Translator.Translate"/> public override void Translate( ScriptCompiler compiler, AbstractNode node ) { ObjectAbstractNode obj = (ObjectAbstractNode)node; // Create the technique from the material Material material = (Material)obj.Parent.Context; _technique = material.CreateTechnique(); obj.Context = _technique; // Get the name of the technique if ( !string.IsNullOrEmpty( obj.Name ) ) _technique.Name = obj.Name; // Set the properties for the technique foreach ( AbstractNode i in obj.Children ) { if ( i is PropertyAbstractNode ) { PropertyAbstractNode prop = (PropertyAbstractNode)i; switch ( (Keywords)prop.Id ) { #region ID_SCHEME case Keywords.ID_SCHEME: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "scheme only supports 1 argument" ); } else { string scheme; if ( getString( prop.Values[ 0 ], out scheme ) ) _technique.Scheme = scheme; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "scheme must have 1 string argument" ); } break; #endregion ID_SCHEME #region ID_LOD_INDEX case Keywords.ID_LOD_INDEX: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "lod_index only supports 1 argument" ); } else { int val; if ( getInt( prop.Values[ 0 ], out val ) ) _technique.LodIndex = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "lod_index cannot accept argument \"" + prop.Values[ 0 ].Value + "\"" ); } break; #endregion ID_LOD_INDEX #region ID_SHADOW_CASTER_MATERIAL case Keywords.ID_SHADOW_CASTER_MATERIAL: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "shadow_caster_material only accepts 1 argument" ); } else { string matName; if ( getString( prop.Values[ 0 ], out matName ) ) { string evtMatName = string.Empty; ScriptCompilerEvent evt = new ProcessResourceNameScriptCompilerEvent( ProcessResourceNameScriptCompilerEvent.ResourceType.Material, matName ); compiler._fireEvent( ref evt ); evtMatName = ( (ProcessResourceNameScriptCompilerEvent)evt ).Name; _technique.ShadowCasterMaterial = (Material)MaterialManager.Instance[ evtMatName ]; // Use the processed name } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "shadow_caster_material cannot accept argument \"" + prop.Values[ 0 ].Value + "\"" ); } break; #endregion ID_SHADOW_CASTER_MATERIAL #region ID_SHADOW_RECEIVER_MATERIAL case Keywords.ID_SHADOW_RECEIVER_MATERIAL: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "shadow_receiver_material only accepts 1 argument" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ); string matName = string.Empty; if ( getString( i0, out matName ) ) { string evtName = string.Empty; ScriptCompilerEvent evt = new ProcessResourceNameScriptCompilerEvent( ProcessResourceNameScriptCompilerEvent.ResourceType.Material, matName ); compiler._fireEvent( ref evt ); evtName = ( (ProcessResourceNameScriptCompilerEvent)evt ).Name; _technique.ShadowReceiverMaterial = (Material)MaterialManager.Instance[ evtName ]; } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "shadow_receiver_material_name cannot accept argument \"" + i0.Value + "\"" ); } break; #endregion ID_SHADOW_RECEIVER_MATERIAL #region ID_GPU_VENDOR_RULE case Keywords.ID_GPU_VENDOR_RULE: if ( prop.Values.Count < 2 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line, "gpu_vendor_rule must have 2 arguments" ); } else if ( prop.Values.Count > 2 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "gpu_vendor_rule must have 2 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ); AbstractNode i1 = getNodeAt( prop.Values, 1 ); Technique.GPUVendorRule rule = new Technique.GPUVendorRule(); if ( i0 is AtomAbstractNode ) { AtomAbstractNode atom0 = (AtomAbstractNode)i0; Keywords atom0Id = (Keywords)atom0.Id; if ( atom0Id == Keywords.ID_INCLUDE ) { rule.Include = true; } else if ( atom0Id == Keywords.ID_EXCLUDE ) { rule.Include = false; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "gpu_vendor_rule cannot accept \"" + i0.Value + "\" as first argument" ); } string vendor = string.Empty; if ( !getString( i1, out vendor ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "gpu_vendor_rule cannot accept \"" + i1.Value + "\" as second argument" ); } rule.Vendor = RenderSystemCapabilities.VendorFromString( vendor ); if ( rule.Vendor != GPUVendor.Unknown ) { _technique.AddGPUVenderRule( rule ); } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "gpu_vendor_rule cannot accept \"" + i0.Value + "\" as first argument" ); } } break; #endregion ID_GPU_VENDOR_RULE #region ID_GPU_DEVICE_RULE case Keywords.ID_GPU_DEVICE_RULE: if ( prop.Values.Count < 2 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line, "gpu_device_rule must have at least 2 arguments" ); } else if ( prop.Values.Count > 3 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "gpu_device_rule must have at most 3 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ); AbstractNode i1 = getNodeAt( prop.Values, 1 ); Technique.GPUDeviceNameRule rule = new Technique.GPUDeviceNameRule(); if ( i0 is AtomAbstractNode ) { AtomAbstractNode atom0 = (AtomAbstractNode)i0; Keywords atom0Id = (Keywords)atom0.Id; if ( atom0Id == Keywords.ID_INCLUDE ) { rule.Include = true; } else if ( atom0Id == Keywords.ID_EXCLUDE ) { rule.Include = false; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "gpu_device_rule cannot accept \"" + i0.Value + "\" as first argument" ); } if ( !getString( i1, out rule.DevicePattern ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "gpu_device_rule cannot accept \"" + i1.Value + "\" as second argument" ); } if ( prop.Values.Count == 3 ) { AbstractNode i2 = getNodeAt( prop.Values, 2 ); if ( !getBoolean( i2, out rule.CaseSensitive ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "gpu_device_rule third argument must be \"true\", \"false\", \"yes\", \"no\", \"on\", or \"off\"" ); } } _technique.AddGPUDeviceNameRule( rule ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "gpu_device_rule cannot accept \"" + i0.Value + "\" as first argument" ); } } break; #endregion ID_GPU_DEVICE_RULE default: compiler.AddError( CompileErrorCode.UnexpectedToken, prop.File, prop.Line, "token \"" + prop.Name + "\" is not recognized" ); break; } //end of switch statement } // end of if ( i is PropertyAbstractNode ) else if ( i is ObjectAbstractNode ) { _processNode( compiler, i ); } } }
/// <see cref="Translator.Translate"/> public override void Translate( ScriptCompiler compiler, AbstractNode node ) { var obj = (ObjectAbstractNode)node; var target = (CompositionTargetPass)obj.Parent.Context; this._Pass = target.CreatePass(); obj.Context = this._Pass; // The name is the type of the pass if ( obj.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, obj.File, obj.Line ); return; } var type = string.Empty; if ( !getString( obj.Values[ 0 ], out type ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, obj.File, obj.Line ); return; } this._Pass.Type = (CompositorPassType)ScriptEnumAttribute.Lookup( type, typeof ( CompositorPassType ) ); if ( this._Pass.Type == CompositorPassType.RenderCustom ) { var customType = string.Empty; //This is the ugly one liner for safe access to the second parameter. if ( obj.Values.Count < 2 || !getString( obj.Values[ 1 ], out customType ) ) { compiler.AddError( CompileErrorCode.StringExpected, obj.File, obj.Line ); return; } this._Pass.CustomType = customType; } else { compiler.AddError( CompileErrorCode.InvalidParameters, obj.File, obj.Line, "pass types must be \"clear\", \"stencil\", \"render_quad\", \"render_scene\" or \"render_custom\"." ); return; } foreach ( var i in obj.Children ) { if ( i is ObjectAbstractNode ) { processNode( compiler, i ); } else if ( i is PropertyAbstractNode ) { var prop = (PropertyAbstractNode)i; switch ( (Keywords)prop.Id ) { #region ID_MATERIAL case Keywords.ID_MATERIAL: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line ); return; } else { var val = string.Empty; if ( getString( prop.Values[ 0 ], out val ) ) { ScriptCompilerEvent evt = new ProcessResourceNameScriptCompilerEvent( ProcessResourceNameScriptCompilerEvent.ResourceType.Material, val ); compiler._fireEvent( ref evt ); this._Pass.MaterialName = ( (ProcessResourceNameScriptCompilerEvent)evt ).Name; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_MATERIAL #region ID_INPUT case Keywords.ID_INPUT: if ( prop.Values.Count < 2 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } else if ( prop.Values.Count > 3 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line ); return; } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ); var id = 0; var name = string.Empty; if ( getInt( i0, out id ) && getString( i1, out name ) ) { var index = 0; if ( !getInt( i2, out index ) ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); return; } this._Pass.SetInput( id, name, index ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_INPUT #region ID_IDENTIFIER case Keywords.ID_IDENTIFIER: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line ); return; } else { uint val; if ( getUInt( prop.Values[ 0 ], out val ) ) { this._Pass.Identifier = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_IDENTIFIER #region ID_FIRST_RENDER_QUEUE case Keywords.ID_FIRST_RENDER_QUEUE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line ); return; } else { uint val; if ( getUInt( prop.Values[ 0 ], out val ) ) { this._Pass.FirstRenderQueue = (RenderQueueGroupID)val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_FIRST_RENDER_QUEUE #region ID_LAST_RENDER_QUEUE case Keywords.ID_LAST_RENDER_QUEUE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line ); return; } else { uint val; if ( getUInt( prop.Values[ 0 ], out val ) ) { this._Pass.LastRenderQueue = (RenderQueueGroupID)val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_LAST_RENDER_QUEUE #region ID_MATERIAL_SCHEME case Keywords.ID_MATERIAL_SCHEME: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line ); return; } else { string val; if ( getString( prop.Values[ 0 ], out val ) ) { this._Pass.MaterialScheme = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_MATERIAL_SCHEME #region ID_QUAD_NORMALS case Keywords.ID_QUAD_NORMALS: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line ); return; } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { var atom = (AtomAbstractNode)prop.Values[ 0 ]; if ( atom.Id == (uint)Keywords.ID_CAMERA_FAR_CORNERS_VIEW_SPACE ) { this._Pass.SetQuadFarCorners( true, true ); } else if ( atom.Id == (uint)Keywords.ID_CAMERA_FAR_CORNERS_WORLD_SPACE ) { this._Pass.SetQuadFarCorners( true, false ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_QUAD_NORMALS default: compiler.AddError( CompileErrorCode.UnexpectedToken, prop.File, prop.Line, "token \"" + prop.Name + "\" is not recognized" ); break; } } } }
private Pass _commonProgramChecks( ScriptCompiler compiler, ObjectAbstractNode node, out string createdProgramName ) { createdProgramName = string.Empty; if ( string.IsNullOrEmpty( node.Name ) ) { compiler.AddError( CompileErrorCode.ObjectNameExpected, node.File, node.Line ); return null; } ScriptCompilerEvent evt = new ProcessResourceNameScriptCompilerEvent( ProcessResourceNameScriptCompilerEvent.ResourceType.GpuProgram, node.Name ); compiler._fireEvent( ref evt ); createdProgramName = ( (ProcessResourceNameScriptCompilerEvent)evt ).Name; if ( GpuProgramManager.Instance.GetByName( createdProgramName ) == null ) { compiler.AddError( CompileErrorCode.ReferenceToaNonExistingObject, node.File, node.Line ); return null; } Pass pass = (Pass)node.Parent.Context; return pass; }
protected void _translateGeometryProgramRef( ScriptCompiler compiler, ObjectAbstractNode node ) { string createdProgramName; Pass pass = _commonProgramChecks( compiler, node, out createdProgramName ); if ( pass == null ) return; pass.SetGeometryProgram( createdProgramName ); if ( pass.GeometryProgram.IsSupported ) { var parameters = pass.GeometryProgramParameters; GpuProgramTranslator.TranslateProgramParameters( compiler, parameters, node ); } }
/// <see cref="Translator.Translate"/> public override void Translate( ScriptCompiler compiler, AbstractNode node ) { var obj = (ObjectAbstractNode)node; // Find the name if ( obj != null ) { if ( string.IsNullOrEmpty( obj.Name ) ) { compiler.AddError( CompileErrorCode.ObjectNameExpected, obj.File, obj.Line ); return; } } else { compiler.AddError( CompileErrorCode.ObjectNameExpected, obj.File, obj.Line ); return; } // Allocate the particle system object sysObject; ScriptCompilerEvent evt = new CreateParticleSystemScriptCompilerEvent( obj.File, obj.Name, compiler.ResourceGroup ); var processed = compiler._fireEvent( ref evt, out sysObject ); if ( !processed ) { this._System = ParticleSystemManager.Instance.CreateTemplate( obj.Name, compiler.ResourceGroup ); } else { this._System = (ParticleSystem)sysObject; } if ( this._System == null ) { compiler.AddError( CompileErrorCode.ObjectAllocationError, obj.File, obj.Line ); return; } this._System.Origin = obj.File; this._System.RemoveAllEmitters(); this._System.RemoveAllAffectors(); obj.Context = this._System; foreach ( var i in obj.Children ) { if ( i is PropertyAbstractNode ) { var prop = (PropertyAbstractNode)i; switch ( (Keywords)prop.Id ) { case Keywords.ID_MATERIAL: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { var name = ( (AtomAbstractNode)prop.Values[ 0 ] ).Value; ScriptCompilerEvent locEvt = new ProcessResourceNameScriptCompilerEvent( ProcessResourceNameScriptCompilerEvent.ResourceType.Material, name ); compiler._fireEvent( ref locEvt ); var locEvtName = ( (ProcessResourceNameScriptCompilerEvent)locEvt ).Name; if ( !this._System.SetParameter( "material", locEvtName ) ) { if ( this._System.Renderer != null ) { if ( !this._System.Renderer.SetParameter( "material", locEvtName ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "material property could not be set with material \"" + locEvtName + "\"" ); } } } } } break; default: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } else { string name = prop.Name, value = string.Empty; // Glob the values together foreach ( var it in prop.Values ) { if ( it is AtomAbstractNode ) { if ( string.IsNullOrEmpty( value ) ) { value = ( (AtomAbstractNode)it ).Value; } else { value = value + " " + ( (AtomAbstractNode)it ).Value; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); return; } } if ( !this._System.SetParameter( name, value ) ) { if ( this._System.Renderer != null ) { if ( !this._System.Renderer.SetParameter( name, value ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } } } break; } } else { processNode( compiler, i ); } } }
public AbstractTreeBuilder( ScriptCompiler compiler ) { this._compiler = compiler; this._current = null; this._nodes = new List<AbstractNode>(); }
protected void _translateShadowReceiverFragmentProgramRef( ScriptCompiler compiler, ObjectAbstractNode node ) { string createdProgramName; var pass = _commonProgramChecks( compiler, node, out createdProgramName ); if ( pass == null ) { return; } pass.SetShadowReceiverFragmentProgram( createdProgramName ); if ( GpuProgramManager.Instance.GetByName( createdProgramName ).IsSupported ) { var parameters = pass.ShadowReceiverFragmentProgramParameters; GpuProgramTranslator.TranslateProgramParameters( compiler, parameters, node ); } }
public virtual SubRenderState CreateInstance( ScriptCompiler compiler, PropertyAbstractNode prop, TextureUnitState texState, SGScriptTranslator translator ) { return null; }
public virtual SubRenderState CreateInstance( ScriptCompiler compiler, PropertyAbstractNode prop, Pass pass, SGScriptTranslator stranslator ) { return null; }
protected void _translateUnifiedGpuProgram( ScriptCompiler compiler, ObjectAbstractNode obj ) { var customParameters = new NameValuePairList(); AbstractNode parameters = null; foreach ( var i in obj.Children ) { if ( i is PropertyAbstractNode ) { var prop = (PropertyAbstractNode)i; if ( prop.Name == "delegate" ) { var value = string.Empty; if ( prop.Values.Count != 0 && prop.Values[ 0 ] is AtomAbstractNode ) { value = ( (AtomAbstractNode)prop.Values[ 0 ] ).Value; } ScriptCompilerEvent evt = new ProcessResourceNameScriptCompilerEvent( ProcessResourceNameScriptCompilerEvent.ResourceType.GpuProgram, value ); compiler._fireEvent( ref evt ); customParameters[ "delegate" ] = ( (ProcessResourceNameScriptCompilerEvent)evt ).Name; } else { var name = prop.Name; var value = string.Empty; var first = true; foreach ( var it in prop.Values ) { if ( it is AtomAbstractNode ) { if ( !first ) { value += " "; } else { first = false; } value += ( (AtomAbstractNode)it ).Value; } } customParameters.Add( name, value ); } } else if ( i is ObjectAbstractNode ) { if ( ( (ObjectAbstractNode)i ).Id == (uint)Keywords.ID_DEFAULT_PARAMS ) { parameters = i; } else { processNode( compiler, i ); } } } // Allocate the program Object progObj; HighLevelGpuProgram prog = null; ScriptCompilerEvent evnt = new CreateHighLevelGpuProgramScriptCompilerEvent( obj.File, obj.Name, compiler.ResourceGroup, string.Empty, "unified", _translateIDToGpuProgramType( obj.Id ) ); var processed = compiler._fireEvent( ref evnt, out progObj ); if ( !processed ) { prog = (HighLevelGpuProgram) ( HighLevelGpuProgramManager.Instance.CreateProgram( obj.Name, compiler.ResourceGroup, "unified", _translateIDToGpuProgramType( obj.Id ) ) ); } else { prog = (HighLevelGpuProgram)progObj; } // Check that allocation worked if ( prog == null ) { compiler.AddError( CompileErrorCode.ObjectAllocationError, obj.File, obj.Line, "gpu program \"" + obj.Name + "\" could not be created" ); return; } obj.Context = prog; prog.IsMorphAnimationIncluded = false; prog.PoseAnimationCount = 0; prog.IsSkeletalAnimationIncluded = false; prog.IsVertexTextureFetchRequired = false; prog.Origin = obj.File; // Set the custom parameters prog.SetParameters( customParameters ); // Set up default parameters if ( prog.IsSupported && parameters != null ) { var ptr = prog.DefaultParameters; GpuProgramTranslator.TranslateProgramParameters( compiler, ptr, (ObjectAbstractNode)parameters ); } }
public static void TranslateProgramParameters( ScriptCompiler compiler, /*it should be GpuProgramParametersShared*/ GpuProgramParameters parameters, ObjectAbstractNode obj ) { int animParametricsCount = 0; foreach ( AbstractNode i in obj.Children ) { if ( i is PropertyAbstractNode ) { PropertyAbstractNode prop = (PropertyAbstractNode)i; LogManager.Instance.Write("TranslateProgramParameters {0}", (Keywords)prop.Id); switch ( (Keywords)prop.Id ) { #region ID_SHARED_PARAMS_REF case Keywords.ID_SHARED_PARAMS_REF: { if ( prop.Values.Count != 1 ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "shared_params_ref requires a single parameter" ); continue; } AbstractNode i0 = getNodeAt( prop.Values, 0 ); if ( !( i0 is AtomAbstractNode ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "shared parameter set name expected" ); continue; } AtomAbstractNode atom0 = (AtomAbstractNode)i0; throw new NotImplementedException(); #if UNREACHABLE_CODE try { //TODO //parameters->addSharedParameters(atom0->value); } catch ( AxiomException e ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, e.Message ); } } break; #else } #endif #endregion ID_SHARED_PARAMS_REF #region ID_PARAM_INDEXED || ID_PARAM_NAMED case Keywords.ID_PARAM_INDEXED: case Keywords.ID_PARAM_NAMED: { if ( prop.Values.Count >= 3 ) { bool named = ( prop.Id == (uint)Keywords.ID_PARAM_NAMED ); AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), k = getNodeAt( prop.Values, 2 ); if ( !(i0 is AtomAbstractNode) || !(i1 is AtomAbstractNode) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "name or index and parameter type expected" ); return; } AtomAbstractNode atom0 = (AtomAbstractNode)i0, atom1 = (AtomAbstractNode)i1; if ( !named && !atom0.IsNumber ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "parameter index expected" ); return; } string name = string.Empty; int index = 0; // Assign the name/index if ( named ) name = atom0.Value; else index = (int)atom0.Number; // Determine the type if ( atom1.Value == "matrix4x4" ) { Matrix4 m; if ( getMatrix4( prop.Values, 2, out m ) ) { try { if ( named ) parameters.SetNamedConstant( name, m ); else parameters.SetConstant( index, m ); } catch { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "setting matrix4x4 parameter failed" ); } } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "incorrect matrix4x4 declaration" ); } } else { // Find the number of parameters var isValid = true; GpuProgramParameters.ElementType type = GpuProgramParameters.ElementType.Real; int count = 0; if ( atom1.Value.Contains( "float" ) ) { type = GpuProgramParameters.ElementType.Real; if ( atom1.Value.Length >= 6 ) count = int.Parse( atom1.Value.Substring( 5 ) ); else { count = 1; } } else if ( atom1.Value.Contains( "int" ) ) { type = GpuProgramParameters.ElementType.Int; if ( atom1.Value.Length >= 4 ) count = int.Parse( atom1.Value.Substring( 3 ) ); else { count = 1; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "incorrect type specified; only variants of int and float allowed" ); isValid = false; } if ( isValid ) { // First, clear out any offending auto constants if ( named ) { parameters.ClearNamedAutoConstant(name); } else { parameters.ClearAutoConstant(index); } int roundedCount = count % 4 != 0 ? count + 4 - ( count % 4 ) : count; if ( type == GpuProgramParameters.ElementType.Int ) { int[] vals = new int[ roundedCount ]; if ( getInts( prop.Values, 2, out vals, roundedCount ) ) { try { if ( named ) { parameters.SetNamedConstant(name, vals, count, 1); } else { parameters.SetConstant(index , vals, roundedCount/4); } } catch { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "setting of constant failed" ); } } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "incorrect integer constant declaration" ); } } else { float[] vals = new float[ roundedCount ]; if ( getFloats( prop.Values, 2, out vals, roundedCount ) ) { try { if ( named ) { parameters.SetNamedConstant(name, vals, count, 1); } else { parameters.SetConstant(index , vals, roundedCount/4); } } catch { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "setting of constant failed" ); } } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "incorrect float constant declaration" ); } } } } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "param_named and param_indexed properties requires at least 3 arguments" ); } } break; #endregion ID_PARAM_INDEXED || ID_PARAM_NAMED #region ID_PARAM_INDEXED_AUTO || ID_PARAM_NAMED_AUTO case Keywords.ID_PARAM_INDEXED_AUTO: case Keywords.ID_PARAM_NAMED_AUTO: { bool named = ( prop.Id == (uint)Keywords.ID_PARAM_NAMED_AUTO ); string name = string.Empty; int index = 0; if ( prop.Values.Count >= 2 ) { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ), i3 = getNodeAt( prop.Values, 3 ); if ( !(i0 is AtomAbstractNode) || !(i1 is AtomAbstractNode) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "name or index and auto constant type expected" ); return; } AtomAbstractNode atom0 = (AtomAbstractNode)i0, atom1 = (AtomAbstractNode)i1; if ( !named && !atom0.IsNumber ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "parameter index expected" ); return; } if ( named ) name = atom0.Value; else index = int.Parse( atom0.Value ); // Look up the auto constant atom1.Value = atom1.Value.ToLower(); GpuProgramParameters.AutoConstantDefinition def; bool defFound = GpuProgramParameters.GetAutoConstantDefinition( atom1.Value, out def ); if ( defFound ) { switch ( def.DataType ) { #region None case GpuProgramParameters.AutoConstantDataType.None: // Set the auto constant try { if ( named ) parameters.SetNamedAutoConstant( name, def.AutoConstantType ); else parameters.SetAutoConstant( index, def.AutoConstantType ); } catch { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "setting of constant failed" ); } break; #endregion None #region Int case GpuProgramParameters.AutoConstantDataType.Int: if ( def.AutoConstantType == GpuProgramParameters.AutoConstantType.AnimationParametric ) { try { if ( named ) parameters.SetNamedAutoConstant( name, def.AutoConstantType, animParametricsCount++ ); else parameters.SetAutoConstant( index, def.AutoConstantType, animParametricsCount++ ); } catch { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "setting of constant failed" ); } } else { // Only certain texture projection auto params will assume 0 // Otherwise we will expect that 3rd parameter if ( i2 == null ) { if ( def.AutoConstantType == GpuProgramParameters.AutoConstantType.TextureViewProjMatrix || def.AutoConstantType == GpuProgramParameters.AutoConstantType.TextureWorldViewProjMatrix || def.AutoConstantType == GpuProgramParameters.AutoConstantType.SpotLightViewProjMatrix || def.AutoConstantType == GpuProgramParameters.AutoConstantType.SpotLightWorldViewProjMatrix ) { try { if ( named ) parameters.SetNamedAutoConstant( name, def.AutoConstantType, 0 ); else parameters.SetAutoConstant( index, def.AutoConstantType, 0 ); } catch { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "setting of constant failed" ); } } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "extra parameters required by constant definition " + atom1.Value ); } } else { bool success = false; int extraInfo = 0; if ( i3 == null ) { // Handle only one extra value if ( getInt( i2, out extraInfo ) ) { success = true; } } else { // Handle two extra values int extraInfo1 = 0, extraInfo2 = 0; if ( getInt( i2, out extraInfo1 ) && getInt( i3, out extraInfo2 ) ) { extraInfo = extraInfo1 | ( extraInfo2 << 16 ); success = true; } } if ( success ) { try { if ( named ) parameters.SetNamedAutoConstant( name, def.AutoConstantType, extraInfo ); else parameters.SetAutoConstant( index, def.AutoConstantType, extraInfo ); } catch { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "setting of constant failed" ); } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "invalid auto constant extra info parameter" ); } } } break; #endregion Int #region Real case GpuProgramParameters.AutoConstantDataType.Real: if ( def.AutoConstantType == GpuProgramParameters.AutoConstantType.Time || def.AutoConstantType == GpuProgramParameters.AutoConstantType.FrameTime ) { Real f = 1.0f; if ( i2 != null ) getReal( i2, out f ); try { if ( named ) { parameters.SetNamedAutoConstantReal(name, def.AutoConstantType, f); } else parameters.SetAutoConstantReal( index, def.AutoConstantType, f ); } catch { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "setting of constant failed" ); } } else { if ( i2 != null ) { Real extraInfo = 0.0f; if ( getReal( i2, out extraInfo ) ) { try { if ( named ) { parameters.SetNamedAutoConstantReal(name, def.AutoConstantType, extraInfo); } else parameters.SetAutoConstantReal( index, def.AutoConstantType, extraInfo ); } catch { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "setting of constant failed" ); } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "incorrect float argument definition in extra parameters" ); } } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "extra parameters required by constant definition " + atom1.Value ); } } break; #endregion Real } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break;
/// <see cref="Translator.Translate"/> public override void Translate( ScriptCompiler compiler, AbstractNode node ) { var obj = (ObjectAbstractNode)node; var technique = (CompositionTechnique)obj.Parent.Context; if ( obj.Id == (uint)Keywords.ID_TARGET ) { this._Target = technique.CreateTargetPass(); if ( !string.IsNullOrEmpty( obj.Name ) ) { this._Target.OutputName = obj.Name; } } else if ( obj.Id == (uint)Keywords.ID_TARGET_OUTPUT ) { this._Target = technique.OutputTarget; } obj.Context = this._Target; foreach ( var i in obj.Children ) { if ( i is ObjectAbstractNode ) { processNode( compiler, i ); } else if ( i is PropertyAbstractNode ) { var prop = (PropertyAbstractNode)i; switch ( (Keywords)prop.Id ) { #region ID_INPUT case Keywords.ID_INPUT: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line ); return; } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { var atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_NONE: this._Target.InputMode = CompositorInputMode.None; break; case Keywords.ID_PREVIOUS: this._Target.InputMode = CompositorInputMode.Previous; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_INPUT #region ID_ONLY_INITIAL case Keywords.ID_ONLY_INITIAL: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line ); return; } else { var val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) { this._Target.OnlyInitial = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_ONLY_INITIAL #region ID_VISIBILITY_MASK case Keywords.ID_VISIBILITY_MASK: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line ); return; } else { uint val; if ( getUInt( prop.Values[ 0 ], out val ) ) { this._Target.VisibilityMask = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_VISIBILITY_MASK #region ID_LOD_BIAS case Keywords.ID_LOD_BIAS: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line ); return; } else { float val; if ( getFloat( prop.Values[ 0 ], out val ) ) { this._Target.LodBias = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_LOD_BIAS #region ID_MATERIAL_SCHEME case Keywords.ID_MATERIAL_SCHEME: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line ); return; } else { string val; if ( getString( prop.Values[ 0 ], out val ) ) { this._Target.MaterialScheme = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_MATERIAL_SCHEME #region ID_SHADOWS_ENABLED case Keywords.ID_SHADOWS_ENABLED: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line ); return; } else { bool val; if ( getBoolean( prop.Values[ 0 ], out val ) ) { this._Target.ShadowsEnabled = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_SHADOWS_ENABLED default: compiler.AddError( CompileErrorCode.UnexpectedToken, prop.File, prop.Line, "token \"" + prop.Name + "\" is not recognized" ); break; } } } }
/// <see cref="Translator.Translate"/> public override void Translate( ScriptCompiler compiler, AbstractNode node ) { var obj = (ObjectAbstractNode)node; this._Pass = (CompositionPass)obj.Parent.Context; // Should be no parameters, just children if ( obj.Values.Count != 0 ) { compiler.AddError( CompileErrorCode.UnexpectedToken, obj.File, obj.Line ); } foreach ( var i in obj.Children ) { if ( i is ObjectAbstractNode ) { processNode( compiler, i ); } else if ( i is PropertyAbstractNode ) { var prop = (PropertyAbstractNode)i; switch ( (Keywords)prop.Id ) { #region ID_CHECK case Keywords.ID_CHECK: { if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } var val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) { this._Pass.StencilCheck = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_CHECK #region ID_COMP_FUNC case Keywords.ID_COMP_FUNC: { if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } CompareFunction func; if ( getEnumeration<CompareFunction>( prop.Values[ 0 ], compiler, out func ) ) { this._Pass.StencilFunc = func; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_COMP_FUNC #region ID_REF_VALUE case Keywords.ID_REF_VALUE: { if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); return; } int val; if ( getInt( prop.Values[ 0 ], out val ) ) { this._Pass.StencilRefValue = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_REF_VALUE #region ID_MASK case Keywords.ID_MASK: { if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); return; } int val; if ( getInt( prop.Values[ 0 ], out val ) ) { this._Pass.StencilMask = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_MASK #region ID_FAIL_OP case Keywords.ID_FAIL_OP: { if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } StencilOperation val; if ( getEnumeration<StencilOperation>( prop.Values[ 0 ], compiler, out val ) ) { this._Pass.StencilFailOp = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_FAIL_OP #region ID_DEPTH_FAIL_OP case Keywords.ID_DEPTH_FAIL_OP: { if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } StencilOperation val; if ( getEnumeration<StencilOperation>( prop.Values[ 0 ], compiler, out val ) ) { this._Pass.StencilDepthFailOp = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_DEPTH_FAIL_OP #region ID_PASS_OP case Keywords.ID_PASS_OP: { if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } StencilOperation val; if ( getEnumeration<StencilOperation>( prop.Values[ 0 ], compiler, out val ) ) { this._Pass.StencilPassOp = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_PASS_OP #region ID_TWO_SIDED case Keywords.ID_TWO_SIDED: { if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); return; } bool val; if ( getBoolean( prop.Values[ 0 ], out val ) ) { this._Pass.StencilTwoSidedOperation = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_TWO_SIDED default: compiler.AddError( CompileErrorCode.UnexpectedToken, prop.File, prop.Line, "token \"" + prop.Name + "\" is not recognized" ); break; } } } }
protected void _translateGeometryProgramRef( ScriptCompiler compiler, ObjectAbstractNode node ) { string createdProgramName; Pass pass = _commonProgramChecks( compiler, node, out createdProgramName ); if ( pass == null ) return; pass.SetGeometryProgram( createdProgramName ); if ( pass.GeometryProgram.IsSupported ) { #warning this need GpuProgramParametersShared implementation //GpuProgramParametersShared parameters = pass.GeometryProgramParameters; //GpuProgramTranslator.TranslateProgramParameters( compiler, parameters, node ); } }
protected void _translateShadowReceiverFragmentProgramRef( ScriptCompiler compiler, ObjectAbstractNode node ) { string createdProgramName; Pass pass = _commonProgramChecks( compiler, node, out createdProgramName ); if ( pass == null ) return; pass.SetShadowReceiverFragmentProgram( createdProgramName ); if ( GpuProgramManager.Instance.GetByName( createdProgramName ).IsSupported ) { #warning this need GpuProgramParametersShared implementation // GpuProgramParametersSharedPtr params = pass->getShadowReceiverFragmentProgramParameters(); // GpuProgramTranslator::translateProgramParameters(compiler, params, node); } }
/// <summary> /// Called when an event occurs during translation, return true if handled /// </summary> /// <remarks> /// This function is called from the translators when an event occurs that /// that can be responded to. Often this is overriding names, or it can be a request for /// custom resource creation. /// </remarks> /// <param name="compiler">A reference to the compiler</param> /// <param name="evt">The event object holding information about the event to be processed</param> /// <param name="retVal">A possible return value from handlers</param> /// <returns>True if the handler processed the event</returns> public virtual bool HandleEvent( ScriptCompiler compiler, ref ScriptCompilerEvent evt, out object retVal ) { retVal = null; return false; }
/// <see cref="Translator.Translate"/> public override void Translate( ScriptCompiler compiler, AbstractNode node ) { ObjectAbstractNode obj = (ObjectAbstractNode)node; Technique technique = (Technique)obj.Parent.Context; _pass = technique.CreatePass(); obj.Context = _pass; // Get the name of the technique if ( !string.IsNullOrEmpty( obj.Name ) ) _pass.Name = obj.Name; // Set the properties for the material foreach ( AbstractNode i in obj.Children ) { if ( i is PropertyAbstractNode ) { PropertyAbstractNode prop = (PropertyAbstractNode)i; switch ( (Keywords)prop.Id ) { #region ID_AMBIENT case Keywords.ID_AMBIENT: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 4 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "ambient must have at most 4 parameters" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode && ( (AtomAbstractNode)prop.Values[ 0 ] ).Id == (uint)Keywords.ID_VERTEX_COLOUR ) { _pass.VertexColorTracking = _pass.VertexColorTracking | TrackVertexColor.Ambient; } else { ColorEx val = ColorEx.White; if ( getColor( prop.Values, 0, out val ) ) _pass.Ambient = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "ambient requires 3 or 4 colour arguments, or a \"vertexcolour\" directive" ); } } break; #endregion ID_AMBIENT #region ID_DIFFUSE case Keywords.ID_DIFFUSE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 4 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "diffuse must have at most 4 arguments" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode && ( (AtomAbstractNode)prop.Values[ 0 ] ).Id == (uint)Keywords.ID_VERTEX_COLOUR ) { _pass.VertexColorTracking = _pass.VertexColorTracking | TrackVertexColor.Diffuse; } else { ColorEx val; if ( getColor( prop.Values, 0, out val ) ) _pass.Diffuse = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "diffuse requires 3 or 4 colour arguments, or a \"vertexcolour\" directive" ); } } break; #endregion ID_DIFFUSE #region ID_SPECULAR case Keywords.ID_SPECULAR: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 5 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "specular must have at most 5 arguments" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode && ( (AtomAbstractNode)prop.Values[ 0 ] ).Id == (uint)Keywords.ID_VERTEX_COLOUR ) { _pass.VertexColorTracking = _pass.VertexColorTracking | TrackVertexColor.Specular; if ( prop.Values.Count >= 2 ) { Real val = 0; if ( getReal( prop.Values[ prop.Values.Count - 1 ], out val ) ) _pass.Shininess = val; else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "specular does not support \"" + prop.Values[ prop.Values.Count - 1 ].Value + "\" as its second argument" ); } } } else { if ( prop.Values.Count < 4 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "specular expects at least 4 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ); ColorEx val = new ColorEx( 0, 0, 0, 0 ); if ( getFloat( i0, out val.r ) && getFloat( i1, out val.g ) && getFloat( i2, out val.b ) ) { if ( prop.Values.Count == 4 ) { _pass.Specular = val; AbstractNode i3 = getNodeAt( prop.Values, 3 ); Real shininess = 0.0f; if ( getReal( i3, out shininess ) ) _pass.Shininess = shininess; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "specular fourth argument must be a valid number for shininess attribute" ); } else { AbstractNode i3 = getNodeAt( prop.Values, 3 ); if ( !getFloat( i3, out val.a ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "specular fourth argument must be a valid color component value" ); } else _pass.Specular = val; AbstractNode i4 = getNodeAt( prop.Values, 4 ); Real shininess = 0.0f; if ( getReal( i4, out shininess ) ) _pass.Shininess = shininess; else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "specular fourth argument must be a valid number for shininess attribute" ); } } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "specular must have first 3 arguments be a valid colour" ); } } } } break; #endregion ID_SPECULAR #region ID_EMISSIVE case Keywords.ID_EMISSIVE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 4 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "emissive must have at most 4 arguments" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode && ( (AtomAbstractNode)prop.Values[ 0 ] ).Id == (uint)Keywords.ID_VERTEX_COLOUR ) { _pass.VertexColorTracking = _pass.VertexColorTracking | TrackVertexColor.Emissive; } else { ColorEx val; if ( getColor( prop.Values, 0, out val ) ) _pass.SelfIllumination = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "emissive requires 3 or 4 colour arguments, or a \"vertexcolour\" directive" ); } } break; #endregion ID_EMISSIVE #region ID_SCENE_BLEND case Keywords.ID_SCENE_BLEND: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 2 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "scene_blend supports at most 2 arguments" ); } else if ( prop.Values.Count == 1 ) { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_ADD: _pass.SetSceneBlending( SceneBlendType.Add ); break; case Keywords.ID_MODULATE: _pass.SetSceneBlending( SceneBlendType.Modulate ); break; case Keywords.ID_COLOUR_BLEND: _pass.SetSceneBlending( SceneBlendType.TransparentColor ); break; case Keywords.ID_ALPHA_BLEND: _pass.SetSceneBlending( SceneBlendType.TransparentAlpha ); break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "scene_blend does not support \"" + prop.Values[ 0 ].Value + "\" for argument 1" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "scene_blend does not support \"" + prop.Values[ 0 ].Value + "\" for argument 1" ); } } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); SceneBlendFactor sbf0, sbf1; if ( getEnumeration<SceneBlendFactor>( i0, compiler, out sbf0 ) && getEnumeration<SceneBlendFactor>( i1, compiler, out sbf1 ) ) { _pass.SetSceneBlending( sbf0, sbf1 ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "scene_blend does not support \"" + i0.Value + "\" and \"" + i1.Value + "\" as arguments" ); } } break; #endregion ID_SCENE_BLEND #region ID_SEPARATE_SCENE_BLEND case Keywords.ID_SEPARATE_SCENE_BLEND: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count == 3 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "separate_scene_blend must have 2 or 4 arguments" ); } else if ( prop.Values.Count > 4 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "separate_scene_blend must have 2 or 4 arguments" ); } else if ( prop.Values.Count == 2 ) { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); if ( i0 is AtomAbstractNode && i1 is AtomAbstractNode ) { AtomAbstractNode atom0 = (AtomAbstractNode)i0, atom1 = (AtomAbstractNode)i1; SceneBlendType sbt0, sbt1; switch ( (Keywords)atom0.Id ) { case Keywords.ID_ADD: sbt0 = SceneBlendType.Add; break; case Keywords.ID_MODULATE: sbt0 = SceneBlendType.Modulate; break; case Keywords.ID_COLOUR_BLEND: sbt0 = SceneBlendType.TransparentColor; break; case Keywords.ID_ALPHA_BLEND: sbt0 = SceneBlendType.TransparentAlpha; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "separate_scene_blend does not support \"" + atom0.Value + "\" as argument 1" ); return; } switch ( (Keywords)atom1.Id ) { case Keywords.ID_ADD: sbt1 = SceneBlendType.Add; break; case Keywords.ID_MODULATE: sbt1 = SceneBlendType.Modulate; break; case Keywords.ID_COLOUR_BLEND: sbt1 = SceneBlendType.TransparentColor; break; case Keywords.ID_ALPHA_BLEND: sbt1 = SceneBlendType.TransparentAlpha; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "separate_scene_blend does not support \"" + atom1.Value + "\" as argument 2" ); return; } throw new NotImplementedException( string.Format("SetSeparateSceneBlending({0}, {1})", sbt0, sbt1)); //TODO //mPass->setSeparateSceneBlending(sbt0, sbt1); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "separate_scene_blend does not support \"" + i0.Value + "\" as argument 1" ); } } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ), i3 = getNodeAt( prop.Values, 3 ); if ( i0 is AtomAbstractNode && i1 is AtomAbstractNode && i2 is AtomAbstractNode && i3 is AtomAbstractNode ) { SceneBlendFactor sbf0, sbf1, sbf2, sbf3; if ( getEnumeration<SceneBlendFactor>( i0, compiler, out sbf0 ) && getEnumeration<SceneBlendFactor>( i1, compiler, out sbf1 ) && getEnumeration<SceneBlendFactor>( i2, compiler, out sbf2 ) && getEnumeration<SceneBlendFactor>( i3, compiler, out sbf3 ) ) { //TODO //mPass->setSeparateSceneBlending(sbf0, sbf1, sbf2, sbf3); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "one of the arguments to separate_scene_blend is not a valid scene blend factor directive" ); } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "one of the arguments to separate_scene_blend is not a valid scene blend factor directive" ); } } break; #endregion ID_SEPARATE_SCENE_BLEND #region ID_SCENE_BLEND_OP case Keywords.ID_SCENE_BLEND_OP: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "scene_blend_op must have 1 argument" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_ADD: //TODO //mPass->setSceneBlendingOperation(SBO_ADD); break; case Keywords.ID_SUBTRACT: //TODO //mPass->setSceneBlendingOperation(SBO_SUBTRACT); break; case Keywords.ID_REVERSE_SUBTRACT: //TODO //mPass->setSceneBlendingOperation(SBO_REVERSE_SUBTRACT); break; case Keywords.ID_MIN: //TODO //mPass->setSceneBlendingOperation(SBO_MIN); break; case Keywords.ID_MAX: //TODO //mPass->setSceneBlendingOperation(SBO_MAX); break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, atom.Value + ": unrecognized argument" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + ": unrecognized argument" ); } } break; #endregion ID_SCENE_BLEND_OP #region ID_SEPARATE_SCENE_BLEND_OP case Keywords.ID_SEPARATE_SCENE_BLEND_OP: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count != 2 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "separate_scene_blend_op must have 2 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); if ( i0 is AtomAbstractNode && i1 is AtomAbstractNode ) { AtomAbstractNode atom0 = (AtomAbstractNode)i0, atom1 = (AtomAbstractNode)i1; //TODO //SceneBlendOperation op = SBO_ADD, alphaOp = SBO_ADD; switch ( (Keywords)atom0.Id ) { case Keywords.ID_ADD: //TODO //op = SBO_ADD; break; case Keywords.ID_SUBTRACT: //TODO //op = SBO_SUBTRACT; break; case Keywords.ID_REVERSE_SUBTRACT: //TODO //op = SBO_REVERSE_SUBTRACT; break; case Keywords.ID_MIN: //TODO //op = SBO_MIN; break; case Keywords.ID_MAX: //TODO //op = SBO_MAX; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, atom0.Value + ": unrecognized first argument" ); break; } switch ( (Keywords)atom1.Id ) { case Keywords.ID_ADD: //TODO //alphaOp = SBO_ADD; break; case Keywords.ID_SUBTRACT: //TODO //alphaOp = SBO_SUBTRACT; break; case Keywords.ID_REVERSE_SUBTRACT: //TODO //alphaOp = SBO_REVERSE_SUBTRACT; break; case Keywords.ID_MIN: //TODO //alphaOp = SBO_MIN; break; case Keywords.ID_MAX: //TODO //alphaOp = SBO_MAX; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, atom1.Value + ": unrecognized second argument" ); break; } //TODO //mPass->setSeparateSceneBlendingOperation(op, alphaOp); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + ": unrecognized argument" ); } } break; #endregion ID_SEPARATE_SCENE_BLEND_OP #region ID_DEPTH_CHECK case Keywords.ID_DEPTH_CHECK: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "depth_check must have 1 argument" ); } else { bool val = true; if ( getBoolean( prop.Values[ 0 ], out val ) ) _pass.DepthCheck = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "depth_check third argument must be \"true\", \"false\", \"yes\", \"no\", \"on\", or \"off\"" ); } break; #endregion ID_DEPTH_CHECK #region ID_DEPTH_WRITE case Keywords.ID_DEPTH_WRITE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "depth_write must have 1 argument" ); } else { bool val = true; if ( getBoolean( prop.Values[ 0 ], out val ) ) _pass.DepthWrite = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "depth_write third argument must be \"true\", \"false\", \"yes\", \"no\", \"on\", or \"off\"" ); } break; #endregion ID_DEPTH_WRITE #region ID_DEPTH_BIAS case Keywords.ID_DEPTH_BIAS: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 2 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "depth_bias must have at most 2 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); float val0, val1 = 0.0f; if ( getFloat( i0, out val0 ) ) { if ( i1 != null ) getFloat( i1, out val1 ); _pass.SetDepthBias( val0, val1 ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "depth_bias does not support \"" + i0.Value + "\" for argument 1" ); } } break; #endregion ID_DEPTH_BIAS #region ID_DEPTH_FUNC case Keywords.ID_DEPTH_FUNC: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "depth_func must have 1 argument" ); } else { CompareFunction func; if ( getEnumeration<CompareFunction>( prop.Values[ 0 ], compiler, out func ) ) _pass.DepthFunction = func; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid CompareFunction" ); } break; #endregion ID_DEPTH_FUNC #region ID_ITERATION_DEPTH_BIAS case Keywords.ID_ITERATION_DEPTH_BIAS: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "iteration_depth_bias must have 1 argument" ); } else { float val = 0.0f; if ( getFloat( prop.Values[ 0 ], out val ) ) { //TODO /*mPass->setIterationDepthBias(val);*/ } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid float value" ); } break; #endregion ID_ITERATION_DEPTH_BIAS #region ID_ALPHA_REJECTION case Keywords.ID_ALPHA_REJECTION: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 2 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "alpha_rejection must have at most 2 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); CompareFunction func; if ( getEnumeration<CompareFunction>( i0, compiler, out func ) ) { if ( i1 != null ) { int val = 0; if ( getInt( i1, out val ) ) _pass.SetAlphaRejectSettings( func, val ); else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i1.Value + " is not a valid integer" ); } else _pass.AlphaRejectFunction = func; } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " is not a valid CompareFunction" ); } break; #endregion ID_ALPHA_REJECTION #region ID_ALPHA_TO_COVERAGE case Keywords.ID_ALPHA_TO_COVERAGE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "alpha_to_coverage must have 1 argument" ); } else { bool val = true; if ( getBoolean( prop.Values[ 0 ], out val ) ) _pass.IsAlphaToCoverageEnabled = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "alpha_to_coverage argument must be \"true\", \"false\", \"yes\", \"no\", \"on\", or \"off\"" ); } break; #endregion ID_ALPHA_TO_COVERAGE #region ID_LIGHT_SCISSOR case Keywords.ID_LIGHT_SCISSOR: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "light_scissor must have only 1 argument" ); } else { bool val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) { //TODO /*mPass->setLightScissoringEnabled(val);*/ } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid boolean" ); } break; #endregion ID_LIGHT_SCISSOR #region ID_LIGHT_CLIP_PLANES case Keywords.ID_LIGHT_CLIP_PLANES: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "light_clip_planes must have at most 1 argument" ); } else { bool val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) { //TODO /*mPass->setLightClipPlanesEnabled(val);*/ } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid boolean" ); } break; #endregion ID_LIGHT_CLIP_PLANES #region ID_TRANSPARENT_SORTING case Keywords.ID_TRANSPARENT_SORTING: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "transparent_sorting must have at most 1 argument" ); } else { bool val = true; if ( getBoolean( prop.Values[ 0 ], out val ) ) { //TODO //mPass->setTransparentSortingEnabled(val); //mPass->setTransparentSortingForced(false); } else { string val2; if ( getString( prop.Values[ 0 ], out val2 ) && val2 == "force" ) { //TODO //mPass->setTransparentSortingEnabled(true); //mPass->setTransparentSortingForced(true); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " must be boolean or force" ); } } } break; #endregion ID_TRANSPARENT_SORTING #region ID_ILLUMINATION_STAGE case Keywords.ID_ILLUMINATION_STAGE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "illumination_stage must have at most 1 argument" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_AMBIENT: //TODO //mPass->setIlluminationStage(IS_AMBIENT); break; case Keywords.ID_PER_LIGHT: //TODO //mPass->setIlluminationStage(IS_PER_LIGHT); break; case Keywords.ID_DECAL: //TODO //mPass->setIlluminationStage(IS_DECAL); break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid IlluminationStage" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid IlluminationStage" ); } } break; #endregion ID_ILLUMINATION_STAGE #region ID_CULL_HARDWARE case Keywords.ID_CULL_HARDWARE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "cull_hardware must have at most 1 argument" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_CLOCKWISE: _pass.CullingMode = CullingMode.Clockwise; break; case Keywords.ID_ANTICLOCKWISE: _pass.CullingMode = CullingMode.CounterClockwise; break; case Keywords.ID_NONE: _pass.CullingMode = CullingMode.None; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid CullingMode" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid CullingMode" ); } } break; #endregion ID_CULL_HARDWARE #region ID_CULL_SOFTWARE case Keywords.ID_CULL_SOFTWARE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "cull_software must have at most 1 argument" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_FRONT: _pass.ManualCullingMode = ManualCullingMode.Front; break; case Keywords.ID_BACK: _pass.ManualCullingMode = ManualCullingMode.Back; break; case Keywords.ID_NONE: _pass.ManualCullingMode = ManualCullingMode.None; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid ManualCullingMode" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid ManualCullingMode" ); } } break; #endregion ID_CULL_SOFTWARE #region ID_NORMALISE_NORMALS case Keywords.ID_NORMALISE_NORMALS: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "normalise_normals must have at most 1 argument" ); } else { bool val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) { //TODO /*mPass->setNormaliseNormals(val);*/ } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid boolean" ); } break; #endregion ID_NORMALISE_NORMALS #region ID_LIGHTING case Keywords.ID_LIGHTING: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "lighting must have at most 1 argument" ); } else { bool val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) _pass.LightingEnabled = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid boolean" ); } break; #endregion ID_LIGHTING #region ID_SHADING case Keywords.ID_SHADING: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "shading must have at most 1 argument" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_FLAT: _pass.ShadingMode = Shading.Flat; break; case Keywords.ID_GOURAUD: _pass.ShadingMode = Shading.Gouraud; break; case Keywords.ID_PHONG: _pass.ShadingMode = Shading.Phong; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid shading mode (flat, gouraud, or phong)" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid shading mode (flat, gouraud, or phong)" ); } } break; #endregion ID_SHADING #region ID_POLYGON_MODE case Keywords.ID_POLYGON_MODE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "polygon_mode must have at most 1 argument" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_SOLID: _pass.PolygonMode = PolygonMode.Solid; break; case Keywords.ID_POINTS: _pass.PolygonMode = PolygonMode.Points; break; case Keywords.ID_WIREFRAME: _pass.PolygonMode = PolygonMode.Wireframe; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid polygon mode (solid, points, or wireframe)" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid polygon mode (solid, points, or wireframe)" ); } } break; #endregion ID_POLYGON_MODE #region ID_POLYGON_MODE_OVERRIDEABLE case Keywords.ID_POLYGON_MODE_OVERRIDEABLE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "polygon_mode_overrideable must have at most 1 argument" ); } else { bool val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) { //TODO /*mPass->setPolygonModeOverrideable(val);*/ } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid boolean" ); } break; #endregion ID_POLYGON_MODE_OVERRIDEABLE #region ID_FOG_OVERRIDE case Keywords.ID_FOG_OVERRIDE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 8 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "fog_override must have at most 8 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ); bool val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) { FogMode mode = FogMode.None; ColorEx clr = ColorEx.White; Real dens = 0.001, start = 0.0f, end = 1.0f; if ( i1 != null ) { if ( i1 is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)i1; switch ( (Keywords)atom.Id ) { case Keywords.ID_NONE: mode = FogMode.None; break; case Keywords.ID_LINEAR: mode = FogMode.Linear; break; case Keywords.ID_EXP: mode = FogMode.Exp; break; case Keywords.ID_EXP2: mode = FogMode.Exp2; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i1.Value + " is not a valid FogMode" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i1.Value + " is not a valid FogMode" ); break; } } if ( i2 != null ) { // following line code was if(!getColour(i2, prop->values.end(), &clr, 3)) if ( !getColor( prop.Values, 2, out clr, 3 ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i2.Value + " is not a valid colour" ); break; } i2 = getNodeAt( prop.Values, 5 ); } if ( i2 != null ) { if ( !getReal( i2, out dens ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i2.Value + " is not a valid number" ); break; } //++i2; i2 = getNodeAt( prop.Values, 6 ); } if ( i2 != null ) { if ( !getReal( i2, out start ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i2.Value + " is not a valid number" ); return; } //++i2; i2 = getNodeAt( prop.Values, 7 ); } if ( i2 != null ) { if ( !getReal( i2, out end ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i2.Value + " is not a valid number" ); return; } //++i2; i2 = getNodeAt( prop.Values, 8 ); } _pass.SetFog( val, mode, clr, dens, start, end ); } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid boolean" ); } break; #endregion ID_FOG_OVERRIDE #region ID_COLOUR_WRITE case Keywords.ID_COLOUR_WRITE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "colour_write must have at most 1 argument" ); } else { bool val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) _pass.ColorWriteEnabled = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid boolean" ); } break; #endregion ID_COLOUR_WRITE #region ID_MAX_LIGHTS case Keywords.ID_MAX_LIGHTS: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "max_lights must have at most 1 argument" ); } else { int val = 0; if ( getInt( prop.Values[ 0 ], out val ) ) _pass.MaxSimultaneousLights = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid integer" ); } break; #endregion ID_MAX_LIGHTS #region ID_START_LIGHT case Keywords.ID_START_LIGHT: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "start_light must have at most 1 argument" ); } else { uint val = 0; if ( getUInt( prop.Values[ 0 ], out val ) ) { //TODO /*mPass->setStartLight(static_cast<unsigned short>(val));*/ } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid integer" ); } break; #endregion ID_START_LIGHT #region ID_ITERATION case Keywords.ID_ITERATION: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ); if ( i0 is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)i0; if ( atom.Id == (uint)Keywords.ID_ONCE ) { _pass.IteratePerLight = false; } else if ( atom.Id == (uint)Keywords.ID_ONCE_PER_LIGHT ) { AbstractNode i1 = getNodeAt( prop.Values, 1 ); if ( i1 != null && i1 is AtomAbstractNode ) { atom = (AtomAbstractNode)i1; switch ( (Keywords)atom.Id ) { case Keywords.ID_POINT: _pass.IteratePerLight = true; break; case Keywords.ID_DIRECTIONAL: //TODO //_pass.SetIteratePerLight(true, true, LightType.Directional ); break; case Keywords.ID_SPOT: //TODO //_pass.SetIteratePerLight(true, true, LightType.Spotlight ); break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid light type (point, directional, or spot)" ); break; } } else { //TODO //_pass.SetIteratePerLight(true, false); } } else if ( atom.IsNumber ) { //TODO _pass.IterationCount = Int32.Parse( atom.Value ); AbstractNode i1 = getNodeAt( prop.Values, 1 ); if ( i1 != null && i1 is AtomAbstractNode ) { atom = (AtomAbstractNode)i1; if ( atom.Id == (uint)Keywords.ID_PER_LIGHT ) { AbstractNode i2 = getNodeAt( prop.Values, 2 ); if ( i2 != null && i2 is AtomAbstractNode ) { atom = (AtomAbstractNode)i2; switch ( (Keywords)atom.Id ) { case Keywords.ID_POINT: _pass.IteratePerLight = true; break; case Keywords.ID_DIRECTIONAL: //TODO //mPass->setIteratePerLight(true, true, Light::LT_DIRECTIONAL); break; case Keywords.ID_SPOT: //TODO //mPass->setIteratePerLight(true, true, Light::LT_SPOTLIGHT); break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i2.Value + " is not a valid light type (point, directional, or spot)" ); break; } } else { //TODO //mPass->setIteratePerLight(true, false); } } else if ( atom.Id == (uint)Keywords.ID_PER_N_LIGHTS ) { AbstractNode i2 = getNodeAt( prop.Values, 2 ); if ( i2 != null && i2 is AtomAbstractNode ) { atom = (AtomAbstractNode)i2; if ( atom.IsNumber ) { //TODO //mPass->setLightCountPerIteration( // static_cast<unsigned short>(StringConverter::parseInt(atom->value))); AbstractNode i3 = getNodeAt( prop.Values, 3 ); if ( i3 != null && i3 is AtomAbstractNode ) { atom = (AtomAbstractNode)i3; switch ( (Keywords)atom.Id ) { case Keywords.ID_POINT: _pass.IteratePerLight = true; break; case Keywords.ID_DIRECTIONAL: //TODO //mPass->setIteratePerLight(true, true, Light::LT_DIRECTIONAL); break; case Keywords.ID_SPOT: //TODO //mPass->setIteratePerLight(true, true, Light::LT_SPOTLIGHT); break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i3.Value + " is not a valid light type (point, directional, or spot)" ); break; } } else { //TODO //mPass->setIteratePerLight(true, false); } } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, i2.Value + " is not a valid number" ); } } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid number" ); } } } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_ITERATION #region ID_POINT_SIZE case Keywords.ID_POINT_SIZE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "point_size must have at most 1 argument" ); } else { Real val = 0.0f; if ( getReal( prop.Values[ 0 ], out val ) ) _pass.PointSize = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid number" ); } break; #endregion ID_POINT_SIZE #region ID_POINT_SPRITES case Keywords.ID_POINT_SPRITES: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "point_sprites must have at most 1 argument" ); } else { bool val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) _pass.PointSpritesEnabled = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid boolean" ); } break; #endregion ID_POINT_SPRITES #region ID_POINT_SIZE_ATTENUATION case Keywords.ID_POINT_SIZE_ATTENUATION: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 4 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "point_size_attenuation must have at most 4 arguments" ); } else { bool val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) { if ( val ) { AbstractNode i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ), i3 = getNodeAt( prop.Values, 3 ); if ( prop.Values.Count > 1 ) { Real constant = 0.0f, linear = 1.0f, quadratic = 0.0f; if ( i1 != null && i1 is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)i1; if ( atom.IsNumber ) constant = atom.Number; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i1.Value + " is not a valid number" ); } if ( i2 != null && i2 is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)i2; if ( atom.IsNumber ) linear = atom.Number; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i2.Value + " is not a valid number" ); } if ( i3 != null && i3 is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)i3; if ( atom.IsNumber ) quadratic = atom.Number; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i3.Value + " is not a valid number" ); } //TODO //mPass->setPointAttenuation(true, constant, linear, quadratic); } else { //TODO //mPass->setPointAttenuation(true); } } else { //TODO //mPass->setPointAttenuation(false); } } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid boolean" ); } break; #endregion ID_POINT_SIZE_ATTENUATION #region ID_POINT_SIZE_MIN case Keywords.ID_POINT_SIZE_MIN: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "point_size_min must have at most 1 argument" ); } else { Real val = 0.0f; if ( getReal( prop.Values[ 0 ], out val ) ) _pass.PointMinSize = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid number" ); } break; #endregion ID_POINT_SIZE_MIN #region ID_POINT_SIZE_MAX case Keywords.ID_POINT_SIZE_MAX: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "point_size_max must have at most 1 argument" ); } else { Real val = 0.0f; if ( getReal( prop.Values[ 0 ], out val ) ) _pass.PointMaxSize = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid number" ); } break; #endregion ID_POINT_SIZE_MAX default: compiler.AddError( CompileErrorCode.UnexpectedToken, prop.File, prop.Line, "token \"" + prop.Name + "\" is not recognized" ); break; } // end of switch statement } // end of if ( i is PropertyAbstractNode ) else if ( i is ObjectAbstractNode ) { ObjectAbstractNode child = (ObjectAbstractNode)i; switch ( (Keywords)child.Id ) { case Keywords.ID_FRAGMENT_PROGRAM_REF: _translateFragmentProgramRef( compiler, child ); break; case Keywords.ID_VERTEX_PROGRAM_REF: _translateVertexProgramRef( compiler, child ); break; case Keywords.ID_GEOMETRY_PROGRAM_REF: _translateGeometryProgramRef( compiler, child ); break; case Keywords.ID_SHADOW_CASTER_VERTEX_PROGRAM_REF: _translateShadowCasterVertexProgramRef( compiler, child ); break; case Keywords.ID_SHADOW_RECEIVER_VERTEX_PROGRAM_REF: _translateShadowReceiverVertexProgramRef( compiler, child ); break; case Keywords.ID_SHADOW_RECEIVER_FRAGMENT_PROGRAM_REF: _translateShadowReceiverFragmentProgramRef( compiler, child ); break; default: _processNode( compiler, i ); break; } } } }
/// <summary> /// Returns the concrete node list from the given file /// </summary> /// <param name="compiler">A reference to the compiler</param> /// <param name="name"></param> /// <returns></returns> public virtual IList<ConcreteNode> ImportFile( ScriptCompiler compiler, String name ) { return null; }
/// <see cref="Translator.Translate"/> public override void Translate( ScriptCompiler compiler, AbstractNode node ) { var obj = (ObjectAbstractNode)node; this._Pass = (CompositionPass)obj.Parent.Context; // Should be no parameters, just children if ( obj.Values.Count != 0 ) { compiler.AddError( CompileErrorCode.UnexpectedToken, obj.File, obj.Line ); } foreach ( var i in obj.Children ) { if ( i is ObjectAbstractNode ) { processNode( compiler, i ); } else if ( i is PropertyAbstractNode ) { var prop = (PropertyAbstractNode)i; switch ( (Keywords)prop.Id ) { #region ID_BUFFERS case Keywords.ID_BUFFERS: { FrameBufferType buffers = 0; foreach ( var k in prop.Values ) { if ( k is AtomAbstractNode ) { switch ( (Keywords)( (AtomAbstractNode)k ).Id ) { case Keywords.ID_COLOUR: buffers |= FrameBufferType.Color; break; case Keywords.ID_DEPTH: buffers |= FrameBufferType.Depth; break; case Keywords.ID_STENCIL: buffers |= FrameBufferType.Stencil; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } this._Pass.ClearBuffers = buffers; } break; #endregion ID_BUFFERS #region ID_COLOUR_VALUE case Keywords.ID_COLOUR_VALUE: { if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); return; } var val = ColorEx.White; if ( getColor( prop.Values, 0, out val ) ) { this._Pass.ClearColor = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_COLOUR_VALUE #region ID_DEPTH_VALUE case Keywords.ID_DEPTH_VALUE: { if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); return; } Real val = 0; if ( getReal( prop.Values[ 0 ], out val ) ) { this._Pass.ClearDepth = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_DEPTH_VALUE #region ID_STENCIL_VALUE case Keywords.ID_STENCIL_VALUE: { if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); return; } var val = 0; if ( getInt( prop.Values[ 0 ], out val ) ) { this._Pass.ClearStencil = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_STENCIL_VALUE default: compiler.AddError( CompileErrorCode.UnexpectedToken, prop.File, prop.Line, "token \"" + prop.Name + "\" is not recognized" ); break; } } } }
/// <summary> /// Allows for responding to and overriding behavior before a CST is translated into an AST /// </summary> /// <param name="compiler">A reference to the compiler</param> /// <param name="nodes"></param> public virtual void PreConversion( ScriptCompiler compiler, IList<ConcreteNode> nodes ) { }
/// <see cref="Translator.Translate"/> public override void Translate( ScriptCompiler compiler, AbstractNode node ) { ObjectAbstractNode obj = (ObjectAbstractNode)node; if ( obj != null ) { if ( string.IsNullOrEmpty( obj.Name ) ) { compiler.AddError( CompileErrorCode.ObjectNameExpected, obj.File, obj.Line ); return; } } else { compiler.AddError( CompileErrorCode.ObjectNameExpected, obj.File, obj.Line ); return; } // Create the compositor object compObject; ScriptCompilerEvent evt = new CreateCompositorScriptCompilerEvent( obj.File, obj.Name, compiler.ResourceGroup ); bool processed = compiler._fireEvent( ref evt, out compObject ); if ( !processed ) { //TODO // The original translated implementation of this code block was simply the following: // _Compositor = (Compositor)CompositorManager.Instance.Create( obj.Name, compiler.ResourceGroup ); // but sometimes it generates an excepiton due to a duplicate resource. // In order to avoid the above mentioned exception, the implementation was changed, but // it need to be checked when ResourceManager._add will be updated to the lastest version Compositor checkForExistingComp = (Compositor)CompositorManager.Instance.GetByName( obj.Name ); if ( checkForExistingComp == null ) _Compositor = (Compositor)CompositorManager.Instance.Create( obj.Name, compiler.ResourceGroup ); else _Compositor = checkForExistingComp; } else _Compositor = (Compositor)compObject; if ( _Compositor == null ) { compiler.AddError( CompileErrorCode.ObjectAllocationError, obj.File, obj.Line ); return; } // Prepare the compositor _Compositor.RemoveAllTechniques(); _Compositor.Origin = obj.File; obj.Context = _Compositor; foreach ( AbstractNode i in obj.Children ) { if ( i is ObjectAbstractNode ) { _processNode( compiler, i ); } else { compiler.AddError( CompileErrorCode.UnexpectedToken, i.File, i.Line, "token not recognized" ); } } }
/// <summary> /// Allows vetoing of continued compilation after the entire AST conversion process finishes /// </summary> /// <remarks> /// Once the script is turned completely into an AST, including import /// and override handling, this function allows a listener to exit /// the compilation process. ///</remarks> /// <param name="compiler">A reference to the compiler</param> /// <param name="nodes"></param> /// <returns>True continues compilation, false aborts</returns> public virtual bool PostConversion( ScriptCompiler compiler, IList<AbstractNode> nodes ) { return true; }
/// <see cref="Translator.Translate"/> public override void Translate( ScriptCompiler compiler, AbstractNode node ) { throw new NotImplementedException(); #if UNREACHABLE_CODE ObjectAbstractNode obj = (ObjectAbstractNode)node; // It has to have one value identifying the texture source name if ( obj.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, node.File, node.Line, "texture_source requires a type value" ); return; } // Set the value of the source //TODO: ExternalTextureSourceManager::getSingleton().setCurrentPlugIn(obj->values.front()->getValue()); // Set up the technique, pass, and texunit levels if ( true/*TODO: ExternalTextureSourceManager::getSingleton().getCurrentPlugIn() != 0*/) { TextureUnitState texunit = (TextureUnitState)obj.Parent.Context; Pass pass = texunit.Parent; Technique technique = pass.Parent; Material material = technique.Parent; ushort techniqueIndex = 0, passIndex = 0, texUnitIndex = 0; for ( ushort i = 0; i < material.TechniqueCount; i++ ) { if ( material.GetTechnique( i ) == technique ) { techniqueIndex = i; break; } } for ( ushort i = 0; i < technique.PassCount; i++ ) { if ( technique.GetPass( i ) == pass ) { passIndex = i; break; } } for ( ushort i = 0; i < pass.TextureUnitStageCount; i++ ) { if ( pass.GetTextureUnitState( i ) == texunit ) { texUnitIndex = i; break; } } string tps = string.Format( "{0} {1} {2}", techniqueIndex, passIndex, texUnitIndex ); //TODO: ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->setParameter( "set_T_P_S", tps ); foreach ( AbstractNode i in obj.Children ) { if ( i is PropertyAbstractNode ) { PropertyAbstractNode prop = (PropertyAbstractNode)i; // Glob the property values all together string str = string.Empty; foreach ( AbstractNode j in prop.Values ) { if ( j != prop.Values[ 0 ] ) str += " "; str = str + j.Value; } //TODO: ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->setParameter(prop->name, str); } else if ( i is ObjectAbstractNode ) { _processNode( compiler, i ); } } //TODO: ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->createDefinedTexture(material->getName(), material->getGroup()); } #endif }
/// <summary> /// Called when an error occurred /// </summary> /// <param name="compiler">A reference to the compiler</param> /// <param name="err"></param> public virtual void HandleError( ScriptCompiler compiler, ScriptCompiler.CompileError err ) { }
/// <see cref="Translator.Translate"/> public override void Translate( ScriptCompiler compiler, AbstractNode node ) { var obj = (ObjectAbstractNode)node; if ( obj != null ) { if ( string.IsNullOrEmpty( obj.Name ) ) { compiler.AddError( CompileErrorCode.ObjectNameExpected, obj.File, obj.Line ); } } else { compiler.AddError( CompileErrorCode.ObjectNameExpected, node.File, node.Line ); return; } // Create a material with the given name object mat; ScriptCompilerEvent evt = new CreateMaterialScriptCompilerEvent( node.File, obj.Name, compiler.ResourceGroup ); var processed = compiler._fireEvent( ref evt, out mat ); if ( !processed ) { //TODO // The original translated implementation of this code block was simply the following: // _material = (Material)MaterialManager.Instance.Create( obj.Name, compiler.ResourceGroup ); // but sometimes it generates an exception due to a duplicate resource. // In order to avoid the above mentioned exception, the implementation was changed, but // it need to be checked when ResourceManager._add will be updated to the latest version var checkForExistingMat = (Material)MaterialManager.Instance.GetByName( obj.Name ); if ( checkForExistingMat == null ) { this._material = (Material)MaterialManager.Instance.Create( obj.Name, compiler.ResourceGroup ); } else { this._material = checkForExistingMat; } } else { this._material = (Material)mat; if ( this._material == null ) { compiler.AddError( CompileErrorCode.ObjectAllocationError, obj.File, obj.Line, "failed to find or create material \"" + obj.Name + "\"" ); } } this._material.RemoveAllTechniques(); obj.Context = this._material; this._material.Origin = obj.File; foreach ( var i in obj.Children ) { if ( i is PropertyAbstractNode ) { var prop = (PropertyAbstractNode)i; switch ( (Keywords)prop.Id ) { #region ID_LOD_VALUES case Keywords.ID_LOD_VALUES: { var lods = new LodValueList(); foreach ( var j in prop.Values ) { Real v = 0; if ( getReal( j, out v ) ) { lods.Add( v ); } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "lod_values expects only numbers as arguments" ); } } this._material.SetLodLevels( lods ); } break; #endregion ID_LOD_VALUES #region ID_LOD_DISTANCES case Keywords.ID_LOD_DISTANCES: { // Set strategy to distance strategy LodStrategy strategy = DistanceLodStrategy.Instance; this._material.LodStrategy = strategy; // Real in lod distances var lods = new LodValueList(); foreach ( var j in prop.Values ) { Real v = 0; if ( getReal( j, out v ) ) { lods.Add( v ); } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "lod_values expects only numbers as arguments" ); } } this._material.SetLodLevels( lods ); } break; #endregion ID_LOD_DISTANCES #region ID_LOD_STRATEGY case Keywords.ID_LOD_STRATEGY: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "lod_strategy only supports 1 argument" ); } else { var strategyName = string.Empty; var result = getString( prop.Values[ 0 ], out strategyName ); if ( result ) { var strategy = LodStrategyManager.Instance.GetStrategy( strategyName ); result = strategy != null; if ( result ) { this._material.LodStrategy = strategy; } } if ( !result ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "lod_strategy argument must be a valid lod strategy" ); } } break; #endregion ID_LOD_STRATEGY #region ID_RECEIVE_SHADOWS case Keywords.ID_RECEIVE_SHADOWS: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "receive_shadows only supports 1 argument" ); } else { var val = true; if ( getBoolean( prop.Values[ 0 ], out val ) ) { this._material.ReceiveShadows = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "receive_shadows argument must be \"true\", \"false\", \"yes\", \"no\", \"on\", or \"off\"" ); } } break; #endregion ID_RECEIVE_SHADOWS #region ID_TRANSPARENCY_CASTS_SHADOWS case Keywords.ID_TRANSPARENCY_CASTS_SHADOWS: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "transparency_casts_shadows only supports 1 argument" ); } else { var val = true; if ( getBoolean( prop.Values[ 0 ], out val ) ) { this._material.TransparencyCastsShadows = val; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "transparency_casts_shadows argument must be \"true\", \"false\", \"yes\", \"no\", \"on\", or \"off\"" ); } } break; #endregion ID_TRANSPARENCY_CASTS_SHADOWS #region ID_SET_TEXTURE_ALIAS case Keywords.ID_SET_TEXTURE_ALIAS: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 3 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); String name, value; if ( getString( i0, out name ) && getString( i1, out value ) ) { this._textureAliases.Add( name, value ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "set_texture_alias must have 2 string argument" ); } } break; #endregion ID_SET_TEXTURE_ALIAS default: compiler.AddError( CompileErrorCode.UnexpectedToken, prop.File, prop.Line, "token \"" + prop.Name + "\" is not recognized" ); break; } //end of switch statement } else if ( i is ObjectAbstractNode ) { processNode( compiler, i ); } } // Apply the texture aliases ScriptCompilerEvent locEvt = new PreApplyTextureAliasesScriptCompilerEvent( this._material, ref this._textureAliases ); compiler._fireEvent( ref locEvt ); this._material.ApplyTextureAliases( this._textureAliases ); this._textureAliases.Clear(); }
protected void _translateGpuProgram( ScriptCompiler compiler, ObjectAbstractNode obj ) { var customParameters = new NameValuePairList(); string syntax = string.Empty, source = string.Empty; AbstractNode parameters = null; foreach ( var i in obj.Children ) { if ( i is PropertyAbstractNode ) { var prop = (PropertyAbstractNode)i; if ( prop.Id == (uint)Keywords.ID_SOURCE ) { if ( prop.Values.Count != 0 ) { if ( prop.Values[ 0 ] is AtomAbstractNode ) { source = ( (AtomAbstractNode)prop.Values[ 0 ] ).Value; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "source file expected" ); } } else { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line, "source file expected" ); } } else if ( prop.Id == (uint)Keywords.ID_SYNTAX ) { if ( prop.Values.Count != 0 ) { if ( prop.Values[ 0 ] is AtomAbstractNode ) { syntax = ( (AtomAbstractNode)prop.Values[ 0 ] ).Value; } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "syntax string expected" ); } } else { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line, "syntax string expected" ); } } else { string name = prop.Name, value = string.Empty; var first = true; foreach ( var it in prop.Values ) { if ( it is AtomAbstractNode ) { if ( !first ) { value += " "; } else { first = false; } value += ( (AtomAbstractNode)it ).Value; } } customParameters.Add( name, value ); } } else if ( i is ObjectAbstractNode ) { if ( ( (ObjectAbstractNode)i ).Id == (uint)Keywords.ID_DEFAULT_PARAMS ) { parameters = i; } else { processNode( compiler, i ); } } } if ( !GpuProgramManager.Instance.IsSyntaxSupported( syntax ) ) { compiler.AddError( CompileErrorCode.UnsupportedByRenderSystem, obj.File, obj.Line ); //Register the unsupported program so that materials that use it know that //it exists but is unsupported var unsupportedProg = GpuProgramManager.Instance.Create( obj.Name, compiler.ResourceGroup, _translateIDToGpuProgramType( obj.Id ), syntax ); return; } // Allocate the program object progObj; GpuProgram prog = null; ScriptCompilerEvent evt = new CreateGpuProgramScriptCompilerEvent( obj.File, obj.Name, compiler.ResourceGroup, source, syntax, _translateIDToGpuProgramType( obj.Id ) ); var processed = compiler._fireEvent( ref evt, out progObj ); if ( !processed ) { prog = (GpuProgram) GpuProgramManager.Instance.CreateProgram( obj.Name, compiler.ResourceGroup, source, _translateIDToGpuProgramType( obj.Id ), syntax ); } else { prog = (GpuProgram)progObj; } // Check that allocation worked if ( prog == null ) { compiler.AddError( CompileErrorCode.ObjectAllocationError, obj.File, obj.Line, "gpu program \"" + obj.Name + "\" could not be created" ); return; } obj.Context = prog; prog.IsMorphAnimationIncluded = false; prog.PoseAnimationCount = 0; prog.IsSkeletalAnimationIncluded = false; prog.IsVertexTextureFetchRequired = false; prog.Origin = obj.File; // Set the custom parameters prog.SetParameters( customParameters ); // Set up default parameters if ( prog.IsSupported && parameters != null ) { var ptr = prog.DefaultParameters; GpuProgramTranslator.TranslateProgramParameters( compiler, ptr, (ObjectAbstractNode)parameters ); } }