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]
293 lines
5.9 KiB
C#
293 lines
5.9 KiB
C#
namespace Editor.Wizards;
|
|
|
|
/// <summary>
|
|
/// A window that has multiple steps, talks you through a process
|
|
/// </summary>
|
|
public abstract class BaseWizard : Widget
|
|
{
|
|
public virtual string Title => "Base Page";
|
|
public virtual string Icon => "people";
|
|
|
|
public Layout BodyLayout;
|
|
public Layout HeaderLayout;
|
|
public Layout FooterRight;
|
|
public Layout FooterLeft;
|
|
public Layout Footer;
|
|
|
|
protected ScrollArea ScrollArea;
|
|
|
|
protected Button BackButton { get; init; }
|
|
protected Button NextButton { get; init; }
|
|
protected Label PageTitle { get; init; }
|
|
protected Label PageSubtitle { get; init; }
|
|
|
|
bool loading;
|
|
BaseWizardPage _current;
|
|
|
|
protected BaseWizardPage Current
|
|
{
|
|
get => _current;
|
|
set
|
|
{
|
|
if ( _current == value ) return;
|
|
|
|
foreach ( var p in Steps )
|
|
p.Visible = false;
|
|
|
|
_current?.TokenSource?.Cancel();
|
|
|
|
_current = value;
|
|
_ = SwitchCurrentPage();
|
|
Update();
|
|
}
|
|
}
|
|
|
|
protected List<BaseWizardPage> Steps = new();
|
|
|
|
public BaseWindow CreateWindow( int width = 1280, int height = 770 )
|
|
{
|
|
var window = new BaseWindow()
|
|
{
|
|
Size = new Vector2( width, height ),
|
|
MinimumSize = new Vector2( width, height ),
|
|
TranslucentBackground = true,
|
|
NoSystemBackground = true,
|
|
WindowTitle = "Wizard"
|
|
};
|
|
|
|
window.SetModal( true, true );
|
|
|
|
window.Layout = Layout.Column();
|
|
window.Layout.Margin = 0;
|
|
window.Layout.Spacing = 0;
|
|
|
|
window.Layout.Add( this );
|
|
|
|
window.WindowTitle = $"{Title}";
|
|
window.SetWindowIcon( Icon );
|
|
window.Show();
|
|
|
|
return window;
|
|
}
|
|
|
|
internal BaseWizard() : base( null )
|
|
{
|
|
Layout = Layout.Column();
|
|
|
|
HeaderLayout = Layout.AddColumn();
|
|
var body = Layout.AddColumn( 1 );
|
|
ScrollArea = new ScrollArea( this );
|
|
body.Add( ScrollArea );
|
|
ScrollArea.Canvas = new Widget( ScrollArea );
|
|
ScrollArea.Canvas.Layout = Layout.Column();
|
|
BodyLayout = ScrollArea.Canvas.Layout;
|
|
BodyLayout.Margin = 32;
|
|
|
|
Layout.AddStretchCell( 0 );
|
|
|
|
Footer = Layout.AddRow();
|
|
Footer.Margin = 16;
|
|
|
|
FooterLeft = Footer.AddRow();
|
|
Footer.AddStretchCell();
|
|
FooterRight = Footer.AddRow();
|
|
FooterRight.Spacing = 4;
|
|
|
|
HeaderLayout.Margin = new Sandbox.UI.Margin( 0, 0, 0, 0 );
|
|
PageTitle = HeaderLayout.Add( new Label.Title( "Title" ) );
|
|
PageTitle.ContentMargins = new Sandbox.UI.Margin( 32, 16, 0, 0 );
|
|
PageSubtitle = HeaderLayout.Add( new Label.Body( "Subtitle" ) { Color = Theme.Primary.Lighten( 0.3f ) } );
|
|
PageSubtitle.ContentMargins = new Sandbox.UI.Margin( 32, 0, 0, 16 );
|
|
|
|
FooterRight.Spacing = 8;
|
|
BackButton = FooterRight.Add( new Button( "Back", "navigate_before" ) );
|
|
BackButton.Clicked = LastPage;
|
|
|
|
NextButton = FooterRight.Add( new Button.Primary( "Next", "navigate_next" ) );
|
|
NextButton.Clicked = NextPage;
|
|
}
|
|
|
|
public Layout StartSection( string name, Layout layout = null )
|
|
{
|
|
layout ??= BodyLayout;
|
|
|
|
var block = layout.AddColumn();
|
|
block.Margin = 8;
|
|
|
|
block.Add( new Label.Subtitle( name ) );
|
|
var inner = block.AddColumn();
|
|
inner.Margin = 8;
|
|
|
|
return inner;
|
|
}
|
|
|
|
public void AddFooterDefaults()
|
|
{
|
|
var revert = new Button( "Revert Changes", "history", this );
|
|
revert.Clicked = Reset;
|
|
|
|
var save = new Button.Primary( "Save", "save", this );
|
|
save.Clicked = OnSave;
|
|
|
|
FooterRight.Add( revert );
|
|
FooterRight.Add( save );
|
|
}
|
|
|
|
public virtual void OnSave()
|
|
{
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rebuild the page on hotload for quick iteration
|
|
/// </summary>
|
|
[EditorEvent.Hotload]
|
|
public void Reset()
|
|
{
|
|
HeaderLayout.Clear( true );
|
|
BodyLayout.Clear( true );
|
|
FooterLeft.Clear( true );
|
|
FooterRight.Clear( true );
|
|
}
|
|
|
|
async Task SwitchCurrentPage()
|
|
{
|
|
try
|
|
{
|
|
loading = true;
|
|
_current.TokenSource = new System.Threading.CancellationTokenSource();
|
|
await _current.OpenAsync();
|
|
loading = false;
|
|
|
|
if ( _current.IsAutoStep && _current.CanProceed() )
|
|
{
|
|
NextPage();
|
|
}
|
|
}
|
|
catch ( System.Exception e )
|
|
{
|
|
Log.Error( e );
|
|
}
|
|
}
|
|
|
|
protected override void OnPaint()
|
|
{
|
|
base.OnPaint();
|
|
|
|
var steps = (float)Steps.Count - 1;
|
|
var index = (float)Steps.IndexOf( Current );
|
|
var progress = index / steps;
|
|
|
|
var left = Color.Lerp( Theme.WindowBackground, Theme.Primary, 0.5f );
|
|
|
|
var r = HeaderLayout.InnerRect;
|
|
Paint.Antialiasing = true;
|
|
Paint.SetBrushAndPen( left );
|
|
Paint.DrawRect( HeaderLayout.InnerRect );
|
|
|
|
Paint.SetBrushAndPen( Theme.WindowBackground );
|
|
Paint.DrawRect( Footer.OuterRect );
|
|
}
|
|
|
|
|
|
|
|
[EditorEvent.Frame]
|
|
public void Tick()
|
|
{
|
|
if ( Current == null )
|
|
Current = Steps.FirstOrDefault();
|
|
|
|
bool finalpage = Current == Steps.LastOrDefault();
|
|
|
|
PageTitle.Text = Current.PageTitle;
|
|
PageSubtitle.Text = Current.PageSubtitle;
|
|
|
|
// special case for end of wizard
|
|
if ( finalpage && Current.CanProceed() && !loading )
|
|
{
|
|
BackButton.Visible = false;
|
|
NextButton.Enabled = true;
|
|
NextButton.Text = "Finished";
|
|
NextButton.Icon = "done";
|
|
return;
|
|
}
|
|
|
|
BackButton.Visible = true;
|
|
BackButton.Enabled = !loading && Steps.First() != Current;
|
|
NextButton.Enabled = !loading && Steps.Last() != Current && Current.CanProceed();
|
|
NextButton.Text = Current.NextButtonText;
|
|
NextButton.Icon = "navigate_next";
|
|
}
|
|
|
|
protected void AddStep( BaseWizardPage p )
|
|
{
|
|
Steps.Add( p );
|
|
BodyLayout.Add( p );
|
|
p.Visible = false;
|
|
}
|
|
|
|
protected void LastPage()
|
|
{
|
|
var i = Steps.IndexOf( Current );
|
|
if ( i <= 0 ) return;
|
|
|
|
OnSave();
|
|
|
|
Current = Steps[i - 1];
|
|
}
|
|
|
|
protected void NextPage()
|
|
{
|
|
if ( !Current.CanProceed() )
|
|
return;
|
|
|
|
OnSave();
|
|
|
|
// Finish closes the window
|
|
bool finalpage = Current == Steps.Last();
|
|
if ( finalpage )
|
|
{
|
|
var p = Parent;
|
|
while ( p.IsValid() )
|
|
{
|
|
if ( p is BaseWindow )
|
|
{
|
|
p.Close();
|
|
return;
|
|
}
|
|
|
|
p = p.Parent;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
_ = TrySwitchToNextPage();
|
|
}
|
|
|
|
async Task TrySwitchToNextPage()
|
|
{
|
|
loading = true;
|
|
var i = Steps.IndexOf( Current );
|
|
var current = Current;
|
|
var next = Steps[i + 1];
|
|
|
|
try
|
|
{
|
|
var result = await current.FinishAsync();
|
|
|
|
loading = false;
|
|
|
|
if ( !result )
|
|
return;
|
|
|
|
Current = next;
|
|
}
|
|
catch ( System.Exception e )
|
|
{
|
|
Log.Error( e );
|
|
}
|
|
}
|
|
|
|
}
|