Files
sbox-public/engine/Sandbox.Engine/Systems/SceneSystem/IManagedCamera.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

92 lines
2.1 KiB
C#

using System.Threading;
namespace Sandbox;
/// <summary>
/// Used for c++ to make callbacks to a camera and be able to find it by id
/// </summary>
internal interface IManagedCamera
{
static Lock _directoryLock = new();
static Dictionary<int, WeakReference<IManagedCamera>> _directory = new();
static int _indexer = 1000;
static WeakReference<IManagedCamera> _mainCamera;
static Lock _mainCameraLock = new();
/// <summary>
/// Called when entering a specific pipeline stage
/// </summary>
void OnRenderStage( Rendering.Stage renderStage );
/// <summary>
/// Allocate a camera id for this camera. This is used to find the camera in the c++ code.
/// </summary>
int AllocateCameraId()
{
Cleanup();
lock ( _directoryLock )
{
var cameraId = _indexer++;
// We treat 0 as invalid, so skip it
if ( cameraId == 0 ) cameraId = _indexer++;
_directory[cameraId] = new WeakReference<IManagedCamera>( this );
return cameraId;
}
}
/// <summary>
/// Find a camera by its id. This is used to find the camera by the calling c++ code. This is called
/// in the render thread, so it's important to be thread-safe.
/// </summary>
public static IManagedCamera FindById( int cameraId )
{
lock ( _directoryLock )
{
if ( !_directory.TryGetValue( cameraId, out var reference ) )
return null;
if ( !reference.TryGetTarget( out var cam ) )
return null;
return cam;
}
}
public static void SetMainCamera( IManagedCamera camera )
{
if ( camera == null ) return;
lock ( _mainCameraLock )
{
_mainCamera = new WeakReference<IManagedCamera>( camera );
}
}
public static IManagedCamera GetMainCamera()
{
lock ( _mainCameraLock )
{
if ( _mainCamera == null )
return null;
if ( !_mainCamera.TryGetTarget( out var cam ) )
return null;
return cam;
}
}
/// <summary>
/// keep the directory clean by trimming all the old ones
/// </summary>
static void Cleanup()
{
lock ( _directoryLock )
{
foreach ( var old in _directory.Where( x => !x.Value.TryGetTarget( out var _ ) ).Select( x => x.Key ).ToArray() )
{
_directory.Remove( old );
}
}
}
}