Files
sbox-public/engine/Sandbox.Engine/Systems/UI/Controls/ScenePanel.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

166 lines
4.4 KiB
C#

// Supporting Obsolete paths
#pragma warning disable CS0612
#pragma warning disable CS0618
namespace Sandbox.UI
{
/// <summary>
/// Allows to render a scene world onto a panel.
/// </summary>
[Expose]
[Library( "scene" )]
public partial class ScenePanel : Panel
{
/// <summary>
/// Shortcut to Camera.World
/// </summary>
[Obsolete( "Handling SceneObjects like this manually will be removed soon. Use the actual Scene." )]
public SceneWorld World
{
get => Camera.World;
set => Camera.World = value;
}
/// <summary>
/// The camera we're going to be using to render
/// </summary>
[Obsolete( "Handling SceneObjects like this manually will be removed soon. Use the actual Scene." )]
public SceneCamera Camera { get; } = new( "Scene Panel" );
/// <summary>
/// If enabled, the scene will only render once. That isn't totally accurate though, because we'll
/// also re-render the scene when the size of the panel changes.
/// </summary>
public bool RenderOnce { get; set; }
/// <summary>
/// The texture that the panel is rendering to internally. This will change to a different
/// texture if the panel changes size, so I wouldn't hold onto this object.
/// </summary>
public Texture RenderTexture { get; private set; }
/// <summary>
/// The Scene this panel renders.
/// </summary>
public Scene RenderScene { get; set; }
public ScenePanel()
{
RenderScene = new() { WantsSystemScene = false };
Camera.FieldOfView = 60;
Camera.BackgroundColor = Color.Transparent;
Camera.ZNear = 0.1f;
Camera.ZFar = 1000.0f;
}
/// <summary>
/// Creates and loads a Scene from a file to render to this panel.
/// </summary>
public ScenePanel( string sceneFilename ) : this()
{
var options = new SceneLoadOptions { ShowLoadingScreen = false };
if ( !options.SetScene( sceneFilename ) )
return;
RenderScene.Load( options );
}
public override void Tick()
{
base.Tick();
if ( !RenderScene.IsValid() )
return;
using ( RenderScene.Push() )
{
RenderScene.GameTick( RealTime.Delta );
}
}
internal bool shouldRenderNextFrame = true;
/// <summary>
/// Render the panel again next frame. This is meant to be used with RenderOnce, where
/// you might want to render on demand or only once.
/// </summary>
public void RenderNextFrame() => shouldRenderNextFrame = true;
public override bool HasContent => RenderScene.IsValid() || World != null;
public override void Delete( bool immediate = false )
{
RenderTexture?.Dispose();
RenderTexture = null;
RenderScene?.Destroy();
RenderScene = null;
base.Delete( immediate );
}
internal override void DrawContent( PanelRenderer renderer, ref RenderState state )
{
if ( Box.RectInner.Size.x <= 0 ) return;
if ( Box.RectInner.Size.y <= 0 ) return;
// work out whether we should actually render the scene
bool shouldRender = shouldRenderNextFrame;
if ( !RenderOnce ) shouldRender = true;
if ( RenderTexture == null ) shouldRender = true;
var oldRt = RenderTexture;
RenderTexture = Texture.CreateRenderTarget( "__scenePanel", ImageFormat.RGBA8888, Box.RectInner.Size, RenderTexture );
if ( RenderTexture == null ) return;
// Texture changed - force an update
if ( oldRt != RenderTexture ) shouldRender = true;
if ( shouldRender )
{
// reset
shouldRenderNextFrame = false;
if ( Camera.World.IsValid() )
{
Camera.RenderToTexture( RenderTexture, null, default );
}
else if ( RenderScene.IsValid() && RenderScene.Camera.IsValid() )
{
RenderScene.PreCameraRender();
RenderScene.Camera.RenderToTexture( RenderTexture );
}
}
renderer.DrawBackgroundTexture( this, RenderTexture, state, Length.Contain );
}
public override void SetProperty( string name, string value )
{
base.SetProperty( name, value );
}
}
namespace Construct
{
public static class SceneConstructor
{
[Obsolete( "Will be deleted if anyone for some reason still uses this" )]
public static ScenePanel ScenePanel( this PanelCreator self, SceneWorld world, Vector3 position, Rotation rotation, float fieldOfView, string classname = null )
{
var control = self.panel.AddChild<ScenePanel>();
control.World = world;
control.Camera.Position = position;
control.Camera.Rotation = rotation;
control.Camera.FieldOfView = fieldOfView;
if ( classname != null )
control.AddClass( classname );
return control;
}
}
}
}