Class representing the state of a single texture unit during a Pass of a Technique, of a Material.
Texture units are pipelines for retrieving texture data for rendering onto your objects in the world. Using them is common to both the fixed-function and the programmable (vertex and fragment program) pipeline, but some of the settings will only have an effect in the fixed-function pipeline (for example, setting a texture rotation will have no effect if you use the programmable pipeline, because this is overridden by the fragment program). The effect of each setting as regards the 2 pipelines is commented in each setting.

When I use the term 'fixed-function pipeline' I mean traditional rendering where you do not use vertex or fragment programs (shaders). Programmable pipeline means that for this pass you are using vertex or fragment programs.

		public virtual SubRenderState CreateInstance( ScriptCompiler compiler, PropertyAbstractNode prop,
		                                              TextureUnitState texState, SGScriptTranslator translator )
		{
			return null;
		}
Exemple #2
0
		/// <summary>
		///    Inserts a new TextureUnitState object into the Pass.
		/// </summary>
		/// <remarks>
		///    This unit is is added on top of all previous texture units.
		///    <p/>
		///    Applies to both fixed-function and programmable passes.
		/// </remarks>
		/// <param name="textureName">The basic name of the texture (i.e. brickwall.jpg)</param>
		/// <param name="texCoordSet">The index of the texture coordinate set to use.</param>
		/// <returns></returns>
		public TextureUnitState CreateTextureUnitState( string textureName, int texCoordSet )
		{
			TextureUnitState state = new TextureUnitState( this );
			state.SetTextureName( textureName );
			state.TextureCoordSet = texCoordSet;
			textureUnitStates.Add( state );
			// needs recompilation
			_parent.NotifyNeedsRecompile();
			DirtyHash();
			return state;
		}
			public TextureUnitTranslator()
				: base()
			{
				_textureunit = null;
			}
		/// <summary>
		/// 
		/// </summary>
		protected void Initialize()
		{
			// Create geometry
			int nvertices = this.slices*4; // n+1 planes
			int elemsize = 3*3;
			int dsize = elemsize*nvertices;
			int x;

			var indexData = new IndexData();
			var vertexData = new VertexData();
			var vertices = new float[dsize];

			var coords = new float[4,2]
			             {
			             	{
			             		0.0f, 0.0f
			             	}, {
			             	   	0.0f, 1.0f
			             	   }, {
			             	      	1.0f, 0.0f
			             	      }, {
			             	         	1.0f, 1.0f
			             	         }
			             };

			for ( x = 0; x < this.slices; x++ )
			{
				for ( int y = 0; y < 4; y++ )
				{
					float xcoord = coords[ y, 0 ] - 0.5f;
					float ycoord = coords[ y, 1 ] - 0.5f;
					float zcoord = -( (float)x/(float)( this.slices - 1 ) - 0.5f );
					// 1.0f .. a/(a+1)
					// coordinate
					vertices[ x*4*elemsize + y*elemsize + 0 ] = xcoord*( this.size/2.0f );
					vertices[ x*4*elemsize + y*elemsize + 1 ] = ycoord*( this.size/2.0f );
					vertices[ x*4*elemsize + y*elemsize + 2 ] = zcoord*( this.size/2.0f );
					// normal
					vertices[ x*4*elemsize + y*elemsize + 3 ] = 0.0f;
					vertices[ x*4*elemsize + y*elemsize + 4 ] = 0.0f;
					vertices[ x*4*elemsize + y*elemsize + 5 ] = 1.0f;
					// tex
					vertices[ x*4*elemsize + y*elemsize + 6 ] = xcoord*Utility.Sqrt( 3.0f );
					vertices[ x*4*elemsize + y*elemsize + 7 ] = ycoord*Utility.Sqrt( 3.0f );
					vertices[ x*4*elemsize + y*elemsize + 8 ] = zcoord*Utility.Sqrt( 3.0f );
				}
			}

			var faces = new short[this.slices*6];
			for ( x = 0; x < this.slices; x++ )
			{
				faces[ x*6 + 0 ] = (short)( x*4 + 0 );
				faces[ x*6 + 1 ] = (short)( x*4 + 1 );
				faces[ x*6 + 2 ] = (short)( x*4 + 2 );
				faces[ x*6 + 3 ] = (short)( x*4 + 1 );
				faces[ x*6 + 4 ] = (short)( x*4 + 2 );
				faces[ x*6 + 5 ] = (short)( x*4 + 3 );
			}

			//setup buffers
			vertexData.vertexStart = 0;
			vertexData.vertexCount = nvertices;

			VertexDeclaration decl = vertexData.vertexDeclaration;
			VertexBufferBinding bind = vertexData.vertexBufferBinding;
			int offset = 0;
			offset += decl.AddElement( 0, 0, VertexElementType.Float3, VertexElementSemantic.Position ).Size;
			offset += decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Normal ).Size;
			offset += decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.TexCoords ).Size;

			HardwareVertexBuffer vertexBuffer = HardwareBufferManager.Instance.CreateVertexBuffer( decl, nvertices,
			                                                                                       BufferUsage.StaticWriteOnly );

			bind.SetBinding( 0, vertexBuffer );

			HardwareIndexBuffer indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, this.slices*6,
			                                                                                    BufferUsage.StaticWriteOnly );

			indexData.indexBuffer = indexBuffer;
			indexData.indexCount = this.slices*6;
			indexData.indexStart = 0;

			indexBuffer.WriteData( 0, indexBuffer.Size, faces, true );
			vertexBuffer.WriteData( 0, vertexBuffer.Size, vertices );
			vertices = null;
			faces = null;

			// Now make the render operation
			renderOperation.operationType = OperationType.TriangleList;
			renderOperation.indexData = indexData;
			renderOperation.vertexData = vertexData;
			renderOperation.useIndices = true;

			// Create a brand new private material
			if ( !ResourceGroupManager.Instance.GetResourceGroups().Contains( "VolumeRendable" ) )
			{
				ResourceGroupManager.Instance.CreateResourceGroup( "VolumeRendable" );
			}

			var material = (Material)MaterialManager.Instance.Create( this.texture, "VolumeRendable" );
			// Remove pre-created technique from defaults
			material.RemoveAllTechniques();

			// Create a techinique and a pass and a texture unit
			Technique technique = material.CreateTechnique();
			Pass pass = technique.CreatePass();
			TextureUnitState textureUnit = pass.CreateTextureUnitState();

			// Set pass parameters
			pass.SetSceneBlending( SceneBlendType.TransparentAlpha );
			pass.DepthWrite = false;
			pass.CullingMode = CullingMode.None;
			pass.LightingEnabled = false;
			textureUnit.SetTextureAddressingMode( TextureAddressing.Clamp );
			textureUnit.SetTextureName( this.texture, TextureType.ThreeD );
			textureUnit.SetTextureFiltering( TextureFiltering.Trilinear );

			this.unit = textureUnit;
			base.material = material;
		}
Exemple #5
0
		/// <summary>
		///		Copy the details of this pass to the target pass.
		/// </summary>
		/// <param name="target">Destination pass to copy this pass's attributes to.</param>
		public void CopyTo( Pass target )
		{
			target._name = _name;
			target._hashCode = _hashCode;

			// surface
			target._ambient = _ambient.Clone();
			target._diffuse = _diffuse.Clone();
			target._specular = _specular.Clone();
			target._emissive = _emissive.Clone();
			target._shininess = _shininess;
			target._tracking = _tracking;

			// fog
			target._fogOverride = _fogOverride;
			target._fogMode = _fogMode;
			target._fogColor = _fogColor.Clone();
			target._fogStart = _fogStart;
			target._fogEnd = _fogEnd;
			target._fogDensity = _fogDensity;

			// default blending
			target._sourceBlendFactor = _sourceBlendFactor;
			target._destinationBlendFactor = _destinationBlendFactor;

			target._depthCheck = _depthCheck;
			target._depthWrite = _depthWrite;
			target._alphaRejectFunction = _alphaRejectFunction;
			target._alphaRejectValue = _alphaRejectValue;
			target._colorWriteEnabled = _colorWriteEnabled;
			target._depthFunction = _depthFunction;
			target._depthBiasConstant = _depthBiasConstant;
			target._depthBiasSlopeScale = _depthBiasSlopeScale;
			target._cullingMode = _cullingMode;
			target._manualCullingMode = _manualCullingMode;
			target._lightingEnabled = _lightingEnabled;
			target._maxSimultaneousLights = _maxSimultaneousLights;
			target._iteratePerLight = _iteratePerLight;
			target._runOnlyForOneLightType = _runOnlyForOneLightType;
			target._onlyLightType = _onlyLightType;
			target._shadingMode = _shadingMode;
			target._polygonMode = _polygonMode;
			target.IterationCount = IterationCount;

			// vertex program
			if ( _vertexProgramUsage != null )
			{
				target._vertexProgramUsage = _vertexProgramUsage.Clone();
			}
			else
			{
				target._vertexProgramUsage = null;
			}

			// shadow caster vertex program
			if ( shadowCasterVertexProgramUsage != null )
			{
				target.shadowCasterVertexProgramUsage = shadowCasterVertexProgramUsage.Clone();
			}
			else
			{
				target.shadowCasterVertexProgramUsage = null;
			}

			// shadow receiver vertex program
			if ( _shadowReceiverVertexProgramUsage != null )
			{
				target._shadowReceiverVertexProgramUsage = _shadowReceiverVertexProgramUsage.Clone();
			}
			else
			{
				target._shadowReceiverVertexProgramUsage = null;
			}

			// fragment program
			if ( _fragmentProgramUsage != null )
			{
				target._fragmentProgramUsage = _fragmentProgramUsage.Clone();
			}
			else
			{
				target._fragmentProgramUsage = null;
			}

			// shadow caster fragment program
			if ( _shadowCasterFragmentProgramUsage != null )
			{
				target._shadowCasterFragmentProgramUsage = _shadowCasterFragmentProgramUsage.Clone();
			}
			else
			{
				target._shadowCasterFragmentProgramUsage = null;
			}

			// shadow receiver fragment program
			if ( _shadowReceiverFragmentProgramUsage != null )
			{
				target._shadowReceiverFragmentProgramUsage = _shadowReceiverFragmentProgramUsage.Clone();
			}
			else
			{
				target._shadowReceiverFragmentProgramUsage = null;
			}


			// Clear texture units but doesn't notify need recompilation in the case
			// we are cloning, The parent material will take care of this.
			target.textureUnitStates.Clear();

			// Copy texture units

			for ( int i = 0; i < textureUnitStates.Count; i++ )
			{
				TextureUnitState newState = new TextureUnitState( target );
				TextureUnitState src = (TextureUnitState)textureUnitStates[ i ];
				src.CopyTo( newState );

				target.textureUnitStates.Add( newState );
			}

			target.DirtyHash();
		}
		/// <summary>
		///     Creates a basic time-based texture coordinate modifier designed for creating rotating textures.
		/// </summary>
		/// <remarks>
		///     This simple method allows you to easily create constant-speed rotating textures. If you want more
		///     control, look up the ControllerManager.CreateTextureWaveTransformer for more complex wave-based
		///     scrollers / stretchers / rotaters.
		/// </remarks>
		/// <param name="layer">The texture unit to animate.</param>
		/// <param name="speed">Speed of the rotation, in counter-clockwise revolutions per second.</param>
		/// <returns>A newly created controller object that will be updated during the main render loop.</returns>
		public Controller<Real> CreateTextureRotator( TextureUnitState layer, Real speed )
		{
			IControllerValue<Real> val = new TexCoordModifierControllerValue( layer, false, false, false, false, true );
			IControllerFunction<Real> func = new MultipyControllerFunction( -speed, true );

			return CreateController( val, func );
		}
		/// <summary>
		///     Creates a basic time-based texture v coordinate modifier designed for creating scrolling textures.
		/// </summary>
		/// <remarks>
		///     This simple method allows you to easily create constant-speed scrolling textures. If you want more
		///     control, look up the <see cref="CreateTextureWaveTransformer"/> for more complex wave-based
		///     scrollers / stretchers / rotaters.
		/// </remarks>
		/// <param name="layer">The texture unit to animate.</param>
		/// <param name="speed">speed, in wraps per second.</param>
		/// <returns>A newly created controller object that will be updated during the main render loop.</returns>
		public Controller<Real> CreateTextureVScroller( TextureUnitState layer, Real speed )
		{
			IControllerValue<Real> val = null;
			IControllerFunction<Real> func = null;
			Controller<Real> controller = null;

			// if both u and v speeds are the same, we can use a single controller for it
			if ( speed != 0 )
			{
				// create the value and function
				val = new TexCoordModifierControllerValue( layer, false, true );
				func = new MultipyControllerFunction( -speed, true );

				// create the controller (uses FrameTime for source by default)
				controller = CreateController( val, func );
			}

			return controller;
		}
		/// <summary>
		///		Used to clone a texture layer.  Mainly used during a call to Clone on a Material or Pass.
		/// </summary>
		/// <returns></returns>
		public TextureUnitState Clone( Pass parent )
		{
			var newState = new TextureUnitState( parent );

			CopyTo( newState );

			newState.parent.DirtyHash();

			return newState;
		}
 /// <summary>
 ///    Adds the passed in TextureUnitState, to the existing Pass.
 /// </summary>
 /// <param name="state">TextureUnitState to add to this pass.</param>
 public void AddTextureUnitState(TextureUnitState state)
 {
     Debug.Assert(state != null, "state is null in Pass.AddTextureUnitState()");
     if (state != null) {
         // only attach TUS to pass if TUS does not belong to another pass
         if ((state.Parent == null) || (state.Parent == this)) {
             textureUnitStates.Add(state);
             // Notify state
             state.Parent = this;
             // if texture unit state name is empty then give it a default name based on its index
             if (state.Name == null || state.Name == "") {
                 // its the last entry in the container so its index is size - 1
                 int idx = textureUnitStates.Count - 1;
                 state.Name = idx.ToString();
                 // since the name was never set and a default one has been made, clear the alias name
                 // so that when the texture unit name is set by the user, the alias name will be set to
                 // that name
                 state.TextureNameAlias = null;
             }
             // needs recompilation
             parent.NotifyNeedsRecompile();
             DirtyHash();
         }
         else
             throw new AxiomException("TextureUnitState already attached to another pass" +
                 "  In Pass.AddTextureUnitState");
         contentTypeLookupBuilt = false;
     }
 }
Exemple #10
0
		private bool NeedsTextureMatrix( TextureUnitState textureUnitState )
		{
			for ( int i = 0; i < textureUnitState.NumEffects; i++ )
			{
				TextureEffect effi = textureUnitState.GetEffect( i );

				switch ( effi.type )
				{
					case TextureEffectType.EnvironmentMap:
					case TextureEffectType.ProjectiveTexture:
					case TextureEffectType.Rotate:
					case TextureEffectType.Transform:
					case TextureEffectType.UScroll:
					case TextureEffectType.UVScroll:
					case TextureEffectType.VScroll:
						return true;
				}
			}
			//TODO
			var matTexture = new Matrix4(); //textureUnitState.getTextureTransform();

			//Resolve texture matrix parameter
			if ( matTexture != Matrix4.Identity )
			{
				return true;
			}

			return false;
		}
		/// <summary>
		///		Used to clone a texture layer.  Mainly used during a call to Clone on a Material.
		/// </summary>
		/// <returns></returns>
		public void CopyTo( TextureUnitState target )
		{
			var props = target.GetType().GetFields( BindingFlags.NonPublic | BindingFlags.Instance );

			// save parent from target, since it will be overwritten by the following loop
			var tmpParent = target.parent;

			for ( var i = 0; i < props.Length; i++ )
			{
				var prop = props[ i ];

				var srcVal = prop.GetValue( this );
				prop.SetValue( target, srcVal );
			}

			// restore correct parent
			target.parent = tmpParent;

			target.frames = new string[MaxAnimationFrames];

			// copy over animation frame texture names
			for ( var i = 0; i < MaxAnimationFrames; i++ )
			{
				target.frames[ i ] = this.frames[ i ];
			}

			// must clone these references
			target.colorBlendMode = this.colorBlendMode.Clone();
			target.alphaBlendMode = this.alphaBlendMode.Clone();

			target.effectList = new TextureEffectList();

			// copy effects
			foreach ( var effect in this.effectList )
			{
				target.effectList.Add( effect.Clone() );
			}

			// dirty the hash of the parent pass
			target.parent.DirtyHash();
		}
Exemple #12
0
		private TexCoordCalcMethod GetCalcMethod( TextureUnitState textureUnitState )
		{
			TexCoordCalcMethod texCoordCalcMethod = TexCoordCalcMethod.None;
			var effectMap = new List<TextureEffect>();
			for ( int i = 0; i < textureUnitState.NumEffects; i++ )
			{
				effectMap.Add( textureUnitState.GetEffect( i ) );
			}

			foreach ( var effi in effectMap )
			{
				switch ( effi.type )
				{
					case TextureEffectType.EnvironmentMap:
						//TODO
						//if (effi.subtype == Curved)
						//{
						//    texCoordCalcMethod = TexCoordCalcMethod.EnvironmentMap;
						//}
						//else if (effi.subtype == Planar)
						//{
						//    texCoordCalcMethod = TexCoordCalcMethod.EnvironmentMapPlanar;
						//}
						//else if (effi.subtype == Reflection)
						//{
						//    texCoordCalcMethod = TexCoordCalcMethod.EnvironmentMapReflection;
						//}
						//else if (effi.subtype == Normal)
						//{
						//    texCoordCalcMethod = TexCoordCalcMethod.EnvironmentMapNormal;
						//}

						break;
					case TextureEffectType.ProjectiveTexture:
						texCoordCalcMethod = TexCoordCalcMethod.ProjectiveTexture;
						break;
					case TextureEffectType.Rotate:
					case TextureEffectType.Transform:
					case TextureEffectType.UScroll:
					case TextureEffectType.UVScroll:
					case TextureEffectType.VScroll:
						break;
				}
			}

			return texCoordCalcMethod;
		}
Exemple #13
0
		private void SetTextureUnit( int index, TextureUnitState textureUnitState )
		{
			if ( index >= this.textureUnitParamsList.Count )
			{
				throw new AxiomException( "FFPTexturing unit index out of bounds !!!" );
			}
			if ( textureUnitState.BindingType == TextureBindingType.Vertex )
			{
				throw new AxiomException( "FFP Texture unit does not support vertex texture fetch !!!" );
			}

			TextureUnitParams curParams = this.textureUnitParamsList[ index ];

			curParams.TextureSamplerIndex = index;
			curParams.TextureUnitState = textureUnitState;

			switch ( curParams.TextureUnitState.TextureType )
			{
				case TextureType.CubeMap:
					curParams.TextureSamplerType = GpuProgramParameters.GpuConstantType.SamplerCube;
					curParams.VSInTextureCoordinateType = GpuProgramParameters.GpuConstantType.Float3;
					break;
				case TextureType.OneD:
					curParams.TextureSamplerType = GpuProgramParameters.GpuConstantType.Sampler1D;
					curParams.VSInTextureCoordinateType = GpuProgramParameters.GpuConstantType.Float1;
					break;
				case TextureType.ThreeD:
					curParams.TextureSamplerType = GpuProgramParameters.GpuConstantType.Sampler3D;
					curParams.VSInTextureCoordinateType = GpuProgramParameters.GpuConstantType.Float3;
					break;
				case TextureType.TwoD:
					curParams.TextureSamplerType = GpuProgramParameters.GpuConstantType.Sampler2D;
					curParams.VSInTextureCoordinateType = GpuProgramParameters.GpuConstantType.Float2;
					break;
			}

			curParams.VSOutTextureCoordinateType = curParams.VSInTextureCoordinateType;
			curParams.TexCoordCalcMethod = GetCalcMethod( curParams.TextureUnitState );

			if ( curParams.TexCoordCalcMethod == TexCoordCalcMethod.ProjectiveTexture )
			{
				curParams.VSOutTextureCoordinateType = GpuProgramParameters.GpuConstantType.Float3;
			}
		}
Exemple #14
0
		protected virtual bool IsProcessingNeeded( TextureUnitState texUnitState )
		{
			return texUnitState.BindingType == TextureBindingType.Fragment;
		}
        private void CreateProceduralTextureMods(int p, TextureUnitState t)
        {
            // Procedural mods
            // Custom - don't use mod if generating environment
            // Because I do env a different way it look horrible
            if(pass[p].texGen != ShaderTextureGen.Environment)
            {
                if(pass[p].tcModRotate != 0.0f)
                    t.SetRotateAnimation(pass[p].tcModRotate);

                if((pass[p].tcModScroll[0] != 0.0f) || (pass[p].tcModScroll[1] != 0.0f))
                {
                    if(pass[p].tcModTurbOn)
                    {
                        // Turbulent scroll
                        if(pass[p].tcModScroll[0] != 0.0f)
                        {
                            t.SetTransformAnimation(TextureTransform.TranslateU, WaveformType.Sine,
                                                    pass[p].tcModTurb[0], pass[p].tcModTurb[3], pass[p].tcModTurb[2], pass[p].tcModTurb[1]);
                        }
                        if(pass[p].tcModScroll[1] != 0.0f)
                        {
                            t.SetTransformAnimation(TextureTransform.TranslateV, WaveformType.Sine,
                                                    pass[p].tcModTurb[0], pass[p].tcModTurb[3], pass[p].tcModTurb[2], pass[p].tcModTurb[1]);
                        }
                    }
                    else
                    {
                        // Constant scroll
                        t.SetScrollAnimation(pass[p].tcModScroll[0], pass[p].tcModScroll[1]);
                    }
                }

                if(pass[p].tcModStretchWave != ShaderWaveType.None)
                {
                    WaveformType wft = WaveformType.Sine;
                    switch(pass[p].tcModStretchWave)
                    {
                        case ShaderWaveType.Sin:
                            wft = WaveformType.Sine;
                            break;
                        case ShaderWaveType.Triangle:
                            wft = WaveformType.Triangle;
                            break;
                        case ShaderWaveType.Square:
                            wft = WaveformType.Square;
                            break;
                        case ShaderWaveType.SawTooth:
                            wft = WaveformType.Sawtooth;
                            break;
                        case ShaderWaveType.InverseSawtooth:
                            wft = WaveformType.InverseSawtooth;
                            break;
                    }

                    // Create wave-based stretcher
                    t.SetTransformAnimation(TextureTransform.ScaleU, wft, pass[p].tcModStretchParams[3],
                                            pass[p].tcModStretchParams[0], pass[p].tcModStretchParams[2], pass[p].tcModStretchParams[1]);
                    t.SetTransformAnimation(TextureTransform.ScaleV, wft, pass[p].tcModStretchParams[3],
                                            pass[p].tcModStretchParams[0], pass[p].tcModStretchParams[2], pass[p].tcModStretchParams[1]);
                }
            }
        }
        /// <summary>
        ///		Copy the details of this pass to the target pass.
        /// </summary>
        /// <param name="target">Destination pass to copy this pass's attributes to.</param>
        public void CopyTo(Pass target)
        {
            target.name = name;
            target.hashCode = hashCode;

            // surface
            target.ambient = ambient.Clone();
            target.diffuse = diffuse.Clone();
            target.specular = specular.Clone();
            target.emissive = emissive.Clone();
            target.shininess = shininess;
            target.tracking = tracking;

            // fog
            target.fogOverride = fogOverride;
            target.fogMode = fogMode;
            target.fogColor = fogColor.Clone();
            target.fogStart = fogStart;
            target.fogEnd = fogEnd;
            target.fogDensity = fogDensity;

            // default blending
            target.sourceBlendFactor = sourceBlendFactor;
            target.destBlendFactor = destBlendFactor;

            target.depthCheck = depthCheck;
            target.depthWrite = depthWrite;
            target.alphaRejectFunction = alphaRejectFunction;
            target.alphaRejectValue = alphaRejectValue;
            target.colorWrite = colorWrite;
            target.depthFunc = depthFunc;
            target.depthBiasConstant = depthBiasConstant;
            target.depthBiasSlopeScale = depthBiasSlopeScale;
            target.cullMode = cullMode;
            target.manualCullMode = manualCullMode;
            target.lightingEnabled = lightingEnabled;
            target.maxLights = maxLights;
            target.startLight = startLight;
            target.runOncePerLight = runOncePerLight;
            target.lightsPerIteration = lightsPerIteration;
            target.runOnlyForOneLightType = runOnlyForOneLightType;
            target.onlyLightType = onlyLightType;
            target.shadeOptions = shadeOptions;
            target.sceneDetail = sceneDetail;
            target.passIterationCount = passIterationCount;
            target.pointSize = pointSize;
            target.pointMinSize = pointMinSize;
            target.pointMaxSize = pointMaxSize;
            target.pointSpritesEnabled = pointSpritesEnabled;
            target.pointAttenuationEnabled = pointAttenuationEnabled;
            target.pointAttenuationConstant = pointAttenuationConstant;
            target.pointAttenuationLinear = pointAttenuationLinear;
            target.pointAttenuationQuadratic = pointAttenuationQuadratic;
            target.contentTypeLookupBuilt = contentTypeLookupBuilt;

            // vertex program
            if(vertexProgramUsage != null) {
                target.vertexProgramUsage = vertexProgramUsage.Clone();
            }
            else {
                target.vertexProgramUsage = null;
            }

            // shadow caster vertex program
            if (shadowCasterVertexProgramUsage != null) {
                target.shadowCasterVertexProgramUsage = shadowCasterVertexProgramUsage.Clone();
            } else {
                target.shadowCasterVertexProgramUsage = null;
            }

            // shadow receiver vertex program
            if (shadowReceiverVertexProgramUsage != null) {
                target.shadowReceiverVertexProgramUsage = shadowReceiverVertexProgramUsage.Clone();
            } else {
                target.shadowReceiverVertexProgramUsage = null;
            }

            // fragment program
            if(fragmentProgramUsage != null) {
                target.fragmentProgramUsage = fragmentProgramUsage.Clone();
            }
            else {
                target.fragmentProgramUsage = null;
            }

            // shadow caster fragment program
            if (shadowCasterFragmentProgramUsage != null) {
                target.shadowCasterFragmentProgramUsage = shadowCasterFragmentProgramUsage.Clone();
            } else {
                target.shadowCasterFragmentProgramUsage = null;
            }

            // shadow receiver fragment program
            if(shadowReceiverFragmentProgramUsage != null) {
                target.shadowReceiverFragmentProgramUsage = shadowReceiverFragmentProgramUsage.Clone();
            }
            else {
                target.shadowReceiverFragmentProgramUsage = null;
            }

            // texture units
            target.RemoveAllTextureUnitStates();

            for(int i = 0; i < textureUnitStates.Count; i++) {
                TextureUnitState newState = new TextureUnitState(target);
                TextureUnitState src = (TextureUnitState)textureUnitStates[i];
                src.CopyTo(newState);

                target.textureUnitStates.Add(newState);
            }

            target.DirtyHash();
        }
		/// <summary>
		///     Creates a texture layer animator controller.
		/// </summary>
		/// <remarks>
		///     This helper method creates the Controller, IControllerValue and IControllerFunction classes required
		///     to animate a texture.
		/// </remarks>
		/// <param name="texUnit">The texture unit to animate.</param>
		/// <param name="sequenceTime">Length of the animation (in seconds).</param>
		/// <returns>A newly created controller object that will be updated during the main render loop.</returns>
		public Controller<Real> CreateTextureAnimator( TextureUnitState texUnit, Real sequenceTime )
		{
			IControllerValue<Real> val = new TextureFrameControllerValue( texUnit );
			IControllerFunction<Real> func = new AnimationControllerFunction( sequenceTime );

			return CreateController( val, func );
		}
 /// <summary>
 ///    Overloaded method.
 /// </summary>
 /// <param name="textureName">The basic name of the texture (i.e. brickwall.jpg)</param>
 /// <returns></returns>
 public TextureUnitState CreateTextureUnitState()
 {
     TextureUnitState state = new TextureUnitState(this);
     AddTextureUnitState(state);
     contentTypeLookupBuilt = false;
     return state;
 }
		/// <summary>
		///     Creates a basic time-based texture u coordinate modifier designed for creating scrolling textures.
		/// </summary>
		/// <remarks>
		///     This simple method allows you to easily create constant-speed scrolling textures. If you want more
		///     control, look up the <see cref="CreateTextureWaveTransformer"/> for more complex wave-based
		///     scrollers / stretchers / rotaters.
		/// </remarks>
		/// <param name="layer">The texture unit to animate.</param>
		/// <param name="speed">speed, in wraps per second.</param>
		/// <returns>A newly created controller object that will be updated during the main render loop.</returns>
		public Controller<Real> CreateTextureUScroller( TextureUnitState layer, Real speed )
		{
			IControllerValue<Real> val = null;
			IControllerFunction<Real> func = null;
			Controller<Real> controller = null;

			// Don't create a controller if the speed is zero
			if ( speed != 0 )
			{
				// create the value and function
				val = new TexCoordModifierControllerValue( layer, true );
				func = new MultipyControllerFunction( -speed, true );

				// create the controller (uses FrameTime for source by default)
				controller = CreateController( val, func );
			}

			return controller;
		}
 /// <summary>
 ///    Inserts a new TextureUnitState object into the Pass.
 /// </summary>
 /// <remarks>
 ///    This unit is is added on top of all previous texture units.
 ///    <p/>
 ///    Applies to both fixed-function and programmable passes.
 /// </remarks>
 /// <param name="textureName">The basic name of the texture (i.e. brickwall.jpg)</param>
 /// <param name="texCoordSet">The index of the texture coordinate set to use.</param>
 /// <returns></returns>
 public TextureUnitState CreateTextureUnitState(string textureName, int texCoordSet)
 {
     TextureUnitState state = new TextureUnitState(this);
     state.SetTextureName(textureName);
     state.TextureCoordSet = texCoordSet;
     AddTextureUnitState(state);
     contentTypeLookupBuilt = false;
     return state;
 }
		/// <summary>
		///	    Creates a very flexible time-based texture transformation which can alter the scale, position or
		///	    rotation of a texture based on a wave function.	
		/// </summary>
		/// <param name="layer">The texture unit to effect.</param>
		/// <param name="type">The type of transform, either translate (scroll), scale (stretch) or rotate (spin).</param>
		/// <param name="waveType">The shape of the wave, see WaveformType enum for details.</param>
		/// <param name="baseVal">The base value of the output.</param>
		/// <param name="frequency">The speed of the wave in cycles per second.</param>
		/// <param name="phase">The offset of the start of the wave, e.g. 0.5 to start half-way through the wave.</param>
		/// <param name="amplitude">Scales the output so that instead of lying within 0..1 it lies within 0..(1 * amplitude) for exaggerated effects</param>
		/// <returns>A newly created controller object that will be updated during the main render loop.</returns>
		public Controller<Real> CreateTextureWaveTransformer( TextureUnitState layer, TextureTransform type,
		                                                      WaveformType waveType, Real baseVal, Real frequency, Real phase,
		                                                      Real amplitude )
		{
			IControllerValue<Real> val = null;
			IControllerFunction<Real> function = null;

			// determine which type of controller value this layer needs
			switch ( type )
			{
				case TextureTransform.TranslateU:
					val = new TexCoordModifierControllerValue( layer, true, false );
					break;

				case TextureTransform.TranslateV:
					val = new TexCoordModifierControllerValue( layer, false, true );
					break;

				case TextureTransform.ScaleU:
					val = new TexCoordModifierControllerValue( layer, false, false, true, false, false );
					break;

				case TextureTransform.ScaleV:
					val = new TexCoordModifierControllerValue( layer, false, false, false, true, false );
					break;

				case TextureTransform.Rotate:
					val = new TexCoordModifierControllerValue( layer, false, false, false, false, true );
					break;
			} // switch

			// create a new waveform controller function
			function = new WaveformControllerFunction( waveType, baseVal, frequency, phase, amplitude, true );

			// finally, create the controller using frame time as the source value
			return CreateController( this.frameTimeController, val, function );
		}
 /// <summary>
 ///    Retrieve the index of the Texture Unit State in the pass.
 /// </summary>
 public int GetTextureUnitStateIndex(TextureUnitState state)
 {
     Debug.Assert(state != null, "state is 0 in Pass.AddTextureUnitState()");
     // only find index for state attached to this pass
     if (state.Parent == this) {
         // iterate through TUS container and find matching pointer to state
         for (int i=0; i<textureUnitStates.Count; i++) {
             TextureUnitState t = (TextureUnitState)textureUnitStates[i];
             if (t == state)
                 return i;
         }
     }
     else
         throw new AxiomException("TextureUnitState is not attached to this pass" +
             "  In Pass.GetTextureUnitStateIndex");
     return 0;
 }
Exemple #23
0
		/// <summary>
		///    Adds the passed in TextureUnitState, to the existing Pass.
		/// </summary>
		/// <param name="state">TextureUnitState to add to this pass.</param>
		public void AddTextureUnitState( TextureUnitState state )
		{
			textureUnitStates.Add( state );
			if ( state.Name == null )
			{
				// it's the last entry in the container so it's index is count - 1
				state.Name = ( textureUnitStates.Count - 1 ).ToString();
				// Since the anme was never set and a default one has been made, 
				// clear the alias name so that when the texture unit name is set 
				// by the user, the alias name will be set to that name.
				state.TextureNameAlias = null;
			}
			// needs recompilation
			_parent.NotifyNeedsRecompile();
			DirtyHash();
		}
        /// <summary>
        ///    Removes the specified TextureUnitState from this pass.
        /// </summary>
        /// <param name="state">A reference to the TextureUnitState to remove from this pass.</param>
        public void RemoveTextureUnitState(TextureUnitState state)
        {
            textureUnitStates.Remove(state);

            if(!queuedForDeletion) {
                // needs recompilation
                parent.NotifyNeedsRecompile();
            }

            DirtyHash();
            contentTypeLookupBuilt = false;
        }
Exemple #25
0
		/// <summary>
		///    Overloaded method.
		/// </summary>
		/// <returns></returns>
		public TextureUnitState CreateTextureUnitState()
		{
			TextureUnitState state = new TextureUnitState( this );
			textureUnitStates.Add( state );
			// needs recompilation
			_parent.NotifyNeedsRecompile();
			DirtyHash();
			return state;
		}
        /// <summary>
        ///		Utility function for setting all the properties of a texture unit at once.
        ///		This method is also worth using over the individual texture unit settings because it
        ///		only sets those settings which are different from the current settings for this
        ///		unit, thus minimising render state changes.
        /// </summary>
        /// <param name="textureUnit">Index of the texture unit to configure</param>
        /// <param name="layer">Reference to a TextureLayer object which defines all the settings.</param>
        public virtual void SetTextureUnit(int unit, TextureUnitState unitState, bool fixedFunction)
        {
            // This method is only ever called to set a texture unit to valid details
            // The method _disableTextureUnit is called to turn a unit off

            // Vertex texture binding?
            if (caps.CheckCap(Capabilities.VertexTextureFetch) &&
                !caps.CheckCap(Capabilities.VertexTextureFetch)) {
                if (unitState.BindingType == GpuProgramType.Vertex) {
                    // Bind vertex texture
                    SetVertexTexture(unit, unitState);
                    // bind nothing to fragment unit (hardware isn't shared but fragment
                    // unit can't be using the same index
                    SetTexture(unit, true, string.Empty);
                }
                else {
                    // vice versa
                    SetVertexTexture(unit, unitState);
                    SetTexture(unit, true, unitState.TextureName);
                }
            }
            else {
                // Shared vertex / fragment textures or no vertex texture support
                // Bind texture (may be blank)
                SetTexture(unit, true, unitState.TextureName);
            }

            // Set texture coordinate set
            // SetTextureCoordSet(unit, unitState.TextureCoordSet);
            if (!fixedFunction)
                // From Direct3D9 error log:
                // Texture coordinate index in the stage must be equal to the stage index when programmable vertex pipeline is used
                SetTextureCoordSet(unit, unit);

            // Texture layer filtering
            SetTextureUnitFiltering(
                unit,
                unitState.GetTextureFiltering(FilterType.Min),
                unitState.GetTextureFiltering(FilterType.Mag),
                unitState.GetTextureFiltering(FilterType.Mip));

            // Texture layer anistropy
            SetTextureLayerAnisotropy(unit, unitState.TextureAnisotropy);

            // Set mipmap biasing
            SetTextureMipmapBias(unit, unitState.MipmapBias);

            // Texture addressing mode
            UVWAddressingMode uvw = unitState.GetTextureAddressingMode();
            SetTextureAddressingMode(unit, uvw);
            // Set texture border colour only if required
            if (uvw.u == TextureAddressing.Border ||
                uvw.v == TextureAddressing.Border ||
                uvw.w == TextureAddressing.Border)
                SetTextureBorderColor(unit, unitState.TextureBorderColor);

            // This stuff only gets done for the fixed function pipeline.  It is not needed
            // if we are using a pixel shader.
            if (fixedFunction)
            {
                // Tex Coord Set
                SetTextureCoordSet(unit, unitState.TextureCoordSet);

                // set the texture blending mode
                SetTextureBlendMode(unit, unitState.ColorBlendMode);

                // set the texture blending mode
                SetTextureBlendMode(unit, unitState.AlphaBlendMode);

                bool anyCalcs = false;

                for (int i = 0; i < unitState.NumEffects; i++)
                {
                    TextureEffect effect = unitState.GetEffect(i);

                    switch (effect.type)
                    {
                        case TextureEffectType.EnvironmentMap:
                            if ((EnvironmentMap)effect.subtype == EnvironmentMap.Curved)
                            {
                                SetTextureCoordCalculation(unit, TexCoordCalcMethod.EnvironmentMap);
                                anyCalcs = true;
                            }
                            else if ((EnvironmentMap)effect.subtype == EnvironmentMap.Planar)
                            {
                                SetTextureCoordCalculation(unit, TexCoordCalcMethod.EnvironmentMapPlanar);
                                anyCalcs = true;
                            }
                            else if ((EnvironmentMap)effect.subtype == EnvironmentMap.Reflection)
                            {
                                SetTextureCoordCalculation(unit, TexCoordCalcMethod.EnvironmentMapReflection);
                                anyCalcs = true;
                            }
                            else if ((EnvironmentMap)effect.subtype == EnvironmentMap.Normal)
                            {
                                SetTextureCoordCalculation(unit, TexCoordCalcMethod.EnvironmentMapNormal);
                                anyCalcs = true;
                            }
                            break;

                        case TextureEffectType.Scroll:
                        case TextureEffectType.Rotate:
                        case TextureEffectType.Transform:
                            break;

                        case TextureEffectType.ProjectiveTexture:
                            SetTextureCoordCalculation(unit, TexCoordCalcMethod.ProjectiveTexture, effect.frustum);
                            anyCalcs = true;
                            break;
                    } // switch
                } // for

                // Ensure any previous texcoord calc settings are reset if there are now none
                if (!anyCalcs)
                {
                    SetTextureCoordCalculation(unit, TexCoordCalcMethod.None);
                }

                // set the texture matrix to that of the current layer for any transformations
                SetTextureMatrix(unit, unitState.TextureMatrix);
            }
        }
Exemple #27
0
		/// <summary>
		///    Removes the specified TextureUnitState from this pass.
		/// </summary>
		/// <param name="state">A reference to the TextureUnitState to remove from this pass.</param>
		public void RemoveTextureUnitState( TextureUnitState state )
		{
			textureUnitStates.Remove( state );

			if ( !queuedForDeletion )
			{
				// needs recompilation
				_parent.NotifyNeedsRecompile();
			}

			DirtyHash();
		}
 /// <summary>
 ///    Binds a texture to a vertex sampler.
 /// </summary>
 /// <remarks>
 ///     Not all rendersystems support separate vertex samplers. For those that
 ///     do, you can set a texture for them, separate to the regular texture
 ///     samplers, using this method. For those that don't, you should use the
 ///     regular texture samplers which are shared between the vertex and
 ///     fragment units; calling this method will throw an exception.
 ///     @see RenderSystemCapabilites::getVertexTextureUnitsShared
 /// </remarks>
 public void SetVertexTexture(int unit, TextureUnitState unitState)
 {
     throw new AxiomException(
         "This rendersystem does not support separate vertex texture samplers, " +
         "you should use the regular texture samplers which are shared between " +
         "the vertex and fragment units." +
         "In RenderSystem.SetVertexTexture");
 }
			/// <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;
Exemple #30
0
		public virtual void WriteInstance( MaterialSerializer ser, SubRenderState subRenderState,
		                                   TextureUnitState srcTextureUnit, TextureUnitState dstTextureUnit )
		{
		}