Files
sbox-public/game/editor/ActionGraph/Code/GameObjectThumbnail.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

103 lines
2.4 KiB
C#

using System.Linq;
using System.Runtime.CompilerServices;
using Editor;
using Facepunch.ActionGraphs.Nodes;
namespace Sandbox.ActionGraphs;
#nullable enable
public static class GameObjectThumbnail
{
public const int Size = 128;
private static ConditionalWeakTable<GameObject, Pixmap> _cache = new();
/// <summary>
/// If this game object is a prefab root, return the prefab asset.
/// </summary>
private static Asset? GetPrefabAsset( GameObject go )
{
if ( go.Scene is not PrefabScene { Source: { } source } || go.Scene != go )
{
return null;
}
return AssetSystem.FindByPath( source.ResourcePath );
}
public static Pixmap GetGameObjectThumb( this GameObject go )
{
if ( GetPrefabAsset( go ) is { } prefabAsset )
{
return prefabAsset.GetAssetThumb();
}
if ( _cache.TryGetValue( go, out var cached ) )
{
return cached;
}
using var sceneScope = go.Scene.Push();
using var camera = new SceneCamera( "Thumbnail Cam" );
var bounds = go.GetBounds();
var center = bounds.Center;
var distance = Math.Max( 16f, (bounds.Maxs - bounds.Mins).Length * 0.5f ) * 4f;
var baseYaw = go.WorldRotation.Yaw();
var cameraRotation = Rotation.From( 30f, baseYaw + 60f, 0f );
var sunRotation = Rotation.From( 80f, baseYaw + 30f, 0f );
var lightRotation = Rotation.From( 60f, baseYaw + 120f, 0f );
var thumb = new Pixmap( Size, Size );
SceneDirectionalLight? sun = null;
SceneLight? light = null;
if ( !go.Scene.GetAllComponents<Light>().Any() )
{
sun = new SceneDirectionalLight( go.Scene.SceneWorld, sunRotation, Color.White * 2.5f + Color.Cyan * 0.05f )
{
ShadowsEnabled = true,
ShadowTextureResolution = 1024
};
light = new SceneLight( go.Scene.SceneWorld, center - lightRotation.Forward * distance, distance * 1.5f,
new Color( 1.0f, 0.9f, 0.9f ) * 10.0f );
}
try
{
camera.World = go.Scene.SceneWorld;
camera.Position = center - cameraRotation.Forward * distance;
camera.Rotation = cameraRotation;
camera.FieldOfView = 30f;
camera.BackgroundColor = Color.Transparent;
camera.RenderToPixmap( thumb );
_cache.TryAdd( go, thumb );
return thumb;
}
finally
{
sun?.Delete();
light?.Delete();
}
}
[Event( "scene.saved" )]
static void OnSceneSaved( Scene scene )
{
foreach ( var (key, value) in _cache.ToArray() )
{
if ( key.Scene == scene )
{
_cache.Remove( key );
}
}
}
}