using Sandbox.Rendering;
using static Sandbox.SceneObject;
namespace Sandbox;
public abstract class Renderer : Component, SceneObjectCallbacks
{
RenderAttributes _attributes;
RenderOptions _renderOptions;
SceneObject _sceneObject;
[Property, MakeDirty, Order( -100 ), InlineEditor( Label = false ), Group( "Advanced Rendering", StartFolded = true )]
public RenderOptions RenderOptions
{
get
{
_renderOptions ??= new( OnRenderOptionsChanged );
return _renderOptions;
}
}
protected virtual void OnRenderOptionsChanged()
{
}
///
/// Copy everything from another renderer
///
public virtual void CopyFrom( Renderer other )
{
//RenderOptions = other.RenderOptions;
}
CommandList _before;
CommandList _after;
///
/// Attributes that are applied to the renderer based on the current material and shader.
/// If the renderer is disabled, the changes are deferred until it is enabled again.
/// Attributes are not saved to disk, and are not cloned when copying the renderer.
///
public RenderAttributes Attributes
{
get
{
if ( _sceneObject.IsValid() )
{
return _sceneObject.Attributes;
}
_attributes ??= new RenderAttributes();
return _attributes;
}
}
///
/// A command list which is executed immediately before rendering this
///
public CommandList ExecuteBefore
{
get => _before;
set
{
if ( _before == value ) return;
_before = value;
UpdateSceneObjectFlags();
}
}
///
/// A command list which is executed immediately after rendering this
///
public CommandList ExecuteAfter
{
get => _after;
set
{
if ( _after == value ) return;
_after = value;
UpdateSceneObjectFlags();
}
}
void SceneObjectCallbacks.OnBeforeObjectRender()
{
ExecuteBefore?.ExecuteOnRenderThread();
}
void SceneObjectCallbacks.OnAfterObjectRender()
{
ExecuteAfter?.ExecuteOnRenderThread();
}
void UpdateSceneObjectFlags()
{
if ( !_sceneObject.IsValid() ) return;
_sceneObject.Flags.WantsExecuteBefore = ExecuteBefore != null;
_sceneObject.Flags.WantsExecuteAfter = ExecuteAfter != null;
}
///
/// Backup the specified RenderAttributes so we can restore them later with
///
protected void BackupRenderAttributes( RenderAttributes attributes )
{
if ( attributes is null || !_sceneObject.IsValid() )
return;
_attributes ??= new RenderAttributes();
attributes.MergeTo( _attributes );
}
///
/// Restore any attributes that were previously backed up with
///
protected void RestoreRenderAttributes( RenderAttributes attributes )
{
if ( _attributes is not null )
{
_attributes.MergeTo( attributes );
}
_attributes = null;
}
internal virtual void OnSceneObjectCreated( SceneObject obj )
{
_sceneObject = obj;
_sceneObject.CallbackTarget = this;
UpdateSceneObjectFlags();
RestoreRenderAttributes( obj.Attributes );
}
///
/// Render the of this renderer with the specified overrides.
///
internal virtual void RenderSceneObject( RendererSetup rendererSetup = default )
{
if ( !_sceneObject.IsValid() )
return;
Graphics.Render( _sceneObject, rendererSetup.Transform, rendererSetup.Color, rendererSetup.Material );
}
}