This is the main class for the compiler. It calls the parser and processes the CST into an AST and then uses translators to translate the AST into the final resources.
			/// <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 );
					}
				}
			}
Пример #2
0
			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;
						}
					}
				}
			}
Пример #4
0
			/// <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;
Пример #5
0
			/// <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;
						}
					}
				}
			}
Пример #7
0
			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;
			}
Пример #8
0
			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 );
					}
				}
			}
Пример #10
0
			public AbstractTreeBuilder( ScriptCompiler compiler )
			{
				this._compiler = compiler;
				this._current = null;
				this._nodes = new List<AbstractNode>();
			}
Пример #11
0
			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 );
				}
			}
Пример #12
0
		public virtual SubRenderState CreateInstance( ScriptCompiler compiler, PropertyAbstractNode prop,
		                                              TextureUnitState texState, SGScriptTranslator translator )
		{
			return null;
		}
Пример #13
0
		public virtual SubRenderState CreateInstance( ScriptCompiler compiler, PropertyAbstractNode prop, Pass pass,
		                                              SGScriptTranslator stranslator )
		{
			return null;
		}
Пример #14
0
			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 );
				}
			}
Пример #15
0
			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;
						}
					}
				}
			}
Пример #18
0
			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 );
				}
			}
Пример #19
0
			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);
				}
			}
Пример #20
0
		/// <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;
		}
Пример #21
0
			/// <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;
						}
					}
				}
			}
Пример #22
0
		/// <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;
						}
					}
				}
			}
Пример #24
0
		/// <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 )
		{
		}
Пример #25
0
			/// <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" );
					}
				}
			}
Пример #26
0
		/// <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;
		}
Пример #27
0
			/// <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
			}
Пример #28
0
		/// <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 )
		{
		}
Пример #29
0
			/// <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();
			}
Пример #30
0
			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 );
				}
			}