public static void TranslateProgramParameters( ScriptCompiler compiler, GpuProgramParameters parameters, ObjectAbstractNode obj ) { var animParametricsCount = 0; foreach ( var i in obj.Children ) { if ( !( i is PropertyAbstractNode ) ) { continue; } var prop = (PropertyAbstractNode)i; switch ( (Keywords)prop.Id ) { #region ID_SHARED_PARAMS_REF case Keywords.ID_SHARED_PARAMS_REF: { if ( prop.Values.Count != 1 ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "shared_params_ref requires a single parameter" ); continue; } var i0 = getNodeAt( prop.Values, 0 ); if ( !( i0 is AtomAbstractNode ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "shared parameter set name expected" ); continue; } var atom0 = (AtomAbstractNode)i0; try { parameters.AddSharedParameters( atom0.Value ); } catch ( AxiomException e ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, e.Message ); } } break; #endregion ID_SHARED_PARAMS_REF #region ID_PARAM_INDEXED || ID_PARAM_NAMED case Keywords.ID_PARAM_INDEXED: case Keywords.ID_PARAM_NAMED: { if ( prop.Values.Count >= 3 ) { var named = ( prop.Id == (uint)Keywords.ID_PARAM_NAMED ); var i0 = getNodeAt( prop.Values, 0 ); var i1 = getNodeAt( prop.Values, 1 ); var k = getNodeAt( prop.Values, 2 ); if ( !( i0 is AtomAbstractNode ) || !( i1 is AtomAbstractNode ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "name or index and parameter type expected" ); return; } var atom0 = (AtomAbstractNode)i0; var atom1 = (AtomAbstractNode)i1; if ( !named && !atom0.IsNumber ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "parameter index expected" ); return; } var name = string.Empty; var index = 0; // Assign the name/index if ( named ) { name = atom0.Value; } else { index = (int)atom0.Number; } // Determine the type if ( atom1.Value == "matrix4x4" ) { Matrix4 m; if ( getMatrix4( prop.Values, 2, out m ) ) { try { if ( named ) { parameters.SetNamedConstant( name, m ); } else { parameters.SetConstant( index, m ); } } catch { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "setting matrix4x4 parameter failed" ); } } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "incorrect matrix4x4 declaration" ); } } else { // Find the number of parameters var isValid = true; var type = GpuProgramParameters.ElementType.Real; var count = 0; if ( atom1.Value.Contains( "float" ) ) { type = GpuProgramParameters.ElementType.Real; if ( atom1.Value.Length >= 6 ) { count = int.Parse( atom1.Value.Substring( 5 ) ); } else { count = 1; } } else if ( atom1.Value.Contains( "int" ) ) { type = GpuProgramParameters.ElementType.Int; if ( atom1.Value.Length >= 4 ) { count = int.Parse( atom1.Value.Substring( 3 ) ); } else { count = 1; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "incorrect type specified; only variants of int and float allowed" ); isValid = false; } if ( isValid ) { // First, clear out any offending auto constants if ( named ) { parameters.ClearNamedAutoConstant( name ); } else { parameters.ClearAutoConstant( index ); } var roundedCount = count%4 != 0 ? count + 4 - ( count%4 ) : count; if ( type == GpuProgramParameters.ElementType.Int ) { var vals = new int[roundedCount]; if ( getInts( prop.Values, 2, out vals, roundedCount ) ) { try { if ( named ) { parameters.SetNamedConstant( name, vals, count, 1 ); } else { parameters.SetConstant( index, vals, roundedCount/4 ); } } catch { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "setting of constant failed" ); } } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "incorrect integer constant declaration" ); } } else { var vals = new float[roundedCount]; if ( getFloats( prop.Values, 2, out vals, roundedCount ) ) { try { if ( named ) { parameters.SetNamedConstant( name, vals, count, 1 ); } else { parameters.SetConstant( index, vals, roundedCount/4 ); } } catch { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "setting of constant failed" ); } } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "incorrect float constant declaration" ); } } } } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "param_named and param_indexed properties requires at least 3 arguments" ); } } break; #endregion ID_PARAM_INDEXED || ID_PARAM_NAMED #region ID_PARAM_INDEXED_AUTO || ID_PARAM_NAMED_AUTO case Keywords.ID_PARAM_INDEXED_AUTO: case Keywords.ID_PARAM_NAMED_AUTO: { var named = ( prop.Id == (uint)Keywords.ID_PARAM_NAMED_AUTO ); var name = string.Empty; var index = 0; if ( prop.Values.Count >= 2 ) { var i0 = getNodeAt( prop.Values, 0 ); var i1 = getNodeAt( prop.Values, 1 ); var i2 = getNodeAt( prop.Values, 2 ); var i3 = getNodeAt( prop.Values, 3 ); if ( !( i0 is AtomAbstractNode ) || !( i1 is AtomAbstractNode ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "name or index and auto constant type expected" ); return; } var atom0 = (AtomAbstractNode)i0; var atom1 = (AtomAbstractNode)i1; if ( !named && !atom0.IsNumber ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "parameter index expected" ); return; } if ( named ) { name = atom0.Value; } else { index = int.Parse( atom0.Value ); } // Look up the auto constant atom1.Value = atom1.Value.ToLower(); GpuProgramParameters.AutoConstantDefinition def; var defFound = GpuProgramParameters.GetAutoConstantDefinition( atom1.Value, out def ); if ( defFound ) { switch ( def.DataType ) { #region None case GpuProgramParameters.AutoConstantDataType.None: // Set the auto constant try { if ( named ) { parameters.SetNamedAutoConstant( name, def.AutoConstantType ); } else { parameters.SetAutoConstant( index, def.AutoConstantType ); } } catch { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "setting of constant failed" ); } break; #endregion None #region Int case GpuProgramParameters.AutoConstantDataType.Int: if ( def.AutoConstantType == GpuProgramParameters.AutoConstantType.AnimationParametric ) { try { if ( named ) { parameters.SetNamedAutoConstant( name, def.AutoConstantType, animParametricsCount++ ); } else { parameters.SetAutoConstant( index, def.AutoConstantType, animParametricsCount++ ); } } catch { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "setting of constant failed" ); } } else { // Only certain texture projection auto params will assume 0 // Otherwise we will expect that 3rd parameter if ( i2 == null ) { if ( def.AutoConstantType == GpuProgramParameters.AutoConstantType.TextureViewProjMatrix || def.AutoConstantType == GpuProgramParameters.AutoConstantType.TextureWorldViewProjMatrix || def.AutoConstantType == GpuProgramParameters.AutoConstantType.SpotLightViewProjMatrix || def.AutoConstantType == GpuProgramParameters.AutoConstantType.SpotLightWorldViewProjMatrix ) { try { if ( named ) { parameters.SetNamedAutoConstant( name, def.AutoConstantType, 0 ); } else { parameters.SetAutoConstant( index, def.AutoConstantType, 0 ); } } catch { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "setting of constant failed" ); } } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "extra parameters required by constant definition " + atom1.Value ); } } else { var success = false; var extraInfo = 0; if ( i3 == null ) { // Handle only one extra value if ( getInt( i2, out extraInfo ) ) { success = true; } } else { // Handle two extra values var extraInfo1 = 0; var extraInfo2 = 0; if ( getInt( i2, out extraInfo1 ) && getInt( i3, out extraInfo2 ) ) { extraInfo = extraInfo1 | ( extraInfo2 << 16 ); success = true; } } if ( success ) { try { if ( named ) { parameters.SetNamedAutoConstant( name, def.AutoConstantType, extraInfo ); } else { parameters.SetAutoConstant( index, def.AutoConstantType, extraInfo ); } } catch { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "setting of constant failed" ); } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "invalid auto constant extra info parameter" ); } } } break; #endregion Int #region Real case GpuProgramParameters.AutoConstantDataType.Real: if ( def.AutoConstantType == GpuProgramParameters.AutoConstantType.Time || def.AutoConstantType == GpuProgramParameters.AutoConstantType.FrameTime ) { Real f = 1.0f; if ( i2 != null ) { getReal( i2, out f ); } try { if ( named ) { parameters.SetNamedAutoConstantReal( name, def.AutoConstantType, f ); } else { parameters.SetAutoConstantReal( index, def.AutoConstantType, f ); } } catch { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "setting of constant failed" ); } } else { if ( i2 != null ) { Real extraInfo = 0.0f; if ( getReal( i2, out extraInfo ) ) { try { if ( named ) { parameters.SetNamedAutoConstantReal( name, def.AutoConstantType, extraInfo ); } else { parameters.SetAutoConstantReal( index, def.AutoConstantType, extraInfo ); } } catch { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "setting of constant failed" ); } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "incorrect float argument definition in extra parameters" ); } } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "extra parameters required by constant definition " + atom1.Value ); } } break; #endregion Real } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_PARAM_INDEXED_AUTO || ID_PARAM_NAMED_AUTO default: compiler.AddError( CompileErrorCode.UnexpectedToken, prop.File, prop.Line, "token \"" + prop.Name + "\" is not recognized" ); break; } } }