mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-04-19 05:48:07 -04:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
291 lines
8.2 KiB
C#
291 lines
8.2 KiB
C#
using Sandbox.Diagnostics;
|
|
using System.IO;
|
|
|
|
namespace Editor;
|
|
|
|
/// <summary>
|
|
/// Resources stored as strings
|
|
/// </summary>
|
|
[CustomEditor( typeof( string ), WithAllAttributes = new[] { typeof( AssetPathAttribute ) } )]
|
|
public class ResourceStringControlWidget : ControlWidget
|
|
{
|
|
AssetType AssetType;
|
|
|
|
public override bool IsControlButton => true;
|
|
public override bool SupportsMultiEdit => true;
|
|
|
|
public string WarningText { get; set; }
|
|
|
|
public ResourceStringControlWidget( SerializedProperty property ) : base( property )
|
|
{
|
|
property.TryGetAttribute<AssetPathAttribute>( out var attr );
|
|
Assert.NotNull( attr, "ResourceStringControlWidget property has no AssetPathAttribute" );
|
|
|
|
var resourceExtension = attr.AssetTypeExtension;
|
|
resourceExtension = resourceExtension.Replace( "resource:", "" );
|
|
resourceExtension = resourceExtension.Trim().ToLower();
|
|
|
|
AssetType = AssetType.All.FirstOrDefault( x => x.FileExtension == resourceExtension );
|
|
|
|
Cursor = CursorShape.Finger;
|
|
MouseTracking = true;
|
|
AcceptDrops = true;
|
|
IsDraggable = true;
|
|
|
|
OnValueChanged();
|
|
}
|
|
|
|
protected override void OnValueChanged()
|
|
{
|
|
base.OnValueChanged();
|
|
|
|
if ( AssetType == AssetType.MapFile )
|
|
{
|
|
var resource = SerializedProperty.GetValue<string>( null );
|
|
var asset = resource != null ? AssetSystem.FindByPath( resource ) : null;
|
|
if ( asset is not null )
|
|
{
|
|
bool isCompiled = File.Exists( Path.ChangeExtension( asset.AbsolutePath, ".vpk" ) );
|
|
if ( !isCompiled ) WarningText = ToolTip = "Map is not compiled";
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void PaintControl()
|
|
{
|
|
var resource = SerializedProperty.GetValue<string>( null );
|
|
var asset = resource != null ? AssetSystem.FindByPath( resource ) : null;
|
|
|
|
var rect = new Rect( 0, Size );
|
|
|
|
var iconRect = rect.Shrink( 2 );
|
|
iconRect.Width = iconRect.Height;
|
|
|
|
rect.Left = iconRect.Right + 10;
|
|
|
|
Paint.ClearPen();
|
|
Paint.SetBrush( Theme.SurfaceBackground.WithAlpha( 0.2f ) );
|
|
Paint.DrawRect( iconRect, 2 );
|
|
|
|
var pickerName = "Unknown Resource";
|
|
if ( AssetType is not null ) pickerName = AssetType.FriendlyName;
|
|
|
|
if ( !string.IsNullOrEmpty( WarningText ) )
|
|
{
|
|
Rect warningRect = iconRect;
|
|
warningRect.Left = rect.Left + 16;
|
|
Paint.SetPen( Theme.Yellow );
|
|
Paint.DrawIcon( warningRect, "warning", Math.Max( 16, warningRect.Height / 2 ) );
|
|
rect.Left += 16;
|
|
}
|
|
|
|
Pixmap icon = AssetType?.Icon64;
|
|
|
|
if ( SerializedProperty.IsMultipleDifferentValues )
|
|
{
|
|
var textRect = rect.Shrink( 0, 3 );
|
|
if ( icon != null ) Paint.Draw( iconRect, icon );
|
|
|
|
Paint.SetDefaultFont();
|
|
Paint.SetPen( Theme.MultipleValues );
|
|
Paint.DrawText( textRect, $"Multiple Values", TextFlag.LeftCenter );
|
|
}
|
|
else if ( asset is not null && !asset.IsDeleted )
|
|
{
|
|
Paint.Draw( iconRect, asset.GetAssetThumb( true ) );
|
|
|
|
var textRect = rect.Shrink( 0, 3 );
|
|
|
|
Paint.SetPen( Theme.Text.WithAlpha( 0.9f ) );
|
|
Paint.SetHeadingFont( 8, 450 );
|
|
var t = Paint.DrawText( textRect, $"{asset.Name}", TextFlag.LeftTop );
|
|
|
|
textRect.Left = t.Right + 6;
|
|
Paint.SetDefaultFont( 7 );
|
|
Theme.DrawFilename( textRect, asset.RelativePath, TextFlag.LeftCenter, Theme.Text.WithAlpha( 0.5f ) );
|
|
}
|
|
else if ( !string.IsNullOrWhiteSpace( resource ) )
|
|
{
|
|
var textRect = rect.Shrink( 0, 3 );
|
|
|
|
bool isPackage = !resource.Contains( ".vmap" ) && Package.TryParseIdent( resource, out _ );
|
|
if ( !isPackage )
|
|
{
|
|
Paint.SetBrush( Theme.Red.Darken( 0.8f ) );
|
|
Paint.DrawRect( iconRect, 2 );
|
|
|
|
Paint.SetPen( Theme.Red );
|
|
Paint.DrawIcon( iconRect, "error", Math.Max( 16, iconRect.Height / 2 ) );
|
|
}
|
|
else if ( icon != null ) Paint.Draw( iconRect, icon );
|
|
|
|
Paint.SetPen( Theme.Text.WithAlpha( 0.9f ) );
|
|
Paint.SetHeadingFont( 8, 450 );
|
|
var t = Paint.DrawText( textRect, isPackage ? (Package.TryGetCached( resource, out Package package ) ? $"{package.Title} ☁️" : $"Cloud {pickerName}") : $"Missing {pickerName}", TextFlag.LeftTop );
|
|
|
|
textRect.Left = t.Right + 6;
|
|
Paint.SetDefaultFont( 7 );
|
|
Theme.DrawFilename( textRect, resource, TextFlag.LeftCenter, Theme.Text.WithAlpha( 0.5f ) );
|
|
}
|
|
else
|
|
{
|
|
var textRect = rect.Shrink( 0, 3 );
|
|
if ( icon != null ) Paint.Draw( iconRect, icon );
|
|
|
|
Paint.SetDefaultFont( italic: true );
|
|
Paint.SetPen( Theme.Text.WithAlpha( 0.2f ) );
|
|
Paint.DrawText( textRect, $"{pickerName}", TextFlag.LeftCenter );
|
|
}
|
|
}
|
|
|
|
protected override void OnContextMenu( ContextMenuEvent e )
|
|
{
|
|
var m = new ContextMenu();
|
|
|
|
var resource = SerializedProperty.GetValue<string>( null );
|
|
var asset = (resource != null) ? AssetSystem.FindByPath( resource ) : null;
|
|
|
|
m.AddOption( "Open in Editor", "edit", () => asset?.OpenInEditor() ).Enabled = asset != null && !asset.IsProcedural;
|
|
m.AddOption( "Find in Asset Browser", "search", () => LocalAssetBrowser.OpenTo( asset, true ) ).Enabled = asset is not null;
|
|
m.AddSeparator();
|
|
m.AddOption( "Copy", "file_copy", action: Copy ).Enabled = AssetType == AssetType.MapFile ? !string.IsNullOrWhiteSpace( resource ) : asset != null;
|
|
m.AddOption( "Paste", "content_paste", action: Paste );
|
|
m.AddSeparator();
|
|
m.AddOption( "Clear", "backspace", action: Clear ).Enabled = resource != null;
|
|
|
|
m.OpenAtCursor( false );
|
|
e.Accepted = true;
|
|
}
|
|
|
|
protected override void OnMouseClick( MouseEvent e )
|
|
{
|
|
base.OnMouseClick( e );
|
|
|
|
if ( ReadOnly ) return;
|
|
|
|
var resource = SerializedProperty.GetValue<string>( null );
|
|
var asset = resource != null ? AssetSystem.FindByPath( resource ) : null;
|
|
|
|
var picker = AssetPicker.Create( null, AssetType );
|
|
PropertyStartEdit();
|
|
|
|
picker.SetSelection( resource );
|
|
picker.Title = $"Select {SerializedProperty.DisplayName}";
|
|
if ( AssetType == AssetType.MapFile )
|
|
{
|
|
picker.OnPackagePicked = ( o ) =>
|
|
{
|
|
SerializedProperty.SetValue( o.FullIdent );
|
|
PropertyFinishEdit();
|
|
};
|
|
}
|
|
else
|
|
{
|
|
picker.OnAssetHighlighted = ( o ) =>
|
|
{
|
|
UpdateFromAsset( o.FirstOrDefault() );
|
|
PropertyFinishEdit();
|
|
};
|
|
}
|
|
picker.OnAssetPicked = ( o ) => UpdateFromAsset( o.FirstOrDefault() );
|
|
picker.Show();
|
|
|
|
picker.SetSelection( asset );
|
|
}
|
|
|
|
private void UpdateFromAsset( Asset asset )
|
|
{
|
|
if ( asset is null ) return;
|
|
|
|
SerializedProperty.Parent?.NoteStartEdit( SerializedProperty );
|
|
SerializedProperty.SetValue( asset.RelativePath );
|
|
SerializedProperty.Parent?.NoteFinishEdit( SerializedProperty );
|
|
}
|
|
|
|
public override void OnDragHover( DragEvent ev )
|
|
{
|
|
if ( AssetType == AssetType.MapFile && ev.Data.Url?.Scheme == "https" )
|
|
{
|
|
ev.Action = DropAction.Link;
|
|
return;
|
|
}
|
|
|
|
if ( !ev.Data.HasFileOrFolder )
|
|
return;
|
|
|
|
var asset = AssetSystem.FindByPath( ev.Data.FileOrFolder );
|
|
|
|
if ( asset == null || AssetType != asset.AssetType )
|
|
return;
|
|
|
|
ev.Action = DropAction.Link;
|
|
}
|
|
|
|
public override void OnDragDrop( DragEvent ev )
|
|
{
|
|
if ( AssetType == AssetType.MapFile && ev.Data.Url?.Scheme == "https" )
|
|
{
|
|
if ( !Package.TryParseIdent( ev.Data.Url.ToString(), out var ident ) )
|
|
return;
|
|
|
|
PropertyStartEdit();
|
|
SerializedProperty.SetValue( $"{ident.org}.{ident.package}" );
|
|
PropertyFinishEdit();
|
|
ev.Action = DropAction.Link;
|
|
return;
|
|
}
|
|
|
|
if ( !ev.Data.HasFileOrFolder )
|
|
return;
|
|
|
|
var asset = AssetSystem.FindByPath( ev.Data.FileOrFolder );
|
|
|
|
if ( asset == null || AssetType != asset.AssetType )
|
|
return;
|
|
|
|
PropertyStartEdit();
|
|
UpdateFromAsset( asset );
|
|
PropertyFinishEdit();
|
|
ev.Action = DropAction.Link;
|
|
}
|
|
|
|
protected override void OnDragStart()
|
|
{
|
|
var resource = SerializedProperty.GetValue<string>( null );
|
|
var asset = resource != null ? AssetSystem.FindByPath( resource ) : null;
|
|
|
|
if ( asset == null )
|
|
return;
|
|
|
|
var drag = new Drag( this );
|
|
drag.Data.Url = new Uri( $"file://{asset.AbsolutePath}" );
|
|
drag.Execute();
|
|
}
|
|
|
|
void Copy()
|
|
{
|
|
var resource = SerializedProperty.GetValue<string>( null );
|
|
if ( resource == null ) return;
|
|
|
|
var asset = AssetSystem.FindByPath( resource );
|
|
if ( asset != null )
|
|
resource = asset.RelativePath;
|
|
|
|
EditorUtility.Clipboard.Copy( resource );
|
|
}
|
|
|
|
void Paste()
|
|
{
|
|
var path = EditorUtility.Clipboard.Paste();
|
|
var asset = AssetSystem.FindByPath( path );
|
|
UpdateFromAsset( asset );
|
|
}
|
|
|
|
void Clear()
|
|
{
|
|
SerializedProperty.Parent.NoteStartEdit( SerializedProperty );
|
|
SerializedProperty.SetValue( (Resource)null );
|
|
SerializedProperty.Parent.NoteFinishEdit( SerializedProperty );
|
|
}
|
|
}
|