using Sandbox.Rendering; using Sandbox.Utility; namespace Sandbox; public sealed partial class CameraComponent : Component, Component.ExecuteInEditor { readonly record struct CommandListEntry( int Priority, CommandList List ); Dictionary> commandlists = new(); /// /// Add a command list to the render /// public void AddCommandList( CommandList buffer, Stage stage, int order = 0 ) { if ( !commandlists.TryGetValue( stage, out var list ) ) { list = new List(); commandlists[stage] = list; } list.Add( new CommandListEntry( order, buffer ) ); } /// /// Remove an entry /// public void RemoveCommandList( CommandList buffer, Stage stage ) { if ( !commandlists.TryGetValue( stage, out var list ) ) return; list.RemoveAll( x => x.List == buffer ); } /// /// Remove an entry /// public void RemoveCommandList( CommandList buffer ) { foreach ( var list in commandlists.Values ) { list.RemoveAll( x => x.List == buffer ); } } /// /// Remove all entries in this stage /// public void ClearCommandLists( Stage stage ) { commandlists.Remove( stage ); } /// /// Remove all entries in this stage /// public void ClearCommandLists() { commandlists.Clear(); } static Superluminal _executeCommandList = new Superluminal( "ExecuteCommandList", Color.Cyan ); /// /// Called during the render pipeline. Currently this is rendered on the main thread, but ideally, one day, this will all be threaded. /// private void ExecuteCommandLists( Stage stage, SceneCamera currentCamera ) { Scene.RunEvent( x => x.OnRenderStage( this, stage ) ); if ( commandlists.TryGetValue( stage, out var list ) ) { foreach ( var entry in list.OrderBy( x => x.Priority ) ) { using ( _executeCommandList.Start( entry.List.DebugName ) ) { if ( entry.List.Flags.Contains( CommandList.Flag.PostProcess ) && !currentCamera.EnablePostProcessing ) continue; entry.List.ExecuteOnRenderThread(); } } } } }