UI update 02
This commit is contained in:
@@ -13,102 +13,30 @@ public class UI_SelectSong_AutoPlayToggle : MonoBehaviour
|
||||
[Header("Tween")]
|
||||
[SerializeField] private float tweenDuration = 0.25f;
|
||||
[SerializeField] private Ease tweenEase = Ease.OutCubic;
|
||||
|
||||
private static readonly Color32 OnBg = new Color32(0x3A, 0x3A, 0x3A, 0xFF);
|
||||
private static readonly Color32 OffBg = new Color32(0xFF, 0xFF, 0xFF, 0xFF);
|
||||
private static readonly Color32 OnText = new Color32(0xFF, 0xFF, 0xFF, 0xFF);
|
||||
private static readonly Color32 OffText = new Color32(0x3A, 0x3A, 0x3A, 0xFF);
|
||||
private Color initialButtonColor = Color.white;
|
||||
private Color initialTextColor = Color.white;
|
||||
private bool hasInitialButtonColor;
|
||||
private bool hasInitialTextColor;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
TryAutoWire();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
TryAutoWire();
|
||||
|
||||
if (button != null)
|
||||
{
|
||||
button.onClick.RemoveListener(OnClick);
|
||||
button.onClick.AddListener(OnClick);
|
||||
}
|
||||
if (toggle != null)
|
||||
{
|
||||
toggle.onValueChanged.RemoveListener(OnToggleChanged);
|
||||
toggle.onValueChanged.AddListener(OnToggleChanged);
|
||||
// Keep UI state consistent with global setting.
|
||||
toggle.SetIsOnWithoutNotify(GameConfig.autoPlayEnabled);
|
||||
}
|
||||
|
||||
ApplyVisual(GameConfig.autoPlayEnabled, instant: true);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (button != null)
|
||||
{
|
||||
button.onClick.RemoveListener(OnClick);
|
||||
}
|
||||
if (toggle != null)
|
||||
{
|
||||
toggle.onValueChanged.RemoveListener(OnToggleChanged);
|
||||
}
|
||||
KillTweens();
|
||||
}
|
||||
|
||||
public void TryAutoWire()
|
||||
{
|
||||
button = button != null ? button : GetComponent<Button>();
|
||||
toggle = toggle != null ? toggle : GetComponent<Toggle>();
|
||||
buttonImage = buttonImage != null ? buttonImage : GetComponent<Image>();
|
||||
if (buttonImage == null && toggle != null && toggle.targetGraphic is Image tgImage)
|
||||
{
|
||||
buttonImage = tgImage;
|
||||
}
|
||||
labelText = labelText != null ? labelText : GetComponentInChildren<Text>(true);
|
||||
}
|
||||
|
||||
private void OnClick()
|
||||
{
|
||||
bool next = !GameConfig.autoPlayEnabled;
|
||||
GameConfig.SetAutoPlayEnabled(next);
|
||||
if (toggle != null)
|
||||
{
|
||||
toggle.SetIsOnWithoutNotify(next);
|
||||
}
|
||||
ApplyVisual(next, instant: false);
|
||||
}
|
||||
|
||||
private void OnToggleChanged(bool isOn)
|
||||
{
|
||||
GameConfig.SetAutoPlayEnabled(isOn);
|
||||
ApplyVisual(isOn, instant: false);
|
||||
}
|
||||
|
||||
private void ApplyVisual(bool enabled, bool instant)
|
||||
{
|
||||
Color targetBg = enabled ? OnBg : OffBg;
|
||||
Color targetText = enabled ? OnText : OffText;
|
||||
|
||||
if (instant || !Application.isPlaying || tweenDuration <= 0f)
|
||||
{
|
||||
if (buttonImage != null) buttonImage.color = targetBg;
|
||||
if (labelText != null) labelText.color = targetText;
|
||||
return;
|
||||
}
|
||||
|
||||
KillTweens();
|
||||
|
||||
if (buttonImage != null)
|
||||
buttonImage.DOColor(targetBg, tweenDuration).SetEase(tweenEase);
|
||||
if (labelText != null)
|
||||
labelText.DOColor(targetText, tweenDuration).SetEase(tweenEase);
|
||||
// Legacy component retained only for scene compatibility.
|
||||
// Autoplay UI is now driven exclusively by selected_songInfo.autoplayButton.
|
||||
}
|
||||
|
||||
private void KillTweens()
|
||||
{
|
||||
if (buttonImage != null) buttonImage.DOKill();
|
||||
if (labelText != null) labelText.DOKill();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,59 +3,10 @@ using UnityEngine.SceneManagement;
|
||||
|
||||
public static class UI_SelectSong_AutoPlayToggleBinder
|
||||
{
|
||||
private const string TargetSceneName = "selectYourSongFirst";
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
private static void Init()
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
SceneManager.sceneLoaded += OnSceneLoaded;
|
||||
}
|
||||
|
||||
private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
||||
{
|
||||
if (scene.name != TargetSceneName)
|
||||
return;
|
||||
|
||||
TryBind(scene);
|
||||
}
|
||||
|
||||
private static void TryBind(Scene scene)
|
||||
{
|
||||
// Ensure we have the latest persisted value (important when entering from editor play).
|
||||
GameConfig.LoadPrefs();
|
||||
|
||||
// Prefer the user's specified hierarchy if present (active only).
|
||||
GameObject go =
|
||||
SceneObjectLookupCache.Find("rightInfos/difficultyBtnInfos/difficultyBtnInfos/select_Auto") ??
|
||||
SceneObjectLookupCache.Find("rightInfos/difficultyBtnInfos/select_Auto");
|
||||
|
||||
if (go == null)
|
||||
{
|
||||
// Fallback: search by name in this scene (includes inactive objects).
|
||||
var transforms = Object.FindObjectsByType<Transform>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
for (int i = 0; i < transforms.Length; i++)
|
||||
{
|
||||
var t = transforms[i];
|
||||
if (t == null) continue;
|
||||
if (t.gameObject.scene != scene) continue;
|
||||
if (t.name != "select_Auto") continue;
|
||||
go = t.gameObject;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (go == null)
|
||||
{
|
||||
if (GameConfig.verboseLogs)
|
||||
Debug.LogWarning("[AutoPlay] select_Auto button not found in selectYourSongFirst scene. Autoplay toggle UI will be unavailable.");
|
||||
return;
|
||||
}
|
||||
|
||||
var toggle = go.GetComponent<UI_SelectSong_AutoPlayToggle>();
|
||||
if (toggle == null)
|
||||
toggle = go.AddComponent<UI_SelectSong_AutoPlayToggle>();
|
||||
|
||||
toggle.TryAutoWire();
|
||||
// Legacy autoplay binding has been retired.
|
||||
// selectYourSongFirst now uses selected_songInfo.autoplayButton as the single source of truth.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ public class UI_SelectSong_EnterAnim : MonoBehaviour
|
||||
for (int i = 0; i < difficultyGroup.childCount; i++)
|
||||
{
|
||||
RectTransform child = difficultyGroup.GetChild(i) as RectTransform;
|
||||
if (child != null)
|
||||
if (child != null && child.gameObject.activeSelf)
|
||||
{
|
||||
difficultyItems.Add(child);
|
||||
}
|
||||
@@ -317,7 +317,7 @@ public class UI_SelectSong_EnterAnim : MonoBehaviour
|
||||
void SnapVisible(RectTransform rect, bool applyScale)
|
||||
{
|
||||
if (rect == null) return;
|
||||
if (!rect.gameObject.activeSelf) rect.gameObject.SetActive(true);
|
||||
if (!rect.gameObject.activeSelf) return;
|
||||
|
||||
CacheBase(rect);
|
||||
if (basePos.TryGetValue(rect, out Vector2 pos))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -23,11 +24,20 @@ public class load_teammatesProfile : MonoBehaviour
|
||||
public Image teammate_profile_boarder_04;
|
||||
public Image teammate_profile_boarder_05;
|
||||
|
||||
[Header("Level Colors")]
|
||||
public Color levelColor_C;
|
||||
public Color levelColor_B;
|
||||
public Color levelColor_A;
|
||||
public Color levelColor_S;
|
||||
[Header("Level Border Sprites")]
|
||||
public Sprite[] levelBorderSprites;
|
||||
|
||||
[Header("Hover Details")]
|
||||
public loadDetailsPrefab hoverDetailsLoader;
|
||||
public GameObject hoverDetailsPrefab;
|
||||
public GameObject hoverDetailsParent;
|
||||
|
||||
private bool hoverTargetsBound;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
EnsureHoverTargetsBound();
|
||||
}
|
||||
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
IEnumerator Start()
|
||||
@@ -36,6 +46,38 @@ public class load_teammatesProfile : MonoBehaviour
|
||||
update_teammates_profile();
|
||||
}
|
||||
|
||||
private void EnsureHoverTargetsBound()
|
||||
{
|
||||
if (hoverTargetsBound)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BindHoverTarget(teammate_profile_01, 1);
|
||||
BindHoverTarget(teammate_profile_02, 2);
|
||||
BindHoverTarget(teammate_profile_03, 3);
|
||||
BindHoverTarget(teammate_profile_04, 4);
|
||||
BindHoverTarget(teammate_profile_05, 5);
|
||||
|
||||
hoverTargetsBound = true;
|
||||
}
|
||||
|
||||
private void BindHoverTarget(Image targetImage, int slotIndex)
|
||||
{
|
||||
if (targetImage == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TeammateProfileHoverTarget hoverTarget = targetImage.GetComponent<TeammateProfileHoverTarget>();
|
||||
if (hoverTarget == null)
|
||||
{
|
||||
hoverTarget = targetImage.gameObject.AddComponent<TeammateProfileHoverTarget>();
|
||||
}
|
||||
|
||||
hoverTarget.Bind(this, slotIndex);
|
||||
}
|
||||
|
||||
private IEnumerator EnsureHeroCache()
|
||||
{
|
||||
if (heroCacheReady) yield break;
|
||||
@@ -49,7 +91,7 @@ public class load_teammatesProfile : MonoBehaviour
|
||||
}
|
||||
|
||||
heroCacheBuilding = true;
|
||||
var allHeroes = Resources.LoadAll<AllyHero_SO>("");
|
||||
var allHeroes = RuntimeResourcesCache.LoadAllAllyHeroes();
|
||||
heroById = new Dictionary<int, AllyHero_SO>();
|
||||
if (allHeroes != null)
|
||||
{
|
||||
@@ -79,6 +121,8 @@ public class load_teammatesProfile : MonoBehaviour
|
||||
|
||||
public void update_teammates_profile()
|
||||
{
|
||||
EnsureHoverTargetsBound();
|
||||
|
||||
if (!heroCacheReady)
|
||||
{
|
||||
StartCoroutine(EnsureHeroCacheThenUpdate());
|
||||
@@ -98,12 +142,12 @@ public class load_teammatesProfile : MonoBehaviour
|
||||
teammate_profile_04.sprite = GetHeroSquareProfile(heroId4);
|
||||
teammate_profile_05.sprite = GetHeroSquareProfile(heroId5);
|
||||
|
||||
// Set border colors based on hero level
|
||||
teammate_profile_boarder_01.color = GetBorderColor(GetHeroLevel(heroId1, 1));
|
||||
teammate_profile_boarder_02.color = GetBorderColor(GetHeroLevel(heroId2, 2));
|
||||
teammate_profile_boarder_03.color = GetBorderColor(GetHeroLevel(heroId3, 3));
|
||||
teammate_profile_boarder_04.color = GetBorderColor(GetHeroLevel(heroId4, 4));
|
||||
teammate_profile_boarder_05.color = GetBorderColor(GetHeroLevel(heroId5, 5));
|
||||
// Set border sprites based on hero level
|
||||
ApplyBorderSprite(teammate_profile_boarder_01, GetHeroLevelKey(heroId1, 1));
|
||||
ApplyBorderSprite(teammate_profile_boarder_02, GetHeroLevelKey(heroId2, 2));
|
||||
ApplyBorderSprite(teammate_profile_boarder_03, GetHeroLevelKey(heroId3, 3));
|
||||
ApplyBorderSprite(teammate_profile_boarder_04, GetHeroLevelKey(heroId4, 4));
|
||||
ApplyBorderSprite(teammate_profile_boarder_05, GetHeroLevelKey(heroId5, 5));
|
||||
}
|
||||
|
||||
private Sprite GetHeroSquareProfile(int heroId)
|
||||
@@ -117,58 +161,153 @@ public class load_teammatesProfile : MonoBehaviour
|
||||
return null;
|
||||
}
|
||||
|
||||
private string GetHeroLevel(int heroId, int slotIndex)
|
||||
private string GetHeroLevelKey(int heroId, int slotIndex)
|
||||
{
|
||||
if (heroId == 0) return "C";
|
||||
if (heroById == null) return "C";
|
||||
if (heroId == 0) return "Fallback";
|
||||
if (heroById == null) return "Fallback";
|
||||
AllyHero_SO hero;
|
||||
if (!heroById.TryGetValue(heroId, out hero) || hero == null) return "C";
|
||||
int exp = hero.ally_currentEXP;
|
||||
int keySlot = Mathf.Clamp(slotIndex, 1, 5);
|
||||
string expKey = $"selected_heroSlot0{keySlot}_exp";
|
||||
if (PlayerPrefs.HasKey(expKey))
|
||||
exp = PlayerPrefs.GetInt(expKey, exp);
|
||||
return GetRatingFromSO(hero, exp);
|
||||
if (!heroById.TryGetValue(heroId, out hero) || hero == null) return "Fallback";
|
||||
return GetRatingKeyFromSO(hero);
|
||||
}
|
||||
|
||||
private string GetRatingFromSO(AllyHero_SO so, int currentExp)
|
||||
private string GetRatingKeyFromSO(AllyHero_SO so)
|
||||
{
|
||||
if (so == null || so.levelStats == null || so.levelStats.Count == 0) return "C";
|
||||
if (so == null || so.levelStats == null || so.levelStats.Count == 0) return "Fallback";
|
||||
return so.GetDisplayLevelRatingKey();
|
||||
}
|
||||
|
||||
List<AllyHero_SO.AllyLevelInfo> sorted = new List<AllyHero_SO.AllyLevelInfo>();
|
||||
foreach (var l in so.levelStats) if (l != null) sorted.Add(l);
|
||||
sorted.Sort((a, b) => a.requiredEXP.CompareTo(b.requiredEXP));
|
||||
int selectedIndex = 0;
|
||||
for (int i = 0; i < sorted.Count; i++)
|
||||
private void ApplyBorderSprite(Image targetImage, string level)
|
||||
{
|
||||
if (targetImage == null)
|
||||
{
|
||||
if (currentExp >= sorted[i].requiredEXP)
|
||||
{
|
||||
selectedIndex = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectedIndex <= 0) return "C";
|
||||
if (selectedIndex == 1) return "B";
|
||||
if (selectedIndex == 2) return "A";
|
||||
return "S";
|
||||
Sprite borderSprite = GetBorderSprite(level);
|
||||
targetImage.sprite = borderSprite;
|
||||
|
||||
targetImage.color = Color.white;
|
||||
}
|
||||
|
||||
private Color GetBorderColor(string level)
|
||||
private Sprite GetBorderSprite(string level)
|
||||
{
|
||||
Color color;
|
||||
if (levelBorderSprites == null || levelBorderSprites.Length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int index;
|
||||
switch (level)
|
||||
{
|
||||
case "C": color = levelColor_C; break;
|
||||
case "B": color = levelColor_B; break;
|
||||
case "A": color = levelColor_A; break;
|
||||
case "S": color = levelColor_S; break;
|
||||
default: color = Color.white; break;
|
||||
case "Fallback": index = 4; break;
|
||||
case "C": index = 0; break;
|
||||
case "B": index = 1; break;
|
||||
case "A": index = 2; break;
|
||||
case "S": index = 3; break;
|
||||
default: index = 4; break;
|
||||
}
|
||||
|
||||
if (index < 0 || index >= levelBorderSprites.Length)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return levelBorderSprites[index];
|
||||
}
|
||||
|
||||
public void ShowHeroDetailsForSlot(int slotIndex)
|
||||
{
|
||||
loadDetailsPrefab detailsLoader = ResolveDetailsLoader();
|
||||
if (detailsLoader == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!heroCacheReady)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int heroId = GetSelectedHeroId(slotIndex);
|
||||
if (heroId == 0 || heroById == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AllyHero_SO hero;
|
||||
if (!heroById.TryGetValue(heroId, out hero) || hero == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string type = "\u89d2\u8272";
|
||||
string name = string.IsNullOrEmpty(hero.ally_heroName) ? "\u672a\u77e5\u89d2\u8272" : hero.ally_heroName;
|
||||
string status = "\u53ef\u7528";
|
||||
string description = string.IsNullOrEmpty(hero.ally_heroDescription) ? "\u65e0\u63cf\u8ff0" : hero.ally_heroDescription;
|
||||
|
||||
if (hoverDetailsPrefab != null)
|
||||
{
|
||||
detailsLoader.detailsPrefab = hoverDetailsPrefab;
|
||||
}
|
||||
|
||||
if (hoverDetailsParent != null)
|
||||
{
|
||||
detailsLoader.detailsParent = hoverDetailsParent;
|
||||
}
|
||||
|
||||
detailsLoader.ShowDetails(type, name, status, description, Input.mousePosition);
|
||||
}
|
||||
|
||||
public void HideHeroDetails()
|
||||
{
|
||||
loadDetailsPrefab detailsLoader = ResolveDetailsLoader();
|
||||
if (detailsLoader != null)
|
||||
{
|
||||
detailsLoader.HideDetails();
|
||||
}
|
||||
}
|
||||
|
||||
private loadDetailsPrefab ResolveDetailsLoader()
|
||||
{
|
||||
if (hoverDetailsLoader != null)
|
||||
{
|
||||
return hoverDetailsLoader;
|
||||
}
|
||||
|
||||
return loadDetailsPrefab.Instance;
|
||||
}
|
||||
|
||||
private int GetSelectedHeroId(int slotIndex)
|
||||
{
|
||||
int keySlot = Mathf.Clamp(slotIndex, 1, 5);
|
||||
return PlayerPrefs.GetInt($"selected_heroSlot0{keySlot}_heroID", 0);
|
||||
}
|
||||
|
||||
private sealed class TeammateProfileHoverTarget : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
|
||||
{
|
||||
private load_teammatesProfile owner;
|
||||
private int slotIndex;
|
||||
|
||||
public void Bind(load_teammatesProfile targetOwner, int targetSlotIndex)
|
||||
{
|
||||
owner = targetOwner;
|
||||
slotIndex = targetSlotIndex;
|
||||
}
|
||||
|
||||
public void OnPointerEnter(PointerEventData eventData)
|
||||
{
|
||||
if (owner != null)
|
||||
{
|
||||
owner.ShowHeroDetailsForSlot(slotIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
if (owner != null)
|
||||
{
|
||||
owner.HideHeroDetails();
|
||||
}
|
||||
}
|
||||
color.a = 1f;
|
||||
return color;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using Bansonic;
|
||||
|
||||
public class returnMainMenu : MonoBehaviour
|
||||
{
|
||||
@@ -27,8 +28,17 @@ public class returnMainMenu : MonoBehaviour
|
||||
|
||||
private IEnumerator LoadSceneAsync(string sceneName)
|
||||
{
|
||||
if (gTransition.LoadScene(sceneName, LoadSceneMode.Single))
|
||||
{
|
||||
while (gTransition.IsBusy)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
|
||||
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName);
|
||||
while (!asyncLoad.isDone)
|
||||
while (asyncLoad != null && !asyncLoad.isDone)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user