(Feat) Add Build

This commit is contained in:
2026-07-22 12:56:13 +02:00
parent 3657b870d8
commit 0052b0d98e
244 changed files with 35752 additions and 3112 deletions
+37 -36
View File
@@ -1,5 +1,4 @@
using UnityEngine;
using UnityEngine.SceneManagement;
using Ashwild.Network;
using Ashwild.Player;
@@ -25,10 +24,6 @@ namespace Ashwild.UI
[Tooltip("The pause menu panel opened by Escape.")]
[SerializeField] private UIPanel pausePanel;
[Header("Quit")]
[Tooltip("Scene loaded when leaving the session back to the main menu.")]
[SerializeField] private string menuSceneName = "MenuScene";
#endregion
#region State
@@ -45,18 +40,16 @@ namespace Ashwild.UI
private UIPanel buildPanel;
/// <summary>
/// True while a panel that pauses the world is open — i.e. anything but the inventory, the
/// construction menu or the chest, all local windows the world keeps running under.
/// True while a panel that pauses the world is open — i.e. anything but the inventory (which a
/// chest reuses) or the construction menu, both local windows the world keeps running under.
/// </summary>
public bool IsPaused => Current != null
&& Current.Kind != PanelKind.Inventory
&& Current.Kind != PanelKind.Build
&& Current.Kind != PanelKind.Chest;
&& Current.Kind != PanelKind.Build;
// Last bus values pushed, so we only fire on real transitions.
private bool lastPaused;
private bool lastInventoryOpen;
private bool lastChestOpen;
private bool lastBuildOpen;
#endregion
@@ -92,11 +85,6 @@ namespace Ashwild.UI
lastInventoryOpen = false;
PlayerEvents.RaiseInventoryOpenChanged(false);
}
if (lastChestOpen)
{
lastChestOpen = false;
PlayerEvents.RaiseChestOpenChanged(false);
}
if (lastBuildOpen)
{
lastBuildOpen = false;
@@ -119,7 +107,18 @@ namespace Ashwild.UI
#region Escape Policy
/// <summary>
/// Escape: close whatever is open (inventory or sub-panel), otherwise open the pause menu.
/// Escape, from the most local context outward: close whatever panel is open (inventory or
/// sub-panel), else back out of an in-world build placement, else open the pause menu.
///
/// The placement step matters because a ghost being positioned is a mode with no panel behind it:
/// the construction menu closes as soon as a card is picked, so HasOpenPanel is already false and
/// Escape used to fall straight through to the pause menu — leaving the player still holding a
/// ghost. It is routed through BuildCancelRequested rather than reaching for BuildManager, so
/// ending a placement stays the bus contract the hammer's right-click tap already uses.
///
/// Demolition mode is deliberately not handled here: it lasts only while right-click is held, so
/// it ends on release, and cancelling it from the outside would leave the hammer thinking it is
/// still held.
/// </summary>
protected override void OnEscape()
{
@@ -132,6 +131,12 @@ namespace Ashwild.UI
return;
}
if (PlayerEvents.IsPlacingBuild)
{
PlayerEvents.RaiseBuildCancelRequested();
return;
}
OpenPause();
}
@@ -172,19 +177,19 @@ namespace Ashwild.UI
/// <summary>
/// Leaves the session and returns to the main menu scene behind the loading curtain. The
/// transition is owned by the persistent NetworkSessionManager (it survives the scene swap,
/// this manager does not); falls back to a direct, uncovered load only if it is missing.
/// transition — and the menu scene name — is owned by the persistent NetworkSessionManager (it
/// survives the scene swap and is the single source of truth for scene names; this manager does
/// neither). Logs and no-ops if it is somehow missing rather than tearing down uncovered.
/// </summary>
public void QuitToMenu()
{
if (NetworkSessionManager.Instance != null)
if (NetworkSessionManager.Instance == null)
{
NetworkSessionManager.Instance.ReturnToMenu(menuSceneName);
Debug.LogError("[GameUIManager] NetworkSessionManager missing — cannot return to menu.", this);
return;
}
Debug.LogWarning("[GameUIManager] NetworkSessionManager missing — loading menu directly without the loading curtain.", this);
SceneManager.LoadScene(menuSceneName);
NetworkSessionManager.Instance.ReturnToMenu();
}
#endregion
@@ -204,9 +209,9 @@ namespace Ashwild.UI
return;
}
// Don't open the inventory on top of the pause menu, the construction menu or a chest.
// Don't open the inventory on top of the pause menu or the construction menu.
if (IsPaused) return;
if (Current != null && (Current.Kind == PanelKind.Build || Current.Kind == PanelKind.Chest)) return;
if (Current != null && Current.Kind == PanelKind.Build) return;
if (inventoryPanel != null)
OpenPanel(inventoryPanel);
@@ -228,7 +233,7 @@ namespace Ashwild.UI
}
if (IsPaused) return;
if (Current != null && (Current.Kind == PanelKind.Inventory || Current.Kind == PanelKind.Chest)) return;
if (Current != null && Current.Kind == PanelKind.Inventory) return;
if (buildPanel != null)
OpenPanel(buildPanel);
@@ -260,19 +265,20 @@ namespace Ashwild.UI
/// <summary>
/// Drives the side effects of the open panel: cursor for any panel, world freeze + GamePaused
/// for pausing panels, and the InventoryOpenChanged / ChestOpenChanged / BuildMenuOpenChanged
/// bus states for the three local windows. The inventory, the chest and the construction menu
/// are windows the world keeps running under, so only "real" menus pause. All four bus states
/// feed PlayerEvents.InputLocked, so player control is cut whenever a panel is open.
/// for pausing panels, and the InventoryOpenChanged / BuildMenuOpenChanged bus states for the
/// two local windows. The inventory (which a chest reuses) and the construction menu are windows
/// the world keeps running under, so only "real" menus pause. The ChestOpenChanged sub-state is
/// owned by the inventory window itself, since a chest is just the inventory panel in chest mode.
/// All these bus states feed PlayerEvents.InputLocked, so player control is cut whenever a panel
/// is open.
/// </summary>
private void ApplyUIState(bool force = false)
{
UIPanel cur = Current;
bool anyOpen = cur != null;
bool inventory = anyOpen && cur.Kind == PanelKind.Inventory;
bool chest = anyOpen && cur.Kind == PanelKind.Chest;
bool build = anyOpen && cur.Kind == PanelKind.Build;
bool paused = anyOpen && !inventory && !chest && !build;
bool paused = anyOpen && !inventory && !build;
Cursor.lockState = anyOpen ? CursorLockMode.None : CursorLockMode.Locked;
Cursor.visible = anyOpen;
@@ -287,11 +293,6 @@ namespace Ashwild.UI
lastInventoryOpen = inventory;
PlayerEvents.RaiseInventoryOpenChanged(inventory);
}
if (force || chest != lastChestOpen)
{
lastChestOpen = chest;
PlayerEvents.RaiseChestOpenChanged(chest);
}
if (force || build != lastBuildOpen)
{
lastBuildOpen = build;