protected static bool ParseBindingType( string parameters, MaterialScriptContext context ) { switch ( parameters.ToLower() ) { case "texture": context.textureUnit.BindingType = TextureBindingType.Fragment; break; case "vertex": context.textureUnit.BindingType = TextureBindingType.Vertex; break; default: LogParseError( context, "Invalid binding type option - {0}", parameters ); break; } return false; }
protected static bool ParseAmbient( string parameters, MaterialScriptContext context ) { string[] values = parameters.Split( new char[] { ' ', '\t' } ); // must be 1, 3 or 4 parameters if ( values.Length == 1 ) { if ( values[ 0 ].ToLower() == "vertexcolour" || values[ 0 ].ToLower() == "vertexcolor" ) { context.pass.VertexColorTracking |= TrackVertexColor.Ambient; } else { LogParseError( context, "Bad ambient attribute, single parameter flag must be 'vertexcolour' or 'vertexcolor'." ); } } else if ( values.Length == 3 || values.Length == 4 ) { context.pass.Ambient = StringConverter.ParseColor( values ); context.pass.VertexColorTracking &= ~TrackVertexColor.Ambient; } else { LogParseError( context, "Bad ambient attribute, wrong number of parameters (expected 1, 3 or 4)." ); } return false; }
protected static bool ParseCullSoftware( string parameters, MaterialScriptContext context ) { // lookup the real enum equivalent to the script value object val = ScriptEnumAttribute.Lookup( parameters, typeof( ManualCullingMode ) ); // if a value was found, assign it if ( val != null ) { context.pass.ManualCullingMode = (ManualCullingMode)val; } else { string legalValues = ScriptEnumAttribute.GetLegalValues( typeof( ManualCullingMode ) ); LogParseError( context, "Bad cull_software attribute, valid parameters are {0}.", legalValues ); } return false; }
protected static bool ParseLodDistances( string parameters, MaterialScriptContext context ) { context.material.LodStrategy = LodStrategyManager.Instance.GetStrategy( DistanceLodStrategy.StrategyName ); string[] values = parameters.Split( new char[] { ' ', '\t' } ); LodValueList lodDistances = new LodValueList(); for ( int i = 0; i < values.Length; i++ ) { lodDistances.Add( StringConverter.ParseFloat( values[ i ] ) ); } context.material.SetLodLevels( lodDistances ); return false; }
protected static bool ParseLodIndex( string parameters, MaterialScriptContext context ) { context.technique.LodIndex = int.Parse( parameters ); return false; }
protected static bool ParseTextureUnit( string parameters, MaterialScriptContext context ) { // create a new texture unit context.textureUnit = context.pass.CreateTextureUnitState(); // get the texture unit name string[] values = parameters.Split( new char[] { ' ', '\t' } ); if ( values.Length > 0 && values[ 0 ].Length > 0 ) context.textureUnit.Name = values[ 0 ]; // update section context.section = MaterialScriptSection.TextureUnit; // increase texture unit level depth context.stateLev++; // return true because this must be followed by a { return true; }
protected static bool ParseSetTextureAlias( string parameters, MaterialScriptContext context ) { // get the texture alias string[] values = parameters.Split( new char[] { ' ', '\t' } ); if ( values.Length != 2 ) { LogParseError( context, "Invalid set_texture_alias entry - expected 2 parameters." ); return true; } // update section if ( context.textureAliases.ContainsKey( values[ 0 ] ) ) { context.textureAliases[ values[ 0 ] ] = values[ 1 ]; } else { context.textureAliases.Add( values[ 0 ], values[ 1 ] ); } return false; }
protected static bool ParseProgramMorphAnimation( string parameters, MaterialScriptContext context ) { context.programDef.supportsMorphAnimation = bool.Parse( parameters ); return false; }
protected static bool ParseProgramPoseAnimation( string parameters, MaterialScriptContext context ) { context.programDef.poseAnimationCount = ushort.Parse( parameters ); return false; }
protected static bool ParseProgramSource( string parameters, MaterialScriptContext context ) { // source filename, preserve case context.programDef.source = parameters; return false; }
protected static bool ParseProgramSyntax( string parameters, MaterialScriptContext context ) { context.programDef.syntax = parameters.ToLower(); return false; }
protected static bool ParseParamNamedAuto( string parameters, MaterialScriptContext context ) { // skip this if the program is not supported or could not be found if ( context.program == null || !context.program.IsSupported ) { return false; } string[] values = parameters.Split( new char[] { ' ', '\t' } ); if ( values.Length != 2 && values.Length != 3 ) { LogParseError( context, "Invalid param_named_auto attribute - expected 2 or 3 parameters." ); return false; } // get start index try { int index = context.programParams.GetParamIndex( values[ 0 ] ); ProcessAutoProgramParam( index, "param_named_auto", values, context ); } catch ( Exception ex ) { LogParseError( context, "Invalid param_named_auto attribute - {0}.", ex.Message ); return false; } return false; }
protected static bool ParseParamIndexedAuto( string parameters, MaterialScriptContext context ) { // skip this if the program is not supported or could not be found if ( context.program == null || !context.program.IsSupported ) { return false; } string[] values = parameters.Split( new char[] { ' ', '\t' } ); if ( values.Length != 2 && values.Length != 3 ) { LogParseError( context, "Invalid param_indexed_auto attribute - expected at 2 or 3 parameters." ); return false; } // get start index int index = int.Parse( values[ 0 ] ); ProcessAutoProgramParam( index, "param_indexed_auto", values, context ); return false; }
protected static bool ParseWaveXForm( string parameters, MaterialScriptContext context ) { string[] values = parameters.Split( new char[] { ' ', '\t' } ); if ( values.Length != 6 ) { LogParseError( context, "Bad wave_xform attribute, wrong number of parameters (expected 6)." ); return false; } TextureTransform transType = 0; WaveformType waveType = 0; // check the transform type object val = ScriptEnumAttribute.Lookup( values[ 0 ], typeof( TextureTransform ) ); if ( val == null ) { string legalValues = ScriptEnumAttribute.GetLegalValues( typeof( TextureTransform ) ); LogParseError( context, "Bad wave_xform attribute, valid transform type values are {0}.", legalValues ); return false; } transType = (TextureTransform)val; // check the wavetype val = ScriptEnumAttribute.Lookup( values[ 1 ], typeof( WaveformType ) ); if ( val == null ) { string legalValues = ScriptEnumAttribute.GetLegalValues( typeof( WaveformType ) ); LogParseError( context, "Bad wave_xform attribute, valid waveform type values are {0}.", legalValues ); return false; } waveType = (WaveformType)val; // set the transform animation context.textureUnit.SetTransformAnimation( transType, waveType, StringConverter.ParseFloat( values[ 2 ] ), StringConverter.ParseFloat( values[ 3 ] ), StringConverter.ParseFloat( values[ 4 ] ), StringConverter.ParseFloat( values[ 5 ] ) ); return false; }
protected static bool ParseTechnique( string parameters, MaterialScriptContext context ) { // create a new technique context.technique = context.material.CreateTechnique(); // update section context.section = MaterialScriptSection.Technique; // increate technique level depth context.techLev++; // get the technique name string[] values = parameters.Split( new char[] { ' ', '\t' } ); if ( values.Length > 0 && values[ 0 ].Length > 0 ) context.technique.Name = values[ 0 ]; // return true because this must be followed by a { return true; }
protected static bool ParseDefaultParams( string parameters, MaterialScriptContext context ) { context.section = MaterialScriptSection.DefaultParameters; // should be a brace next return true; }
protected static bool ParsePass( string parameters, MaterialScriptContext context ) { // get the pass name string[] values = parameters.Split( new char[] { ' ', '\t' } ); // if params is not empty then see if the pass name already exists if ( values.Length > 0 && values[ 0 ].Length > 0 && context.technique.PassCount > 0 ) { // find the pass with name = params Pass foundPass = context.technique.GetPass( values[ 0 ] ); if ( foundPass != null ) context.passLev = foundPass.Index; else // name was not found so a new pass is needed // position pass level to the end index // a new pass will be created later on context.passLev = context.technique.PassCount; } else { // increase the pass level depth; context.passLev++; } if ( context.technique.PassCount > context.passLev ) { context.pass = context.technique.GetPass( context.passLev ); } else { // create a new pass context.pass = context.technique.CreatePass(); if ( values.Length > 0 && values[ 0 ].Length > 0 ) context.pass.Name = values[ 0 ]; } // update section context.section = MaterialScriptSection.Pass; // return true because this must be followed by a { return true; }
/// <summary> /// /// </summary> /// <param name="index"></param> /// <param name="commandName"></param> /// <param name="parameters"></param> /// <param name="context"></param> protected static void ProcessManualProgramParam( int index, string commandName, string[] parameters, MaterialScriptContext context ) { // NB we assume that the first element of vecparams is taken up with either // the index or the parameter name, which we ignore int dims, roundedDims; bool isFloat = false; string type = parameters[ 1 ].ToLower(); if ( type == "matrix4x4" ) { dims = 16; isFloat = true; } else if ( type.IndexOf( "float" ) != -1 ) { if ( type == "float" ) { dims = 1; } else { // the first 5 letters are "float", get the dim indicator at the end // this handles entries like 'float4' dims = int.Parse( type.Substring( 5 ) ); } isFloat = true; } else if ( type.IndexOf( "int" ) != -1 ) { if ( type == "int" ) { dims = 1; } else { // the first 5 letters are "int", get the dim indicator at the end dims = int.Parse( type.Substring( 3 ) ); } } else { LogParseError( context, "Invalid {0} attribute - unrecognized parameter type {1}.", commandName, type ); return; } // make sure we have enough params for this type's size if ( parameters.Length != 2 + dims ) { LogParseError( context, "Invalid {0} attribute - you need {1} parameters for a parameter of type {2}", commandName, 2 + dims, type ); return; } // Round dims to multiple of 4 if ( dims % 4 != 0 ) { roundedDims = dims + 4 - ( dims % 4 ); } else { roundedDims = dims; } int i = 0; // now parse all the values if ( isFloat ) { float[] buffer = new float[ roundedDims ]; // do specified values for ( i = 0; i < dims; i++ ) { buffer[ i ] = StringConverter.ParseFloat( parameters[ i + 2 ] ); } // fill up to multiple of 4 with zero for ( ; i < roundedDims; i++ ) { buffer[ i ] = 0.0f; } context.programParams.SetConstant( index, buffer ); } else { int[] buffer = new int[ roundedDims ]; // do specified values for ( i = 0; i < dims; i++ ) { buffer[ i ] = int.Parse( parameters[ i + 2 ] ); } // fill up to multiple of 4 with zero for ( ; i < roundedDims; i++ ) { buffer[ i ] = 0; } context.programParams.SetConstant( index, buffer ); } }
protected static bool ParseTextureAlias( string parameters, MaterialScriptContext context ) { Debug.Assert( context.textureUnit != null ); // get the texture alias string[] values = parameters.Split( new char[] { ' ', '\t' } ); if ( values.Length != 1 ) { LogParseError( context, "Invalid texture_alias entry - expected 1 parameter." ); return true; } // update section context.textureUnit.TextureNameAlias = values[ 0 ]; return false; }
/// <summary> /// /// </summary> /// <param name="index"></param> /// <param name="commandName"></param> /// <param name="parameters"></param> /// <param name="context"></param> protected static void ProcessAutoProgramParam( int index, string commandName, string[] parameters, MaterialScriptContext context ) { bool extras = false; object val = ScriptEnumAttribute.Lookup( parameters[ 1 ], typeof( GpuProgramParameters.AutoConstantType ) ); if ( val != null ) { bool isFloat = false; GpuProgramParameters.AutoConstantType constantType = (GpuProgramParameters.AutoConstantType)val; // these types require extra data if ( constantType == GpuProgramParameters.AutoConstantType.LightDiffuseColor || constantType == GpuProgramParameters.AutoConstantType.LightSpecularColor || constantType == GpuProgramParameters.AutoConstantType.LightAttenuation || constantType == GpuProgramParameters.AutoConstantType.LightPosition || constantType == GpuProgramParameters.AutoConstantType.LightDirection || constantType == GpuProgramParameters.AutoConstantType.LightPositionObjectSpace || constantType == GpuProgramParameters.AutoConstantType.LightDirectionObjectSpace || constantType == GpuProgramParameters.AutoConstantType.Custom ) { extras = true; isFloat = false; } else if ( constantType == GpuProgramParameters.AutoConstantType.Time_0_X || constantType == GpuProgramParameters.AutoConstantType.SinTime_0_X ) { extras = true; isFloat = true; } // do we require extra data for this parameter? if ( extras ) { if ( parameters.Length != 3 ) { LogParseError( context, "Invalid {0} attribute - Expected 3 parameters.", commandName ); return; } } if ( isFloat && extras ) context.programParams.SetAutoConstant( index, constantType, float.Parse( parameters[ 2 ] ) ); else if ( extras ) context.programParams.SetAutoConstant( index, constantType, int.Parse( parameters[ 2 ] ) ); else if ( constantType == GpuProgramParameters.AutoConstantType.Time ) { if ( parameters.Length == 3 ) context.programParams.SetAutoConstant( index, constantType, float.Parse( parameters[ 2 ] ) ); else context.programParams.SetAutoConstant( index, constantType, 1.0f ); } else context.programParams.SetAutoConstant( index, constantType, 0 ); } else { string legalValues = ScriptEnumAttribute.GetLegalValues( typeof( GpuProgramParameters.AutoConstantType ) ); LogParseError( context, "Bad auto gpu program param - Invalid param type '{0}', valid values are {1}.", parameters[ 1 ], legalValues ); return; } }
protected static bool ParseLodStrategy( string parameters, MaterialScriptContext context ) { LodStrategy lodStrategy = LodStrategyManager.Instance.GetStrategy( parameters ); if ( lodStrategy == null ) { LogParseError( context, "Bad lod_strategy attribute, , available lod strategy name expected." ); } context.material.LodStrategy = lodStrategy; return false; }
/// <summary> /// Helper method for logging parser errors. /// </summary> /// <param name="context">Current parsing context.</param> /// <param name="error">Error message.</param> /// <param name="substitutions">Items to sub in for the error message, if the error contains them.</param> protected static void LogParseError( MaterialScriptContext context, string error, params object[] substitutions ) { StringBuilder errorBuilder = new StringBuilder(); // log material name only if filename not specified if ( context.filename == null && context.material != null ) { errorBuilder.Append( "Error in material " ); errorBuilder.Append( context.material.Name ); errorBuilder.Append( " : " ); errorBuilder.AppendFormat( error, substitutions ); } else { if ( context.material != null ) { errorBuilder.Append( "Error in material " ); errorBuilder.Append( context.material.Name ); errorBuilder.AppendFormat( " at line {0} ", context.lineNo ); errorBuilder.AppendFormat( " of {0}: ", context.filename ); errorBuilder.AppendFormat( error, substitutions ); } else { errorBuilder.AppendFormat( "Error at line {0} ", context.lineNo ); errorBuilder.AppendFormat( " of {0}: ", context.filename ); errorBuilder.AppendFormat( error, substitutions ); } } LogManager.Instance.Write( errorBuilder.ToString() ); }
protected static bool ParseTransparencyCastsShadows( string parameters, MaterialScriptContext context ) { if ( parameters != "on" && parameters != "off" ) { LogParseError( context, "Bad transparency_casts_shadows attribute, valid parameters are 'on' or 'off'." ); } context.material.TransparencyCastsShadows = StringConverter.ParseBool( parameters ); return false; }
/// <summary> /// Parse custom GPU program parameters. /// </summary> /// <remarks> /// This one is called explicitly, and is not added to any parser list. /// </remarks> protected static bool ParseProgramCustomParameter( string parameters, MaterialScriptContext context ) { // This params object does not have the command stripped // Lower case the command, but not the value incase it's relevant // Split only up to first delimiter, program deals with the rest string[] values = StringConverter.Split( parameters, new char[] { ' ', '\t' }, 2 ); if ( values.Length != 2 ) { LogParseError( context, "Invalid custom program parameter entry; there must be a parameter name and at least one value." ); return false; } context.programDef.customParameters.Add( new KeyValuePair<string, string>( values[ 0 ], values[ 1 ] ) ); return false; }
protected static bool ParseScheme( string parameters, MaterialScriptContext context ) { context.technique.SchemeName = parameters; return false; }
protected static bool ParseMaterial( string parameters, MaterialScriptContext context ) { // check params for reference to parent material to copy from // syntax: material name : parentMaterialName // check params for a colon after the first name and extract the parent name string[] values = parameters.Split( new char[] { ':' } ); Material basematerial = null; // create a brand new material if ( values.Length >= 2 ) { // if a second parameter exists then assume its the name of the base material // that this new material should clone from values[ 1 ] = values[ 1 ].Trim(); // make sure base material exists basematerial = (Material)MaterialManager.Instance.GetByName( values[ 1 ] ); // if it doesn't exist then report error in log and just create a new material if ( basematerial == null ) { LogParseError( context, "parent material:" + values[ 1 ] + " not found for new material:" + values[ 0 ] ); } } string materialName = values[ 0 ].Trim(); context.material = (Material)MaterialManager.Instance.Create( materialName, context.groupName ); if ( basematerial != null ) { // copy parent material details to new material basematerial.CopyTo( context.material, false ); } else { // remove pre-created technique from defaults context.material.RemoveAllTechniques(); } context.material.Origin = context.filename; // update section context.section = MaterialScriptSection.Material; // return true because this must be followed by a { return true; }
protected static bool ParseColorWrite( string parameters, MaterialScriptContext context ) { switch ( parameters.ToLower() ) { case "on": context.pass.ColorWriteEnabled = true; break; case "off": context.pass.ColorWriteEnabled = false; break; default: LogParseError( context, "Bad color_write attribute, valid parameters are 'on' or 'off'." ); break; } return false; }
protected static bool ParseFragmentProgram( string parameters, MaterialScriptContext context ) { // update section context.section = MaterialScriptSection.Program; // create new program definition-in-progress context.programDef = new MaterialScriptProgramDefinition(); context.programDef.progType = GpuProgramType.Fragment; context.programDef.supportsSkeletalAnimation = false; context.programDef.supportsMorphAnimation = false; context.programDef.poseAnimationCount = 0; // get name and language code string[] values = parameters.Split( new char[] { ' ', '\t' } ); if ( values.Length != 2 ) { LogParseError( context, "Invalid fragment_program entry - expected 2 parameters." ); return true; } // name, preserve case context.programDef.name = values[ 0 ]; // language code, make lower case context.programDef.language = values[ 1 ].ToLower(); // return true, because this must be followed by a { return true; }
protected static bool ParseDepthBias( string parameters, MaterialScriptContext context ) { string[] values = parameters.Split( new char[] { ' ', '\t' } ); float constantBias = float.Parse( values[ 0 ] ); float slopeScaleBias = 0.0f; if ( values.Length > 1 ) { slopeScaleBias = float.Parse( values[ 1 ] ); } context.pass.SetDepthBias( constantBias, slopeScaleBias ); return false; }
protected static bool ParseTexture( string parameters, MaterialScriptContext context ) { string[] values = parameters.Split( new char[] { ' ', '\t' } ); if ( values.Length > 5 ) { LogParseError( context, "Invalid texture attribute - expecting 5 parameters or less." ); return false; } // use 2d as default if anything goes wrong TextureType texType = TextureType.TwoD; int mipmaps = (int)TextureMipmap.Default; // When passed to TextureManager::load, this means default to default number of mipmaps bool isAlpha = false; bool hwGamma = false; PixelFormat desiredFormat = PixelFormat.Unknown; for ( int p = 1; p < values.Length; p++ ) { switch ( values[ p ].ToLower() ) { case "1d": texType = TextureType.OneD; break; case "2d": texType = TextureType.TwoD; break; case "3d": texType = TextureType.ThreeD; break; case "cubic": texType = TextureType.CubeMap; break; case "unlimited": mipmaps = (int)TextureMipmap.Unlimited; break; case "alpha": isAlpha = true; break; case "gamma": hwGamma = true; break; default: int num; if ( StringConverter.ParseInt( values[ p ], out num ) ) { mipmaps = num; } else if ( ( desiredFormat = PixelUtil.GetFormatFromName( values[ p ], true, false ) ) != PixelFormat.Unknown ) { // Nothing to do here. } else { LogParseError( context, "Invalid texture option - " + values[ p ] + "." ); } break; } } context.textureUnit.SetTextureName( values[ 0 ], texType ); context.textureUnit.MipmapCount = mipmaps; context.textureUnit.IsAlpha = isAlpha; context.textureUnit.DesiredFormat = desiredFormat; context.textureUnit.IsHardwareGammaEnabled = hwGamma; return false; }