Razor UI panel for the game's start menu. Renders top bar and a list of scene vials from the ResourceLibrary, handles opening scenes, pausing/unpausing (by setting Scene.TimeScale), navigation to start scene, settings, and exit actions.
@using Sandbox;
@using Sandbox.UI;
@inherits PanelComponent
@namespace Sandbox
<root class=@(isPaused?"":"resumed")>
<!--https://sbox.game/dev/doc/ui/razor-panels/razor-components-->
<!--<div class="title">@MyStringValue</div>-->
<div class="topBar">
<div class="topLeft">
<p><a class="resumeButton @(@isInStart?"hidden":"")" onClick=@ResumeGame><iconify icon="material-symbols:arrow-back" size=@(48)/></a></p>
<p class="topTitle">🪛 Testpen!</p>
<p><a class="homeButton @(isInStart?"hidden":"")" onClick=@ReturnToMenu>🏠</a></p>
</div>
<div class="topCenter">
<p>@openedSceneName</p>
</div>
<div class="topRight">
<p><a class="settingButton" onClick=@SettingGame>⚙️</a></p>
<p><a class="selfInfoButton" onClick=@SelfInfoGame>ℹ️</a></p>
<p><a class="exitButton" onClick=@ExitGame>❌</a></p>
</div>
</div>
<hr/>
<div class="body">
<div class="manualSceneList">
<!--<p><a onClick=@TestGoToScene>Go To Scene</a></p>-->
<!--<p class=@(@isInStart?"hidden":"")><a onClick=@ReturnToMenu>Go To Home</a></p>-->
</div>
<div class="sceneList">
@foreach (var sceneVial in ResourceLibrary.GetAll<SceneFile>().Where(x => x.ResourcePath.Contains("/vials/")).OrderBy(x => x.GetMetadata("Title")))
{
<SceneVialSelectable Scene="@sceneVial" OnSelected=@OpenScene></SceneVialSelectable>
}
</div>
</div>
</root>
@code
{
/*
//@foreach (var sceneVial in ResourceLibrary.GetAll<SceneFile>().Where(x => x.ResourcePath.Contains("/Vials/") && x.GetMetadata("Group", "None") == SceneCategory).OrderBy(x => x.GetMetadata("Title")))
//@foreach (var sceneVial in ResourceLibrary.GetAll<SceneFile>().Where(x => x.ResourcePath.Contains("/vials/")).OrderBy(x => x.GetMetadata("Title")))
@foreach (var sceneVial in ResourceLibrary.GetAll<SceneFile>())
*/
[Property] public bool isPaused {get; internal set;} = false;
protected bool hathPaused {get;set;} = false;
[Property] public bool isInStart {get;set;} = false;
[Property, TextArea] public string MyStringValue { get; set; } = "Testpen!";
protected string openedSceneName {get;set;} = "Select test";
[Property] public SceneInformation ObtainSceneInfo {get;set;}
//[Property] protected DoNotFreezeOnPause? noFreeze {get; set;}
[Property] public bool PlsDoNotFreeze {get;set;} = false;
protected bool hathFrozen {get; set;} = false;
// Yoink Scene List from Facepunch!
// https://github.com/Facepunch/sbox-scenestaging/blob/main/Code/SceneMenu/SceneMenuPanel.razor
[ConVar( "testbed_category", ConVarFlags.Saved )]
public static string SceneCategory { get; set; } = "Random";
protected override void OnStart()
{
base.OnStart();
//TODO: Make it singleton, find other UI like this. If found other instance, let that guy alone, and self destruct. Just like Unity.
// Search these SceneProperties Components!
//noFreeze = Scene.Directory.FindByName( "DoNotFreezeOnPause" ).First().GetComponent<DoNotFreezeOnPause>();
//ObtainSceneInfo = Scene.Directory.FindByName("Scene Information").First().GetComponent<SceneInformation>();
}
protected override void OnUpdate()
{
base.OnUpdate();
if(Input.EscapePressed)
{
//Log.Info("escape press");
if(!isInStart){
Input.EscapePressed = false;
TogglePause();
}
}
if(Input.Pressed("Jump"))
{
//Log.Info("aaa");
}
if(isPaused)
{
if(!hathPaused)
{
if(!hathFrozen)
{
/*
if(!noFreeze.IsValid())
{
//Log.Info("try find if noPause");
//noFreeze = Scene.Directory.FindByName( "DoNotFreezeOnPause" ).First().GetComponent<DoNotFreezeOnPause>();
}
if(noFreeze.IsValid())
{
// then we won't freeze time
} else
{
// freeze it now!
if(!hathFrozen)
{
Log.Info("try freeze");
Scene.TimeScale = 0f;
hathFrozen = true;
}
}
*/
if(PlsDoNotFreeze)
{
// then we won't freeze
} else
{
// Freeze Now!
Scene.TimeScale = 0f;
hathFrozen = true;
}
}
hathPaused = true;
}
} else {
if(hathFrozen)
{
// unfreeze just in case there was
Scene.TimeScale = 1f;
hathFrozen = false;
}
hathPaused = false;
}
}
protected void TestGoToScene()
{
Log.Info("Let\'s go!");
Scene.LoadFromFile("scenes/Vials/minimal.scene");
isInStart = false;
}
protected void OpenScene( SceneFile file )
{
// https://github.com/Facepunch/sbox-scenestaging/blob/main/Code/SceneMenu/SceneMenuPanel.razor
// https://github.com/Facepunch/sbox-public/blob/master/engine/Sandbox.Engine/Scene/Scene/Scene.cs
// https://github.com/Facepunch/sbox-public/blob/master/engine/Sandbox.Engine/Game/Game/Game.Scene.cs
// https://github.com/Facepunch/sbox-public/blob/master/engine/Sandbox.Engine/Systems/SceneSystem/SceneLoadOptions.cs
// pls I was just had to learn.
var toThisScene = new SceneLoadOptions();
toThisScene.SetScene(file);
//Game.ActiveScene.Load(file);
Game.ChangeScene(toThisScene);
//Scene.LoadFromFile(file);
//var go = new GameObject(true, "Return To Menu");
//go.Components.Create<ReturnToMenu>();
}
/*
protected void OpenScene( String filename)
{
}
*/
protected void ReturnToMenu()
{
Log.Info("Let\'s go home!");
//Scene.LoadFromFile("scenes/start.scene");
var toThisScene = new SceneLoadOptions();
toThisScene.SetScene("scenes/start.scene");
Game.ChangeScene(toThisScene);
isInStart = true;
}
protected void ResumeGame()
{
Log.Info("Resume Now!");
if(!isInStart)
isPaused = false;
}
protected void TogglePause()
{
isPaused = !isPaused;
//Log.Info("isPaused is now " + isPaused);
}
protected void SettingGame()
{
Log.Info("Open Setting!!");
// found!
//https://github.com/Facepunch/sbox-public/blob/master/engine/Sandbox.Engine/Game/Game/Game.Overlay.cs
// Jesus Christ on an Innova, at least copy paste the old docs to sbox docs until you can remake the new one, wtf!
Game.Overlay.ShowSettingsModal("");
}
protected void SelfInfoGame()
{
Log.Info("Open Self Info!!");
Game.Overlay.ShowPauseMenu();
}
protected void ExitGame()
{
Log.Info("Exit Game Now!");
// We had to scour examples, coz the documentation as of rn is infancy
// https://github.com/Facepunch/sbox-battlebugs/blob/main/code/UI/PanelComponents/MainMenu.razor
// https://github.com/Facepunch/sbox-public/blob/master/engine/Sandbox.Engine/Game/Game/Game.cs
// if(Game.IsEditor) return;
Game.Close();
// Oh Hey, Carson, what's up?
}
/// <summary>
/// the hash determines if the system should be rebuilt. If it changes, it will be rebuilt
/// </summary>
//protected override int BuildHash() => System.HashCode.Combine( MyStringValue );
protected override int BuildHash() {
return System.HashCode.Combine(
MyStringValue,
"",
isInStart,
ResourceLibrary.GetAll<SceneFile>().Where(x => x.ResourcePath.Contains("/vials/")).OrderBy(x => x.GetMetadata("Title")),
isPaused
);
}
}