/// <summary> /// Internal constructor. This class cannot be instantiated externally. /// </summary> /// <remarks> /// Protected internal because this singleton will actually hold the instance of a subclass /// created by a render system plugin. /// </remarks> protected internal CompositorManager() { if (instance == null) { instance = this; } rectangle = null; }
public static void ParseScript( CompositorManager compositorManager, Stream data, string groupName, string fileName ) { string file = ( (FileStream)data ).Name; string line = ""; CompositorScriptContext context = new CompositorScriptContext(); context.filename = file; context.lineNo = 0; StreamReader script = new StreamReader( data, System.Text.Encoding.UTF8 ); // parse through the data to the end while ( ( line = ParseHelper.ReadLine( script ) ) != null ) { context.lineNo++; string[] splitCmd; string[] args; string arg; // ignore blank lines and comments if ( !( line.Length == 0 || line.StartsWith( "//" ) ) ) { context.line = line; splitCmd = SplitByWhitespace( line, 2 ); string token = splitCmd[ 0 ]; args = SplitArgs( splitCmd.Length == 2 ? splitCmd[ 1 ] : "" ); arg = ( args.Length > 0 ? args[ 0 ] : "" ); if ( context.section == CompositorScriptSection.None ) { if ( token != "compositor" ) { LogError( context, "First token is not 'compositor'!" ); break; // Give up } string compositorName = RemoveQuotes( splitCmd[ 1 ].Trim() ); context.compositor = (Compositor)compositorManager.Create( compositorName, groupName ); context.section = CompositorScriptSection.Compositor; context.seenOpen = false; continue; // next line } else { if ( !context.seenOpen ) { if ( token == "{" ) context.seenOpen = true; else LogError( context, "Expected open brace; instead got {0}", token ); continue; // next line } switch ( context.section ) { case CompositorScriptSection.Compositor: switch ( token ) { case "technique": context.section = CompositorScriptSection.Technique; context.technique = context.compositor.CreateTechnique(); context.seenOpen = false; continue; // next line case "}": context.section = CompositorScriptSection.None; context.seenOpen = false; if ( context.technique == null ) { LogError( context, "No 'technique' section in compositor" ); continue; } break; default: LogError( context, "After opening brace '{' of compositor definition, expected 'technique', but got '{0}'", token ); continue; // next line } break; case CompositorScriptSection.Technique: switch ( token ) { case "texture": ParseTextureLine( context, args ); break; case "target": context.section = CompositorScriptSection.Target; context.target = context.technique.CreateTargetPass(); context.target.OutputName = arg.Trim(); context.seenOpen = false; break; case "target_output": context.section = CompositorScriptSection.Target; context.target = context.technique.OutputTarget; context.seenOpen = false; break; case "compositor_logic": if ( !OptionCount( context, token, 1, args.Length ) ) break; context.technique.CompositorLogicName = args[ 0 ].Trim(); break; case "}": context.section = CompositorScriptSection.Compositor; context.seenOpen = true; break; default: LogIllegal( context, "technique", token ); break; } break; case CompositorScriptSection.Target: switch ( token ) { case "input": if ( OptionCount( context, token, 1, args.Length ) ) { arg = args[ 0 ]; if ( arg == "previous" ) context.target.InputMode = CompositorInputMode.Previous; else if ( arg == "none" ) context.target.InputMode = CompositorInputMode.None; else LogError( context, "Illegal 'input' arg '{0}'", arg ); } break; case "only_initial": context.target.OnlyInitial = OnOffArg( context, token, args ); break; case "visibility_mask": if ( !OptionCount( context, token, 1, args.Length ) ) break; context.target.VisibilityMask = ParseUint( context, arg ); break; case "lod_bias": if ( !OptionCount( context, token, 1, args.Length ) ) break; context.target.LodBias = ParseInt( context, arg ); break; case "material_scheme": if ( !OptionCount( context, token, 1, args.Length ) ) break; context.target.MaterialScheme = arg.Trim(); break; case "pass": context.section = CompositorScriptSection.Pass; context.pass = context.target.CreatePass(); context.seenOpen = false; if ( !OptionCount( context, token, 1, args.Length ) && !OptionCount( context, token, 2, args.Length ) ) break; arg = args[ 0 ].Trim(); switch ( arg ) { case "render_quad": context.pass.Type = CompositorPassType.RenderQuad; break; case "clear": context.pass.Type = CompositorPassType.Clear; break; case "stencil": context.pass.Type = CompositorPassType.Stencil; break; case "render_scene": context.pass.Type = CompositorPassType.RenderScene; break; case "render_custom": context.pass.Type = CompositorPassType.RenderCustom; context.pass.CustomType = args[ 1 ].Trim(); break; default: LogError( context, "In line '{0}', unrecognized compositor pass type '{1}'", arg ); break; } break; case "}": context.section = CompositorScriptSection.Technique; context.seenOpen = true; break; default: LogIllegal( context, "target", token ); break; } break; case CompositorScriptSection.Pass: switch ( token ) { case "first_render_queue": if ( !OptionCount( context, token, 1, args.Length ) ) break; context.pass.FirstRenderQueue = (RenderQueueGroupID)ParseInt( context, args[ 0 ] ); break; case "last_render_queue": if ( !OptionCount( context, token, 1, args.Length ) ) break; context.pass.LastRenderQueue = (RenderQueueGroupID)ParseInt( context, args[ 0 ] ); break; case "identifier": if ( !OptionCount( context, token, 1, args.Length ) ) break; context.pass.Identifier = ParseUint( context, args[ 0 ] ); break; case "material": if ( !OptionCount( context, token, 1, args.Length ) ) break; context.pass.MaterialName = args[ 0 ].Trim(); break; case "input": if ( !OptionCount( context, token, 3, args.Length ) ) break; int index = 0; if ( args.Length == 3 ) index = ParseInt( context, args[ 2 ] ); context.pass.SetInput( ParseInt( context, args[ 0 ] ), args[ 1 ].Trim(), index ); break; case "clear": context.section = CompositorScriptSection.Clear; context.seenOpen = false; break; case "stencil": context.section = CompositorScriptSection.Clear; context.seenOpen = false; break; case "}": context.section = CompositorScriptSection.Target; context.seenOpen = true; break; default: LogIllegal( context, "pass", token ); break; } break; case CompositorScriptSection.Clear: switch ( token ) { case "buffers": FrameBufferType fb = (FrameBufferType)0; foreach ( string cb in args ) { switch ( cb ) { case "colour": fb |= FrameBufferType.Color; break; case "color": fb |= FrameBufferType.Color; break; case "depth": fb |= FrameBufferType.Depth; break; case "stencil": fb |= FrameBufferType.Stencil; break; default: LogError( context, "When parsing pass clear buffers options, illegal option '{0}'", cb ); break; } } break; case "colour": context.pass.ClearColor = ParseClearColor( context, args ); break; case "color": context.pass.ClearColor = ParseClearColor( context, args ); break; case "depth_value": if ( !OptionCount( context, token, 1, args.Length ) ) break; context.pass.ClearDepth = ParseFloat( context, args[ 0 ] ); break; case "stencil_value": if ( !OptionCount( context, token, 1, args.Length ) ) break; context.pass.ClearDepth = ParseInt( context, args[ 0 ] ); break; case "}": context.section = CompositorScriptSection.Pass; context.seenOpen = true; break; default: LogIllegal( context, "clear", token ); break; } break; case CompositorScriptSection.Stencil: switch ( token ) { case "check": context.pass.StencilCheck = OnOffArg( context, token, args ); break; case "compare_func": if ( !OptionCount( context, token, 1, args.Length ) ) break; context.pass.StencilFunc = ParseCompareFunc( context, arg ); break; case "ref_value": if ( !OptionCount( context, token, 1, args.Length ) ) break; context.pass.StencilRefValue = ParseInt( context, arg ); break; case "mask": if ( !OptionCount( context, token, 1, args.Length ) ) break; context.pass.StencilMask = ParseInt( context, arg ); break; case "fail_op": if ( !OptionCount( context, token, 1, args.Length ) ) break; context.pass.StencilFailOp = ParseStencilOperation( context, arg ); break; case "depth_fail_op": if ( !OptionCount( context, token, 1, args.Length ) ) break; context.pass.StencilDepthFailOp = ParseStencilOperation( context, arg ); break; case "pass_op": if ( !OptionCount( context, token, 1, args.Length ) ) break; context.pass.StencilPassOp = ParseStencilOperation( context, arg ); break; case "two_sided": if ( !OptionCount( context, token, 1, args.Length ) ) break; context.pass.StencilTwoSidedOperation = OnOffArg( context, token, args ); break; case "}": context.section = CompositorScriptSection.Pass; context.seenOpen = true; break; default: LogIllegal( context, "stencil", token ); break; } break; default: LogError( context, "Internal compositor parser error: illegal context" ); break; } } // if } // if } // while if ( context.section != CompositorScriptSection.None ) LogError( context, "At end of file, unterminated compositor script!" ); }
public static void ParseScript(CompositorManager compositorManager, Stream data, string groupName, string fileName) { var line = ""; var context = new CompositorScriptContext(); context.filename = fileName + (data is FileStream ? " (" + (data as FileStream).Name + ")" : ""); context.lineNo = 0; var script = new StreamReader(data, System.Text.Encoding.UTF8); // parse through the data to the end while ((line = ParseHelper.ReadLine(script)) != null) { context.lineNo++; string[] splitCmd; string[] args; string arg; // ignore blank lines and comments if (!(line.Length == 0 || line.StartsWith("//"))) { context.line = line; splitCmd = SplitByWhitespace(line, 2); var token = splitCmd[0]; args = SplitArgs(splitCmd.Length == 2 ? splitCmd[1] : ""); arg = (args.Length > 0 ? args[0] : ""); if (context.section == CompositorScriptSection.None) { if (token != "compositor") { LogError(context, "First token is not 'compositor'!"); break; // Give up } var compositorName = RemoveQuotes(splitCmd[1].Trim()); context.compositor = (Compositor)compositorManager.Create(compositorName, groupName); context.section = CompositorScriptSection.Compositor; context.seenOpen = false; continue; // next line } else { if (!context.seenOpen) { if (token == "{") { context.seenOpen = true; } else { LogError(context, "Expected open brace; instead got {0}", token); } continue; // next line } switch (context.section) { case CompositorScriptSection.Compositor: switch (token) { case "technique": context.section = CompositorScriptSection.Technique; context.technique = context.compositor.CreateTechnique(); context.seenOpen = false; continue; // next line case "}": context.section = CompositorScriptSection.None; context.seenOpen = false; if (context.technique == null) { LogError(context, "No 'technique' section in compositor"); continue; } break; default: LogError(context, "After opening brace '{' of compositor definition, expected 'technique', but got '{0}'", token); continue; // next line } break; case CompositorScriptSection.Technique: switch (token) { case "texture": ParseTextureLine(context, args); break; case "target": context.section = CompositorScriptSection.Target; context.target = context.technique.CreateTargetPass(); context.target.OutputName = arg.Trim(); context.seenOpen = false; break; case "target_output": context.section = CompositorScriptSection.Target; context.target = context.technique.OutputTarget; context.seenOpen = false; break; case "compositor_logic": if (!OptionCount(context, token, 1, args.Length)) { break; } context.technique.CompositorLogicName = args[0].Trim(); break; case "}": context.section = CompositorScriptSection.Compositor; context.seenOpen = true; break; default: LogIllegal(context, "technique", token); break; } break; case CompositorScriptSection.Target: switch (token) { case "input": if (OptionCount(context, token, 1, args.Length)) { arg = args[0]; if (arg == "previous") { context.target.InputMode = CompositorInputMode.Previous; } else if (arg == "none") { context.target.InputMode = CompositorInputMode.None; } else { LogError(context, "Illegal 'input' arg '{0}'", arg); } } break; case "only_initial": context.target.OnlyInitial = OnOffArg(context, token, args); break; case "visibility_mask": if (!OptionCount(context, token, 1, args.Length)) { break; } context.target.VisibilityMask = ParseUint(context, arg); break; case "lod_bias": if (!OptionCount(context, token, 1, args.Length)) { break; } context.target.LodBias = ParseInt(context, arg); break; case "material_scheme": if (!OptionCount(context, token, 1, args.Length)) { break; } context.target.MaterialScheme = arg.Trim(); break; case "pass": context.section = CompositorScriptSection.Pass; context.pass = context.target.CreatePass(); context.seenOpen = false; if (!OptionCount(context, token, 1, args.Length) && !OptionCount(context, token, 2, args.Length)) { break; } arg = args[0].Trim(); switch (arg) { case "render_quad": context.pass.Type = CompositorPassType.RenderQuad; break; case "clear": context.pass.Type = CompositorPassType.Clear; break; case "stencil": context.pass.Type = CompositorPassType.Stencil; break; case "render_scene": context.pass.Type = CompositorPassType.RenderScene; break; case "render_custom": context.pass.Type = CompositorPassType.RenderCustom; context.pass.CustomType = args[1].Trim(); break; default: LogError(context, "In line '{0}', unrecognized compositor pass type '{1}'", arg); break; } break; case "}": context.section = CompositorScriptSection.Technique; context.seenOpen = true; break; default: LogIllegal(context, "target", token); break; } break; case CompositorScriptSection.Pass: switch (token) { case "first_render_queue": if (!OptionCount(context, token, 1, args.Length)) { break; } context.pass.FirstRenderQueue = (RenderQueueGroupID)ParseInt(context, args[0]); break; case "last_render_queue": if (!OptionCount(context, token, 1, args.Length)) { break; } context.pass.LastRenderQueue = (RenderQueueGroupID)ParseInt(context, args[0]); break; case "identifier": if (!OptionCount(context, token, 1, args.Length)) { break; } context.pass.Identifier = ParseUint(context, args[0]); break; case "material": if (!OptionCount(context, token, 1, args.Length)) { break; } context.pass.MaterialName = args[0].Trim(); break; case "input": if (!OptionCount(context, token, 3, args.Length)) { break; } var index = 0; if (args.Length == 3) { index = ParseInt(context, args[2]); } context.pass.SetInput(ParseInt(context, args[0]), args[1].Trim(), index); break; case "clear": context.section = CompositorScriptSection.Clear; context.seenOpen = false; break; case "stencil": context.section = CompositorScriptSection.Clear; context.seenOpen = false; break; case "}": context.section = CompositorScriptSection.Target; context.seenOpen = true; break; default: LogIllegal(context, "pass", token); break; } break; case CompositorScriptSection.Clear: switch (token) { case "buffers": var fb = (FrameBufferType)0; foreach (var cb in args) { switch (cb) { case "colour": fb |= FrameBufferType.Color; break; case "color": fb |= FrameBufferType.Color; break; case "depth": fb |= FrameBufferType.Depth; break; case "stencil": fb |= FrameBufferType.Stencil; break; default: LogError(context, "When parsing pass clear buffers options, illegal option '{0}'", cb); break; } } break; case "colour": context.pass.ClearColor = ParseClearColor(context, args); break; case "color": context.pass.ClearColor = ParseClearColor(context, args); break; case "depth_value": if (!OptionCount(context, token, 1, args.Length)) { break; } context.pass.ClearDepth = ParseFloat(context, args[0]); break; case "stencil_value": if (!OptionCount(context, token, 1, args.Length)) { break; } context.pass.ClearDepth = ParseInt(context, args[0]); break; case "}": context.section = CompositorScriptSection.Pass; context.seenOpen = true; break; default: LogIllegal(context, "clear", token); break; } break; case CompositorScriptSection.Stencil: switch (token) { case "check": context.pass.StencilCheck = OnOffArg(context, token, args); break; case "compare_func": if (!OptionCount(context, token, 1, args.Length)) { break; } context.pass.StencilFunc = ParseCompareFunc(context, arg); break; case "ref_value": if (!OptionCount(context, token, 1, args.Length)) { break; } context.pass.StencilRefValue = ParseInt(context, arg); break; case "mask": if (!OptionCount(context, token, 1, args.Length)) { break; } context.pass.StencilMask = ParseInt(context, arg); break; case "fail_op": if (!OptionCount(context, token, 1, args.Length)) { break; } context.pass.StencilFailOp = ParseStencilOperation(context, arg); break; case "depth_fail_op": if (!OptionCount(context, token, 1, args.Length)) { break; } context.pass.StencilDepthFailOp = ParseStencilOperation(context, arg); break; case "pass_op": if (!OptionCount(context, token, 1, args.Length)) { break; } context.pass.StencilPassOp = ParseStencilOperation(context, arg); break; case "two_sided": if (!OptionCount(context, token, 1, args.Length)) { break; } context.pass.StencilTwoSidedOperation = OnOffArg(context, token, args); break; case "}": context.section = CompositorScriptSection.Pass; context.seenOpen = true; break; default: LogIllegal(context, "stencil", token); break; } break; default: LogError(context, "Internal compositor parser error: illegal context"); break; } } // if } // if } // while if (context.section != CompositorScriptSection.None) { LogError(context, "At end of file, unterminated compositor script!"); } }
/// <summary> /// Internal constructor. This class cannot be instantiated externally. /// </summary> /// <remarks> /// Protected internal because this singleton will actually hold the instance of a subclass /// created by a render system plugin. /// </remarks> protected internal CompositorManager() { if (instance == null) { instance = this; } rectangle = null; }