mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-27 15:50:36 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
161 lines
3.9 KiB
C#
161 lines
3.9 KiB
C#
namespace Editor;
|
|
|
|
/// <summary>
|
|
/// A widget (usually window) implementing this will be able to edit assets via the asset browser.
|
|
/// The widget should be marked with the attribute of the asset's extension, like this <c>[CanEdit( "asset:vsndstck" )]</c>
|
|
/// </summary>
|
|
public interface IAssetEditor : IValid
|
|
{
|
|
/// <summary>
|
|
/// A list of open editors that support multiple assets at once.
|
|
/// </summary>
|
|
static Dictionary<string, IAssetEditor> OpenMultiAssetEditors = new();
|
|
|
|
/// <summary>
|
|
/// A list of open editors for individual assets.
|
|
/// </summary>
|
|
static Dictionary<string, IAssetEditor> OpenSingleEditors = new();
|
|
|
|
/// <summary>
|
|
/// Open given asset in a new asset editor window. Will reuse already open editors for same asset type if the editor supports it. (<see cref="CanOpenMultipleAssets"/>)
|
|
/// </summary>
|
|
/// <returns>Whether an asset editor was found for given asset.</returns>
|
|
public static bool OpenInEditor( Asset asset, out IAssetEditor editor )
|
|
{
|
|
System.ArgumentNullException.ThrowIfNull( asset );
|
|
|
|
//
|
|
// Stick this on the recent opened list
|
|
//
|
|
asset.RecordOpened();
|
|
|
|
var path = asset.AbsolutePath ?? asset.Name;
|
|
|
|
if ( OpenSingleEditors.TryGetValue( path, out var openEditor ) && openEditor.IsValid )
|
|
{
|
|
// ReSharper disable once SuspiciousTypeConversion.Global
|
|
if ( openEditor is BaseWindow window )
|
|
{
|
|
window.Focus();
|
|
}
|
|
|
|
editor = openEditor;
|
|
return true;
|
|
}
|
|
|
|
var extension = asset.AssetType.FileExtension;
|
|
|
|
if ( OpenMultiAssetEditors.TryGetValue( extension, out openEditor ) && openEditor.IsValid )
|
|
{
|
|
openEditor.AssetOpen( asset );
|
|
|
|
editor = openEditor;
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// This is the new way, anything else should be considered bullshit
|
|
//
|
|
|
|
|
|
TryAgain:
|
|
|
|
if ( TryOpenUsingStaticMethod( asset ) )
|
|
{
|
|
editor = null;
|
|
return true;
|
|
}
|
|
|
|
var found = EditorTypeLibrary.GetTypesWithAttribute<EditorForAssetTypeAttribute>()
|
|
.Where( x => x.Attribute.Extension == extension )
|
|
.FirstOrDefault();
|
|
|
|
// not found lets create a generic editor
|
|
if ( found.Type == null && extension != "__fallback" && asset.AssetType.IsGameResource )
|
|
{
|
|
extension = "__fallback";
|
|
goto TryAgain;
|
|
}
|
|
|
|
// nothing found for real
|
|
if ( found.Type == null )
|
|
{
|
|
editor = null;
|
|
return false;
|
|
}
|
|
|
|
var created = found.Type.Create<Widget>();
|
|
|
|
if ( created is not IAssetEditor ae )
|
|
{
|
|
created.Destroy();
|
|
Log.Warning( $"Found editor {created} for {extension} - but it didn't implement IAssetEditor" );
|
|
|
|
editor = null;
|
|
return false;
|
|
}
|
|
|
|
ae.AssetOpen( asset );
|
|
|
|
if ( ae.CanOpenMultipleAssets )
|
|
{
|
|
OpenMultiAssetEditors[extension] = ae;
|
|
}
|
|
else
|
|
{
|
|
OpenSingleEditors[path] = ae;
|
|
}
|
|
|
|
editor = ae;
|
|
return true;
|
|
}
|
|
|
|
static bool TryOpenUsingStaticMethod( Asset asset )
|
|
{
|
|
var extension = asset.AssetType.FileExtension;
|
|
|
|
var found = EditorTypeLibrary.GetMethodsWithAttribute<EditorForAssetTypeAttribute>()
|
|
.Where( x => x.Attribute.Extension == extension )
|
|
.FirstOrDefault();
|
|
|
|
if ( found.Method is null )
|
|
return false;
|
|
|
|
if ( found.Method.Parameters.Count() == 1 )
|
|
{
|
|
var p = found.Method.Parameters[0];
|
|
|
|
// if it wants an asset, pass it in
|
|
if ( p.ParameterType == typeof( Asset ) )
|
|
{
|
|
found.Method.Invoke( null, new[] { asset } );
|
|
return true;
|
|
}
|
|
|
|
// if it wants a gameresource type, load it and convert it
|
|
if ( p.ParameterType.IsAssignableTo( typeof( GameResource ) ) )
|
|
{
|
|
var resource = asset.LoadResource( p.ParameterType );
|
|
found.Method.Invoke( null, new[] { resource } );
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// If this editor is able to edit multiple assets at the same time then return true
|
|
/// and we'll try to create only one version of that editor and AssetOpen will be called multiple times.
|
|
/// </summary>
|
|
public bool CanOpenMultipleAssets { get; }
|
|
|
|
/// <summary>
|
|
/// Open the asset in this editor.
|
|
/// </summary>
|
|
public void AssetOpen( Asset asset );
|
|
|
|
void SelectMember( string memberName );
|
|
}
|