Files
bansonic_beta_main/Assets/scripts/UI/Panel/UI_Panel_Main.cs
T

3775 lines
112 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using DG.Tweening;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Bansonic;
public class UI_Panel_Main : Singleton_Mono<UI_Panel_Main>
{
public int Character_Index
{
set
{
character_Index = value;
if(character_Index >= 0 && character_Index < data_List.Count)
Set_Character_Illustration(Get_Character_Image_Data(character_Index).ally_hero_HD_image);
}
get => character_Index;
}
public int character_Index = 0;
[SerializeField] List<AllyHero_SO> data_List = new List<AllyHero_SO>();
public List<AllyHero_SO> Data_List => data_List;
[SerializeField] Button button_Character_Set;
[SerializeField] GameObject ui_Panel_Character;
[SerializeField] Button button_Encyclopendia;
[SerializeField] GameObject ui_Panel_Encyclopendia;
[SerializeField] Transform notebook_father;
[SerializeField] Image image_Character;
[SerializeField] Button button_Mail;
[SerializeField] GameObject ui_Panel_Mail;
[SerializeField] Button button_Notice;
[SerializeField] GameObject ui_Panel_Notice;
[SerializeField] Button button_Level;
[SerializeField] GameObject ui_Panel_Level;
[SerializeField] MusicPlayer music_Player;
[SerializeField] GameObject ui_Panel_Music;
[SerializeField] Button button_Story;
[SerializeField] GameObject ui_Panel_Story;
[SerializeField] Button button_Setting;
[SerializeField] GameObject ui_Panel_Setting;
[SerializeField] float prefab_Enter_Time = 0.35f;
[SerializeField] float prefab_Enter_Scale_From = 0.92f;
[SerializeField] Ease prefab_Enter_Ease = Ease.OutCubic;
[SerializeField] Button button_Idol;
[SerializeField] GameObject ui_Panel_Idol;
[SerializeField] Button button_Select_Music;
[SerializeField] string ui_Select_Music_Scene_Name= "selectYourSongFirst";
[Header("Entry Animation")]
[SerializeField] bool play_Enter_OnEnable = true;
[SerializeField] float enter_Wait_Timeout = 1.5f;
[SerializeField] float enter_UI_Speed = 1.25f;
[SerializeField] float enter_Zoom_Time = 0.6f;
[SerializeField] float enter_Zoom_Scale_From = 1.2f;
[SerializeField] Ease enter_Zoom_Ease = Ease.OutCubic;
[SerializeField] float enter_Background_Time = 0.6f;
[SerializeField] float enter_Background_Scale_From = 1.12f;
[SerializeField] Ease enter_Background_Ease = Ease.OutCubic;
[SerializeField] float enter_Bar_Time = 0.45f;
[SerializeField] float enter_Item_Time = 0.35f;
[SerializeField] float enter_Stagger = 0.06f;
[SerializeField] float enter_Offset_X = 140f;
[SerializeField] float enter_Offset_Y = 120f;
[SerializeField] float enter_Item_Offset_X = 40f;
[SerializeField] float enter_Item_Offset_Y = 40f;
[SerializeField] Ease enter_Move_Ease = Ease.OutCubic;
[Header("Background Decorations Entry")]
[SerializeField] bool play_Background_Deco_Enter = true;
[SerializeField] float bg_Deco_Time = 0.45f;
[SerializeField] float bg_Deco_Stagger = 0.04f;
[SerializeField] float bg_Deco_Offset = 60f;
[SerializeField] float bg_Deco_Rotate = 6f;
[SerializeField] float bg_Deco_Scale_From = 0.9f;
[SerializeField] Ease bg_Deco_Ease = Ease.OutCubic;
[SerializeField] RectTransform background_Bg2;
[Header("Background Loop (Disabled)")]
[SerializeField] bool play_Background_Loop = false;
[SerializeField] float bg_Loop_Offset = 12f;
[SerializeField] float bg_Loop_Time = 6f;
[SerializeField] Ease bg_Loop_Ease = Ease.InOutSine;
[Header("Mouse Gyro")]
[SerializeField] bool play_Mouse_Gyro = true;
[SerializeField] bool gyro_Require_Enter_Complete = true;
[SerializeField] bool gyro_Use_Unscaled = true;
[SerializeField] RectTransform gyro_Target;
[SerializeField] RectTransform gyro_Character_Rect;
[SerializeField] RectTransform gyro_Dialog_Rect;
[SerializeField] float gyro_Max_Offset = 5f;
[SerializeField] float gyro_Offset_Scale = 7f;
[SerializeField] float gyro_Character_Weight = 1f;
[SerializeField] float gyro_Dialog_Weight = 1.35f;
[SerializeField] float gyro_Background_Weight = 0.8f;
[SerializeField] float gyro_RightButtons_Rotation_Weight = 0.6f;
[SerializeField] float gyro_DailyTasks_Rotation_Weight = 0.6f;
[SerializeField] float gyro_Max_Rotation = 2f;
[SerializeField] float gyro_Rotation_X = 1f;
[SerializeField] float gyro_Rotation_Y = 1f;
[SerializeField] float gyro_Rotation_Z = 0.35f;
[SerializeField] float gyro_Smooth = 8f;
[SerializeField] bool gyro_Apply_BG_Scale = false;
[SerializeField] float gyro_BG_Extra_Scale = 1.06f;
[SerializeField] float gyro_All_Offset_Min = 0.6f;
[SerializeField] float gyro_All_Offset_Max = 1.2f;
[SerializeField] bool gyro_Only_Leaf = true;
[SerializeField] bool gyro_Include_BG_Children = false;
[SerializeField] float gyro_BG_Child_Offset_Min = 0.2f;
[SerializeField] float gyro_BG_Child_Offset_Max = 0.8f;
[SerializeField] float gyro_BG_Child_Rotation_Min = 0.1f;
[SerializeField] float gyro_BG_Child_Rotation_Max = 0.5f;
[Header("Button Interactions")]
[SerializeField] bool play_Button_Interact = true;
[SerializeField] float button_Hover_Scale = 1.04f;
[SerializeField] float button_Press_Scale = 0.96f;
[SerializeField] float button_Hover_Time = 0.08f;
[SerializeField] float button_Press_Time = 0.06f;
[SerializeField] float button_Release_Time = 0.12f;
[SerializeField] Ease button_Hover_Ease = Ease.OutQuad;
[SerializeField] Ease button_Press_Ease = Ease.OutQuad;
[SerializeField] Ease button_Release_Ease = Ease.OutBack;
[Header("Right Buttons Hover")]
[SerializeField] bool play_RightButtons_Hover = true;
[SerializeField] float rightButton_Image_Idle_Offset = 180f;
[SerializeField] float rightButton_Image_Final_Offset = 60f;
[SerializeField] float rightButton_Image_Move_Time = 0.18f;
[SerializeField] Ease rightButton_Image_Ease = Ease.OutCubic;
[SerializeField] float rightButton_Text_Flash_Time = 0.06f;
[SerializeField] int rightButton_Text_Flash_Count = 2;
[SerializeField] float rightButton_Text_Flash_Interval = 0.02f;
[Header("Button Raycast Fix")]
[SerializeField] bool fix_Button_Raycast = true;
[SerializeField] bool fix_Button_Raycast_Log = false;
[Header("Entry References")]
[SerializeField] RectTransform content_Root;
[SerializeField] RectTransform zoom_MainRoot;
[SerializeField] RectTransform zoom_BarsRoot;
[SerializeField] RectTransform group_Background;
[SerializeField] RectTransform group_Top;
[SerializeField] RectTransform group_Bottom;
[SerializeField] RectTransform group_Center;
[SerializeField] RectTransform group_DailyTasks;
[SerializeField] RectTransform group_RightButtons;
[SerializeField] RectTransform group_RightButtons_Alt;
[SerializeField] RectTransform else_Button;
[SerializeField] RectTransform group_StartButton;
[SerializeField] RectTransform dailyTask_BG;
[SerializeField] RectTransform dailyTask_BG_1;
[SerializeField] RectTransform dailyTask_BG_2;
[SerializeField] RectTransform top_PlayerName;
[SerializeField] RectTransform button_Character_Set_Rect;
[SerializeField] RectTransform launch_EzGame_Rect;
[Header("Jiantou Loop")]
[SerializeField] bool play_Jiantou_Loop = true;
[SerializeField] bool jiantou_Require_Hover = true;
[SerializeField] RectTransform jiantou_Left_Template;
[SerializeField] RectTransform jiantou_Right_Template;
[SerializeField] string jiantou_Name_Contains = "jiantou";
[SerializeField] int jiantou_Pool_Size = 6;
[SerializeField] float jiantou_Move_Amplitude = 120f;
[SerializeField] float jiantou_Move_Duration = 8f;
[SerializeField] float jiantou_Stagger = 0.35f;
[SerializeField] float jiantou_Spacing = 180f;
[SerializeField] float jiantou_Hover_Move_Duration = 3f;
[SerializeField] float jiantou_Hover_Stagger = 0.15f;
[SerializeField] float jiantou_Hover_Spacing = 120f;
[SerializeField] float jiantou_Random_Y = 0f;
[SerializeField] float jiantou_Alpha_Min = 0.35f;
[SerializeField] float jiantou_Alpha_Max = 1f;
[SerializeField] int jiantou_Flash_Count = 3;
[SerializeField] float jiantou_Flash_Time = 0.06f;
[SerializeField] float jiantou_Flash_Interval = 0.04f;
class JiantouFlow
{
public RectTransform template;
public RectTransform parent;
public float direction;
public Vector2 basePos;
public float endLimitY;
public float speed;
public float spacing;
public readonly List<RectTransform> instances = new();
public readonly List<float> startY = new();
}
Sequence enter_Sequence;
Sequence bars_Sequence;
Coroutine enter_Routine;
readonly List<Tween> bg_Loop_Tweens = new();
readonly List<RectTransform> top_Items = new();
readonly List<RectTransform> task_Items = new();
readonly List<RectTransform> bottom_ButtonItems = new();
readonly List<RectTransform> right_ButtonItems = new();
readonly List<RectTransform> right_ButtonItems_Alt = new();
readonly List<RectTransform> center_Extra_Items = new();
readonly List<RectTransform> content_Extra_Items = new();
readonly List<RectTransform> bg_Loop_Items = new();
readonly Dictionary<RectTransform, Vector2> cached_Pos = new();
readonly Dictionary<RectTransform, Vector3> cached_Scale = new();
readonly Dictionary<RectTransform, float> cached_RotationZ = new();
bool enter_Debug_Logged;
bool enter_Played;
Vector2 pos_Top;
Vector2 pos_Bottom;
Vector2 pos_Daily;
Vector2 pos_Start;
Vector3 scale_Background;
Vector3 scale_MainRoot;
Vector3 scale_BarsRoot;
float enter_Background_Time_Runtime;
float enter_Bar_Time_Runtime;
float enter_Item_Time_Runtime;
float enter_Stagger_Runtime;
float enter_Blink_Time_Scale = 1f;
float bg_Deco_Time_Runtime;
float bg_Deco_Stagger_Runtime;
readonly List<RectTransform> gyro_Targets = new();
readonly Dictionary<RectTransform, Vector2> gyro_Base_Pos_Map = new();
readonly Dictionary<RectTransform, Vector3> gyro_Base_Rot_Map = new();
readonly Dictionary<RectTransform, float> gyro_Offset_Weight_Map = new();
readonly Dictionary<RectTransform, float> gyro_Rot_Weight_Map = new();
Vector2 gyro_Current_Offset;
Vector3 gyro_Current_RotDelta;
Vector3 gyro_BG_Base_Scale;
bool gyro_BG_Base_Scale_Set;
bool gyro_Inited;
readonly List<JiantouFlow> jiantou_Flows = new();
bool jiantou_Inited;
int gyro_LastFrame = -1;
bool jiantou_Running;
bool jiantou_Hovered;
Coroutine jiantou_Flash_Routine;
readonly List<Tween> jiantou_Flash_Tweens = new();
readonly List<UI_ButtonTween> button_Tweeners = new();
bool selectScene_Loading;
GameObject encyclopedia_Instance;
protected override void In_Init()
{
Cache_Enter_Refs();
}
protected override bool Is_Singleton_Auto()
{
return true;
}
protected override void OnDestroy()
{
Kill_Enter_Tweens();
// data_List contains references to assets in Resources, do not Destroy them.
data_List.Clear();
base.OnDestroy();
}
private void Start()
{
StartCoroutine(InitDataRoutine());
}
private IEnumerator InitDataRoutine()
{
var rawData = Resources.LoadAll<AllyHero_SO>("so/ally");
data_List = new List<AllyHero_SO>(rawData);
data_List.Sort((a, b) => a.ally_heroID.CompareTo(b.ally_heroID));
yield return null;
// 璇诲彇淇濆瓨鐨勮鑹?ID 骞跺垵濮嬪寲绱㈠紩
int savedHeroID = PlayerPrefs.GetInt("SelectedMainHeroID", -1);
if (savedHeroID != -1)
{
int foundIndex = data_List.FindIndex(h => h.ally_heroID == savedHeroID);
if (foundIndex != -1)
{
character_Index = foundIndex;
}
}
Character_Index = character_Index;
if(Character_Index >= 0 && Character_Index < data_List.Count)
Set_Character_Illustration(Get_Character_Image_Data(Character_Index).ally_hero_HD_image);
if (button_Character_Set != null)
button_Character_Set.onClick.AddListener(
() => Try_Open_Panel(ui_Panel_Character));
if (button_Mail != null)
button_Mail.onClick.AddListener(
() => Try_Open_Panel(ui_Panel_Mail));
if (button_Notice != null)
button_Notice.onClick.AddListener(
() => Try_Open_Panel(ui_Panel_Notice));
if (button_Level != null)
button_Level.onClick.AddListener(
() => Try_Open_Panel(ui_Panel_Level));
Character_Index = character_Index;
if (button_Encyclopendia != null)
button_Encyclopendia.onClick.AddListener(
() =>
{
Try_Open_Prefab(ui_Panel_Encyclopendia, ref encyclopedia_Instance);
DailyTaskEventHub.ReportWatchStory();
});
if (button_Story != null)
button_Story.onClick.AddListener(
() =>
{
gNotice.warning.display("姝ょ増鏈湭寮€鏀捐鍔熻兘");
//Try_Open_Panel(ui_Panel_Story);
});
if (button_Idol != null)
button_Idol.onClick.AddListener(
() =>
{
Toggle_Panel(ui_Panel_Idol);
});
if (music_Player != null && music_Player.Button_List != null)
music_Player.Button_List.onClick.AddListener(
() => Try_Open_Panel(ui_Panel_Music));
if (button_Setting != null)
button_Setting.onClick.AddListener(
() => Try_Open_Panel(ui_Panel_Setting));
if (button_Select_Music != null)
button_Select_Music.onClick.AddListener(
() => Try_Load_Select_Scene());
}
bool Try_Open_Panel(GameObject panel)
{
if (panel == null)
{
return false;
}
if (panel.activeInHierarchy)
{
return false;
}
if (panel == ui_Panel_Setting)
{
UI_SettingsPanelEnterAnim enterAnim = panel.GetComponent<UI_SettingsPanelEnterAnim>();
if (enterAnim == null)
enterAnim = panel.AddComponent<UI_SettingsPanelEnterAnim>();
enterAnim.enabled = true;
}
panel.SetActive(true);
return true;
}
void Toggle_Panel(GameObject panel)
{
if (panel == null)
{
return;
}
if (panel.activeSelf)
{
panel.SetActive(false);
return;
}
if (panel == ui_Panel_Setting)
{
UI_SettingsPanelEnterAnim enterAnim = panel.GetComponent<UI_SettingsPanelEnterAnim>();
if (enterAnim == null)
enterAnim = panel.AddComponent<UI_SettingsPanelEnterAnim>();
enterAnim.enabled = true;
}
panel.SetActive(true);
}
GameObject Try_Open_Prefab(GameObject prefab, ref GameObject instance)
{
if (prefab == null) return null;
if (instance == null)
{
var parent = notebook_father != null ? notebook_father : (transform.parent != null ? transform.parent : transform);
instance = Instantiate(prefab, parent);
}
AssignPrefabCanvasCamera(instance);
if (!instance.activeSelf) instance.SetActive(true);
Play_Prefab_Enter(instance);
return instance;
}
void AssignPrefabCanvasCamera(GameObject instance)
{
if (instance == null) return;
var canvases = instance.GetComponentsInChildren<Canvas>(true);
if (canvases == null || canvases.Length == 0) return;
Camera targetCamera = Camera.main;
if (targetCamera == null)
{
var cams = Camera.allCameras;
if (cams != null && cams.Length > 0) targetCamera = cams[0];
}
if (targetCamera == null) return;
for (int i = 0; i < canvases.Length; i++)
{
var canvas = canvases[i];
if (canvas == null) continue;
canvas.worldCamera = targetCamera;
}
}
void Play_Prefab_Enter(GameObject panel)
{
if (panel == null) return;
var rect = panel.transform as RectTransform;
if (rect == null) rect = panel.GetComponent<RectTransform>();
if (rect == null) return;
rect.DOKill();
var cg = panel.GetComponent<CanvasGroup>();
if (cg == null) cg = panel.AddComponent<CanvasGroup>();
cg.DOKill();
rect.localScale = Vector3.one * prefab_Enter_Scale_From;
cg.alpha = 0f;
rect.DOScale(Vector3.one, prefab_Enter_Time).SetEase(prefab_Enter_Ease);
cg.DOFade(1f, prefab_Enter_Time).SetEase(prefab_Enter_Ease);
}
void Try_Load_Select_Scene()
{
if (selectScene_Loading)
{
return;
}
selectScene_Loading = true;
// Documentation text normalized.
StartCoroutine(LoadSelectSceneAsync());
}
IEnumerator LoadSelectSceneAsync()
{
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(ui_Select_Music_Scene_Name, LoadSceneMode.Single);
// Documentation text normalized.
while (!asyncLoad.isDone)
{
yield return null;
}
}
private void OnEnable()
{
if (SceneManager.GetActiveScene().name == "UI_UI")
{
play_Mouse_Gyro = false;
Reset_Gyro_To_Base();
}
enter_Played = false;
gyro_Inited = false;
Canvas.willRenderCanvases += OnWillRenderCanvases;
Setup_Button_Tweens();
Setup_RightButtons_Hover();
Setup_Jiantou_Hover();
Fix_Button_Raycast();
Ensure_Character_Dialog_Controller();
StartCoroutine(Ensure_Character_Dialog_Controller_Delayed());
if (play_Enter_OnEnable)
{
Start_Enter_Routine();
}
else if (play_Jiantou_Loop)
{
Start_Jiantou_Loop();
}
}
IEnumerator Ensure_Character_Dialog_Controller_Delayed()
{
yield return null;
Ensure_Character_Dialog_Controller();
yield return null;
Ensure_Character_Dialog_Controller();
}
void Ensure_Character_Dialog_Controller()
{
Scene scene = SceneManager.GetActiveScene();
if (!scene.IsValid() || !string.Equals(scene.name, "UI_UI", StringComparison.OrdinalIgnoreCase))
{
return;
}
GameObject host = null;
Transform[] all = UnityEngine.Object.FindObjectsByType<Transform>(FindObjectsInactive.Include, FindObjectsSortMode.None);
for (int i = 0; i < all.Length; i++)
{
Transform t = all[i];
if (t == null || t.gameObject.scene != scene)
{
continue;
}
if (string.Equals(t.name, "__UICharacterDialogControllerHost", StringComparison.Ordinal))
{
host = t.gameObject;
break;
}
}
if (host == null)
{
host = new GameObject("__UICharacterDialogControllerHost");
try { SceneManager.MoveGameObjectToScene(host, scene); } catch { }
}
UI_CharacterDialogController controller = host.GetComponent<UI_CharacterDialogController>();
if (controller == null)
{
controller = host.AddComponent<UI_CharacterDialogController>();
}
if (!controller.enabled)
{
controller.enabled = true;
}
controller.RebindSoon();
}
void Fix_Button_Raycast()
{
if (!fix_Button_Raycast)
{
return;
}
Cache_Enter_Refs();
Apply_Button_RaycastLimiter(group_DailyTasks);
Apply_Button_RaycastLimiter(group_RightButtons);
Apply_Button_RaycastLimiter(group_RightButtons_Alt);
}
void Apply_Button_RaycastLimiter(RectTransform root)
{
if (root == null)
{
return;
}
Button[] buttons = root.GetComponentsInChildren<Button>(true);
for (int i = 0; i < buttons.Length; i++)
{
Button button = buttons[i];
if (button == null)
{
continue;
}
Graphic target = button.targetGraphic != null ? button.targetGraphic : button.GetComponent<Graphic>();
if (target == null)
{
continue;
}
Graphic[] graphics = button.GetComponentsInChildren<Graphic>(true);
for (int j = 0; j < graphics.Length; j++)
{
Graphic g = graphics[j];
if (g == null)
{
continue;
}
g.raycastTarget = g == target;
}
if (fix_Button_Raycast_Log)
{
Debug.Log($"[UI_Panel_Main] Raycast limited for '{button.name}' under '{root.name}'. TargetGraphic='{target.name}'.");
}
}
}
private void OnDisable()
{
if (enter_Routine != null)
{
StopCoroutine(enter_Routine);
enter_Routine = null;
}
Kill_Enter_Tweens();
Reset_Gyro_To_Base();
Stop_Jiantou_Loop();
button_Tweeners.Clear();
Canvas.willRenderCanvases -= OnWillRenderCanvases;
}
void Setup_Button_Tweens()
{
if (!play_Button_Interact)
{
return;
}
Cache_Enter_Refs();
button_Tweeners.Clear();
Transform root = transform;
Button[] buttons = root.GetComponentsInChildren<Button>(true);
for (int i = 0; i < buttons.Length; i++)
{
Button button = buttons[i];
if (button == null)
{
continue;
}
UI_ButtonTween tweener = button.GetComponent<UI_ButtonTween>();
if (tweener == null)
{
tweener = button.gameObject.AddComponent<UI_ButtonTween>();
}
tweener.ApplyConfig(button_Hover_Scale, button_Press_Scale, button_Hover_Time, button_Press_Time,
button_Release_Time, button_Hover_Ease, button_Press_Ease, button_Release_Ease);
button_Tweeners.Add(tweener);
}
}
void Setup_Jiantou_Hover()
{
if (!play_Jiantou_Loop || !jiantou_Require_Hover)
{
return;
}
Cache_Enter_Refs();
RectTransform startRect = group_StartButton;
if (startRect == null)
{
startRect = Find_Rect(transform, "Button_Start", "Start", "START");
}
if (startRect == null)
{
return;
}
Button startButton = startRect.GetComponent<Button>();
if (startButton == null)
{
startButton = startRect.GetComponentInChildren<Button>(true);
}
if (startButton == null)
{
return;
}
UI_JiantouHover hover = startButton.GetComponent<UI_JiantouHover>();
if (hover == null)
{
hover = startButton.gameObject.AddComponent<UI_JiantouHover>();
}
hover.Bind(this);
if (!jiantou_Inited)
{
Cache_Jiantou_Templates();
Build_Jiantou_Pool();
jiantou_Inited = jiantou_Flows.Count > 0;
}
Hide_Jiantou_All();
}
void Setup_StartButton_Hover(Button startButton)
{
if (startButton == null)
{
return;
}
UI_StartButtonHover hover = startButton.GetComponent<UI_StartButtonHover>();
if (hover == null)
{
hover = startButton.gameObject.AddComponent<UI_StartButtonHover>();
}
hover.ApplyTexts("鎵ц浠诲姟", "Start", "鎰忓織澶嶆紨", "REITERATION OF WILL");
}
void Setup_RightButtons_Hover()
{
if (!play_RightButtons_Hover)
{
return;
}
Cache_Enter_Refs();
if (group_RightButtons == null)
{
return;
}
Button[] buttons = group_RightButtons.GetComponentsInChildren<Button>(true);
for (int i = 0; i < buttons.Length; i++)
{
Button button = buttons[i];
if (button == null)
{
continue;
}
UI_RightButtonHover hover = button.GetComponent<UI_RightButtonHover>();
if (hover == null)
{
hover = button.gameObject.AddComponent<UI_RightButtonHover>();
}
hover.ApplyConfig(rightButton_Image_Idle_Offset, rightButton_Image_Final_Offset, rightButton_Image_Move_Time,
rightButton_Image_Ease, rightButton_Text_Flash_Time, rightButton_Text_Flash_Count, rightButton_Text_Flash_Interval);
}
}
private void LateUpdate()
{
if (play_Mouse_Gyro)
{
if (!gyro_Require_Enter_Complete || enter_Sequence == null || !enter_Sequence.IsPlaying())
{
if (gyro_LastFrame != Time.frameCount)
{
Update_Gyro();
}
}
}
Update_Jiantou_Loop();
}
void OnWillRenderCanvases()
{
if (!play_Mouse_Gyro)
{
return;
}
if (gyro_Require_Enter_Complete && enter_Sequence != null && enter_Sequence.IsPlaying())
{
return;
}
if (gyro_LastFrame == Time.frameCount)
{
return;
}
Update_Gyro();
}
void Update_Gyro()
{
gyro_LastFrame = Time.frameCount;
if (!gyro_Inited)
{
Ensure_Gyro_Targets();
Capture_Gyro_Base();
}
if (gyro_Targets.Count == 0)
{
return;
}
float width = Screen.width;
float height = Screen.height;
if (width <= 0f || height <= 0f)
{
return;
}
Vector2 center = new Vector2(width * 0.5f, height * 0.5f);
Vector2 delta = (Vector2)Input.mousePosition - center;
Vector2 norm = new Vector2(
center.x > 0f ? delta.x / center.x : 0f,
center.y > 0f ? delta.y / center.y : 0f);
norm = Vector2.ClampMagnitude(norm, 1f);
Vector2 targetOffset = new Vector2(norm.x * gyro_Max_Offset, 0f);
targetOffset *= Mathf.Max(gyro_Offset_Scale, 0f);
Vector3 targetRotDelta = new Vector3(
-norm.y * gyro_Max_Rotation * gyro_Rotation_X,
norm.x * gyro_Max_Rotation * gyro_Rotation_Y,
norm.x * gyro_Max_Rotation * gyro_Rotation_Z);
float dt = gyro_Use_Unscaled ? Time.unscaledDeltaTime : Time.deltaTime;
float t = 1f - Mathf.Exp(-Mathf.Max(gyro_Smooth, 0.01f) * dt);
gyro_Current_Offset = Vector2.Lerp(gyro_Current_Offset, targetOffset, t);
gyro_Current_RotDelta = Vector3.Lerp(gyro_Current_RotDelta, targetRotDelta, t);
for (int i = 0; i < gyro_Targets.Count; i++)
{
RectTransform target = gyro_Targets[i];
if (target == null || !gyro_Base_Pos_Map.TryGetValue(target, out Vector2 basePos))
{
continue;
}
float offsetWeight = gyro_Offset_Weight_Map.TryGetValue(target, out float ow) ? ow : 1f;
float rotWeight = gyro_Rot_Weight_Map.TryGetValue(target, out float rw) ? rw : 1f;
target.anchoredPosition = basePos + gyro_Current_Offset * offsetWeight;
if (gyro_Base_Rot_Map.TryGetValue(target, out Vector3 baseRot))
{
Vector3 euler = baseRot + gyro_Current_RotDelta * rotWeight;
target.localEulerAngles = euler;
}
}
}
public AllyHero_SO Get_Character_Image_Data(int index)
{
if(index < 0 || index >= data_List.Count) return null;
return data_List[index];
}
public AllyHero_SO Get_Character_Image_Data()
{
if(character_Index < 0 || character_Index >= data_List.Count) return null;
return data_List[character_Index];
}
public void Set_Character_Illustration(Sprite sprite)
{
if (c_Character_Illustration_Anim != null)
{
StopCoroutine(c_Character_Illustration_Anim);
}
if (image_Character.TryGetComponent(out CanvasGroup canvasGroup))
{
c_Character_Illustration_Anim = StartCoroutine(C_Character_Illustration_Anim(canvasGroup, () =>
{
image_Character.sprite = sprite;
// image_Character.SetNativeSize(); // 娉ㄩ噴鎺?SetNativeSize 浠ラ槻鏀瑰彉鐩爣鍥剧墖澶у皬
}));
}
}
Coroutine c_Character_Illustration_Anim;
[SerializeField] float character_Illustration_Time = 0.5f;
IEnumerator C_Character_Illustration_Anim(CanvasGroup canvasGroup, Action onHide)
{
float a = 1f / character_Illustration_Time;
while (canvasGroup.alpha > 0)
{
canvasGroup.alpha -= a * Time.unscaledDeltaTime;
yield return null;
}
onHide?.Invoke();
while (canvasGroup.alpha < 1)
{
canvasGroup.alpha += a * Time.unscaledDeltaTime;
yield return null;
}
}
void Cache_Enter_Refs()
{
Ensure_Scene_Ref(ref group_Top);
Ensure_Scene_Ref(ref group_Bottom);
Ensure_Scene_Ref(ref group_Background);
Ensure_Scene_Ref(ref group_Center);
Ensure_Scene_Ref(ref group_DailyTasks);
Ensure_Scene_Ref(ref group_RightButtons);
Ensure_Scene_Ref(ref group_RightButtons_Alt);
Ensure_Scene_Ref(ref else_Button);
Ensure_Scene_Ref(ref group_StartButton);
Ensure_Scene_Ref(ref top_PlayerName);
Ensure_Scene_Ref(ref zoom_MainRoot);
Ensure_Scene_Ref(ref zoom_BarsRoot);
Ensure_Scene_Ref(ref button_Character_Set_Rect);
Ensure_Scene_Ref(ref launch_EzGame_Rect);
if (content_Root == null)
{
content_Root = transform.Find("Content") as RectTransform;
}
Transform searchRoot = content_Root != null ? content_Root : transform;
if (zoom_MainRoot == null)
{
zoom_MainRoot = content_Root != null ? content_Root : transform as RectTransform;
}
if (group_Background == null)
{
group_Background = Find_Rect(searchRoot, "BG");
}
if (background_Bg2 == null && group_Background != null)
{
background_Bg2 = Find_Rect(group_Background, "bg2", "BG2", "BackGround_2", "Background_2", "BackGround2", "Background2");
if (background_Bg2 == null && group_Background.childCount > 1)
{
background_Bg2 = group_Background.GetChild(group_Background.childCount - 1) as RectTransform;
}
}
if (background_Bg2 == null)
{
background_Bg2 = Find_Rect(searchRoot, "bg2", "BG2", "BackGround_2", "Background_2", "BackGround2", "Background2");
}
if (background_Bg2 == null)
{
background_Bg2 = Find_Rect_Global("bg2", "BG2", "BackGround_2", "Background_2", "BackGround2", "Background2");
}
if (group_Top == null)
{
group_Top = Find_Rect(searchRoot, "TOP", "Top", "TopBar", "Top_Bar");
}
if (group_Bottom == null)
{
group_Bottom = Find_Rect(searchRoot, "BTM", "Bottom", "BottomBar", "Bottom_Bar");
}
if (group_Center == null)
{
group_Center = Find_Rect(searchRoot, "CTR", "Center", "Middle");
}
if (group_DailyTasks == null)
{
group_DailyTasks = Find_Rect(group_Center != null ? group_Center : searchRoot, "UI_DAILY_TASKS", "DailyTasks");
}
if (group_DailyTasks != null)
{
if (dailyTask_BG == null)
{
dailyTask_BG = Find_Rect(group_DailyTasks, "DTask BG", "DTASK BG", "DTask_BG");
}
if (dailyTask_BG_1 == null)
{
dailyTask_BG_1 = Find_Rect(group_DailyTasks, "DTask BG (1)", "DTASK BG (1)", "DTask_BG (1)");
}
if (dailyTask_BG_2 == null)
{
dailyTask_BG_2 = Find_Rect(group_DailyTasks, "DTask BG (2)", "DTASK BG (2)", "DTask_BG (2)");
}
}
if (group_RightButtons == null)
{
group_RightButtons = Find_Rect(group_Center != null ? group_Center : searchRoot, "R_OTHER_BUTTON_G", "RightButtons", "Right_Button_G");
}
if (group_RightButtons_Alt == null)
{
group_RightButtons_Alt = Find_Rect(group_Center != null ? group_Center : searchRoot, "R_OTHER_BUTTON_G2", "RightButtons2", "Right_Button_G2");
}
if (else_Button == null)
{
else_Button = Find_Rect(group_Center != null ? group_Center : searchRoot, "else_button", "Else_Button", "ELSE_BUTTON");
}
if (group_StartButton == null)
{
group_StartButton = Find_Rect(searchRoot, "Button_Start", "Start", "START");
}
if (top_PlayerName == null && group_Top != null)
{
top_PlayerName = Find_Rect(group_Top, "UI_PLAYER", "Player", "PlayerName");
}
if (button_Character_Set_Rect == null)
{
if (button_Character_Set != null && Is_Scene_Object(button_Character_Set))
{
button_Character_Set_Rect = button_Character_Set.transform as RectTransform;
}
}
if (button_Character_Set_Rect == null)
{
button_Character_Set_Rect = Find_Rect(group_Center != null ? group_Center : searchRoot, "Button_CHARACTER_SET", "CHARACTER_SET", "Character_Set");
}
if (button_Character_Set_Rect == null)
{
button_Character_Set_Rect = Find_Rect_Global("Button_CHARACTER_SET", "CHARACTER_SET", "Character_Set");
}
if (launch_EzGame_Rect == null)
{
launch_EzGame_Rect = Find_Rect(searchRoot, "launchEzGame", "LaunchEzGame", "launch_ezgame");
}
if (launch_EzGame_Rect == null)
{
launch_EzGame_Rect = Find_Rect_Global("launchEzGame", "LaunchEzGame", "launch_ezgame");
}
if (gyro_Character_Rect == null && image_Character != null && Is_Scene_Object(image_Character))
{
gyro_Character_Rect = image_Character.transform as RectTransform;
}
if (gyro_Dialog_Rect == null)
{
gyro_Dialog_Rect = Find_Rect(searchRoot, "UI_DIALOG", "Dialog", "UI_Dialog");
}
if (group_DailyTasks == null)
{
group_DailyTasks = Find_Rect_Global("UI_DAILY_TASKS", "DailyTasks");
}
if (dailyTask_BG == null)
{
dailyTask_BG = Find_Rect_Global("DTask BG", "DTASK BG", "DTask_BG");
}
if (dailyTask_BG_1 == null)
{
dailyTask_BG_1 = Find_Rect_Global("DTask BG (1)", "DTASK BG (1)", "DTask_BG (1)");
}
if (dailyTask_BG_2 == null)
{
dailyTask_BG_2 = Find_Rect_Global("DTask BG (2)", "DTASK BG (2)", "DTask_BG (2)");
}
if (group_DailyTasks != null && group_Center == null)
{
group_Center = group_DailyTasks.parent as RectTransform;
}
if (group_RightButtons == null)
{
group_RightButtons = Find_Rect_Global("R_OTHER_BUTTON_G", "RightButtons", "Right_Button_G");
}
if (group_RightButtons_Alt == null)
{
group_RightButtons_Alt = Find_Rect_Global("R_OTHER_BUTTON_G2", "RightButtons2", "Right_Button_G2");
}
if (else_Button == null)
{
else_Button = Find_Rect_Global("else_button", "Else_Button", "ELSE_BUTTON");
}
if (content_Root == null && group_Center != null)
{
content_Root = group_Center.parent as RectTransform;
searchRoot = content_Root != null ? content_Root : searchRoot;
}
if (group_Top == null)
{
group_Top = Find_Rect(searchRoot, "TOP", "Top", "TopBar", "Top_Bar");
}
if (group_Bottom == null)
{
group_Bottom = Find_Rect(searchRoot, "BTM", "Bottom", "BottomBar", "Bottom_Bar", "bottom", "bbotom");
}
if (group_Top == null)
{
group_Top = Find_Rect_Global("TOP", "Top", "TopBar", "Top_Bar");
}
if (group_Bottom == null)
{
group_Bottom = Find_Rect_Global("BTM", "Bottom", "BottomBar", "Bottom_Bar", "bottom", "bbotom");
}
if (zoom_BarsRoot == null)
{
RectTransform topParent = group_Top != null ? group_Top.parent as RectTransform : null;
RectTransform bottomParent = group_Bottom != null ? group_Bottom.parent as RectTransform : null;
if (topParent != null && topParent == bottomParent)
{
zoom_BarsRoot = topParent;
}
else if (topParent != null)
{
zoom_BarsRoot = topParent;
}
else if (bottomParent != null)
{
zoom_BarsRoot = bottomParent;
}
}
if (content_Root != null)
{
if (group_Top == null)
{
group_Top = Find_Bar_By_Position(content_Root, true);
}
if (group_Bottom == null)
{
group_Bottom = Find_Bar_By_Position(content_Root, false);
}
}
if (group_Top != null && content_Root == null)
{
content_Root = group_Top.parent as RectTransform;
}
if (group_Bottom != null && content_Root == null)
{
content_Root = group_Bottom.parent as RectTransform;
}
if (group_Top == null || group_Bottom == null)
{
return;
}
}
void Cache_Enter_Defaults()
{
Prune_Cached_Pos();
top_Items.Clear();
task_Items.Clear();
bottom_ButtonItems.Clear();
right_ButtonItems.Clear();
right_ButtonItems_Alt.Clear();
center_Extra_Items.Clear();
content_Extra_Items.Clear();
bg_Loop_Items.Clear();
if (zoom_MainRoot != null)
{
scale_MainRoot = zoom_MainRoot.localScale;
}
if (zoom_BarsRoot != null)
{
scale_BarsRoot = zoom_BarsRoot.localScale;
}
if (group_Background != null)
{
scale_Background = group_Background.localScale;
}
if (group_Top != null)
{
Cache_Pos(group_Top);
pos_Top = cached_Pos[group_Top];
}
if (group_Bottom != null)
{
Cache_Pos(group_Bottom);
pos_Bottom = cached_Pos[group_Bottom];
}
if (group_DailyTasks != null)
{
Cache_Pos(group_DailyTasks);
pos_Daily = cached_Pos[group_DailyTasks];
}
if (group_StartButton != null)
{
Cache_Pos(group_StartButton);
pos_Start = cached_Pos[group_StartButton];
}
if (button_Character_Set_Rect != null)
{
Cache_Pos(button_Character_Set_Rect);
}
if (launch_EzGame_Rect != null)
{
Cache_Pos(launch_EzGame_Rect);
}
if (group_Top != null)
{
foreach (Transform child in group_Top)
{
RectTransform rect = child as RectTransform;
if (rect == null || rect == top_PlayerName)
{
continue;
}
if (Is_Background_Name(rect.name))
{
continue;
}
if (Is_Jiantou_Name(rect.name))
{
continue;
}
top_Items.Add(rect);
}
top_Items.Sort(Compare_By_X);
foreach (var item in top_Items)
{
Cache_Pos(item);
}
}
if (group_DailyTasks != null)
{
foreach (Transform child in group_DailyTasks)
{
RectTransform rect = child as RectTransform;
if (rect == null)
{
continue;
}
if (Is_Background_Name(rect.name))
{
continue;
}
if (Is_Jiantou_Name(rect.name))
{
continue;
}
task_Items.Add(rect);
}
task_Items.Sort(Compare_By_X);
foreach (var item in task_Items)
{
Cache_Pos(item);
}
}
if (group_Bottom != null || group_StartButton != null)
{
HashSet<RectTransform> bottomSet = new();
if (group_Bottom != null)
{
foreach (var button in group_Bottom.GetComponentsInChildren<Button>(true))
{
if (button == null) continue;
bottomSet.Add(button.transform as RectTransform);
}
}
if (group_StartButton != null && group_StartButton.GetComponent<Button>() != null)
{
bottomSet.Add(group_StartButton);
}
foreach (var item in bottomSet)
{
if (item != null)
{
bottom_ButtonItems.Add(item);
}
}
bottom_ButtonItems.Sort(Compare_By_X);
foreach (var item in bottom_ButtonItems)
{
Cache_Pos(item);
}
}
if (group_RightButtons != null)
{
HashSet<RectTransform> rightSet = new();
foreach (var button in group_RightButtons.GetComponentsInChildren<Button>(true))
{
if (button == null) continue;
rightSet.Add(button.transform as RectTransform);
}
foreach (var item in rightSet)
{
if (item != null)
{
right_ButtonItems.Add(item);
}
}
right_ButtonItems.Sort(Compare_By_Y_Desc);
foreach (var item in right_ButtonItems)
{
Cache_Pos(item);
}
}
if (group_RightButtons_Alt != null)
{
HashSet<RectTransform> altSet = new();
foreach (Transform child in group_RightButtons_Alt)
{
RectTransform rect = child as RectTransform;
if (rect == null)
{
continue;
}
altSet.Add(rect);
}
foreach (var item in altSet)
{
if (item != null)
{
right_ButtonItems_Alt.Add(item);
}
}
right_ButtonItems_Alt.Sort(Compare_By_Y_Desc);
foreach (var item in right_ButtonItems_Alt)
{
Cache_Pos(item);
}
}
if (group_Center != null)
{
foreach (Transform child in group_Center)
{
RectTransform rect = child as RectTransform;
if (rect == null)
{
continue;
}
if (rect == group_DailyTasks || rect == group_RightButtons || rect == group_RightButtons_Alt || rect == group_StartButton)
{
continue;
}
if (rect == button_Character_Set_Rect || rect == launch_EzGame_Rect)
{
continue;
}
if (Is_Background_Name(rect.name))
{
continue;
}
if (Is_Jiantou_Name(rect.name))
{
continue;
}
center_Extra_Items.Add(rect);
}
center_Extra_Items.Sort(Compare_By_X);
foreach (var item in center_Extra_Items)
{
Cache_Pos(item);
}
}
if (content_Root != null)
{
foreach (Transform child in content_Root)
{
RectTransform rect = child as RectTransform;
if (rect == null)
{
continue;
}
if (rect == group_Background || rect == group_Top || rect == group_Bottom || rect == group_Center || rect == group_StartButton)
{
continue;
}
if (rect == button_Character_Set_Rect || rect == launch_EzGame_Rect)
{
continue;
}
if (Is_Background_Name(rect.name) || Is_Jiantou_Name(rect.name))
{
continue;
}
if (Is_BG2(rect))
{
continue;
}
if (Has_Jiantou_Descendant(rect))
{
continue;
}
if (group_Top != null && group_Top.IsChildOf(rect))
{
continue;
}
if (group_Bottom != null && group_Bottom.IsChildOf(rect))
{
continue;
}
content_Extra_Items.Add(rect);
}
content_Extra_Items.Sort(Compare_By_X);
foreach (var item in content_Extra_Items)
{
Cache_Pos(item);
}
}
if (group_Background != null)
{
foreach (Transform child in group_Background)
{
RectTransform rect = child as RectTransform;
if (rect == null)
{
continue;
}
if (Is_Jiantou_Name(rect.name))
{
continue;
}
bg_Loop_Items.Add(rect);
Cache_Pos(rect);
Cache_Scale(rect);
Cache_Rotation(rect);
}
}
if (background_Bg2 != null && !bg_Loop_Items.Contains(background_Bg2))
{
bg_Loop_Items.Add(background_Bg2);
Cache_Pos(background_Bg2);
Cache_Scale(background_Bg2);
Cache_Rotation(background_Bg2);
}
Cache_Pos(group_Top);
Cache_Pos(group_Bottom);
Cache_Pos(group_DailyTasks);
Cache_Pos(group_StartButton);
Cache_Pos(button_Character_Set_Rect);
Cache_Pos(launch_EzGame_Rect);
}
void Kill_Enter_Tweens()
{
if (enter_Sequence != null)
{
enter_Sequence.Kill();
enter_Sequence = null;
}
Kill_Bars_Tweens();
Stop_Background_Loop();
Kill_Target(zoom_MainRoot);
Kill_Target(zoom_BarsRoot);
Kill_Target(group_Background);
Kill_Target(group_Top);
Kill_Target(group_Bottom);
Kill_Target(group_DailyTasks);
Kill_Target(group_RightButtons);
Kill_Target(group_RightButtons_Alt);
Kill_Target(group_StartButton);
Kill_Target(top_PlayerName);
Kill_Target(button_Character_Set_Rect);
Kill_Target(launch_EzGame_Rect);
for (int i = 0; i < top_Items.Count; i++)
{
Kill_Target(top_Items[i]);
}
for (int i = 0; i < task_Items.Count; i++)
{
Kill_Target(task_Items[i]);
}
for (int i = 0; i < bottom_ButtonItems.Count; i++)
{
Kill_Target(bottom_ButtonItems[i]);
}
for (int i = 0; i < right_ButtonItems.Count; i++)
{
Kill_Target(right_ButtonItems[i]);
}
for (int i = 0; i < right_ButtonItems_Alt.Count; i++)
{
Kill_Target(right_ButtonItems_Alt[i]);
}
for (int i = 0; i < center_Extra_Items.Count; i++)
{
Kill_Target(center_Extra_Items[i]);
}
for (int i = 0; i < content_Extra_Items.Count; i++)
{
Kill_Target(content_Extra_Items[i]);
}
for (int i = 0; i < bg_Loop_Items.Count; i++)
{
Kill_Target(bg_Loop_Items[i]);
}
}
void Kill_Bars_Tweens()
{
if (bars_Sequence != null)
{
bars_Sequence.Kill();
bars_Sequence = null;
}
Kill_Target(group_Top);
Kill_Target(group_Bottom);
for (int i = 0; i < top_Items.Count; i++)
{
Kill_Target(top_Items[i]);
}
}
public void Play_Enter_Anim()
{
enter_Played = true;
Cache_Enter_Refs();
Kill_Enter_Tweens();
Cache_Enter_Defaults();
Update_Enter_Runtime_Times();
transform.localScale = Vector3.one;
bool applyBarsZoom = zoom_BarsRoot != null
&& zoom_BarsRoot != zoom_MainRoot
&& (zoom_MainRoot == null || !zoom_BarsRoot.IsChildOf(zoom_MainRoot));
if (zoom_MainRoot != null)
{
zoom_MainRoot.localScale = scale_MainRoot * enter_Zoom_Scale_From;
}
if (applyBarsZoom)
{
zoom_BarsRoot.localScale = scale_BarsRoot * enter_Zoom_Scale_From;
}
if (group_Background != null)
{
group_Background.localScale = scale_Background * enter_Background_Scale_From;
}
for (int i = 0; i < bg_Loop_Items.Count; i++)
{
RectTransform rect = bg_Loop_Items[i];
if (rect == null)
{
continue;
}
if (cached_Pos.TryGetValue(rect, out Vector2 pos))
{
rect.anchoredPosition = pos;
}
if (cached_Scale.TryGetValue(rect, out Vector3 scale))
{
rect.localScale = scale;
}
if (cached_RotationZ.TryGetValue(rect, out float rotZ))
{
Vector3 euler = rect.localEulerAngles;
euler.z = rotZ;
rect.localEulerAngles = euler;
}
}
if (group_Top != null)
{
group_Top.anchoredPosition = pos_Top + Vector2.up * enter_Offset_Y;
}
if (group_Bottom != null)
{
group_Bottom.anchoredPosition = pos_Bottom - Vector2.up * enter_Offset_Y;
}
if (group_DailyTasks != null)
{
group_DailyTasks.anchoredPosition = pos_Daily + Vector2.left * enter_Offset_X;
}
if (group_StartButton != null)
{
group_StartButton.anchoredPosition = pos_Start;
}
for (int i = 0; i < top_Items.Count; i++)
{
Prepare_Item(top_Items[i], Vector2.down * enter_Item_Offset_Y, true);
}
for (int i = 0; i < task_Items.Count; i++)
{
Prepare_Item(task_Items[i], Vector2.left * enter_Item_Offset_X, true);
}
for (int i = 0; i < bottom_ButtonItems.Count; i++)
{
Prepare_Item(bottom_ButtonItems[i], Vector2.down * enter_Item_Offset_Y, true);
}
for (int i = 0; i < right_ButtonItems.Count; i++)
{
Prepare_Item(right_ButtonItems[i], Vector2.right * enter_Offset_X, true);
}
for (int i = 0; i < right_ButtonItems_Alt.Count; i++)
{
Prepare_FadeOnly(right_ButtonItems_Alt[i]);
}
if (group_RightButtons_Alt != null)
{
Prepare_FadeOnly(group_RightButtons_Alt);
}
for (int i = 0; i < center_Extra_Items.Count; i++)
{
Prepare_Item(center_Extra_Items[i], Vector2.down * enter_Item_Offset_Y, true);
}
for (int i = 0; i < content_Extra_Items.Count; i++)
{
Prepare_Item(content_Extra_Items[i], Vector2.down * enter_Item_Offset_Y, true);
}
if (button_Character_Set_Rect != null
&& !top_Items.Contains(button_Character_Set_Rect)
&& !task_Items.Contains(button_Character_Set_Rect)
&& !bottom_ButtonItems.Contains(button_Character_Set_Rect)
&& !right_ButtonItems.Contains(button_Character_Set_Rect))
{
Prepare_Item(button_Character_Set_Rect, Vector2.down * enter_Item_Offset_Y, true);
}
if (launch_EzGame_Rect != null
&& !top_Items.Contains(launch_EzGame_Rect)
&& !task_Items.Contains(launch_EzGame_Rect)
&& !bottom_ButtonItems.Contains(launch_EzGame_Rect)
&& !right_ButtonItems.Contains(launch_EzGame_Rect))
{
Prepare_Item(launch_EzGame_Rect, Vector2.right * enter_Offset_X, true);
}
if (top_PlayerName != null)
{
CanvasGroup playerGroup = Ensure_CanvasGroup(top_PlayerName.gameObject);
playerGroup.alpha = 0f;
}
if (play_Background_Deco_Enter)
{
for (int i = 0; i < bg_Loop_Items.Count; i++)
{
Prepare_Background_Deco(bg_Loop_Items[i], i);
}
}
enter_Sequence = DOTween.Sequence();
enter_Sequence.SetUpdate(true);
enter_Sequence.SetAutoKill(false);
enter_Sequence.OnKill(() => enter_Sequence = null);
if (zoom_MainRoot != null)
{
enter_Sequence.Insert(0f, zoom_MainRoot.DOScale(scale_MainRoot, enter_Zoom_Time).SetEase(enter_Zoom_Ease));
}
if (applyBarsZoom)
{
enter_Sequence.Insert(0f, zoom_BarsRoot.DOScale(scale_BarsRoot, enter_Zoom_Time).SetEase(enter_Zoom_Ease));
}
if (group_Background != null)
{
enter_Sequence.Append(group_Background.DOScale(scale_Background, enter_Background_Time_Runtime)
.SetEase(enter_Background_Ease));
}
if (play_Background_Deco_Enter)
{
float decoStart = 0f;
for (int i = 0; i < bg_Loop_Items.Count; i++)
{
RectTransform rect = bg_Loop_Items[i];
float at = decoStart + (bg_Deco_Stagger_Runtime * i);
Animate_Background_Deco(enter_Sequence, rect, at);
}
}
if (play_Background_Loop || play_Mouse_Gyro || play_Jiantou_Loop)
{
enter_Sequence.OnComplete(() =>
{
if (play_Background_Loop)
{
Start_Background_Loop();
}
if (play_Mouse_Gyro)
{
Capture_Gyro_Base();
}
if (play_Jiantou_Loop)
{
Start_Jiantou_Loop();
}
});
}
float uiStart = enter_Sequence.Duration();
if (group_Top != null)
{
enter_Sequence.Insert(uiStart, group_Top.DOAnchorPos(pos_Top, enter_Bar_Time_Runtime).SetEase(enter_Move_Ease));
}
if (group_Bottom != null)
{
enter_Sequence.Insert(uiStart, group_Bottom.DOAnchorPos(pos_Bottom, enter_Bar_Time_Runtime).SetEase(enter_Move_Ease));
}
if (group_DailyTasks != null)
{
enter_Sequence.Insert(uiStart, group_DailyTasks.DOAnchorPos(pos_Daily, enter_Bar_Time_Runtime).SetEase(enter_Move_Ease));
}
float topItemsStart = uiStart + enter_Bar_Time_Runtime * 0.6f;
for (int i = 0; i < top_Items.Count; i++)
{
RectTransform item = top_Items[i];
float at = topItemsStart + (enter_Stagger_Runtime * i);
Animate_Item(enter_Sequence, item, at);
}
if (top_PlayerName != null)
{
CanvasGroup playerGroup = Ensure_CanvasGroup(top_PlayerName.gameObject);
Sequence blink = DOTween.Sequence().SetUpdate(true);
blink.Append(playerGroup.DOFade(1f, 0.15f * enter_Blink_Time_Scale));
blink.AppendInterval(0.05f * enter_Blink_Time_Scale);
blink.Append(playerGroup.DOFade(0.2f, 0.1f * enter_Blink_Time_Scale));
blink.Append(playerGroup.DOFade(1f, 0.2f * enter_Blink_Time_Scale));
enter_Sequence.Insert(topItemsStart + enter_Stagger_Runtime * 0.5f, blink);
}
if (button_Character_Set_Rect != null)
{
float characterStart = topItemsStart + enter_Stagger_Runtime * (top_Items.Count + 0.5f);
Animate_Item(enter_Sequence, button_Character_Set_Rect, characterStart);
}
float tasksItemsStart = uiStart + enter_Bar_Time_Runtime * 0.7f;
for (int i = 0; i < task_Items.Count; i++)
{
RectTransform item = task_Items[i];
float at = tasksItemsStart + (enter_Stagger_Runtime * i);
Animate_Item(enter_Sequence, item, at);
}
float bottomItemsStart = uiStart + enter_Bar_Time_Runtime * 0.7f;
for (int i = 0; i < bottom_ButtonItems.Count; i++)
{
RectTransform item = bottom_ButtonItems[i];
float at = bottomItemsStart + (enter_Stagger_Runtime * i);
Animate_Item(enter_Sequence, item, at);
}
float rightStart = uiStart + 0.05f;
for (int i = 0; i < right_ButtonItems.Count; i++)
{
RectTransform item = right_ButtonItems[i];
float at = rightStart + (enter_Stagger_Runtime * i);
Animate_Item(enter_Sequence, item, at);
}
float altStart = uiStart + 0.05f;
for (int i = 0; i < right_ButtonItems_Alt.Count; i++)
{
RectTransform item = right_ButtonItems_Alt[i];
float at = altStart + (enter_Stagger_Runtime * i);
Animate_Flicker(enter_Sequence, item, at, 3, 0.045f, 0.02f);
}
if (group_RightButtons_Alt != null)
{
Animate_Flicker(enter_Sequence, group_RightButtons_Alt, altStart, 3, 0.045f, 0.02f);
}
float centerExtraStart = uiStart + enter_Bar_Time_Runtime * 0.5f;
for (int i = 0; i < center_Extra_Items.Count; i++)
{
RectTransform item = center_Extra_Items[i];
float at = centerExtraStart + (enter_Stagger_Runtime * i);
Animate_Item(enter_Sequence, item, at);
}
float contentExtraStart = centerExtraStart + enter_Stagger_Runtime * 0.25f;
for (int i = 0; i < content_Extra_Items.Count; i++)
{
RectTransform item = content_Extra_Items[i];
float at = contentExtraStart + (enter_Stagger_Runtime * i);
Animate_Item(enter_Sequence, item, at);
}
if (launch_EzGame_Rect != null)
{
float ezStart = rightStart + enter_Stagger_Runtime * (right_ButtonItems.Count + 0.5f);
Animate_Item(enter_Sequence, launch_EzGame_Rect, ezStart);
}
}
public void Bind_Top_Bottom(RectTransform top, RectTransform bottom)
{
if (Is_Scene_Object(top))
{
group_Top = top;
}
if (Is_Scene_Object(bottom))
{
group_Bottom = bottom;
}
enter_Debug_Logged = false;
Setup_Button_Tweens();
if (!gameObject.activeInHierarchy || !play_Enter_OnEnable)
{
return;
}
if (!enter_Played)
{
Start_Enter_Routine();
return;
}
Play_Bars_Anim();
}
void Start_Enter_Routine()
{
if (enter_Played)
{
return;
}
if (enter_Routine != null)
{
StopCoroutine(enter_Routine);
}
enter_Routine = StartCoroutine(C_Wait_For_Bars_And_Play());
}
IEnumerator C_Wait_For_Bars_And_Play()
{
float endTime = Time.unscaledTime + enter_Wait_Timeout;
while (Time.unscaledTime < endTime)
{
Cache_Enter_Refs();
if (Has_Valid_Bars())
{
break;
}
yield return null;
}
if (!Has_Valid_Bars())
{
if (!enter_Debug_Logged)
{
enter_Debug_Logged = true;
Debug.LogWarning("[UI_Panel_Main] TOP/BTM not found after wait. Please assign references in Inspector or check hierarchy names.");
}
}
Play_Enter_Anim();
enter_Routine = null;
}
bool Has_Valid_Bars()
{
return Is_Scene_Object(group_Top) && Is_Scene_Object(group_Bottom);
}
List<RectTransform> Collect_Bottom_Items()
{
List<RectTransform> items = new();
if (group_Bottom == null)
{
return items;
}
HashSet<RectTransform> set = new();
foreach (var button in group_Bottom.GetComponentsInChildren<Button>(true))
{
if (button == null)
{
continue;
}
RectTransform rect = button.transform as RectTransform;
if (rect != null)
{
set.Add(rect);
}
}
items.AddRange(set);
items.Sort(Compare_By_X);
return items;
}
void Play_Bars_Anim()
{
Cache_Enter_Refs();
Kill_Bars_Tweens();
Cache_Enter_Defaults();
Update_Enter_Runtime_Times();
if (!Is_Scene_Object(group_Top) || !Is_Scene_Object(group_Bottom))
{
return;
}
if (group_Top != null)
{
group_Top.anchoredPosition = pos_Top + Vector2.up * enter_Offset_Y;
}
if (group_Bottom != null)
{
group_Bottom.anchoredPosition = pos_Bottom - Vector2.up * enter_Offset_Y;
}
for (int i = 0; i < top_Items.Count; i++)
{
Prepare_Item(top_Items[i], Vector2.down * enter_Item_Offset_Y, true);
}
List<RectTransform> bottomItems = Collect_Bottom_Items();
for (int i = 0; i < bottomItems.Count; i++)
{
Prepare_Item(bottomItems[i], Vector2.down * enter_Item_Offset_Y, true);
}
if (top_PlayerName != null)
{
CanvasGroup playerGroup = Ensure_CanvasGroup(top_PlayerName.gameObject);
playerGroup.alpha = 0f;
}
bars_Sequence = DOTween.Sequence();
bars_Sequence.SetUpdate(true);
bars_Sequence.SetAutoKill(false);
bars_Sequence.OnKill(() => bars_Sequence = null);
bars_Sequence.Append(group_Top.DOAnchorPos(pos_Top, enter_Bar_Time_Runtime).SetEase(enter_Move_Ease));
float topItemsStart = bars_Sequence.Duration();
for (int i = 0; i < top_Items.Count; i++)
{
RectTransform item = top_Items[i];
float at = topItemsStart + (enter_Stagger_Runtime * i);
Animate_Item(bars_Sequence, item, at);
}
if (top_PlayerName != null)
{
CanvasGroup playerGroup = Ensure_CanvasGroup(top_PlayerName.gameObject);
Sequence blink = DOTween.Sequence().SetUpdate(true);
blink.Append(playerGroup.DOFade(1f, 0.15f * enter_Blink_Time_Scale));
blink.AppendInterval(0.05f * enter_Blink_Time_Scale);
blink.Append(playerGroup.DOFade(0.2f, 0.1f * enter_Blink_Time_Scale));
blink.Append(playerGroup.DOFade(1f, 0.2f * enter_Blink_Time_Scale));
bars_Sequence.Insert(topItemsStart + enter_Stagger_Runtime * 0.5f, blink);
}
float bottomStart = topItemsStart + enter_Bar_Time_Runtime * 0.5f;
bars_Sequence.Insert(bottomStart, group_Bottom.DOAnchorPos(pos_Bottom, enter_Bar_Time_Runtime).SetEase(enter_Move_Ease));
float bottomItemsStart = bottomStart + enter_Bar_Time_Runtime;
for (int i = 0; i < bottomItems.Count; i++)
{
RectTransform item = bottomItems[i];
float at = bottomItemsStart + (enter_Stagger_Runtime * i);
Animate_Item(bars_Sequence, item, at);
}
}
void Start_Background_Loop()
{
if (!play_Background_Loop || bg_Loop_Items.Count == 0)
{
return;
}
Stop_Background_Loop();
for (int i = 0; i < bg_Loop_Items.Count; i++)
{
RectTransform rect = bg_Loop_Items[i];
if (rect == null)
{
continue;
}
if (!cached_Pos.TryGetValue(rect, out Vector2 origin))
{
origin = rect.anchoredPosition;
cached_Pos[rect] = origin;
}
float dir = (i % 2 == 0) ? 1f : -1f;
Vector2 offset = new(bg_Loop_Offset * dir, bg_Loop_Offset * -dir * 0.6f);
rect.anchoredPosition = origin;
Tween tween = rect.DOAnchorPos(origin + offset, bg_Loop_Time + i * 0.3f)
.SetEase(bg_Loop_Ease)
.SetLoops(-1, LoopType.Yoyo)
.SetUpdate(true);
bg_Loop_Tweens.Add(tween);
}
}
void Stop_Background_Loop()
{
for (int i = 0; i < bg_Loop_Tweens.Count; i++)
{
Tween tween = bg_Loop_Tweens[i];
if (tween != null)
{
tween.Kill();
}
}
bg_Loop_Tweens.Clear();
for (int i = 0; i < bg_Loop_Items.Count; i++)
{
RectTransform rect = bg_Loop_Items[i];
if (rect == null)
{
continue;
}
if (cached_Pos.TryGetValue(rect, out Vector2 pos))
{
rect.anchoredPosition = pos;
}
if (cached_Scale.TryGetValue(rect, out Vector3 scale))
{
rect.localScale = scale;
}
if (cached_RotationZ.TryGetValue(rect, out float rotZ))
{
Vector3 euler = rect.localEulerAngles;
euler.z = rotZ;
rect.localEulerAngles = euler;
}
CanvasGroup group = rect.GetComponent<CanvasGroup>();
if (group != null)
{
group.alpha = 1f;
}
}
}
void Cache_Pos(RectTransform rect)
{
if (rect == null)
{
return;
}
if (!cached_Pos.ContainsKey(rect))
{
cached_Pos.Add(rect, rect.anchoredPosition);
}
}
void Cache_Scale(RectTransform rect)
{
if (rect == null)
{
return;
}
if (!cached_Scale.ContainsKey(rect))
{
cached_Scale.Add(rect, rect.localScale);
}
}
void Cache_Rotation(RectTransform rect)
{
if (rect == null)
{
return;
}
if (!cached_RotationZ.ContainsKey(rect))
{
cached_RotationZ.Add(rect, rect.localEulerAngles.z);
}
}
void Prune_Cached_Pos()
{
if (cached_Pos.Count == 0)
{
return;
}
List<RectTransform> toRemove = null;
foreach (var kvp in cached_Pos)
{
if (kvp.Key == null)
{
if (toRemove == null)
{
toRemove = new List<RectTransform>();
}
toRemove.Add(kvp.Key);
}
}
if (toRemove != null)
{
for (int i = 0; i < toRemove.Count; i++)
{
cached_Pos.Remove(toRemove[i]);
cached_Scale.Remove(toRemove[i]);
cached_RotationZ.Remove(toRemove[i]);
}
}
}
void Prepare_Background_Deco(RectTransform rect, int index)
{
if (rect == null)
{
return;
}
if (Is_BG2(rect))
{
Cache_Pos(rect);
Cache_Scale(rect);
Cache_Rotation(rect);
CanvasGroup bg2Group = Ensure_CanvasGroup(rect.gameObject);
if (bg2Group != null)
{
bg2Group.alpha = 0f;
}
return;
}
Cache_Pos(rect);
Cache_Scale(rect);
Cache_Rotation(rect);
int seed = Stable_Hash(rect.name) + (index + 1) * 17;
float offsetX = Mathf.Lerp(-bg_Deco_Offset, bg_Deco_Offset, Hash01(seed, 1));
float offsetY = Mathf.Lerp(-bg_Deco_Offset, bg_Deco_Offset, Hash01(seed, 2));
float rotate = Mathf.Lerp(-bg_Deco_Rotate, bg_Deco_Rotate, Hash01(seed, 3));
float scaleMul = Mathf.Lerp(bg_Deco_Scale_From, bg_Deco_Scale_From + 0.15f, Hash01(seed, 4));
rect.anchoredPosition = cached_Pos[rect] + new Vector2(offsetX, offsetY);
rect.localScale = cached_Scale[rect] * Mathf.Max(0.01f, scaleMul);
Vector3 euler = rect.localEulerAngles;
euler.z = cached_RotationZ[rect] + rotate;
rect.localEulerAngles = euler;
CanvasGroup group = Ensure_CanvasGroup(rect.gameObject);
if (group != null)
{
group.alpha = 0f;
}
}
void Animate_Background_Deco(Sequence sequence, RectTransform rect, float at)
{
if (sequence == null || rect == null)
{
return;
}
bool isBg2 = Is_BG2(rect);
if (isBg2)
{
Animate_Flicker(sequence, rect, at, 3, 0.05f, 0.03f);
return;
}
if (cached_Pos.TryGetValue(rect, out Vector2 targetPos))
{
sequence.Insert(at, rect.DOAnchorPos(targetPos, bg_Deco_Time_Runtime).SetEase(bg_Deco_Ease));
}
if (cached_Scale.TryGetValue(rect, out Vector3 targetScale))
{
sequence.Insert(at, rect.DOScale(targetScale, bg_Deco_Time_Runtime).SetEase(bg_Deco_Ease));
}
if (cached_RotationZ.TryGetValue(rect, out float targetRotZ))
{
sequence.Insert(at, rect.DORotate(new Vector3(0f, 0f, targetRotZ), bg_Deco_Time_Runtime, RotateMode.Fast));
}
if (rect.TryGetComponent(out CanvasGroup group))
{
sequence.Insert(at, group.DOFade(1f, bg_Deco_Time_Runtime).SetEase(bg_Deco_Ease));
}
}
void Prepare_Item(RectTransform rect, Vector2 offset, bool fade)
{
if (rect == null)
{
return;
}
Cache_Pos(rect);
rect.anchoredPosition = cached_Pos[rect] + offset;
if (fade)
{
CanvasGroup group = Ensure_CanvasGroup(rect.gameObject);
group.alpha = 0f;
}
}
void Prepare_FadeOnly(RectTransform rect)
{
if (rect == null)
{
return;
}
Cache_Pos(rect);
CanvasGroup group = Ensure_CanvasGroup(rect.gameObject);
if (group != null)
{
group.alpha = 0f;
}
}
void Animate_Item(Sequence sequence, RectTransform rect, float at)
{
if (sequence == null || rect == null)
{
return;
}
if (!cached_Pos.TryGetValue(rect, out Vector2 target))
{
target = rect.anchoredPosition;
}
float duration = enter_Item_Time_Runtime > 0f ? enter_Item_Time_Runtime : enter_Item_Time;
sequence.Insert(at, rect.DOAnchorPos(target, duration).SetEase(enter_Move_Ease));
if (rect.TryGetComponent(out CanvasGroup group))
{
sequence.Insert(at, group.DOFade(1f, duration).SetEase(enter_Move_Ease));
}
}
void Animate_Flicker(Sequence sequence, RectTransform rect, float at, int flashes, float flashTime, float interval)
{
if (sequence == null || rect == null)
{
return;
}
CanvasGroup group = Ensure_CanvasGroup(rect.gameObject);
if (group == null)
{
return;
}
group.alpha = 0f;
int count = Mathf.Max(1, flashes);
float time = Mathf.Max(0.01f, flashTime);
float gap = Mathf.Max(0f, interval);
Sequence flicker = DOTween.Sequence().SetUpdate(true);
for (int i = 0; i < count; i++)
{
flicker.Append(group.DOFade(1f, time).SetEase(Ease.OutQuad));
flicker.Append(group.DOFade(0f, time).SetEase(Ease.InQuad));
if (gap > 0f)
{
flicker.AppendInterval(gap);
}
}
flicker.Append(group.DOFade(1f, time).SetEase(Ease.OutQuad));
sequence.Insert(at, flicker);
}
void Kill_Target(RectTransform rect)
{
if (rect == null)
{
return;
}
DOTween.Kill(rect);
if (rect.TryGetComponent(out CanvasGroup group))
{
DOTween.Kill(group);
}
}
CanvasGroup Ensure_CanvasGroup(GameObject target)
{
if (target == null)
{
return null;
}
target.Try_Get_Component(out CanvasGroup canvasGroup);
return canvasGroup;
}
RectTransform Find_Rect(Transform root, params string[] names)
{
if (root == null || names == null || names.Length == 0)
{
return null;
}
for (int i = 0; i < names.Length; i++)
{
string name = names[i];
if (string.IsNullOrEmpty(name))
{
continue;
}
Transform direct = root.Find(name);
if (direct != null)
{
return direct as RectTransform;
}
}
RectTransform[] rects = root.GetComponentsInChildren<RectTransform>(true);
for (int i = 0; i < rects.Length; i++)
{
RectTransform rect = rects[i];
if (rect == null)
{
continue;
}
for (int j = 0; j < names.Length; j++)
{
string name = names[j];
if (string.IsNullOrEmpty(name))
{
continue;
}
if (string.Equals(rect.name, name, StringComparison.OrdinalIgnoreCase))
{
return rect;
}
}
}
return null;
}
RectTransform Find_Rect_Global(params string[] names)
{
if (names == null || names.Length == 0)
{
return null;
}
RectTransform[] rects = UnityEngine.Object.FindObjectsByType<RectTransform>(FindObjectsInactive.Include, FindObjectsSortMode.InstanceID);
RectTransform exact = Find_Rect_In_List(rects, names, false);
if (exact != null)
{
return exact;
}
return Find_Rect_In_List(rects, names, true);
}
void Ensure_Scene_Ref(ref RectTransform rect)
{
if (rect == null)
{
return;
}
if (!Is_Scene_Object(rect))
{
rect = null;
}
}
bool Is_Scene_Object(Component component)
{
if (component == null)
{
return false;
}
return component.gameObject.scene.IsValid();
}
RectTransform Find_Rect_In_List(RectTransform[] rects, string[] names, bool allowContains)
{
if (rects == null)
{
return null;
}
for (int i = 0; i < rects.Length; i++)
{
RectTransform rect = rects[i];
if (rect == null)
{
continue;
}
string rectName = rect.name;
for (int j = 0; j < names.Length; j++)
{
string name = names[j];
if (string.IsNullOrEmpty(name))
{
continue;
}
if (allowContains)
{
if (rectName.IndexOf(name, StringComparison.OrdinalIgnoreCase) >= 0)
{
return rect;
}
}
else if (string.Equals(rectName, name, StringComparison.OrdinalIgnoreCase))
{
return rect;
}
}
}
return null;
}
RectTransform Find_Bar_By_Position(RectTransform root, bool isTop)
{
if (root == null)
{
return null;
}
RectTransform[] rects = root.GetComponentsInChildren<RectTransform>(true);
RectTransform best = null;
float bestY = isTop ? float.NegativeInfinity : float.PositiveInfinity;
for (int i = 0; i < rects.Length; i++)
{
RectTransform rect = rects[i];
if (rect == null || rect == root)
{
continue;
}
if (Is_Background_Name(rect.name))
{
continue;
}
float width = rect.rect.width;
float height = rect.rect.height;
if (width < height * 1.8f)
{
continue;
}
float y = rect.position.y;
if (isTop)
{
if (y > bestY)
{
bestY = y;
best = rect;
}
}
else
{
if (y < bestY)
{
bestY = y;
best = rect;
}
}
}
return best;
}
int Get_Hierarchy_Depth(RectTransform rect, RectTransform root)
{
if (rect == null)
{
return 0;
}
int depth = 0;
Transform current = rect.parent;
while (current != null && current != root)
{
depth++;
current = current.parent;
}
return depth;
}
bool Has_Selected_Ancestor(RectTransform rect, HashSet<RectTransform> selected, RectTransform root)
{
if (rect == null || selected == null || selected.Count == 0)
{
return false;
}
Transform current = rect.parent;
while (current != null && current != root)
{
RectTransform parentRect = current as RectTransform;
if (parentRect != null && selected.Contains(parentRect))
{
return true;
}
current = current.parent;
}
return false;
}
bool Is_Gyro_Root(RectTransform rect)
{
if (rect == null)
{
return false;
}
if (rect.GetComponent<Selectable>() != null)
{
return true;
}
if (rect.GetComponent<Graphic>() != null)
{
return true;
}
return false;
}
int Compare_By_X(RectTransform a, RectTransform b)
{
if (a == null && b == null)
{
return 0;
}
if (a == null)
{
return 1;
}
if (b == null)
{
return -1;
}
int cmp = a.position.x.CompareTo(b.position.x);
if (cmp != 0)
{
return cmp;
}
return b.position.y.CompareTo(a.position.y);
}
int Compare_By_Y_Desc(RectTransform a, RectTransform b)
{
if (a == null && b == null)
{
return 0;
}
if (a == null)
{
return 1;
}
if (b == null)
{
return -1;
}
int cmp = b.position.y.CompareTo(a.position.y);
if (cmp != 0)
{
return cmp;
}
return a.position.x.CompareTo(b.position.x);
}
bool Is_Background_Name(string name)
{
if (string.IsNullOrEmpty(name))
{
return false;
}
string lower = name.ToLowerInvariant();
if (lower.Contains("background") || lower.Contains("mask"))
{
return true;
}
if (lower == "bg")
{
return true;
}
if (lower.EndsWith("_bg") || lower.EndsWith(" bg"))
{
return true;
}
return false;
}
bool Is_Jiantou_Name(string name)
{
if (string.IsNullOrEmpty(name))
{
return false;
}
string key = string.IsNullOrEmpty(jiantou_Name_Contains) ? "jiantou" : jiantou_Name_Contains;
return name.IndexOf(key, StringComparison.OrdinalIgnoreCase) >= 0;
}
bool Is_BG2_Name(string name)
{
if (string.IsNullOrEmpty(name))
{
return false;
}
string lower = name.ToLowerInvariant();
if (lower.Contains("bg2") || lower.Contains("background_2") || lower.Contains("background2"))
{
return true;
}
return false;
}
bool Is_BG2(RectTransform rect)
{
if (rect == null)
{
return false;
}
if (background_Bg2 != null && rect == background_Bg2)
{
return true;
}
if (Is_BG2_Name(rect.name))
{
return true;
}
if (background_Bg2 == null && group_Background != null && group_Background.childCount > 1)
{
RectTransform lastChild = group_Background.GetChild(group_Background.childCount - 1) as RectTransform;
if (rect == lastChild)
{
return true;
}
}
return false;
}
bool Has_Jiantou_Descendant(Transform root)
{
if (root == null)
{
return false;
}
for (int i = 0; i < root.childCount; i++)
{
Transform child = root.GetChild(i);
if (child == null)
{
continue;
}
if (Is_Jiantou_Name(child.name))
{
return true;
}
if (Has_Jiantou_Descendant(child))
{
return true;
}
}
return false;
}
int Stable_Hash(string text)
{
if (string.IsNullOrEmpty(text))
{
return 0;
}
unchecked
{
int hash = 23;
for (int i = 0; i < text.Length; i++)
{
hash = (hash * 31) + text[i];
}
return hash;
}
}
float Hash01(int seed, int salt)
{
unchecked
{
uint value = (uint)(seed ^ (salt * 0x9E3779B9));
value ^= value >> 16;
value *= 0x85ebca6b;
value ^= value >> 13;
return (value & 0xFFFF) / 65535f;
}
}
void Update_Enter_Runtime_Times()
{
float speed = Mathf.Max(enter_UI_Speed, 0.01f);
enter_Background_Time_Runtime = enter_Background_Time / speed;
enter_Bar_Time_Runtime = enter_Bar_Time / speed;
enter_Item_Time_Runtime = enter_Item_Time / speed;
enter_Stagger_Runtime = enter_Stagger / speed;
enter_Blink_Time_Scale = 1f / speed;
bg_Deco_Time_Runtime = bg_Deco_Time / speed;
bg_Deco_Stagger_Runtime = bg_Deco_Stagger / speed;
}
void Capture_Gyro_Base()
{
Ensure_Gyro_Targets();
if (gyro_Targets.Count == 0)
{
return;
}
gyro_Base_Pos_Map.Clear();
gyro_Base_Rot_Map.Clear();
for (int i = 0; i < gyro_Targets.Count; i++)
{
RectTransform target = gyro_Targets[i];
if (target == null)
{
continue;
}
gyro_Base_Pos_Map[target] = target.anchoredPosition;
gyro_Base_Rot_Map[target] = target.localEulerAngles;
}
gyro_Current_Offset = Vector2.zero;
gyro_Current_RotDelta = Vector3.zero;
if (gyro_Apply_BG_Scale && group_Background != null && gyro_Targets.Contains(group_Background))
{
if (!gyro_BG_Base_Scale_Set)
{
gyro_BG_Base_Scale = group_Background.localScale;
gyro_BG_Base_Scale_Set = true;
}
float extra = Mathf.Max(gyro_BG_Extra_Scale, 1f);
group_Background.localScale = gyro_BG_Base_Scale * extra;
}
gyro_Inited = true;
}
void Ensure_Gyro_Targets()
{
gyro_Targets.Clear();
gyro_Offset_Weight_Map.Clear();
gyro_Rot_Weight_Map.Clear();
Cache_Enter_Refs();
RectTransform characterRect = gyro_Character_Rect;
if (characterRect == null && image_Character != null && Is_Scene_Object(image_Character))
{
characterRect = image_Character.transform as RectTransform;
}
RectTransform dialogRect = gyro_Dialog_Rect;
RectTransform backgroundRect = group_Background;
if (Is_Scene_Object(backgroundRect))
{
float w = Mathf.Abs(gyro_Background_Weight);
Add_Gyro_Target(backgroundRect, -w, -w, true);
}
if (Is_Scene_Object(characterRect))
{
float w = Mathf.Abs(gyro_Character_Weight);
Add_Gyro_Target(characterRect, w, w, false);
}
if (Is_Scene_Object(dialogRect))
{
float w = Mathf.Abs(gyro_Dialog_Weight);
Add_Gyro_Target(dialogRect, w, w, false);
}
if (Is_Scene_Object(group_RightButtons))
{
float w = Mathf.Abs(gyro_RightButtons_Rotation_Weight);
Add_Gyro_Target(group_RightButtons, 0f, w, false);
}
if (Is_Scene_Object(group_RightButtons_Alt))
{
float w = Mathf.Abs(gyro_RightButtons_Rotation_Weight);
Add_Gyro_Target(group_RightButtons_Alt, 0f, w, false);
}
if (Is_Scene_Object(group_DailyTasks))
{
float w = Mathf.Abs(gyro_DailyTasks_Rotation_Weight);
Add_Gyro_Target(group_DailyTasks, 0f, w, false);
}
if (Is_Scene_Object(dailyTask_BG) && (group_DailyTasks == null || !dailyTask_BG.IsChildOf(group_DailyTasks)))
{
float w = Mathf.Abs(gyro_DailyTasks_Rotation_Weight);
Add_Gyro_Target(dailyTask_BG, 0f, w, false);
}
if (Is_Scene_Object(dailyTask_BG_1) && (group_DailyTasks == null || !dailyTask_BG_1.IsChildOf(group_DailyTasks)))
{
float w = Mathf.Abs(gyro_DailyTasks_Rotation_Weight);
Add_Gyro_Target(dailyTask_BG_1, 0f, w, false);
}
if (Is_Scene_Object(dailyTask_BG_2) && (group_DailyTasks == null || !dailyTask_BG_2.IsChildOf(group_DailyTasks)))
{
float w = Mathf.Abs(gyro_DailyTasks_Rotation_Weight);
Add_Gyro_Target(dailyTask_BG_2, 0f, w, false);
}
if (Is_Scene_Object(else_Button))
{
float w = Mathf.Abs(gyro_RightButtons_Rotation_Weight);
Add_Gyro_Target(else_Button, 0f, w, false);
}
}
void Reset_Gyro_To_Base()
{
if (gyro_Targets.Count > 0)
{
for (int i = 0; i < gyro_Targets.Count; i++)
{
RectTransform target = gyro_Targets[i];
if (target == null)
{
continue;
}
if (gyro_Base_Pos_Map.TryGetValue(target, out Vector2 basePos))
{
target.anchoredPosition = basePos;
}
if (gyro_Base_Rot_Map.TryGetValue(target, out Vector3 baseRot))
{
target.localEulerAngles = baseRot;
}
}
}
if (gyro_BG_Base_Scale_Set && group_Background != null)
{
group_Background.localScale = gyro_BG_Base_Scale;
}
gyro_BG_Base_Scale_Set = false;
gyro_Targets.Clear();
gyro_Base_Pos_Map.Clear();
gyro_Base_Rot_Map.Clear();
gyro_Offset_Weight_Map.Clear();
gyro_Rot_Weight_Map.Clear();
gyro_Current_Offset = Vector2.zero;
gyro_Current_RotDelta = Vector3.zero;
gyro_Inited = false;
}
void Start_Jiantou_Loop()
{
if (!play_Jiantou_Loop)
{
return;
}
Cache_Enter_Refs();
if (!jiantou_Inited)
{
Cache_Jiantou_Templates();
Build_Jiantou_Pool();
jiantou_Inited = jiantou_Flows.Count > 0;
}
if (jiantou_Require_Hover && !jiantou_Hovered)
{
Hide_Jiantou_All();
jiantou_Running = false;
return;
}
Restart_Jiantou_Loop();
}
void Stop_Jiantou_Loop()
{
jiantou_Running = false;
Stop_Jiantou_Flash();
for (int f = 0; f < jiantou_Flows.Count; f++)
{
JiantouFlow flow = jiantou_Flows[f];
if (flow == null)
{
continue;
}
for (int i = 0; i < flow.instances.Count; i++)
{
RectTransform rect = flow.instances[i];
if (rect == null)
{
continue;
}
Kill_Target(rect);
rect.anchoredPosition = flow.basePos;
if (rect != flow.template)
{
rect.gameObject.SetActive(false);
}
}
flow.startY.Clear();
}
}
void Hide_Jiantou_All()
{
Stop_Jiantou_Flash();
for (int f = 0; f < jiantou_Flows.Count; f++)
{
JiantouFlow flow = jiantou_Flows[f];
if (flow == null)
{
continue;
}
for (int i = 0; i < flow.instances.Count; i++)
{
RectTransform rect = flow.instances[i];
if (rect == null)
{
continue;
}
CanvasGroup group = Ensure_CanvasGroup(rect.gameObject);
if (group != null)
{
group.alpha = 0f;
}
if (rect != flow.template)
{
rect.gameObject.SetActive(false);
}
}
}
}
void Show_Jiantou_All()
{
for (int f = 0; f < jiantou_Flows.Count; f++)
{
JiantouFlow flow = jiantou_Flows[f];
if (flow == null)
{
continue;
}
for (int i = 0; i < flow.instances.Count; i++)
{
RectTransform rect = flow.instances[i];
if (rect == null)
{
continue;
}
rect.gameObject.SetActive(true);
}
}
}
public void On_Jiantou_Hover_Enter()
{
if (!play_Jiantou_Loop || !jiantou_Require_Hover)
{
return;
}
jiantou_Hovered = true;
Start_Jiantou_Loop();
if (jiantou_Flash_Routine != null)
{
StopCoroutine(jiantou_Flash_Routine);
}
jiantou_Flash_Routine = StartCoroutine(C_Jiantou_Flash_Then_Run());
StartCoroutine(C_Ensure_Jiantou_Run());
}
public void On_Jiantou_Hover_Exit()
{
if (!play_Jiantou_Loop || !jiantou_Require_Hover)
{
return;
}
jiantou_Hovered = false;
jiantou_Running = false;
Stop_Jiantou_Flash();
Hide_Jiantou_All();
}
IEnumerator C_Jiantou_Flash_Then_Run()
{
jiantou_Running = false;
Stop_Jiantou_Flash();
Show_Jiantou_All();
float flashTime = Mathf.Max(jiantou_Flash_Time, 0.01f);
int flashCount = Mathf.Max(1, jiantou_Flash_Count);
float interval = Mathf.Max(jiantou_Flash_Interval, 0f);
for (int f = 0; f < jiantou_Flows.Count; f++)
{
JiantouFlow flow = jiantou_Flows[f];
if (flow == null)
{
continue;
}
for (int i = 0; i < flow.instances.Count; i++)
{
RectTransform rect = flow.instances[i];
if (rect == null)
{
continue;
}
CanvasGroup group = Ensure_CanvasGroup(rect.gameObject);
if (group == null)
{
continue;
}
group.alpha = 0f;
Tween flash = group.DOFade(1f, flashTime)
.SetEase(Ease.InOutQuad)
.SetLoops(flashCount * 2, LoopType.Yoyo)
.SetUpdate(true);
jiantou_Flash_Tweens.Add(flash);
}
}
float wait = (flashTime * 2f * flashCount) + interval;
if (wait > 0f)
{
yield return gyro_Use_Unscaled ? new WaitForSecondsRealtime(wait) : new WaitForSeconds(wait);
}
for (int i = 0; i < jiantou_Flash_Tweens.Count; i++)
{
Tween tween = jiantou_Flash_Tweens[i];
if (tween != null)
{
tween.Kill();
}
}
jiantou_Flash_Tweens.Clear();
for (int f = 0; f < jiantou_Flows.Count; f++)
{
JiantouFlow flow = jiantou_Flows[f];
if (flow == null)
{
continue;
}
for (int i = 0; i < flow.instances.Count; i++)
{
RectTransform rect = flow.instances[i];
if (rect == null)
{
continue;
}
if (rect.TryGetComponent(out CanvasGroup group))
{
group.alpha = 1f;
}
}
}
if (jiantou_Hovered)
{
Restart_Jiantou_Loop();
}
jiantou_Running = jiantou_Hovered;
jiantou_Flash_Routine = null;
}
IEnumerator C_Ensure_Jiantou_Run()
{
float flashTime = Mathf.Max(jiantou_Flash_Time, 0.01f);
int flashCount = Mathf.Max(1, jiantou_Flash_Count);
float interval = Mathf.Max(jiantou_Flash_Interval, 0f);
float wait = (flashTime * 2f * flashCount) + interval + 0.05f;
if (wait > 0f)
{
yield return gyro_Use_Unscaled ? new WaitForSecondsRealtime(wait) : new WaitForSeconds(wait);
}
if (jiantou_Hovered)
{
Restart_Jiantou_Loop();
}
}
void Stop_Jiantou_Flash()
{
if (jiantou_Flash_Routine != null)
{
StopCoroutine(jiantou_Flash_Routine);
jiantou_Flash_Routine = null;
}
for (int i = 0; i < jiantou_Flash_Tweens.Count; i++)
{
Tween tween = jiantou_Flash_Tweens[i];
if (tween != null)
{
tween.Kill();
}
}
jiantou_Flash_Tweens.Clear();
}
void Update_Jiantou_Loop()
{
if (!play_Jiantou_Loop || !jiantou_Running || jiantou_Flows.Count == 0)
{
return;
}
float dt = gyro_Use_Unscaled ? Time.unscaledDeltaTime : Time.deltaTime;
if (dt <= 0f)
{
return;
}
for (int f = 0; f < jiantou_Flows.Count; f++)
{
JiantouFlow flow = jiantou_Flows[f];
if (flow == null || flow.instances.Count == 0 || flow.speed <= 0f)
{
continue;
}
float delta = flow.speed * dt * flow.direction;
for (int i = 0; i < flow.instances.Count; i++)
{
RectTransform rect = flow.instances[i];
if (rect == null)
{
continue;
}
Vector2 pos = rect.anchoredPosition;
pos.y += delta;
rect.anchoredPosition = pos;
if (flow.direction > 0f && pos.y > flow.endLimitY)
{
float resetY = (flow.startY.Count > i) ? flow.startY[i] : flow.basePos.y;
rect.anchoredPosition = new Vector2(flow.basePos.x, resetY);
}
else if (flow.direction < 0f && pos.y < flow.endLimitY)
{
float resetY = (flow.startY.Count > i) ? flow.startY[i] : flow.basePos.y;
rect.anchoredPosition = new Vector2(flow.basePos.x, resetY);
}
}
}
}
void Cache_Jiantou_Templates()
{
jiantou_Flows.Clear();
RectTransform left = jiantou_Left_Template;
RectTransform right = jiantou_Right_Template;
if (left == null || right == null)
{
RectTransform[] rects = content_Root != null
? content_Root.GetComponentsInChildren<RectTransform>(true)
: UnityEngine.Object.FindObjectsByType<RectTransform>(FindObjectsInactive.Include, FindObjectsSortMode.InstanceID);
List<RectTransform> candidates = new();
for (int i = 0; i < rects.Length; i++)
{
RectTransform rect = rects[i];
if (rect == null)
{
continue;
}
if (!Is_Jiantou_Name(rect.name))
{
continue;
}
string lowerName = rect.name.ToLowerInvariant();
if (lowerName.Contains("_loop_") || lowerName.Contains("_flow_"))
{
continue;
}
candidates.Add(rect);
}
candidates.Sort((a, b) => Get_Rect_Area(b).CompareTo(Get_Rect_Area(a)));
if (left == null && candidates.Count > 0)
{
left = candidates[0];
}
if (right == null && candidates.Count > 1)
{
right = candidates[1];
}
}
if (left != null && right != null && left == right)
{
right = null;
}
if (left != null && right != null && left.position.x > right.position.x)
{
RectTransform temp = left;
left = right;
right = temp;
}
if (left != null && right != null)
{
Add_Jiantou_Flow(left, 1f);
Add_Jiantou_Flow(right, -1f);
}
else if (left != null)
{
float dir = left.position.x <= 0f ? 1f : -1f;
Add_Jiantou_Flow(left, dir);
}
else if (right != null)
{
float dir = right.position.x >= 0f ? -1f : 1f;
Add_Jiantou_Flow(right, dir);
}
}
void Add_Jiantou_Flow(RectTransform template, float direction)
{
if (template == null)
{
return;
}
if (!Is_Scene_Object(template))
{
return;
}
JiantouFlow flow = new JiantouFlow
{
template = template,
parent = template.parent as RectTransform,
direction = direction,
basePos = template.anchoredPosition
};
jiantou_Flows.Add(flow);
}
void Build_Jiantou_Pool()
{
if (jiantou_Flows.Count == 0)
{
return;
}
int poolSize = Mathf.Max(1, jiantou_Pool_Size);
for (int f = 0; f < jiantou_Flows.Count; f++)
{
JiantouFlow flow = jiantou_Flows[f];
if (flow == null || flow.template == null)
{
continue;
}
flow.instances.Clear();
flow.startY.Clear();
RectTransform template = flow.template;
RectTransform parent = template.parent as RectTransform;
flow.parent = parent;
List<RectTransform> pool = new();
pool.Add(template);
List<RectTransform> extras = new();
if (parent != null)
{
for (int i = 0; i < parent.childCount; i++)
{
RectTransform child = parent.GetChild(i) as RectTransform;
if (child == null || child == template)
{
continue;
}
if (child.name.StartsWith($"{template.name}_Loop_", StringComparison.Ordinal)
|| child.name.StartsWith($"{template.name}_Flow_", StringComparison.Ordinal))
{
extras.Add(child);
}
}
}
extras.Sort((a, b) => string.CompareOrdinal(a.name, b.name));
for (int i = 0; i < extras.Count; i++)
{
RectTransform child = extras[i];
if (pool.Count < poolSize)
{
pool.Add(child);
}
else
{
child.gameObject.SetActive(false);
}
}
for (int i = pool.Count; i < poolSize; i++)
{
RectTransform instance = Instantiate(template, parent);
if (instance == null)
{
continue;
}
instance.name = $"{template.name}_Loop_{i}";
pool.Add(instance);
}
for (int i = 0; i < pool.Count; i++)
{
RectTransform instance = pool[i];
if (instance == null)
{
continue;
}
instance.gameObject.SetActive(true);
flow.instances.Add(instance);
}
}
}
void Restart_Jiantou_Loop()
{
Stop_Jiantou_Loop();
if (jiantou_Flows.Count == 0 || jiantou_Move_Duration <= 0f)
{
return;
}
float duration = Mathf.Max(jiantou_Move_Duration, 0.01f);
float staggerValue = jiantou_Stagger;
float spacingValue = jiantou_Spacing;
if (jiantou_Hovered)
{
if (jiantou_Hover_Move_Duration > 0f)
{
duration = Mathf.Max(jiantou_Hover_Move_Duration, 0.01f);
}
if (jiantou_Hover_Stagger > 0f)
{
staggerValue = jiantou_Hover_Stagger;
}
if (jiantou_Hover_Spacing > 0f)
{
spacingValue = jiantou_Hover_Spacing;
}
}
for (int f = 0; f < jiantou_Flows.Count; f++)
{
JiantouFlow flow = jiantou_Flows[f];
if (flow == null || flow.template == null || flow.instances.Count == 0)
{
continue;
}
flow.basePos = flow.template.anchoredPosition;
flow.parent = flow.template.parent as RectTransform;
float parentHeight = Get_Rect_Height(flow.parent);
float fallbackHeight = Get_Rect_Height(content_Root);
if (parentHeight <= 0f || Mathf.Abs(flow.basePos.y) > parentHeight * 0.6f)
{
parentHeight = fallbackHeight;
}
if (parentHeight <= 0f)
{
parentHeight = Screen.height;
}
float rectHeight = Get_Rect_Height(flow.template);
float extra = Mathf.Max(jiantou_Move_Amplitude, 0f);
flow.endLimitY = flow.direction > 0f
? (parentHeight * 0.5f + rectHeight * 0.5f + extra)
: (-parentHeight * 0.5f - rectHeight * 0.5f - extra);
float distanceToEnd = Mathf.Abs(flow.endLimitY - flow.basePos.y);
flow.speed = distanceToEnd / duration;
float staggerTime = Mathf.Max(staggerValue, 0.01f);
float minSpacing = Mathf.Max(1f, rectHeight * 1.1f);
float targetSpacing = spacingValue > 0f ? spacingValue : minSpacing;
flow.spacing = Mathf.Max(minSpacing, targetSpacing);
float jitter = 0f;
flow.startY.Clear();
for (int i = 0; i < flow.instances.Count; i++)
{
RectTransform rect = flow.instances[i];
if (rect == null)
{
continue;
}
rect.gameObject.SetActive(true);
float startY = flow.basePos.y + jitter - flow.direction * flow.spacing * i;
rect.anchoredPosition = new Vector2(flow.basePos.x, startY);
flow.startY.Add(startY);
CanvasGroup group = Ensure_CanvasGroup(rect.gameObject);
if (group != null)
{
group.alpha = UnityEngine.Random.Range(jiantou_Alpha_Min, jiantou_Alpha_Max);
}
}
}
jiantou_Running = !jiantou_Require_Hover || jiantou_Hovered;
}
float Get_Rect_Width(RectTransform rect)
{
if (rect == null)
{
return 0f;
}
float width = rect.rect.width;
if (width <= 0f)
{
width = rect.sizeDelta.x;
}
return Mathf.Abs(width);
}
float Get_Rect_Height(RectTransform rect)
{
if (rect == null)
{
return 0f;
}
float height = rect.rect.height;
if (height <= 0f)
{
height = rect.sizeDelta.y;
}
return Mathf.Abs(height);
}
float Get_Rect_Area(RectTransform rect)
{
return Get_Rect_Width(rect) * Get_Rect_Height(rect);
}
void Add_Gyro_Target(RectTransform rect, float offsetWeight, float rotWeight, bool allowBG)
{
if (rect == null)
{
return;
}
if (Is_Top_Bottom_Related(rect))
{
return;
}
if (!allowBG && Is_BG_Related(rect))
{
return;
}
if (!allowBG && Is_Jiantou_Name(rect.name))
{
return;
}
if (!allowBG && Has_Jiantou_Descendant(rect))
{
return;
}
if (gyro_Offset_Weight_Map.ContainsKey(rect))
{
return;
}
gyro_Targets.Add(rect);
gyro_Offset_Weight_Map[rect] = Mathf.Clamp(offsetWeight, -2f, 2f);
gyro_Rot_Weight_Map[rect] = Mathf.Clamp(rotWeight, -2f, 2f);
}
float Get_Gyro_Weight(RectTransform rect, int index)
{
if (rect == null)
{
return 1f;
}
float min = Mathf.Min(gyro_All_Offset_Min, gyro_All_Offset_Max);
float max = Mathf.Max(gyro_All_Offset_Min, gyro_All_Offset_Max);
int seed = Stable_Hash(rect.name) + (index + 1) * 97;
float weight = Mathf.Lerp(min, max, Hash01(seed, 1));
if (content_Root != null)
{
float contentArea = content_Root.rect.width * content_Root.rect.height;
float rectArea = rect.rect.width * rect.rect.height;
if (contentArea > 1f && rectArea > 0f)
{
float size01 = Mathf.Clamp01(rectArea / contentArea);
float sizeFactor = Mathf.Lerp(1.25f, 0.75f, size01);
weight *= sizeFactor;
}
}
return Mathf.Clamp(weight, 0f, 2f);
}
bool Is_BG_Related(RectTransform rect)
{
if (rect == null || group_Background == null)
{
return false;
}
if (rect == group_Background)
{
return true;
}
return rect.IsChildOf(group_Background);
}
bool Is_Top_Bottom_Related(RectTransform rect)
{
if (rect == null)
{
return false;
}
if (group_Top != null && (rect == group_Top || rect.IsChildOf(group_Top)))
{
return true;
}
if (group_Bottom != null && (rect == group_Bottom || rect.IsChildOf(group_Bottom)))
{
return true;
}
return false;
}
}
public class UI_ButtonTween : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler,
IPointerUpHandler, ISelectHandler, IDeselectHandler
{
float hoverScale = 1.04f;
float pressScale = 0.96f;
float hoverTime = 0.08f;
float pressTime = 0.06f;
float releaseTime = 0.12f;
Ease hoverEase = Ease.OutQuad;
Ease pressEase = Ease.OutQuad;
Ease releaseEase = Ease.OutBack;
Vector3 baseScale = Vector3.one;
Tween scaleTween;
bool pointerInside;
bool pointerDown;
bool selected;
public void ApplyConfig(float hoverScaleValue, float pressScaleValue, float hoverTimeValue, float pressTimeValue,
float releaseTimeValue, Ease hoverEaseValue, Ease pressEaseValue, Ease releaseEaseValue)
{
hoverScale = hoverScaleValue;
pressScale = pressScaleValue;
hoverTime = hoverTimeValue;
pressTime = pressTimeValue;
releaseTime = releaseTimeValue;
hoverEase = hoverEaseValue;
pressEase = pressEaseValue;
releaseEase = releaseEaseValue;
baseScale = transform.localScale;
}
void OnEnable()
{
baseScale = transform.localScale;
}
void OnDisable()
{
KillTween();
transform.localScale = baseScale;
pointerInside = false;
pointerDown = false;
selected = false;
}
void OnDestroy()
{
KillTween();
}
public void OnPointerEnter(PointerEventData eventData)
{
pointerInside = true;
if (!pointerDown)
{
ApplyScale(hoverScale, hoverTime, hoverEase);
}
}
public void OnPointerExit(PointerEventData eventData)
{
pointerInside = false;
if (!pointerDown && !selected)
{
ApplyScale(1f, hoverTime, hoverEase);
}
}
public void OnPointerDown(PointerEventData eventData)
{
pointerDown = true;
ApplyScale(pressScale, pressTime, pressEase);
}
public void OnPointerUp(PointerEventData eventData)
{
pointerDown = false;
float target = (pointerInside || selected) ? hoverScale : 1f;
ApplyScale(target, releaseTime, releaseEase);
}
public void OnSelect(BaseEventData eventData)
{
selected = true;
if (!pointerDown)
{
ApplyScale(hoverScale, hoverTime, hoverEase);
}
}
public void OnDeselect(BaseEventData eventData)
{
selected = false;
if (!pointerDown && !pointerInside)
{
ApplyScale(1f, hoverTime, hoverEase);
}
}
void ApplyScale(float targetScale, float time, Ease ease)
{
KillTween();
scaleTween = transform.DOScale(baseScale * targetScale, Mathf.Max(time, 0.01f))
.SetEase(ease)
.SetUpdate(true);
}
void KillTween()
{
if (scaleTween != null)
{
scaleTween.Kill();
scaleTween = null;
}
}
}
public class UI_RightButtonHover : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
float idleOffset = 60f;
float finalOffset = 0f;
float moveTime = 0.18f;
Ease moveEase = Ease.OutCubic;
float textFlashTime = 0.06f;
int textFlashCount = 2;
float textFlashInterval = 0.02f;
RectTransform imageRect;
Vector2 imageBasePos;
CanvasGroup imageGroup;
readonly List<CanvasGroup> textGroups = new();
Tween imageTween;
public void ApplyConfig(float idleOffsetValue, float finalOffsetValue, float moveTimeValue, Ease moveEaseValue,
float textFlashTimeValue, int textFlashCountValue, float textFlashIntervalValue)
{
idleOffset = Mathf.Max(0f, idleOffsetValue);
// Keep icon inside the button frame: positive config means "shift left by this amount".
// Use a softened offset so icon sits slightly more to the right.
finalOffset = -Mathf.Abs(finalOffsetValue) * 0.75f;
moveTime = Mathf.Max(0.01f, moveTimeValue);
moveEase = moveEaseValue;
textFlashTime = Mathf.Max(0.01f, textFlashTimeValue);
textFlashCount = Mathf.Max(1, textFlashCountValue);
textFlashInterval = Mathf.Max(0f, textFlashIntervalValue);
CacheTargets();
SetIdleState();
}
void OnEnable()
{
CacheTargets();
SetIdleState();
}
void OnDisable()
{
KillTweens();
}
void CacheTargets()
{
if (imageRect == null)
{
Transform imageChild = transform.Find("Image");
if (imageChild != null)
{
imageRect = imageChild as RectTransform;
}
}
if (imageRect != null)
{
imageBasePos = imageRect.anchoredPosition;
if (imageGroup == null)
{
imageGroup = imageRect.GetComponent<CanvasGroup>();
if (imageGroup == null)
imageGroup = imageRect.gameObject.AddComponent<CanvasGroup>();
}
}
textGroups.Clear();
for (int i = 0; i < transform.childCount; i++)
{
Transform child = transform.GetChild(i);
if (child == null)
{
continue;
}
string lower = child.name.ToLowerInvariant();
if (lower == "image" || lower == "boarder" || lower == "border")
{
continue;
}
Text uiText = child.GetComponent<Text>();
if (uiText != null)
{
CanvasGroup group = child.GetComponent<CanvasGroup>();
if (group == null)
{
group = child.gameObject.AddComponent<CanvasGroup>();
}
textGroups.Add(group);
continue;
}
Component tmp = child.GetComponent("TMP_Text");
if (tmp != null)
{
CanvasGroup group = child.GetComponent<CanvasGroup>();
if (group == null)
{
group = child.gameObject.AddComponent<CanvasGroup>();
}
textGroups.Add(group);
}
}
}
void SetIdleState()
{
if (imageRect != null)
{
// Keep icon at its final position; only toggle visibility on hover.
imageRect.anchoredPosition = imageBasePos + Vector2.right * finalOffset;
}
if (imageGroup != null)
{
imageGroup.alpha = 0f; // hidden until hover
}
for (int i = 0; i < textGroups.Count; i++)
{
if (textGroups[i] != null)
{
// Text should always be visible (no flash-in).
textGroups[i].alpha = 1f;
}
}
}
public void OnPointerEnter(PointerEventData eventData)
{
FlashImage();
}
public void OnPointerExit(PointerEventData eventData)
{
HideImage();
}
void FlashImage()
{
if (imageRect == null || imageGroup == null)
{
return;
}
if (imageTween != null)
{
imageTween.Kill();
imageTween = null;
}
// Ensure icon is at its final position (no translation anim).
imageRect.anchoredPosition = imageBasePos + Vector2.right * finalOffset;
// Flash-in (blink) on hover, then stay visible.
imageGroup.alpha = 0f;
Sequence seq = DOTween.Sequence().SetUpdate(true);
for (int c = 0; c < textFlashCount; c++)
{
seq.Append(imageGroup.DOFade(1f, textFlashTime).SetEase(Ease.OutQuad));
seq.Append(imageGroup.DOFade(0f, textFlashTime).SetEase(Ease.InQuad));
if (textFlashInterval > 0f)
{
seq.AppendInterval(textFlashInterval);
}
}
seq.Append(imageGroup.DOFade(1f, textFlashTime).SetEase(Ease.OutQuad));
imageTween = seq;
}
void HideImage()
{
if (imageTween != null)
{
imageTween.Kill();
imageTween = null;
}
if (imageGroup != null)
{
imageGroup.alpha = 0f;
}
}
void KillTweens()
{
HideImage();
}
}
public class UI_JiantouHover : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
UI_Panel_Main main;
public void Bind(UI_Panel_Main target)
{
main = target;
}
public void OnPointerEnter(PointerEventData eventData)
{
if (main != null)
{
main.On_Jiantou_Hover_Enter();
}
}
public void OnPointerExit(PointerEventData eventData)
{
if (main != null)
{
main.On_Jiantou_Hover_Exit();
}
}
}
public class UI_StartButtonHover : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
string offCn = "鎵ц浠诲姟";
string offEn = "Start";
string onCn = "鎰忓織澶嶆紨";
string onEn = "REITERATION OF WILL";
float charInterval = 0.03f;
Text cnText;
Text enText;
Component cnTmp;
Component enTmp;
Coroutine animateRoutine;
public void ApplyTexts(string offCnValue, string offEnValue, string onCnValue, string onEnValue)
{
offCn = offCnValue;
offEn = offEnValue;
onCn = onCnValue;
onEn = onEnValue;
CacheTexts();
SetText(offCn, cnText, cnTmp);
SetText(offEn, enText, enTmp);
}
void OnEnable()
{
CacheTexts();
SetText(offCn, cnText, cnTmp);
SetText(offEn, enText, enTmp);
}
void OnDisable()
{
if (animateRoutine != null)
{
StopCoroutine(animateRoutine);
animateRoutine = null;
}
}
public void OnPointerEnter(PointerEventData eventData)
{
if (animateRoutine != null)
{
StopCoroutine(animateRoutine);
}
animateRoutine = StartCoroutine(C_TypeTexts(onCn, onEn));
}
public void OnPointerExit(PointerEventData eventData)
{
if (animateRoutine != null)
{
StopCoroutine(animateRoutine);
animateRoutine = null;
}
SetText(offCn, cnText, cnTmp);
SetText(offEn, enText, enTmp);
}
void CacheTexts()
{
if (cnText != null || cnTmp != null)
{
return;
}
Text[] texts = GetComponentsInChildren<Text>(true);
for (int i = 0; i < texts.Length; i++)
{
Text t = texts[i];
string lower = t.name.ToLowerInvariant();
if (lower.Contains("start") || lower.Contains("will") || lower.Contains("reiter"))
{
enText = t;
}
else
{
cnText = t;
}
}
Component[] tmps = GetComponentsInChildren<Component>(true);
for (int i = 0; i < tmps.Length; i++)
{
Component comp = tmps[i];
if (comp == null)
{
continue;
}
if (!comp.GetType().Name.Contains("TMP_Text"))
{
continue;
}
string lower = comp.name.ToLowerInvariant();
if (lower.Contains("start") || lower.Contains("will") || lower.Contains("reiter"))
{
enTmp = comp;
}
else
{
cnTmp = comp;
}
}
}
IEnumerator C_TypeTexts(string targetCn, string targetEn)
{
bool cnDone = false;
bool enDone = false;
if (!string.IsNullOrEmpty(targetCn))
{
StartCoroutine(C_TypeText(targetCn, cnText, cnTmp, () => cnDone = true));
}
else
{
cnDone = true;
}
if (!string.IsNullOrEmpty(targetEn))
{
StartCoroutine(C_TypeText(targetEn, enText, enTmp, () => enDone = true));
}
else
{
enDone = true;
}
while (!cnDone || !enDone)
{
yield return null;
}
animateRoutine = null;
}
IEnumerator C_TypeText(string target, Text uiText, Component tmpText, Action onDone)
{
if (string.IsNullOrEmpty(target))
{
onDone?.Invoke();
yield break;
}
char[] chars = target.ToCharArray();
bool useDot = false;
for (int i = 0; i < chars.Length; i++)
{
if (chars[i] > 127)
{
useDot = true;
break;
}
}
string randomChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i <= chars.Length; i++)
{
string prefix = new string(chars, 0, i);
string suffix = "";
if (i < chars.Length)
{
int remain = chars.Length - i;
char[] filler = new char[remain];
for (int r = 0; r < remain; r++)
{
filler[r] = useDot ? '.' : randomChars[(i + r) % randomChars.Length];
}
suffix = new string(filler);
}
SetText(prefix + suffix, uiText, tmpText);
yield return new WaitForSecondsRealtime(charInterval);
}
SetText(target, uiText, tmpText);
onDone?.Invoke();
}
void SetText(string value, Text uiText, Component tmpText)
{
if (uiText != null)
{
uiText.text = value;
return;
}
if (tmpText != null)
{
var prop = tmpText.GetType().GetProperty("text");
if (prop != null)
{
prop.SetValue(tmpText, value, null);
}
}
}
}