146 lines
7.5 KiB
C#
146 lines
7.5 KiB
C#
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
namespace MegaKoop.EditorTools
|
|
{
|
|
public static class UGUIMenuBuilder
|
|
{
|
|
[MenuItem("Tools/MegaKoop/Generate UGUI Main Menu", priority = 0)]
|
|
public static void GenerateUGUIMainMenu()
|
|
{
|
|
// Create or use dedicated UI_Canvas (do NOT bind to a random existing Canvas)
|
|
Canvas canvas = null;
|
|
var canvasGO = GameObject.Find("UI_Canvas");
|
|
if (canvasGO == null)
|
|
{
|
|
canvasGO = new GameObject("UI_Canvas", typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster));
|
|
Undo.RegisterCreatedObjectUndo(canvasGO, "Create Canvas");
|
|
}
|
|
canvas = canvasGO.GetComponent<Canvas>();
|
|
if (canvas == null) canvas = canvasGO.AddComponent<Canvas>();
|
|
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
|
canvas.sortingOrder = 100;
|
|
var scaler = canvasGO.GetComponent<CanvasScaler>();
|
|
if (scaler == null) scaler = canvasGO.AddComponent<CanvasScaler>();
|
|
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
|
scaler.referenceResolution = new Vector2(1920, 1080);
|
|
scaler.matchWidthOrHeight = 0.5f;
|
|
var raycaster = canvasGO.GetComponent<GraphicRaycaster>();
|
|
if (raycaster == null) raycaster = canvasGO.AddComponent<GraphicRaycaster>();
|
|
|
|
// Ensure/upgrade EventSystem based on available modules
|
|
var existingES = Object.FindObjectOfType<UnityEngine.EventSystems.EventSystem>();
|
|
var inputSystemModuleType = System.Type.GetType("UnityEngine.InputSystem.UI.InputSystemUIInputModule, Unity.InputSystem", false);
|
|
bool wantIS = inputSystemModuleType != null;
|
|
bool wantLegacy = !wantIS;
|
|
|
|
GameObject esGO = null;
|
|
if (existingES == null)
|
|
{
|
|
var es = new GameObject("EventSystem", typeof(UnityEngine.EventSystems.EventSystem));
|
|
if (wantIS) es.AddComponent(inputSystemModuleType);
|
|
if (wantLegacy) es.AddComponent<UnityEngine.EventSystems.StandaloneInputModule>();
|
|
Undo.RegisterCreatedObjectUndo(es, "Create EventSystem");
|
|
esGO = es;
|
|
}
|
|
else
|
|
{
|
|
esGO = existingES.gameObject;
|
|
var sim = existingES.GetComponent<UnityEngine.EventSystems.StandaloneInputModule>();
|
|
var ism = inputSystemModuleType != null ? existingES.GetComponent(inputSystemModuleType) : null;
|
|
if (wantIS && ism == null) Undo.AddComponent(existingES.gameObject, inputSystemModuleType);
|
|
if (wantLegacy && sim == null) Undo.AddComponent<UnityEngine.EventSystems.StandaloneInputModule>(existingES.gameObject);
|
|
}
|
|
|
|
// Assign actionsAsset only if the picked InputActionAsset contains a "UI" action map
|
|
bool assignedUIActions = false;
|
|
if (wantIS && inputSystemModuleType != null && esGO != null)
|
|
{
|
|
var module = esGO.GetComponent(inputSystemModuleType);
|
|
if (module != null)
|
|
{
|
|
var prop = inputSystemModuleType.GetProperty("actionsAsset");
|
|
if (prop != null)
|
|
{
|
|
var current = prop.GetValue(module, null) as UnityEngine.Object;
|
|
if (current == null)
|
|
{
|
|
var iaaType = System.Type.GetType("UnityEngine.InputSystem.InputActionAsset, Unity.InputSystem", false);
|
|
string ChooseUIAsset()
|
|
{
|
|
var guids = AssetDatabase.FindAssets("t:InputActionAsset");
|
|
foreach (var g in guids)
|
|
{
|
|
var path = AssetDatabase.GUIDToAssetPath(g);
|
|
var asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path);
|
|
if (asset != null && iaaType != null && iaaType.IsInstanceOfType(asset))
|
|
{
|
|
var map = iaaType.GetMethod("FindActionMap", new[] { typeof(string), typeof(bool) })?.Invoke(asset, new object[] { "UI", true });
|
|
if (map != null) return path;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
var best = ChooseUIAsset();
|
|
if (!string.IsNullOrEmpty(best))
|
|
{
|
|
var asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(best);
|
|
prop.SetValue(module, asset, null);
|
|
var comp = module as Component; if (comp != null) EditorUtility.SetDirty(comp);
|
|
assignedUIActions = true;
|
|
}
|
|
// else: leave null to let module use its default actions
|
|
}
|
|
else { assignedUIActions = true; }
|
|
}
|
|
}
|
|
}
|
|
|
|
if (esGO != null)
|
|
{
|
|
var hasSIM = esGO.GetComponent<UnityEngine.EventSystems.StandaloneInputModule>() != null;
|
|
var hasIS = inputSystemModuleType != null && esGO.GetComponent(inputSystemModuleType) != null;
|
|
if (hasIS && !assignedUIActions && !hasSIM)
|
|
{
|
|
Undo.AddComponent<UnityEngine.EventSystems.StandaloneInputModule>(esGO);
|
|
}
|
|
Debug.Log($"[UGUIMenuBuilder] EventSystem configured. InputSystem={(hasIS ? "ON" : "OFF")} (actions={(assignedUIActions ? "OK" : "none")}), Standalone={(hasSIM ? "ON" : "OFF")}");
|
|
}
|
|
|
|
// Clean old generated panels if present to avoid duplicates
|
|
void DestroyChildIfExists(Transform parent, string childName)
|
|
{
|
|
var child = parent.Find(childName);
|
|
if (child != null)
|
|
{
|
|
Undo.DestroyObjectImmediate(child.gameObject);
|
|
}
|
|
}
|
|
DestroyChildIfExists(canvas.transform, "Panel_MainMenu");
|
|
DestroyChildIfExists(canvas.transform, "Panel_Settings");
|
|
DestroyChildIfExists(canvas.transform, "Panel_Lobby");
|
|
|
|
var mainPanel = new MainMenuPanelBuilder(canvas.transform).Build();
|
|
var settingsPanel = new SettingsPanelBuilder(canvas.transform).Build();
|
|
var lobbyPanel = new LobbyPanelBuilder(canvas.transform).Build();
|
|
|
|
// Controllers
|
|
var mainCtrl = canvas.gameObject.GetComponent<MegaKoop.UI.UGUIMainMenuController>();
|
|
if (mainCtrl == null) mainCtrl = canvas.gameObject.AddComponent<MegaKoop.UI.UGUIMainMenuController>();
|
|
var lobbyCtrl = canvas.gameObject.GetComponent<MegaKoop.UI.UGUIMultiplayerLobbyController>();
|
|
if (lobbyCtrl == null) lobbyCtrl = canvas.gameObject.AddComponent<MegaKoop.UI.UGUIMultiplayerLobbyController>();
|
|
|
|
// Inject panel references for reliability
|
|
mainCtrl.SetPanels(mainPanel, settingsPanel, lobbyPanel);
|
|
lobbyCtrl.SetLobbyRoot(lobbyPanel);
|
|
|
|
Selection.activeGameObject = canvas.gameObject;
|
|
|
|
Debug.Log("[UGUIMenuBuilder] UGUI Main Menu generated successfully. You can press Play and test.");
|
|
}
|
|
}
|
|
}
|
|
#endif
|