AddError() приватный Метод

private AddError ( CompileErrorCode code, string file, uint line ) : void
code CompileErrorCode
file string
line uint
Результат void
			/// <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 );
					}
				}
			}
			/// <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
			}
Пример #3
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;
Пример #4
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" );
					}
				}
			}
Пример #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;

				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;
						}
					}
				}
			}
			/// <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;
						}
					}
				}
			}
Пример #8
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 );
				}
			}
Пример #9
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;
			}
			/// <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;
						}
					}
				}
			}
Пример #11
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,
							"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 );
			}
Пример #12
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;

				// 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 );
					}
				}
			}
			/// <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;
						}
					}
				}
			}
Пример #16
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;
						}
					}
				}
			}
Пример #17
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();
			}
Пример #18
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 );
				}
			}