mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-04-19 13:59:22 -04:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
257 lines
5.9 KiB
C#
257 lines
5.9 KiB
C#
using Microsoft.CodeAnalysis;
|
|
|
|
namespace Editor;
|
|
|
|
internal class CodeCompileNotice : NoticeWidget
|
|
{
|
|
CompileGroup CompilerGroup;
|
|
|
|
public CodeCompileNotice()
|
|
{
|
|
|
|
}
|
|
|
|
public CodeCompileNotice( CompileGroup compiler )
|
|
{
|
|
Icon = "build_circle";
|
|
Position = 10;
|
|
CompilerGroup = compiler;
|
|
Reset();
|
|
}
|
|
|
|
protected override Vector2 SizeHint()
|
|
{
|
|
return 1000;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when it's about to be re-used by a new compiler
|
|
/// </summary>
|
|
public override void Reset()
|
|
{
|
|
base.Reset();
|
|
|
|
IsRunning = true;
|
|
Tick();
|
|
SetBodyWidget( null );
|
|
FixedWidth = 300;
|
|
FixedHeight = 76;
|
|
Title = $"Compile '{CompilerGroup.Name}'";
|
|
BorderColor = Theme.Primary;
|
|
isErrored = false;
|
|
}
|
|
|
|
bool isErrored = false;
|
|
|
|
private readonly List<string> files = [];
|
|
|
|
public override bool WantsVisible
|
|
{
|
|
get
|
|
{
|
|
if ( EditorPreferences.CompileNotifications == EditorPreferences.NotificationLevel.ShowAlways )
|
|
return true;
|
|
|
|
if ( EditorPreferences.CompileNotifications == EditorPreferences.NotificationLevel.ShowOnError )
|
|
return isErrored;
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public override void Tick()
|
|
{
|
|
if ( !IsRunning )
|
|
return;
|
|
|
|
var buildCount = CompilerGroup.Compilers.Count( x => x.IsBuilding );
|
|
var finishCount = CompilerGroup.Compilers.Count( x => !x.IsBuilding );
|
|
var warnings = CompilerGroup.Compilers.Where( x => x.Diagnostics != null )
|
|
.SelectMany( x => x.Diagnostics )
|
|
.Where( x => x.Severity >= DiagnosticSeverity.Warning )
|
|
.Count();
|
|
|
|
IsRunning = CompilerGroup.IsBuilding;
|
|
Subtitle = $"{buildCount} pending, {finishCount} completed";
|
|
|
|
if ( warnings > 0 )
|
|
Subtitle += $", {warnings} warnings";
|
|
|
|
if ( IsRunning )
|
|
return;
|
|
|
|
bool success = CompilerGroup.Compilers.All( x => x.BuildSuccess );
|
|
|
|
files.Clear();
|
|
|
|
if ( success )
|
|
{
|
|
isErrored = false;
|
|
BorderColor = Theme.Green;
|
|
NoticeManager.Remove( this, 1 );
|
|
|
|
if ( EditorPreferences.NotificationSounds )
|
|
EditorUtility.PlayRawSound( "sounds/editor/success.wav" );
|
|
}
|
|
else
|
|
{
|
|
isErrored = true;
|
|
BorderColor = Theme.Red;
|
|
Subtitle = "";
|
|
NoticeManager.Remove( this, EditorPreferences.ErrorNotificationTimeout );
|
|
AddDiagnostics();
|
|
|
|
if ( EditorPreferences.NotificationSounds )
|
|
EditorUtility.PlayRawSound( "sounds/editor/fail.wav" );
|
|
}
|
|
}
|
|
|
|
protected override void OnPaint()
|
|
{
|
|
if ( !EditorPreferences.NotificationPopups ) return;
|
|
|
|
base.OnPaint();
|
|
}
|
|
|
|
protected override void OnMousePress( MouseEvent e )
|
|
{
|
|
base.OnMousePress( e );
|
|
|
|
if ( e.LeftMouseButton && e.HasShift )
|
|
{
|
|
foreach ( var file in files )
|
|
{
|
|
CodeEditor.OpenFile( file );
|
|
}
|
|
|
|
e.Accepted = true;
|
|
return;
|
|
}
|
|
}
|
|
|
|
private void AddDiagnostics()
|
|
{
|
|
var diagnostics = CompilerGroup.Compilers
|
|
.Where( x => x.Diagnostics != null )
|
|
.SelectMany( x => x.Diagnostics )
|
|
.Where( x => x.Severity >= DiagnosticSeverity.Error )
|
|
.OrderByDescending( x => (int)x.Severity )
|
|
.Take( 5 )
|
|
.ToArray();
|
|
|
|
if ( diagnostics.Length == 0 ) return;
|
|
|
|
var bodyWidget = new Widget( this );
|
|
bodyWidget.Layout = Layout.Column();
|
|
|
|
foreach ( var diag in diagnostics )
|
|
{
|
|
var btn = bodyWidget.Layout.Add( new DiagnosticWidget( diag ) );
|
|
files.Add( btn.FilePath );
|
|
}
|
|
|
|
SetBodyWidget( bodyWidget );
|
|
}
|
|
|
|
[Event( "compile.started" )]
|
|
public static void OnCompileStarted( CompileGroup compiler )
|
|
{
|
|
// find an old notice to replace
|
|
var notice = NoticeManager.All.OfType<CodeCompileNotice>().FirstOrDefault( x => x.CompilerGroup.Name == compiler.Name );
|
|
if ( !notice.IsValid() ) notice = new CodeCompileNotice( compiler );
|
|
|
|
notice.CompilerGroup = compiler;
|
|
notice.Reset();
|
|
}
|
|
}
|
|
|
|
internal class DiagnosticWidget : Widget
|
|
{
|
|
private Diagnostic diag;
|
|
|
|
public string FilePath { get; private set; }
|
|
public int LineNumber { get; private set; }
|
|
public int CharNumber { get; private set; }
|
|
public string Message { get; private set; }
|
|
|
|
public DiagnosticWidget( Diagnostic diag ) : base( null )
|
|
{
|
|
this.diag = diag;
|
|
FixedHeight = 18;
|
|
MinimumWidth = 400;
|
|
Cursor = CursorShape.Finger;
|
|
|
|
ToolTip = $"{diag.GetMessage()}\n{diag.Location}";
|
|
|
|
var span = diag.Location.GetLineSpan();
|
|
var mappedSpan = diag.Location.GetMappedLineSpan();
|
|
|
|
Message = diag.GetMessage();
|
|
// Path can be null if the spans are not valid (not related to a file)
|
|
FilePath = mappedSpan.HasMappedPath ? mappedSpan.Path : span.Path;
|
|
LineNumber = mappedSpan.Span.Start.Line + 1;
|
|
CharNumber = mappedSpan.Span.Start.Character + 1;
|
|
}
|
|
|
|
protected override void DoLayout()
|
|
{
|
|
base.DoLayout();
|
|
}
|
|
|
|
protected override void OnPaint()
|
|
{
|
|
base.OnPaint();
|
|
|
|
Paint.Antialiasing = true;
|
|
Paint.TextAntialiasing = true;
|
|
|
|
var color = Theme.Red;
|
|
if ( diag.Severity == DiagnosticSeverity.Warning ) color = Theme.Yellow;
|
|
var bareFilename = System.IO.Path.GetFileName( FilePath );
|
|
var rect = LocalRect;
|
|
|
|
var textColor = Color.Lerp( Color.White, color, 0.5f );
|
|
|
|
if ( IsUnderMouse )
|
|
{
|
|
Paint.ClearPen();
|
|
Paint.SetBrush( color.WithAlpha( 0.1f ) );
|
|
Paint.DrawRect( rect );
|
|
}
|
|
|
|
var measureText = $"{diag.Id}: {Message} {bareFilename}:{LineNumber}";
|
|
var size = Paint.MeasureText( new Rect( 0, 1000 ), measureText, TextFlag.LeftCenter );
|
|
|
|
rect = rect.Shrink( 4, 0 );
|
|
|
|
Paint.SetPen( textColor.WithAlpha( 0.8f ) );
|
|
var fileRect = Paint.DrawText( rect, $"{bareFilename}:{LineNumber}", TextFlag.RightCenter );
|
|
|
|
rect.Right -= fileRect.Width;
|
|
rect.Right -= 8;
|
|
|
|
Paint.SetPen( textColor.WithAlpha( 0.5f ) );
|
|
Paint.DrawText( rect.Shrink( 16, 0, 0, 0 ), $"{diag.Id}: {Message}", TextFlag.LeftCenter );
|
|
|
|
Paint.ClearPen();
|
|
Paint.SetBrush( color );
|
|
Paint.DrawCircle( new Rect( 0, 16 ).Shrink( 2 ) );
|
|
}
|
|
|
|
protected override void OnMouseClick( MouseEvent e )
|
|
{
|
|
if ( e.LeftMouseButton )
|
|
{
|
|
// Can be null if our diagnostic spans are not valid
|
|
if ( FilePath != null )
|
|
{
|
|
CodeEditor.OpenFile( FilePath, LineNumber, CharNumber );
|
|
}
|
|
e.Accepted = true;
|
|
return;
|
|
}
|
|
|
|
base.OnMouseClick( e );
|
|
}
|
|
}
|