Nekopletní fix
This commit is contained in:
@@ -23,17 +23,92 @@ namespace MegaKoop.EditorTools
|
|||||||
canvas = canvasGO.GetComponent<Canvas>();
|
canvas = canvasGO.GetComponent<Canvas>();
|
||||||
if (canvas == null) canvas = canvasGO.AddComponent<Canvas>();
|
if (canvas == null) canvas = canvasGO.AddComponent<Canvas>();
|
||||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||||
|
canvas.sortingOrder = 100;
|
||||||
var scaler = canvasGO.GetComponent<CanvasScaler>();
|
var scaler = canvasGO.GetComponent<CanvasScaler>();
|
||||||
if (scaler == null) scaler = canvasGO.AddComponent<CanvasScaler>();
|
if (scaler == null) scaler = canvasGO.AddComponent<CanvasScaler>();
|
||||||
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
||||||
scaler.referenceResolution = new Vector2(1920, 1080);
|
scaler.referenceResolution = new Vector2(1920, 1080);
|
||||||
scaler.matchWidthOrHeight = 0.5f;
|
scaler.matchWidthOrHeight = 0.5f;
|
||||||
|
var raycaster = canvasGO.GetComponent<GraphicRaycaster>();
|
||||||
|
if (raycaster == null) raycaster = canvasGO.AddComponent<GraphicRaycaster>();
|
||||||
|
|
||||||
// Ensure EventSystem exists
|
// Ensure/upgrade EventSystem based on available modules
|
||||||
if (Object.FindObjectOfType<UnityEngine.EventSystems.EventSystem>() == null)
|
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), typeof(UnityEngine.EventSystems.StandaloneInputModule));
|
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");
|
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
|
// Clean old generated panels if present to avoid duplicates
|
||||||
@@ -73,9 +148,15 @@ namespace MegaKoop.EditorTools
|
|||||||
|
|
||||||
var gfxGroup = CreateVerticalGroup(settingsContainer.transform, "Graphics_Group", 10, TextAnchor.UpperLeft, new RectOffset(10,10,10,10));
|
var gfxGroup = CreateVerticalGroup(settingsContainer.transform, "Graphics_Group", 10, TextAnchor.UpperLeft, new RectOffset(10,10,10,10));
|
||||||
CreateText(gfxGroup.transform, "Text_Graphics", "Graphics", 24, TextAnchor.MiddleLeft, Color.white, FontStyles.Bold);
|
CreateText(gfxGroup.transform, "Text_Graphics", "Graphics", 24, TextAnchor.MiddleLeft, Color.white, FontStyles.Bold);
|
||||||
CreateDropdown(gfxGroup.transform, "Dropdown_Quality", new string[]{"Low","Medium","High","Ultra"});
|
CreateUnityDropdown(gfxGroup.transform, "Dropdown_Quality", new string[]{"Low","Medium","High","Ultra"});
|
||||||
CreateToggle(gfxGroup.transform, "Toggle_Fullscreen", "Fullscreen", true);
|
CreateToggle(gfxGroup.transform, "Toggle_Fullscreen", "Fullscreen", true);
|
||||||
CreateDropdown(gfxGroup.transform, "Dropdown_Resolution", new string[]{"1280x720","1920x1080","2560x1440","3840x2160"});
|
CreateUnityDropdown(gfxGroup.transform, "Dropdown_Resolution", new string[]{"1280x720","1920x1080","2560x1440","3840x2160"});
|
||||||
|
|
||||||
|
var audioGroup = CreateVerticalGroup(settingsContainer.transform, "Audio_Group", 10, TextAnchor.UpperLeft, new RectOffset(10,10,10,10));
|
||||||
|
CreateText(audioGroup.transform, "Text_Audio", "Audio", 24, TextAnchor.MiddleLeft, Color.white, FontStyles.Bold);
|
||||||
|
CreateLabeledSlider(audioGroup.transform, "Master Volume", "Slider_MasterVolume", 0, 100, 100);
|
||||||
|
CreateLabeledSlider(audioGroup.transform, "Music Volume", "Slider_MusicVolume", 0, 100, 80);
|
||||||
|
CreateLabeledSlider(audioGroup.transform, "SFX Volume", "Slider_SFXVolume", 0, 100, 100);
|
||||||
|
|
||||||
var settingsButtons = CreateHorizontalGroup(settingsContainer.transform, "Settings_Buttons", 10, TextAnchor.MiddleCenter, new RectOffset(0,0,0,0));
|
var settingsButtons = CreateHorizontalGroup(settingsContainer.transform, "Settings_Buttons", 10, TextAnchor.MiddleCenter, new RectOffset(0,0,0,0));
|
||||||
CreateMenuButton(settingsButtons.transform, "Button_ApplySettings", "APPLY");
|
CreateMenuButton(settingsButtons.transform, "Button_ApplySettings", "APPLY");
|
||||||
@@ -206,6 +287,22 @@ namespace MegaKoop.EditorTools
|
|||||||
return go;
|
return go;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static GameObject CreateUnityDropdown(Transform parent, string name, string[] options)
|
||||||
|
{
|
||||||
|
var resources = new DefaultControls.Resources();
|
||||||
|
var go = DefaultControls.CreateDropdown(resources);
|
||||||
|
go.name = name;
|
||||||
|
go.transform.SetParent(parent, false);
|
||||||
|
var rt = (RectTransform)go.transform; rt.sizeDelta = new Vector2(600, 50);
|
||||||
|
|
||||||
|
var font = Resources.GetBuiltinResource<Font>("Arial.ttf");
|
||||||
|
foreach (var t in go.GetComponentsInChildren<Text>(true)) t.font = font;
|
||||||
|
var dd = go.GetComponent<Dropdown>();
|
||||||
|
dd.options = (options != null ? options.Select(o => new Dropdown.OptionData(o)).ToList() : new System.Collections.Generic.List<Dropdown.OptionData>());
|
||||||
|
dd.RefreshShownValue();
|
||||||
|
return go;
|
||||||
|
}
|
||||||
|
|
||||||
private static GameObject CreateVerticalGroup(Transform parent, string name, float spacing, TextAnchor align, RectOffset padding)
|
private static GameObject CreateVerticalGroup(Transform parent, string name, float spacing, TextAnchor align, RectOffset padding)
|
||||||
{
|
{
|
||||||
var go = new GameObject(name, typeof(RectTransform), typeof(VerticalLayoutGroup), typeof(ContentSizeFitter));
|
var go = new GameObject(name, typeof(RectTransform), typeof(VerticalLayoutGroup), typeof(ContentSizeFitter));
|
||||||
@@ -316,12 +413,18 @@ namespace MegaKoop.EditorTools
|
|||||||
template.SetActive(false);
|
template.SetActive(false);
|
||||||
var templateImg = template.GetComponent<Image>(); templateImg.color = new Color(0.1f,0.1f,0.1f,0.95f);
|
var templateImg = template.GetComponent<Image>(); templateImg.color = new Color(0.1f,0.1f,0.1f,0.95f);
|
||||||
|
|
||||||
|
var tplCanvas = template.GetComponent<Canvas>();
|
||||||
|
if (tplCanvas == null) tplCanvas = template.AddComponent<Canvas>();
|
||||||
|
tplCanvas.overrideSorting = true;
|
||||||
|
tplCanvas.sortingOrder = 5000;
|
||||||
|
if (!template.GetComponent<GraphicRaycaster>()) template.AddComponent<GraphicRaycaster>();
|
||||||
|
|
||||||
// Viewport
|
// Viewport
|
||||||
var viewport = new GameObject("Viewport", typeof(RectTransform), typeof(Mask), typeof(Image));
|
var viewport = new GameObject("Viewport", typeof(RectTransform), typeof(Mask), typeof(Image));
|
||||||
viewport.transform.SetParent(template.transform, false);
|
viewport.transform.SetParent(template.transform, false);
|
||||||
var viewportRT = (RectTransform)viewport.transform; viewportRT.anchorMin = new Vector2(0,0); viewportRT.anchorMax = new Vector2(1,1); viewportRT.offsetMin = Vector2.zero; viewportRT.offsetMax = Vector2.zero;
|
var viewportRT = (RectTransform)viewport.transform; viewportRT.anchorMin = new Vector2(0,0); viewportRT.anchorMax = new Vector2(1,1); viewportRT.offsetMin = Vector2.zero; viewportRT.offsetMax = Vector2.zero;
|
||||||
var vImg = viewport.GetComponent<Image>(); vImg.color = new Color(0,0,0,0.2f);
|
var vImg = viewport.GetComponent<Image>(); vImg.color = new Color(0,0,0,0.2f); vImg.raycastTarget = false;
|
||||||
viewport.GetComponent<Mask>().showMaskGraphic = false;
|
var mask = viewport.GetComponent<Mask>(); mask.showMaskGraphic = false;
|
||||||
|
|
||||||
// Scroll content
|
// Scroll content
|
||||||
var content = new GameObject("Content", typeof(RectTransform), typeof(VerticalLayoutGroup));
|
var content = new GameObject("Content", typeof(RectTransform), typeof(VerticalLayoutGroup));
|
||||||
@@ -356,6 +459,7 @@ namespace MegaKoop.EditorTools
|
|||||||
dd.captionText = caption.GetComponent<TextMeshProUGUI>();
|
dd.captionText = caption.GetComponent<TextMeshProUGUI>();
|
||||||
dd.itemText = itemLabelGO.GetComponent<TextMeshProUGUI>();
|
dd.itemText = itemLabelGO.GetComponent<TextMeshProUGUI>();
|
||||||
dd.options = options.Select(o => new TMP_Dropdown.OptionData(o)).ToList();
|
dd.options = options.Select(o => new TMP_Dropdown.OptionData(o)).ToList();
|
||||||
|
dd.alphaFadeSpeed = 0.15f;
|
||||||
dd.RefreshShownValue();
|
dd.RefreshShownValue();
|
||||||
|
|
||||||
// ScrollRect wiring
|
// ScrollRect wiring
|
||||||
@@ -366,6 +470,53 @@ namespace MegaKoop.EditorTools
|
|||||||
return go;
|
return go;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static GameObject CreateSlider(Transform parent, string name, float min, float max, float value)
|
||||||
|
{
|
||||||
|
var go = new GameObject(name, typeof(RectTransform), typeof(Slider));
|
||||||
|
go.transform.SetParent(parent, false);
|
||||||
|
var slider = go.GetComponent<Slider>();
|
||||||
|
slider.minValue = min; slider.maxValue = max; slider.value = value; slider.direction = Slider.Direction.LeftToRight; slider.wholeNumbers = true;
|
||||||
|
var rt = (RectTransform)go.transform; rt.sizeDelta = new Vector2(600, 30);
|
||||||
|
|
||||||
|
var background = new GameObject("Background", typeof(RectTransform), typeof(Image));
|
||||||
|
background.transform.SetParent(go.transform, false);
|
||||||
|
var bgRT = (RectTransform)background.transform; bgRT.anchorMin = new Vector2(0,0.25f); bgRT.anchorMax = new Vector2(1,0.75f); bgRT.offsetMin = Vector2.zero; bgRT.offsetMax = Vector2.zero;
|
||||||
|
var bgImg = background.GetComponent<Image>(); bgImg.color = new Color(0.1f,0.1f,0.1f,1f);
|
||||||
|
|
||||||
|
var fillArea = new GameObject("Fill Area", typeof(RectTransform));
|
||||||
|
fillArea.transform.SetParent(go.transform, false);
|
||||||
|
var faRT = (RectTransform)fillArea.transform; faRT.anchorMin = new Vector2(0,0.25f); faRT.anchorMax = new Vector2(1,0.75f); faRT.offsetMin = new Vector2(10,0); faRT.offsetMax = new Vector2(-10,0);
|
||||||
|
|
||||||
|
var fill = new GameObject("Fill", typeof(RectTransform), typeof(Image));
|
||||||
|
fill.transform.SetParent(fillArea.transform, false);
|
||||||
|
var fillImg = fill.GetComponent<Image>(); fillImg.color = new Color(0.4f,0.9f,0.4f,1f);
|
||||||
|
var fillRT = (RectTransform)fill.transform; fillRT.anchorMin = new Vector2(0,0); fillRT.anchorMax = new Vector2(1,1); fillRT.offsetMin = Vector2.zero; fillRT.offsetMax = Vector2.zero;
|
||||||
|
|
||||||
|
var handleArea = new GameObject("Handle Slide Area", typeof(RectTransform));
|
||||||
|
handleArea.transform.SetParent(go.transform, false);
|
||||||
|
var haRT = (RectTransform)handleArea.transform; haRT.anchorMin = new Vector2(0,0); haRT.anchorMax = new Vector2(1,1); haRT.offsetMin = Vector2.zero; haRT.offsetMax = Vector2.zero;
|
||||||
|
|
||||||
|
var handle = new GameObject("Handle", typeof(RectTransform), typeof(Image));
|
||||||
|
handle.transform.SetParent(handleArea.transform, false);
|
||||||
|
var handleImg = handle.GetComponent<Image>(); handleImg.color = new Color(0.8f,1f,0.8f,1f);
|
||||||
|
var hRT = (RectTransform)handle.transform; hRT.sizeDelta = new Vector2(16, 24); hRT.anchorMin = new Vector2(0.5f,0.5f); hRT.anchorMax = new Vector2(0.5f,0.5f); hRT.anchoredPosition = Vector2.zero;
|
||||||
|
|
||||||
|
slider.fillRect = fill.GetComponent<RectTransform>();
|
||||||
|
slider.handleRect = handle.GetComponent<RectTransform>();
|
||||||
|
slider.targetGraphic = handleImg;
|
||||||
|
slider.direction = Slider.Direction.LeftToRight;
|
||||||
|
|
||||||
|
return go;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GameObject CreateLabeledSlider(Transform parent, string label, string name, float min, float max, float value)
|
||||||
|
{
|
||||||
|
var group = CreateVerticalGroup(parent, name + "_Group", 4, TextAnchor.UpperLeft, new RectOffset(0,0,0,0));
|
||||||
|
CreateText(group.transform, name + "_Label", label, 18, TextAnchor.MiddleLeft, Color.white, FontStyles.Normal);
|
||||||
|
CreateSlider(group.transform, name, min, max, value);
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
private static GameObject CreateToggle(Transform parent, string name, string labelText, bool initial)
|
private static GameObject CreateToggle(Transform parent, string name, string labelText, bool initial)
|
||||||
{
|
{
|
||||||
var go = new GameObject(name, typeof(RectTransform), typeof(Toggle));
|
var go = new GameObject(name, typeof(RectTransform), typeof(Toggle));
|
||||||
|
|||||||
@@ -643,6 +643,7 @@ GameObject:
|
|||||||
- component: {fileID: 7469640283978802878}
|
- component: {fileID: 7469640283978802878}
|
||||||
- component: {fileID: 1813583201016405249}
|
- component: {fileID: 1813583201016405249}
|
||||||
- component: {fileID: 3442404066554451922}
|
- component: {fileID: 3442404066554451922}
|
||||||
|
- component: {fileID: -2591875487324942466}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: Wizard 2.0
|
m_Name: Wizard 2.0
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@@ -733,6 +734,10 @@ MonoBehaviour:
|
|||||||
jumpHeight: 1.6
|
jumpHeight: 1.6
|
||||||
gravity: -20
|
gravity: -20
|
||||||
groundedGravity: -5
|
groundedGravity: -5
|
||||||
|
jumpBufferTime: 0.1
|
||||||
|
coyoteTime: 0.1
|
||||||
|
upwardGravityMultiplier: 1
|
||||||
|
fallGravityMultiplier: 2.5
|
||||||
cameraTransform: {fileID: 6707832248248563092}
|
cameraTransform: {fileID: 6707832248248563092}
|
||||||
animator: {fileID: 9099213046038254594}
|
animator: {fileID: 9099213046038254594}
|
||||||
animationDamping: 0.075
|
animationDamping: 0.075
|
||||||
@@ -906,6 +911,7 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::MegaKoop.Game.Networking.SteamCharacterNetworkBridge
|
m_EditorClassIdentifier: Assembly-CSharp::MegaKoop.Game.Networking.SteamCharacterNetworkBridge
|
||||||
characterController: {fileID: 3919077998180469670}
|
characterController: {fileID: 3919077998180469670}
|
||||||
|
animator: {fileID: 9099213046038254594}
|
||||||
identity: {fileID: 3262185422700989869}
|
identity: {fileID: 3262185422700989869}
|
||||||
rootTransform: {fileID: 3042213512511893744}
|
rootTransform: {fileID: 3042213512511893744}
|
||||||
networkInputProxy: {fileID: 3442404066554451922}
|
networkInputProxy: {fileID: 3442404066554451922}
|
||||||
@@ -955,6 +961,23 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: e3118c9c432a7acbd824645749251552, type: 3}
|
m_Script: {fileID: 11500000, guid: e3118c9c432a7acbd824645749251552, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::MegaKoop.Game.Networking.NetworkCharacterInputProxy
|
m_EditorClassIdentifier: Assembly-CSharp::MegaKoop.Game.Networking.NetworkCharacterInputProxy
|
||||||
|
--- !u!114 &-2591875487324942466
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 2809934685114486836}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 79fb1fbc20d80f546ba695c751860930, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::MegaKoop.Game.UI.SteamNameTag
|
||||||
|
followHead: {fileID: 852694279969892930}
|
||||||
|
worldOffset: {x: 0, y: 2.5, z: 0}
|
||||||
|
billboardToCamera: 1
|
||||||
|
hideForLocal: 1
|
||||||
|
visibleDistance: 60
|
||||||
--- !u!1 &2999616957953547817
|
--- !u!1 &2999616957953547817
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|||||||
@@ -1859,6 +1859,7 @@ GameObject:
|
|||||||
- component: {fileID: 7618815643042096284}
|
- component: {fileID: 7618815643042096284}
|
||||||
- component: {fileID: 2662658783078050447}
|
- component: {fileID: 2662658783078050447}
|
||||||
- component: {fileID: 2417536914360261273}
|
- component: {fileID: 2417536914360261273}
|
||||||
|
- component: {fileID: 2931281317230154068}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: Wizard
|
m_Name: Wizard
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@@ -2099,6 +2100,23 @@ MonoBehaviour:
|
|||||||
SwitchTransformSpaceWhenParented: 0
|
SwitchTransformSpaceWhenParented: 0
|
||||||
Interpolate: 1
|
Interpolate: 1
|
||||||
SlerpPosition: 0
|
SlerpPosition: 0
|
||||||
|
--- !u!114 &2931281317230154068
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 7059514996416789454}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 79fb1fbc20d80f546ba695c751860930, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::MegaKoop.Game.UI.SteamNameTag
|
||||||
|
followHead: {fileID: 7928616218613849049}
|
||||||
|
worldOffset: {x: 0, y: 1.2, z: 0}
|
||||||
|
billboardToCamera: 1
|
||||||
|
hideForLocal: 1
|
||||||
|
visibleDistance: 60
|
||||||
--- !u!1 &7094911519708027617
|
--- !u!1 &7094911519708027617
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|||||||
250
Game/Scripts/UI/SteamNameTag.cs
Normal file
250
Game/Scripts/UI/SteamNameTag.cs
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using TMPro;
|
||||||
|
using Steamworks;
|
||||||
|
using MegaKoop.Game.Networking;
|
||||||
|
|
||||||
|
namespace MegaKoop.Game.UI
|
||||||
|
{
|
||||||
|
[DefaultExecutionOrder(10000)]
|
||||||
|
[DisallowMultipleComponent]
|
||||||
|
public class SteamNameTag : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] private Transform followHead;
|
||||||
|
[SerializeField] private Vector3 worldOffset = new Vector3(0f, 2.5f, 0f);
|
||||||
|
[SerializeField] private bool billboardToCamera = true;
|
||||||
|
[SerializeField] private bool hideForLocal = true;
|
||||||
|
[SerializeField] private float visibleDistance = 60f;
|
||||||
|
|
||||||
|
private TextMeshPro text;
|
||||||
|
private Transform tagTransform;
|
||||||
|
private Transform camTransform;
|
||||||
|
private SteamCharacterNetworkBridge bridge;
|
||||||
|
private Callback<PersonaStateChange_t> personaChanged;
|
||||||
|
private ulong lastSteamId;
|
||||||
|
private float camFindTimer;
|
||||||
|
private Coroutine ensureActiveRoutine;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
// Reuse existing NameTag child if present (prevents duplicates when cloning templates)
|
||||||
|
var existing = transform.Find("NameTag");
|
||||||
|
GameObject go;
|
||||||
|
if (existing != null)
|
||||||
|
{
|
||||||
|
tagTransform = existing;
|
||||||
|
go = existing.gameObject;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
go = new GameObject("NameTag");
|
||||||
|
go.layer = gameObject.layer;
|
||||||
|
tagTransform = go.transform;
|
||||||
|
tagTransform.SetParent(transform, worldPositionStays: false);
|
||||||
|
}
|
||||||
|
if (!go.activeSelf) go.SetActive(true);
|
||||||
|
|
||||||
|
text = go.GetComponent<TextMeshPro>();
|
||||||
|
if (text == null)
|
||||||
|
{
|
||||||
|
text = go.AddComponent<TextMeshPro>();
|
||||||
|
}
|
||||||
|
text.alignment = TextAlignmentOptions.Center;
|
||||||
|
text.color = Color.white;
|
||||||
|
text.fontSize = 2.5f;
|
||||||
|
text.enableAutoSizing = true;
|
||||||
|
text.fontSizeMin = 1.5f;
|
||||||
|
text.fontSizeMax = 4.5f;
|
||||||
|
text.text = GetObjectDisplayName();
|
||||||
|
if (!text.gameObject.activeSelf) text.gameObject.SetActive(true);
|
||||||
|
text.enabled = true;
|
||||||
|
|
||||||
|
bridge = GetComponent<SteamCharacterNetworkBridge>();
|
||||||
|
|
||||||
|
if (followHead == null)
|
||||||
|
{
|
||||||
|
followHead = FindChildRecursive(transform, "Head");
|
||||||
|
if (followHead == null)
|
||||||
|
{
|
||||||
|
followHead = transform;
|
||||||
|
worldOffset = new Vector3(0f, 2.5f, 0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetFollowHead(Transform head, SteamCharacterNetworkBridge b)
|
||||||
|
{
|
||||||
|
if (head != null) followHead = head;
|
||||||
|
if (b != null) bridge = b;
|
||||||
|
UpdateDisplayName(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
camTransform = Camera.main != null ? Camera.main.transform : null;
|
||||||
|
TryCreatePersonaCallback();
|
||||||
|
if (tagTransform != null && !tagTransform.gameObject.activeSelf)
|
||||||
|
{
|
||||||
|
tagTransform.gameObject.SetActive(true);
|
||||||
|
}
|
||||||
|
if (text != null)
|
||||||
|
{
|
||||||
|
if (!text.gameObject.activeSelf) text.gameObject.SetActive(true);
|
||||||
|
text.enabled = true;
|
||||||
|
}
|
||||||
|
if (ensureActiveRoutine == null)
|
||||||
|
{
|
||||||
|
ensureActiveRoutine = StartCoroutine(EnsureActiveLoop());
|
||||||
|
}
|
||||||
|
UpdateDisplayName(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDisable()
|
||||||
|
{
|
||||||
|
personaChanged = null;
|
||||||
|
if (ensureActiveRoutine != null)
|
||||||
|
{
|
||||||
|
StopCoroutine(ensureActiveRoutine);
|
||||||
|
ensureActiveRoutine = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TryCreatePersonaCallback()
|
||||||
|
{
|
||||||
|
if (personaChanged == null)
|
||||||
|
{
|
||||||
|
personaChanged = Callback<PersonaStateChange_t>.Create(OnPersonaChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private System.Collections.IEnumerator EnsureActiveLoop()
|
||||||
|
{
|
||||||
|
var waiter = new WaitForEndOfFrame();
|
||||||
|
while (isActiveAndEnabled)
|
||||||
|
{
|
||||||
|
if (tagTransform != null && !tagTransform.gameObject.activeSelf)
|
||||||
|
{
|
||||||
|
tagTransform.gameObject.SetActive(true);
|
||||||
|
}
|
||||||
|
if (text != null)
|
||||||
|
{
|
||||||
|
if (!text.gameObject.activeSelf) text.gameObject.SetActive(true);
|
||||||
|
text.enabled = true;
|
||||||
|
}
|
||||||
|
yield return waiter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPersonaChanged(PersonaStateChange_t cb)
|
||||||
|
{
|
||||||
|
if (bridge == null) return;
|
||||||
|
if (cb.m_ulSteamID == bridge.OwnerSteamId)
|
||||||
|
{
|
||||||
|
UpdateDisplayName(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LateUpdate()
|
||||||
|
{
|
||||||
|
camFindTimer -= Time.unscaledDeltaTime;
|
||||||
|
if ((camTransform == null || !camTransform.gameObject.activeInHierarchy) && camFindTimer <= 0f)
|
||||||
|
{
|
||||||
|
var cam = Camera.main;
|
||||||
|
camTransform = cam != null ? cam.transform : null;
|
||||||
|
camFindTimer = 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Never deactivate the NameTag GameObject; only toggle text rendering
|
||||||
|
if (tagTransform != null && !tagTransform.gameObject.activeSelf)
|
||||||
|
{
|
||||||
|
tagTransform.gameObject.SetActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 basePos = followHead != null ? followHead.position : transform.position;
|
||||||
|
tagTransform.position = basePos + worldOffset;
|
||||||
|
|
||||||
|
if (billboardToCamera && camTransform != null)
|
||||||
|
{
|
||||||
|
Vector3 dir = tagTransform.position - camTransform.position;
|
||||||
|
if (dir.sqrMagnitude > 0.001f)
|
||||||
|
{
|
||||||
|
tagTransform.rotation = Quaternion.LookRotation(dir, Vector3.up);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text != null)
|
||||||
|
{
|
||||||
|
if (!text.gameObject.activeSelf) text.gameObject.SetActive(true);
|
||||||
|
text.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateDisplayName(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateDisplayName(bool force)
|
||||||
|
{
|
||||||
|
if (text == null) return;
|
||||||
|
ulong sid = 0;
|
||||||
|
if (bridge != null) sid = bridge.OwnerSteamId;
|
||||||
|
if (!force && sid == lastSteamId && !string.IsNullOrEmpty(text.text)) return;
|
||||||
|
|
||||||
|
lastSteamId = sid;
|
||||||
|
string display = null;
|
||||||
|
if (sid != 0)
|
||||||
|
{
|
||||||
|
display = ResolvePersonaName(sid);
|
||||||
|
}
|
||||||
|
if (string.IsNullOrWhiteSpace(display))
|
||||||
|
{
|
||||||
|
display = GetObjectDisplayName();
|
||||||
|
}
|
||||||
|
if (!string.Equals(text.text, display))
|
||||||
|
{
|
||||||
|
text.text = display;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ResolvePersonaName(ulong sid)
|
||||||
|
{
|
||||||
|
if (!SteamBootstrap.IsInitialized)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong local = SteamUser.GetSteamID().m_SteamID;
|
||||||
|
if (sid == local)
|
||||||
|
{
|
||||||
|
return SteamFriends.GetPersonaName();
|
||||||
|
}
|
||||||
|
|
||||||
|
var csid = new CSteamID(sid);
|
||||||
|
string name = SteamFriends.GetFriendPersonaName(csid);
|
||||||
|
if (string.IsNullOrEmpty(name) || name == "???")
|
||||||
|
{
|
||||||
|
SteamFriends.RequestUserInformation(csid, true);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetObjectDisplayName()
|
||||||
|
{
|
||||||
|
string n = transform.root != null ? transform.root.name : gameObject.name;
|
||||||
|
if (n.StartsWith("Wizard_"))
|
||||||
|
{
|
||||||
|
return n.Substring("Wizard_".Length);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Transform FindChildRecursive(Transform root, string name)
|
||||||
|
{
|
||||||
|
if (root == null) return null;
|
||||||
|
foreach (Transform c in root)
|
||||||
|
{
|
||||||
|
if (c.name == name) return c;
|
||||||
|
var r = FindChildRecursive(c, name);
|
||||||
|
if (r != null) return r;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Game/Scripts/UI/SteamNameTag.cs.meta
Normal file
2
Game/Scripts/UI/SteamNameTag.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 79fb1fbc20d80f546ba695c751860930
|
||||||
@@ -198,7 +198,7 @@ Transform:
|
|||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!1001 &1602869657
|
--- !u!1001 &1722262462
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@@ -615,4 +615,4 @@ SceneRoots:
|
|||||||
- {fileID: 1754255436}
|
- {fileID: 1754255436}
|
||||||
- {fileID: 1956492400}
|
- {fileID: 1956492400}
|
||||||
- {fileID: 1529537539}
|
- {fileID: 1529537539}
|
||||||
- {fileID: 1602869657}
|
- {fileID: 1722262462}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using TMPro;
|
|||||||
#else
|
#else
|
||||||
using TMPro;
|
using TMPro;
|
||||||
#endif
|
#endif
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace MegaKoop.UI
|
namespace MegaKoop.UI
|
||||||
{
|
{
|
||||||
@@ -37,6 +38,11 @@ namespace MegaKoop.UI
|
|||||||
private TMP_Dropdown ddResolution;
|
private TMP_Dropdown ddResolution;
|
||||||
private Button btnApplySettings;
|
private Button btnApplySettings;
|
||||||
private Button btnBackFromSettings;
|
private Button btnBackFromSettings;
|
||||||
|
private Slider slMaster;
|
||||||
|
private Slider slMusic;
|
||||||
|
private Slider slSFX;
|
||||||
|
private Dropdown ddQualityUI;
|
||||||
|
private Dropdown ddResolutionUI;
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
@@ -44,25 +50,54 @@ namespace MegaKoop.UI
|
|||||||
RefreshPanelReferences();
|
RefreshPanelReferences();
|
||||||
|
|
||||||
// Buttons
|
// Buttons
|
||||||
btnNewGame = FindButton("Button_NewGame");
|
btnNewGame = FindButton("Button_NewGame", panelMain ? panelMain.transform : this.transform);
|
||||||
btnContinue = FindButton("Button_Continue");
|
btnContinue = FindButton("Button_Continue", panelMain ? panelMain.transform : this.transform);
|
||||||
btnMultiplayer = FindButton("Button_Multiplayer");
|
btnMultiplayer = FindButton("Button_Multiplayer", panelMain ? panelMain.transform : this.transform);
|
||||||
btnSettings = FindButton("Button_Settings");
|
btnSettings = FindButton("Button_Settings", panelMain ? panelMain.transform : this.transform);
|
||||||
btnQuit = FindButton("Button_Quit");
|
btnQuit = FindButton("Button_Quit", panelMain ? panelMain.transform : this.transform);
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
ddQuality = FindDropdown("Dropdown_Quality");
|
ddQuality = FindDropdown("Dropdown_Quality", panelSettings ? panelSettings.transform : this.transform);
|
||||||
tgFullscreen = FindToggle("Toggle_Fullscreen");
|
if (!ddQuality) ddQualityUI = FindUIDropdown("Dropdown_Quality", panelSettings ? panelSettings.transform : this.transform);
|
||||||
ddResolution = FindDropdown("Dropdown_Resolution");
|
tgFullscreen = FindToggle("Toggle_Fullscreen", panelSettings ? panelSettings.transform : this.transform);
|
||||||
btnApplySettings = FindButton("Button_ApplySettings");
|
ddResolution = FindDropdown("Dropdown_Resolution", panelSettings ? panelSettings.transform : this.transform);
|
||||||
btnBackFromSettings = FindButton("Button_BackFromSettings");
|
if (!ddResolution) ddResolutionUI = FindUIDropdown("Dropdown_Resolution", panelSettings ? panelSettings.transform : this.transform);
|
||||||
|
btnApplySettings = FindButton("Button_ApplySettings", panelSettings ? panelSettings.transform : this.transform);
|
||||||
|
btnBackFromSettings = FindButton("Button_BackFromSettings", panelSettings ? panelSettings.transform : this.transform);
|
||||||
|
slMaster = FindSlider("Slider_MasterVolume", panelSettings ? panelSettings.transform : this.transform);
|
||||||
|
slMusic = FindSlider("Slider_MusicVolume", panelSettings ? panelSettings.transform : this.transform);
|
||||||
|
slSFX = FindSlider("Slider_SFXVolume", panelSettings ? panelSettings.transform : this.transform);
|
||||||
|
|
||||||
|
if (!btnApplySettings && panelSettings) btnApplySettings = FindButtonByLabel("APPLY", panelSettings.transform);
|
||||||
|
if (!btnBackFromSettings && panelSettings) btnBackFromSettings = FindButtonByLabel("BACK", panelSettings.transform);
|
||||||
|
|
||||||
WireEvents();
|
WireEvents();
|
||||||
|
|
||||||
|
InitializeSettingsUI();
|
||||||
|
|
||||||
// Ensure initial panels
|
// Ensure initial panels
|
||||||
ShowMainMenu();
|
ShowMainMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Dropdown FindUIDropdown(string name, Transform scope = null)
|
||||||
|
{
|
||||||
|
if (scope != null)
|
||||||
|
{
|
||||||
|
var comps = scope.GetComponentsInChildren<Dropdown>(true);
|
||||||
|
foreach (var c in comps)
|
||||||
|
{
|
||||||
|
if (c && c.name == name) return c;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var all = Resources.FindObjectsOfTypeAll<Dropdown>();
|
||||||
|
foreach (var c in all)
|
||||||
|
{
|
||||||
|
if (c && c.name == name && c.gameObject.scene.IsValid() && c.gameObject.scene.isLoaded) return c;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Allow UGUIMenuBuilder to inject panel refs directly
|
// Allow UGUIMenuBuilder to inject panel refs directly
|
||||||
public void SetPanels(GameObject main, GameObject settings, GameObject lobby)
|
public void SetPanels(GameObject main, GameObject settings, GameObject lobby)
|
||||||
{
|
{
|
||||||
@@ -93,32 +128,110 @@ namespace MegaKoop.UI
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Button FindButton(string name)
|
private Button FindButton(string name, Transform scope = null)
|
||||||
{
|
{
|
||||||
var go = GameObject.Find(name);
|
if (scope != null)
|
||||||
return go ? go.GetComponent<Button>() : null;
|
{
|
||||||
|
var comps = scope.GetComponentsInChildren<Button>(true);
|
||||||
|
foreach (var c in comps)
|
||||||
|
{
|
||||||
|
if (c && c.name == name) return c;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var all = Resources.FindObjectsOfTypeAll<Button>();
|
||||||
|
foreach (var c in all)
|
||||||
|
{
|
||||||
|
if (c && c.name == name && c.gameObject.scene.IsValid() && c.gameObject.scene.isLoaded) return c;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
private TMP_Dropdown FindDropdown(string name)
|
private TMP_Dropdown FindDropdown(string name, Transform scope = null)
|
||||||
{
|
{
|
||||||
var go = GameObject.Find(name);
|
if (scope != null)
|
||||||
return go ? go.GetComponent<TMP_Dropdown>() : null;
|
{
|
||||||
|
var comps = scope.GetComponentsInChildren<TMP_Dropdown>(true);
|
||||||
|
foreach (var c in comps)
|
||||||
|
{
|
||||||
|
if (c && c.name == name) return c;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var all = Resources.FindObjectsOfTypeAll<TMP_Dropdown>();
|
||||||
|
foreach (var c in all)
|
||||||
|
{
|
||||||
|
if (c && c.name == name && c.gameObject.scene.IsValid() && c.gameObject.scene.isLoaded) return c;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
private Toggle FindToggle(string name)
|
private Toggle FindToggle(string name, Transform scope = null)
|
||||||
{
|
{
|
||||||
var go = GameObject.Find(name);
|
if (scope != null)
|
||||||
return go ? go.GetComponent<Toggle>() : null;
|
{
|
||||||
|
var comps = scope.GetComponentsInChildren<Toggle>(true);
|
||||||
|
foreach (var c in comps)
|
||||||
|
{
|
||||||
|
if (c && c.name == name) return c;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var all = Resources.FindObjectsOfTypeAll<Toggle>();
|
||||||
|
foreach (var c in all)
|
||||||
|
{
|
||||||
|
if (c && c.name == name && c.gameObject.scene.IsValid() && c.gameObject.scene.isLoaded) return c;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Slider FindSlider(string name, Transform scope = null)
|
||||||
|
{
|
||||||
|
if (scope != null)
|
||||||
|
{
|
||||||
|
var comps = scope.GetComponentsInChildren<Slider>(true);
|
||||||
|
foreach (var c in comps)
|
||||||
|
{
|
||||||
|
if (c && c.name == name) return c;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var all = Resources.FindObjectsOfTypeAll<Slider>();
|
||||||
|
foreach (var c in all)
|
||||||
|
{
|
||||||
|
if (c && c.name == name && c.gameObject.scene.IsValid() && c.gameObject.scene.isLoaded) return c;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Button FindButtonByLabel(string label, Transform scope)
|
||||||
|
{
|
||||||
|
if (!scope) return null;
|
||||||
|
var btns = scope.GetComponentsInChildren<Button>(true);
|
||||||
|
for (int i = 0; i < btns.Length; i++)
|
||||||
|
{
|
||||||
|
var t = btns[i].GetComponentInChildren<TextMeshProUGUI>(true);
|
||||||
|
if (t && string.Equals(t.text?.Trim(), label, System.StringComparison.OrdinalIgnoreCase))
|
||||||
|
return btns[i];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WireEvents()
|
private void WireEvents()
|
||||||
{
|
{
|
||||||
if (btnNewGame) btnNewGame.onClick.AddListener(OnNewGame);
|
if (btnNewGame) btnNewGame.onClick.AddListener(OnNewGame); else Debug.LogWarning("[UGUIMainMenu] Button_NewGame not found");
|
||||||
if (btnContinue) btnContinue.onClick.AddListener(OnContinue);
|
if (btnContinue) btnContinue.onClick.AddListener(OnContinue); else Debug.LogWarning("[UGUIMainMenu] Button_Continue not found");
|
||||||
if (btnMultiplayer) btnMultiplayer.onClick.AddListener(OnOpenMultiplayer);
|
if (btnMultiplayer) btnMultiplayer.onClick.AddListener(OnOpenMultiplayer); else Debug.LogWarning("[UGUIMainMenu] Button_Multiplayer not found");
|
||||||
if (btnSettings) btnSettings.onClick.AddListener(OnOpenSettings);
|
if (btnSettings) btnSettings.onClick.AddListener(OnOpenSettings); else Debug.LogWarning("[UGUIMainMenu] Button_Settings not found");
|
||||||
if (btnQuit) btnQuit.onClick.AddListener(OnQuit);
|
if (btnQuit) btnQuit.onClick.AddListener(OnQuit); else Debug.LogWarning("[UGUIMainMenu] Button_Quit not found");
|
||||||
|
|
||||||
if (btnApplySettings) btnApplySettings.onClick.AddListener(ApplySettings);
|
if (btnApplySettings) btnApplySettings.onClick.AddListener(OnApplySettings); else Debug.LogWarning("[UGUIMainMenu] Button_ApplySettings not found");
|
||||||
if (btnBackFromSettings) btnBackFromSettings.onClick.AddListener(ShowMainMenu);
|
if (btnBackFromSettings) btnBackFromSettings.onClick.AddListener(ShowMainMenu); else Debug.LogWarning("[UGUIMainMenu] Button_BackFromSettings not found");
|
||||||
|
|
||||||
|
if (ddQuality) ddQuality.onValueChanged.AddListener(i => { Debug.Log("[UGUIMainMenu] Quality changed to index " + i); ddQuality.RefreshShownValue(); });
|
||||||
|
if (ddResolution) ddResolution.onValueChanged.AddListener(i => { Debug.Log("[UGUIMainMenu] Resolution changed to index " + i); ddResolution.RefreshShownValue(); });
|
||||||
|
if (ddQualityUI) ddQualityUI.onValueChanged.AddListener(i => { Debug.Log("[UGUIMainMenu] UI Quality changed to index " + i); ddQualityUI.RefreshShownValue(); });
|
||||||
|
if (ddResolutionUI) ddResolutionUI.onValueChanged.AddListener(i => { Debug.Log("[UGUIMainMenu] UI Resolution changed to index " + i); ddResolutionUI.RefreshShownValue(); });
|
||||||
|
if (tgFullscreen) tgFullscreen.onValueChanged.AddListener(v => { Debug.Log("[UGUIMainMenu] Fullscreen " + v); });
|
||||||
|
if (slMaster) slMaster.onValueChanged.AddListener(v => { AudioListener.volume = v / 100f; });
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowMainMenu()
|
private void ShowMainMenu()
|
||||||
@@ -158,6 +271,7 @@ namespace MegaKoop.UI
|
|||||||
if (panelMain) panelMain.SetActive(false);
|
if (panelMain) panelMain.SetActive(false);
|
||||||
if (panelSettings) panelSettings.SetActive(true);
|
if (panelSettings) panelSettings.SetActive(true);
|
||||||
if (panelLobby) panelLobby.SetActive(false);
|
if (panelLobby) panelLobby.SetActive(false);
|
||||||
|
Debug.Log("[UGUIMainMenu] Open Settings");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnNewGame()
|
private void OnNewGame()
|
||||||
@@ -211,19 +325,302 @@ namespace MegaKoop.UI
|
|||||||
{
|
{
|
||||||
QualitySettings.SetQualityLevel(ddQuality.value, true);
|
QualitySettings.SetQualityLevel(ddQuality.value, true);
|
||||||
}
|
}
|
||||||
|
else if (ddQualityUI)
|
||||||
|
{
|
||||||
|
QualitySettings.SetQualityLevel(ddQualityUI.value, true);
|
||||||
|
}
|
||||||
if (tgFullscreen)
|
if (tgFullscreen)
|
||||||
{
|
{
|
||||||
Screen.fullScreen = tgFullscreen.isOn;
|
Screen.fullScreen = tgFullscreen.isOn;
|
||||||
}
|
}
|
||||||
if (ddResolution)
|
if (ddResolution)
|
||||||
{
|
{
|
||||||
var opt = ddResolution.options[ddResolution.value].text; // e.g., "1920x1080"
|
if (ddResolution.options != null && ddResolution.options.Count > 0 && ddResolution.value >= 0 && ddResolution.value < ddResolution.options.Count)
|
||||||
var parts = opt.ToLower().Split('x');
|
|
||||||
if (parts.Length == 2 && int.TryParse(parts[0], out int w) && int.TryParse(parts[1], out int h))
|
|
||||||
{
|
{
|
||||||
Screen.SetResolution(w, h, Screen.fullScreenMode);
|
var opt = ddResolution.options[ddResolution.value].text; // e.g., "1920x1080"
|
||||||
|
var parts = opt.ToLower().Split('x');
|
||||||
|
if (parts.Length == 2 && int.TryParse(parts[0], out int w) && int.TryParse(parts[1], out int h))
|
||||||
|
{
|
||||||
|
Screen.SetResolution(w, h, Screen.fullScreenMode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (ddResolutionUI)
|
||||||
|
{
|
||||||
|
if (ddResolutionUI.options != null && ddResolutionUI.options.Count > 0 && ddResolutionUI.value >= 0 && ddResolutionUI.value < ddResolutionUI.options.Count)
|
||||||
|
{
|
||||||
|
var opt = ddResolutionUI.options[ddResolutionUI.value].text;
|
||||||
|
var parts = opt.ToLower().Split('x');
|
||||||
|
if (parts.Length == 2 && int.TryParse(parts[0], out int w) && int.TryParse(parts[1], out int h))
|
||||||
|
{
|
||||||
|
Screen.SetResolution(w, h, Screen.fullScreenMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (slMaster)
|
||||||
|
{
|
||||||
|
AudioListener.volume = slMaster.value / 100f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnApplySettings()
|
||||||
|
{
|
||||||
|
ApplySettings();
|
||||||
|
SaveSettings();
|
||||||
|
ShowMainMenu();
|
||||||
|
Debug.Log("[UGUIMainMenu] Apply & Back to Main");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeSettingsUI()
|
||||||
|
{
|
||||||
|
if (ddQuality)
|
||||||
|
{
|
||||||
|
var names = QualitySettings.names;
|
||||||
|
if (names != null && names.Length > 0)
|
||||||
|
{
|
||||||
|
ddQuality.ClearOptions();
|
||||||
|
ddQuality.AddOptions(new List<string>(names));
|
||||||
|
ddQuality.value = Mathf.Clamp(QualitySettings.GetQualityLevel(), 0, ddQuality.options.Count - 1);
|
||||||
|
ddQuality.RefreshShownValue();
|
||||||
|
}
|
||||||
|
ddQuality.interactable = true;
|
||||||
|
FixDropdownRaycasts(ddQuality);
|
||||||
|
SetupDropdownTemplateCanvas(ddQuality);
|
||||||
|
}
|
||||||
|
else if (ddQualityUI)
|
||||||
|
{
|
||||||
|
var names = QualitySettings.names;
|
||||||
|
if (names != null && names.Length > 0)
|
||||||
|
{
|
||||||
|
ddQualityUI.ClearOptions();
|
||||||
|
ddQualityUI.AddOptions(new List<Dropdown.OptionData>(System.Array.ConvertAll(names, s => new Dropdown.OptionData(s))));
|
||||||
|
ddQualityUI.value = Mathf.Clamp(QualitySettings.GetQualityLevel(), 0, ddQualityUI.options.Count - 1);
|
||||||
|
ddQualityUI.RefreshShownValue();
|
||||||
|
}
|
||||||
|
if (ddQualityUI.captionText == null)
|
||||||
|
{
|
||||||
|
var cap = ddQualityUI.transform.Find("Label");
|
||||||
|
if (cap) ddQualityUI.captionText = cap.GetComponent<Text>();
|
||||||
|
}
|
||||||
|
if (ddQualityUI.itemText == null && ddQualityUI.template)
|
||||||
|
{
|
||||||
|
var it = ddQualityUI.template.Find("Item");
|
||||||
|
if (it)
|
||||||
|
{
|
||||||
|
var lbl = it.Find("Item Label");
|
||||||
|
if (lbl) ddQualityUI.itemText = lbl.GetComponent<Text>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ddQualityUI.interactable = true;
|
||||||
|
FixDropdownRaycasts(ddQualityUI);
|
||||||
|
SetupDropdownTemplateCanvas(ddQualityUI);
|
||||||
|
Debug.Log("[UGUIMainMenu] UI Quality options=" + (ddQualityUI.options != null ? ddQualityUI.options.Count : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ddResolution)
|
||||||
|
{
|
||||||
|
var seen = new HashSet<string>();
|
||||||
|
var opts = new List<string>();
|
||||||
|
string cur = Screen.currentResolution.width + "x" + Screen.currentResolution.height;
|
||||||
|
int curIdx = 0;
|
||||||
|
foreach (var r in Screen.resolutions)
|
||||||
|
{
|
||||||
|
string s = r.width + "x" + r.height;
|
||||||
|
if (seen.Add(s))
|
||||||
|
{
|
||||||
|
if (s == cur) curIdx = opts.Count;
|
||||||
|
opts.Add(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (opts.Count == 0)
|
||||||
|
{
|
||||||
|
opts.Add(cur);
|
||||||
|
curIdx = 0;
|
||||||
|
}
|
||||||
|
ddResolution.ClearOptions();
|
||||||
|
ddResolution.AddOptions(opts);
|
||||||
|
ddResolution.value = Mathf.Clamp(curIdx, 0, ddResolution.options.Count - 1);
|
||||||
|
ddResolution.RefreshShownValue();
|
||||||
|
ddResolution.interactable = true;
|
||||||
|
FixDropdownRaycasts(ddResolution);
|
||||||
|
SetupDropdownTemplateCanvas(ddResolution);
|
||||||
|
}
|
||||||
|
else if (ddResolutionUI)
|
||||||
|
{
|
||||||
|
var seen = new HashSet<string>();
|
||||||
|
var opts = new List<string>();
|
||||||
|
string cur = Screen.currentResolution.width + "x" + Screen.currentResolution.height;
|
||||||
|
int curIdx = 0;
|
||||||
|
foreach (var r in Screen.resolutions)
|
||||||
|
{
|
||||||
|
string s = r.width + "x" + r.height;
|
||||||
|
if (seen.Add(s))
|
||||||
|
{
|
||||||
|
if (s == cur) curIdx = opts.Count;
|
||||||
|
opts.Add(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (opts.Count == 0)
|
||||||
|
{
|
||||||
|
opts.Add(cur);
|
||||||
|
curIdx = 0;
|
||||||
|
}
|
||||||
|
ddResolutionUI.ClearOptions();
|
||||||
|
ddResolutionUI.AddOptions(opts.ConvertAll(o => new Dropdown.OptionData(o)));
|
||||||
|
ddResolutionUI.value = Mathf.Clamp(curIdx, 0, ddResolutionUI.options.Count - 1);
|
||||||
|
ddResolutionUI.RefreshShownValue();
|
||||||
|
ddResolutionUI.interactable = true;
|
||||||
|
FixDropdownRaycasts(ddResolutionUI);
|
||||||
|
SetupDropdownTemplateCanvas(ddResolutionUI);
|
||||||
|
if (ddResolutionUI.captionText == null)
|
||||||
|
{
|
||||||
|
var cap = ddResolutionUI.transform.Find("Label");
|
||||||
|
if (cap) ddResolutionUI.captionText = cap.GetComponent<Text>();
|
||||||
|
}
|
||||||
|
if (ddResolutionUI.itemText == null && ddResolutionUI.template)
|
||||||
|
{
|
||||||
|
var it = ddResolutionUI.template.Find("Item");
|
||||||
|
if (it)
|
||||||
|
{
|
||||||
|
var lbl = it.Find("Item Label");
|
||||||
|
if (lbl) ddResolutionUI.itemText = lbl.GetComponent<Text>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Debug.Log("[UGUIMainMenu] UI Resolution options=" + (ddResolutionUI.options != null ? ddResolutionUI.options.Count : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tgFullscreen)
|
||||||
|
{
|
||||||
|
tgFullscreen.isOn = Screen.fullScreen;
|
||||||
|
tgFullscreen.interactable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveSettings()
|
||||||
|
{
|
||||||
|
if (ddQuality) PlayerPrefs.SetInt("QualityLevel", ddQuality.value);
|
||||||
|
PlayerPrefs.SetInt("Fullscreen", Screen.fullScreen ? 1 : 0);
|
||||||
|
if (ddResolution && ddResolution.options.Count > 0)
|
||||||
|
{
|
||||||
|
var opt = ddResolution.options[ddResolution.value].text;
|
||||||
|
var parts = opt.Split('x');
|
||||||
|
if (parts.Length == 2 && int.TryParse(parts[0], out int w) && int.TryParse(parts[1], out int h))
|
||||||
|
{
|
||||||
|
PlayerPrefs.SetInt("ResolutionWidth", w);
|
||||||
|
PlayerPrefs.SetInt("ResolutionHeight", h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (slMaster) PlayerPrefs.SetFloat("MasterVolume", slMaster.value);
|
||||||
|
if (slMusic) PlayerPrefs.SetFloat("MusicVolume", slMusic.value);
|
||||||
|
if (slSFX) PlayerPrefs.SetFloat("SFXVolume", slSFX.value);
|
||||||
|
PlayerPrefs.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadSettings()
|
||||||
|
{
|
||||||
|
if (ddQuality && ddQuality.options.Count > 0)
|
||||||
|
{
|
||||||
|
int q = PlayerPrefs.GetInt("QualityLevel", QualitySettings.GetQualityLevel());
|
||||||
|
ddQuality.value = Mathf.Clamp(q, 0, ddQuality.options.Count - 1);
|
||||||
|
ddQuality.RefreshShownValue();
|
||||||
|
}
|
||||||
|
else if (ddQualityUI && ddQualityUI.options.Count > 0)
|
||||||
|
{
|
||||||
|
int q = PlayerPrefs.GetInt("QualityLevel", QualitySettings.GetQualityLevel());
|
||||||
|
ddQualityUI.value = Mathf.Clamp(q, 0, ddQualityUI.options.Count - 1);
|
||||||
|
ddQualityUI.RefreshShownValue();
|
||||||
|
}
|
||||||
|
if (tgFullscreen)
|
||||||
|
{
|
||||||
|
bool full = PlayerPrefs.GetInt("Fullscreen", Screen.fullScreen ? 1 : 0) == 1;
|
||||||
|
tgFullscreen.isOn = full;
|
||||||
|
}
|
||||||
|
if (ddResolution && ddResolution.options.Count > 0)
|
||||||
|
{
|
||||||
|
int w = PlayerPrefs.GetInt("ResolutionWidth", Screen.currentResolution.width);
|
||||||
|
int h = PlayerPrefs.GetInt("ResolutionHeight", Screen.currentResolution.height);
|
||||||
|
string key = w + "x" + h;
|
||||||
|
int idx = ddResolution.options.FindIndex(o => o.text == key);
|
||||||
|
if (idx >= 0)
|
||||||
|
{
|
||||||
|
ddResolution.value = idx;
|
||||||
|
ddResolution.RefreshShownValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ddResolutionUI && ddResolutionUI.options.Count > 0)
|
||||||
|
{
|
||||||
|
int w = PlayerPrefs.GetInt("ResolutionWidth", Screen.currentResolution.width);
|
||||||
|
int h = PlayerPrefs.GetInt("ResolutionHeight", Screen.currentResolution.height);
|
||||||
|
string key = w + "x" + h;
|
||||||
|
int idx = ddResolutionUI.options.FindIndex(o => o.text == key);
|
||||||
|
if (idx >= 0)
|
||||||
|
{
|
||||||
|
ddResolutionUI.value = idx;
|
||||||
|
ddResolutionUI.RefreshShownValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (slMaster)
|
||||||
|
{
|
||||||
|
var mv = PlayerPrefs.GetFloat("MasterVolume", 100f);
|
||||||
|
slMaster.value = mv;
|
||||||
|
AudioListener.volume = mv / 100f;
|
||||||
|
}
|
||||||
|
if (slMusic)
|
||||||
|
{
|
||||||
|
slMusic.value = PlayerPrefs.GetFloat("MusicVolume", 80f);
|
||||||
|
}
|
||||||
|
if (slSFX)
|
||||||
|
{
|
||||||
|
slSFX.value = PlayerPrefs.GetFloat("SFXVolume", 100f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FixDropdownRaycasts(TMP_Dropdown dd)
|
||||||
|
{
|
||||||
|
if (!dd || dd.template == null) return;
|
||||||
|
var tpl = dd.template;
|
||||||
|
var vp = tpl.Find("Viewport");
|
||||||
|
if (vp)
|
||||||
|
{
|
||||||
|
var img = vp.GetComponent<Image>();
|
||||||
|
if (img) img.raycastTarget = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupDropdownTemplateCanvas(TMP_Dropdown dd)
|
||||||
|
{
|
||||||
|
if (!dd || dd.template == null) return;
|
||||||
|
var tpl = dd.template;
|
||||||
|
var cv = tpl.GetComponent<Canvas>();
|
||||||
|
if (cv == null) cv = tpl.gameObject.AddComponent<Canvas>();
|
||||||
|
cv.overrideSorting = true;
|
||||||
|
cv.sortingOrder = 5000;
|
||||||
|
if (!tpl.GetComponent<GraphicRaycaster>()) tpl.gameObject.AddComponent<GraphicRaycaster>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FixDropdownRaycasts(Dropdown dd)
|
||||||
|
{
|
||||||
|
if (!dd || dd.template == null) return;
|
||||||
|
var tpl = dd.template;
|
||||||
|
var vp = tpl.Find("Viewport");
|
||||||
|
if (vp)
|
||||||
|
{
|
||||||
|
var img = vp.GetComponent<Image>();
|
||||||
|
if (img) img.raycastTarget = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupDropdownTemplateCanvas(Dropdown dd)
|
||||||
|
{
|
||||||
|
if (!dd || dd.template == null) return;
|
||||||
|
var tpl = dd.template;
|
||||||
|
var cv = tpl.GetComponent<Canvas>();
|
||||||
|
if (cv == null) cv = tpl.gameObject.AddComponent<Canvas>();
|
||||||
|
cv.overrideSorting = true;
|
||||||
|
cv.sortingOrder = 5000;
|
||||||
|
if (!tpl.GetComponent<GraphicRaycaster>()) tpl.gameObject.AddComponent<GraphicRaycaster>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
17162
UI/UI_Canvas 1.prefab
Normal file
17162
UI/UI_Canvas 1.prefab
Normal file
File diff suppressed because it is too large
Load Diff
7
UI/UI_Canvas 1.prefab.meta
Normal file
7
UI/UI_Canvas 1.prefab.meta
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5d7cbc36e4a870b4a8f9960c98e02388
|
||||||
|
PrefabImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Reference in New Issue
Block a user