diff --git a/Assets/ModelRenderer/Editor.meta b/Assets/ModelRenderer/Editor.meta new file mode 100644 index 0000000000..0a8faaa99c --- /dev/null +++ b/Assets/ModelRenderer/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ace5809ec565f244b96e257e231b4abc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModelRenderer/Editor/CombineActionSOAssigner.cs b/Assets/ModelRenderer/Editor/CombineActionSOAssigner.cs new file mode 100644 index 0000000000..5fe1ff8806 --- /dev/null +++ b/Assets/ModelRenderer/Editor/CombineActionSOAssigner.cs @@ -0,0 +1,321 @@ +// UTF-8 with BOM — required for Chinese character paths +using System.Collections.Generic; +using System.IO; +using System.Text; +using BrewMonster.Scripts.ECModel; +using UnityEditor; +using UnityEngine; + +public class CombineActionSOAssigner : EditorWindow +{ + // Fixed — this is always where the weapon prefabs live + private const string PrefabRootPath = "Assets/ModelRenderer/Art/Models/models/weapons"; + + // Log files land next to the project's Logs/ folder + private static readonly string LogDir = Path.GetFullPath("Logs/SOAssigner"); + + private string _soRootPath = "Assets/ModelRenderer/Art/Models/models/weapons"; + private bool _isDryRun = true; + private Vector2 _scrollPos; + private readonly List _log = new(); + private string _lastLogFile; + + private static readonly GUIStyle HeaderStyle = new(EditorStyles.boldLabel) + { + fontSize = 14 + }; + + [MenuItem("Tools/Brew Monster/Combine Action SO Assigner")] + public static void ShowWindow() + { + var win = GetWindow(false, "SO Assigner", true); + win.minSize = new Vector2(520, 480); + } + + private void OnGUI() + { + DrawHeader(); + DrawConfig(); + DrawButtons(); + DrawLog(); + } + + // ── UI sections ────────────────────────────────────────────────────────── + + private void DrawHeader() + { + EditorGUILayout.Space(6); + EditorGUILayout.LabelField("Combine Action SO Assigner", HeaderStyle); + EditorGUILayout.LabelField("Batch-assigns CombinedActionSO assets to weapon prefabs.", EditorStyles.miniLabel); + DrawSeparator(); + } + + private void DrawConfig() + { + EditorGUILayout.LabelField("Paths", EditorStyles.boldLabel); + + using (new EditorGUI.DisabledScope(true)) + EditorGUILayout.TextField("Prefab Root (fixed)", PrefabRootPath); + + _soRootPath = EditorGUILayout.TextField("SO Root Path", _soRootPath); + + EditorGUILayout.HelpBox( + "SO Root must mirror the prefab folder tree.\n" + + "e.g. SO: {SO Root}/人物/刀剑/15品单刀/15品单刀.asset\n" + + " Prefab: " + PrefabRootPath + "/人物/刀剑/15品单刀/15品单刀.prefab", + MessageType.Info); + + DrawSeparator(); + + EditorGUILayout.LabelField("Options", EditorStyles.boldLabel); + _isDryRun = EditorGUILayout.Toggle("Dry Run (no writes)", _isDryRun); + + if (_isDryRun) + EditorGUILayout.HelpBox("Dry Run ON — matches will be logged but nothing will be saved to disk.", MessageType.Warning); + else + EditorGUILayout.HelpBox("Dry Run OFF — prefabs WILL be modified and saved.", MessageType.Error); + + DrawSeparator(); + } + + private void DrawButtons() + { + EditorGUILayout.BeginHorizontal(); + + if (GUILayout.Button("Orphan Check", GUILayout.Height(30))) + RunOrphanCheck(); + + GUI.backgroundColor = _isDryRun ? Color.yellow : Color.red; + if (GUILayout.Button(_isDryRun ? "Run (Dry)" : "Run (LIVE — writes disk)", GUILayout.Height(30))) + RunAssignment(); + GUI.backgroundColor = Color.white; + + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.Space(4); + } + + private void DrawLog() + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Log", EditorStyles.boldLabel); + if (!string.IsNullOrEmpty(_lastLogFile) && GUILayout.Button("Open Log File", GUILayout.Width(100))) + EditorUtility.RevealInFinder(_lastLogFile); + if (GUILayout.Button("Clear", GUILayout.Width(60))) + { + _log.Clear(); + _lastLogFile = null; + } + EditorGUILayout.EndHorizontal(); + + if (!string.IsNullOrEmpty(_lastLogFile)) + EditorGUILayout.LabelField(_lastLogFile, EditorStyles.miniLabel); + + _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos, GUILayout.ExpandHeight(true)); + foreach (var line in _log) + EditorGUILayout.LabelField(line, EditorStyles.wordWrappedLabel); + EditorGUILayout.EndScrollView(); + } + + private static void DrawSeparator() + { + EditorGUILayout.Space(4); + Rect r = EditorGUILayout.GetControlRect(false, 1); + EditorGUI.DrawRect(r, new Color(0.5f, 0.5f, 0.5f, 0.5f)); + EditorGUILayout.Space(4); + } + + // ── Core logic ─────────────────────────────────────────────────────────── + + private void RunOrphanCheck() + { + _log.Clear(); + _log.Add("=== ORPHAN CHECK ==="); + + string[] guids = AssetDatabase.FindAssets("t:Prefab", new[] { PrefabRootPath }); + int orphans = 0; + var fileLines = new List { $"=== ORPHAN CHECK {Timestamp()} ===" }; + + foreach (string guid in guids) + { + string prefabPath = AssetDatabase.GUIDToAssetPath(guid); + string soPath = BuildSOPath(prefabPath); + + if (AssetDatabase.LoadAssetAtPath(soPath) == null) + { + string line1 = $"[ORPHAN] {Path.GetFileNameWithoutExtension(prefabPath)}"; + string line2 = $" expected SO: {soPath}"; + _log.Add(line1); + _log.Add(line2); + fileLines.Add(line1); + fileLines.Add(line2); + orphans++; + } + } + + string summary = $"=== {orphans} orphan(s) out of {guids.Length} prefab(s) ==="; + _log.Add(summary); + fileLines.Add(summary); + + _lastLogFile = WriteLogFile("OrphanCheck", fileLines); + Debug.Log($"[SO Assigner] Orphan Check — {orphans}/{guids.Length} orphans. Log: {_lastLogFile}"); + Repaint(); + } + + private void RunAssignment() + { + _log.Clear(); + string header = _isDryRun ? "=== DRY RUN ===" : "=== LIVE RUN ==="; + _log.Add(header); + + string[] guids = AssetDatabase.FindAssets("t:Prefab", new[] { PrefabRootPath }); + int matched = 0, skipped = 0, failed = 0; + + var fileLines = new List { $"{header} {Timestamp()}" }; + + try + { + for (int i = 0; i < guids.Length; i++) + { + string prefabPath = AssetDatabase.GUIDToAssetPath(guids[i]); + string prefabName = Path.GetFileNameWithoutExtension(prefabPath); + string soPath = BuildSOPath(prefabPath); + + EditorUtility.DisplayProgressBar( + "Assigning CombinedActionSO", + prefabName, + (float)i / guids.Length); + + CombinedActionSO so = AssetDatabase.LoadAssetAtPath(soPath); + if (so == null) + { + string skipLine = $"[SKIP] {prefabName} → {soPath}"; + fileLines.Add(skipLine); + if (!_isDryRun) + _log.Add(skipLine); // window only gets skips in live mode + skipped++; + continue; + } + + if (_isDryRun) + { + // File gets every match; window stays quiet + fileLines.Add($"[MATCH] {prefabName} → {soPath}"); + matched++; + } + else + { + if (!TryAssign(prefabPath, so, out string error)) + { + string errLine = $"[ERROR] {prefabName} — {error}"; + _log.Add(errLine); + fileLines.Add(errLine); + failed++; + } + else + { + fileLines.Add($"[OK] {prefabName}"); + matched++; + } + } + + // Memory management every 100 items + if (i > 0 && i % 100 == 0) + { + Resources.UnloadUnusedAssets(); + System.GC.Collect(); + } + } + } + finally + { + EditorUtility.ClearProgressBar(); + } + + if (!_isDryRun) + AssetDatabase.SaveAssets(); + + string summary = $"matched: {matched}, skipped: {skipped}, failed: {failed} (total: {guids.Length})"; + string summaryLine = $"=== DONE — {summary} ==="; + _log.Add(summaryLine); + fileLines.Add(summaryLine); + + _lastLogFile = WriteLogFile(_isDryRun ? "DryRun" : "LiveRun", fileLines); + + Debug.Log($"[SO Assigner] {(_isDryRun ? "DRY RUN" : "LIVE")} — {summary} | Log: {_lastLogFile}"); + + if (skipped > 0) + Debug.LogWarning($"[SO Assigner] {skipped} unmatched prefab(s) — see log file for details: {_lastLogFile}"); + + Repaint(); + } + + private static bool TryAssign(string prefabPath, CombinedActionSO so, out string error) + { + error = null; + GameObject root = null; + try + { + root = PrefabUtility.LoadPrefabContents(prefabPath); + + CombineActHolder holder = root.GetComponent(); + if (holder == null) + { + error = "CombineActHolder not found on root GameObject"; + return false; + } + + using SerializedObject serializedHolder = new(holder); + SerializedProperty prop = serializedHolder.FindProperty("combinedActionSO"); + if (prop == null) + { + error = "SerializedProperty 'combinedActionSO' not found"; + return false; + } + + prop.objectReferenceValue = so; + serializedHolder.ApplyModifiedPropertiesWithoutUndo(); + + PrefabUtility.SaveAsPrefabAsset(root, prefabPath); + return true; + } + catch (System.Exception ex) + { + error = ex.Message; + return false; + } + finally + { + if (root != null) + PrefabUtility.UnloadPrefabContents(root); + } + } + + // ── File logging ───────────────────────────────────────────────────────── + + private static string WriteLogFile(string prefix, List lines) + { + Directory.CreateDirectory(LogDir); + string fileName = $"{prefix}_{System.DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log"; + string fullPath = Path.Combine(LogDir, fileName); + File.WriteAllLines(fullPath, lines, new UTF8Encoding(encoderShouldEmitUTF8Identifier: true)); + return fullPath; + } + + private static string Timestamp() => + System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + + // ── Path helpers ───────────────────────────────────────────────────────── + + /// + /// Maps a prefab path to its expected SO path using mirror structure. + /// Prefab: Assets/ModelRenderer/Art/Models/models/weapons/X/Y/Z.prefab + /// SO: {_soRootPath}/X/Y/Z.asset + /// + private string BuildSOPath(string prefabPath) + { + string relative = prefabPath.Substring(PrefabRootPath.Length).TrimStart('/'); + string assetRelative = Path.ChangeExtension(relative, ".asset").Replace('\\', '/'); + return _soRootPath.TrimEnd('/') + "/" + assetRelative; + } +} diff --git a/Assets/ModelRenderer/Editor/CombineActionSOAssigner.cs.meta b/Assets/ModelRenderer/Editor/CombineActionSOAssigner.cs.meta new file mode 100644 index 0000000000..c280205fb8 --- /dev/null +++ b/Assets/ModelRenderer/Editor/CombineActionSOAssigner.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 9a82642463c35e244802b6f20f754c7a \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Chat/UI/ChatSystemlUI.cs b/Assets/PerfectWorld/Scripts/Chat/UI/ChatSystemlUI.cs index 17d416447b..fdb12bd4b2 100644 --- a/Assets/PerfectWorld/Scripts/Chat/UI/ChatSystemlUI.cs +++ b/Assets/PerfectWorld/Scripts/Chat/UI/ChatSystemlUI.cs @@ -156,7 +156,7 @@ namespace BrewMonster.Scripts.ChatUI void OnOpenChatPanelRequested(OpenChatPanelRequestedEvent _) { if (this == null) return; - OpenChatPanel(); + OpenChatPanel(_.focusInputOnOpen); } private bool ShouldShowMessage(ChatMessageData data) @@ -347,13 +347,18 @@ namespace BrewMonster.Scripts.ChatUI } public void OpenChatPanel() + { + OpenChatPanel(true); + } + + public void OpenChatPanel(bool focusInputOnOpen) { if (chatPanelUIGO == null) return; SetChatPanelAndBgVisible(true); RefreshVisible(); _chatInput ??= GetComponent(); - if (_chatInput != null && _chatInput.inputField != null) + if (focusInputOnOpen && _chatInput != null && _chatInput.inputField != null) _chatInput.inputField.ActivateInputField(); } @@ -392,5 +397,13 @@ namespace BrewMonster.Scripts.ChatUI /// /// Mini chat (hoặc HUD) publish để mở panel chat đầy đủ; subscribe. /// - public struct OpenChatPanelRequestedEvent { } + public struct OpenChatPanelRequestedEvent + { + public bool focusInputOnOpen; + + public OpenChatPanelRequestedEvent(bool focusInputOnOpen) + { + this.focusInputOnOpen = focusInputOnOpen; + } + } } diff --git a/Assets/PerfectWorld/Scripts/Chat/UI/MiniChatUI.cs b/Assets/PerfectWorld/Scripts/Chat/UI/MiniChatUI.cs index 101a4f021e..132a66326a 100644 --- a/Assets/PerfectWorld/Scripts/Chat/UI/MiniChatUI.cs +++ b/Assets/PerfectWorld/Scripts/Chat/UI/MiniChatUI.cs @@ -84,7 +84,7 @@ namespace BrewMonster.Scripts.ChatUI if (!string.IsNullOrEmpty(chatDialogName) && CECUIManager.Instance != null) CECUIManager.Instance.ShowUI(chatDialogName); - EventBus.Publish(new OpenChatPanelRequestedEvent()); + EventBus.Publish(new OpenChatPanelRequestedEvent(false)); } void OnChannelFilterChanged(ChatChannelFilterChangedEvent e) diff --git a/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs b/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs index 8184cf7522..c71f88878e 100644 --- a/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs +++ b/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs @@ -271,6 +271,54 @@ namespace BrewMonster "胧族变身月仙男", "胧族变身月仙女", }; + public Dictionary> m_aWeaponSFX = new Dictionary>() + { + {0, new List{"item/weaponattack/1hshorta", "item/weaponattack/1hshortb", "item/weaponattack/1hshortc"}}, + {1, new List{"item/weaponattack/1hshorta", "item/weaponattack/1hshortb", "item/weaponattack/1hshortc"}}, + {2, new List{"item/weaponattack/2hlonga", "item/weaponattack/2hlongb", "item/weaponattack/2hlongc", "item/weaponattack/2hlongd"}}, + {3, new List{"item/weaponattack/1hshorta", "item/weaponattack/1hshortb", "item/weaponattack/1hshortc"}}, + {4, new List{"item/weaponattack/2hlonga", "item/weaponattack/2hlongb", "item/weaponattack/2hlongc", "item/weaponattack/2hlongd"}}, + {5, new List{"item/weaponattack/1hshorta", "item/weaponattack/1hshortb"}}, + {6, new List{"item/weaponattack/bow", "item/weaponattack/bowb", "item/weaponattack/drawbow"}}, + {7, new List{"item/weaponattack/bow", "item/weaponattack/bowb", "item/weaponattack/drawbow"}}, + {8, new List{"item/weaponattack/fista", "item/weaponattack/fistb", "item/weaponattack/fistc", "item/weaponattack/fistd"}}, + {9, new List{"item/weaponattack/bow", "item/weaponattack/bowb", "item/weaponattack/drawbow"}}, + {10, new List{"item/weaponattack/fista", "item/weaponattack/fistb", "item/weaponattack/fistc", "item/weaponattack/fistd"}}, + // {0, new List{"item/weaponattack/1hshorta", "item/weaponattack/1hshortb", "item/weaponattack/1hshortc"}}, + // {1, new List{"item/weaponattack/2hheavya", "item/weaponattack/2hheavyb", "item/weaponattack/2hheavyc", "item/weaponattack/2hheavyd"}}, + // {2, new List{"item/weaponattack/2hlonga", "item/weaponattack/2hlongb", "item/weaponattack/2hlongc", "item/weaponattack/2hlongd"}}, + // {3, new List{"item/weaponattack/bow", "item/weaponattack/bowb", "item/weaponattack/drawbow"}}, + // {4, new List{"item/weaponattack/fista", "item/weaponattack/fistb", "item/weaponattack/fistc", "item/weaponattack/fistd"}}, + // {5, new List{"item/weaponattack/magic", "item/weaponattack/magicb"}}, + }; + public Dictionary> m_aWeaponHitSFX = new Dictionary>() + { + {0, new List{"item/weaponattack/hitsword", "item/weaponattack/hitswordbig"}}, + {1, new List{"item/weaponattack/hitsword", "item/weaponattack/hitswordbig"}}, + {2, new List{"item/weaponattack/hitmace", "item/weaponattack/hitmacebig"}}, + {3, new List{"item/weaponattack/hithammer", "item/weaponattack/hithammerbig"}}, + {4, new List{"item/weaponattack/hitaxe", "item/weaponattack/hitaxebig"}}, + {5, new List{"item/weaponattack/hithammer"}}, + {6, new List{"item/weaponattack/hitthrow"}}, + {7, new List{"item/weaponattack/hitthrow"}}, + {8, new List{"item/weaponattack/hithand"}}, + {9, new List{"item/weaponattack/hitthrow"}}, + {10, new List{"item/weaponattack/hithand"}}, + // {0, new List{"item/weaponattack/hitaxe", "item/weaponattack/hitaxebig"}}, + // {1, new List{"item/weaponattack/hithammer", "item/weaponattack/hithammerbig"}}, + // {2, new List{"item/weaponattack/hitblade", "item/weaponattack/hitbladebig"}}, + // {3, new List{"item/weaponattack/hitdagger"}}, + // {4, new List{"item/weaponattack/hitfist"}}, + // {5, new List{"item/weaponattack/hithand"}}, + // {6, new List{"item/weaponattack/hitstaff"}}, + // {7, new List{"item/weaponattack/hitmace", "item/weaponattack/hitmacebig"}}, + // {8, new List{"item/weaponattack/hitoriginal"}}, + // {9, new List{"item/weaponattack/hitsword", "item/weaponattack/hitswordbig"}}, + // {10, new List{"item/weaponattack/hittiger"}}, + // {11, new List{"item/weaponattack/hitwhip"}}, + // {12, new List{"item/weaponattack/hitthrow"}}, + // {13, new List{"item/weaponattack/hitbow", "item/weaponattack/hitbowbig"}}, + }; public static class Effect_type { public const int EFF_FACEPILL = 1; @@ -1631,11 +1679,13 @@ namespace BrewMonster int nRand = UnityEngine.Random.Range(0, 4); string szAct = string.Empty; - string szShapeName = string.Empty; - GetShapeName(ref szShapeName); int weapon_type = GetShowingWeaponType(); + Debug.Log("PlayAttackAction: weapon_type=" + weapon_type); int nTime1 = 0, nTime2 = 0; int iAction = (int)PLAYER_ACTION_TYPE.ACT_ATTACK_1 + nRand; + + string soundPath = m_aWeaponSFX[weapon_type][nRand%m_aWeaponSFX[weapon_type].Count]; + string hitSoundPath = m_aWeaponHitSFX[weapon_type][nRand%m_aWeaponHitSFX[weapon_type].Count]; bool bHideFX = false;//!CECOptimize::Instance().GetGFX().CanShowAttack(GetCharacterID(), GetClassID()); PLAYER_ACTION action = m_PlayerActions[iAction]; @@ -1654,12 +1704,19 @@ namespace BrewMonster // “起�? 动作(挥起) szAct = EC_Utility.BuildActionName(action, weapon_type, "起"); int iTransTime = 200; - //EventBus.PublishChannel(m_PlayerInfo.cid, new PlayActionEvent(szShapeName, szAct, iTransTime, true)); m_pActionController.PlayNonSkillActionWithName(iAction, szAct, true, iTransTime, bHideFX, attackEvent,COMACT_FLAG_MODE_ONCE_MULTIIGNOREGFX); + //swing sfx + //workaround for sound effect delay, it need to trigger via weapon combine action + SFXManager.Instance.PlaySkillSfxAtPointAsync(soundPath, Vector3.zero,iTransTime/1000f).Forget(); + szAct = EC_Utility.BuildActionName(action, weapon_type, "落"); - queueActionEvent.SetData(szShapeName, szAct, SetApplyDamage, true, attackEvent, iTransTime,false); - //EventBus.PublishChannelClass(m_PlayerInfo.cid, queueActionEvent); m_pActionController.QueueNonSkillActionWithName(iAction, szAct, 0, false, bHideFX); + + //hit sfx + //workaround for sound effect delay, it need to trigger via weapon combine action + //.1f is a magic number to make sure the sound effect is triggered after the action is finished + SFXManager.Instance.PlaySkillSfxAtPointAsync(hitSoundPath, Vector3.zero,iTransTime/1000f+.1f).Forget(); + //PlayNonSkillActionWithName(iAction, szAct, true, 200, true, ref pActFlag, COMACT_FLAG_MODE_ONCE_MULTIIGNOREGFX);gagága /* if (pRightHandWeapon != null && IsUsingMagicWeapon()) @@ -1705,7 +1762,6 @@ namespace BrewMonster // nTime1 = m_pPlayerModel.GetComActTimeSpanByName(szAct); szAct = EC_Utility.BuildActionName(action, weapon_type, "落", szActionMiddleName); - queueActionEvent.SetData(szShapeName, szAct, SetApplyDamage, false, attackEvent, 0, false); //EventBus.PublishChannelClass(m_PlayerInfo.cid, queueActionEvent); m_pActionController.QueueNonSkillActionWithName(iAction, szAct, 0, false, false, true, false); @@ -3911,7 +3967,7 @@ namespace BrewMonster public CECAttackEvent AttackEvent; public bool IsHitAnim; public bool IsForceStopPrevious; - public bool IsLoop; + public bool IsLoop; public QueueActionEvent(string animationName, Action setFlag, bool isHitAnim, CECAttackEvent attackEvent, int iTransTime, bool isForceStopPrevious = false, bool isLoop = false) { diff --git a/Assets/PerfectWorld/Scripts/NPC/CECModel.cs b/Assets/PerfectWorld/Scripts/NPC/CECModel.cs index 450200a90c..a776135f1f 100644 --- a/Assets/PerfectWorld/Scripts/NPC/CECModel.cs +++ b/Assets/PerfectWorld/Scripts/NPC/CECModel.cs @@ -686,7 +686,12 @@ public class CECModel { if(sfx.m_strFilePaths != null && sfx.m_strFilePaths.Count > 0) { - string soundpath = AFile.NormalizePath(sfx.m_strFilePaths[0]); + string soundpath = AFile.NormalizePath(sfx.m_strFilePaths[0],true); + //we need to determine sfx and gfx. now we dont have logic for this path + if(soundpath.Contains("gfx")) + { + continue; + } soundpath = soundpath.ToLower(); SFXManager.Instance.PlaySkillSfxAtPointAsync(soundpath, Vector3.zero).Forget(); } diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs index 05c1150c86..4bcd7bb5a8 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs @@ -52,6 +52,8 @@ namespace CSNetwork private Action _createRoleCallback; private RoleInfo _selectedRole; public bool IsConnected => _networkManager?.IsConnected ?? false; + public bool IsConnectedInternet => Application.internetReachability != NetworkReachability.NotReachable; + // When true, suppress *gameplay traffic* (mostly gamedatasend C2S commands) during logout/scene transitions. // We still allow account/role flow protocols like rolelist/selectrole so "Return to Select Role" can work. private volatile bool _suppressGameplayTraffic = false; diff --git a/Assets/PerfectWorld/Scripts/Sound/AudioManager.cs b/Assets/PerfectWorld/Scripts/Sound/AudioManager.cs index 13887d890a..a59c019a0b 100644 --- a/Assets/PerfectWorld/Scripts/Sound/AudioManager.cs +++ b/Assets/PerfectWorld/Scripts/Sound/AudioManager.cs @@ -11,7 +11,8 @@ public class AudioManager : MonoBehaviour [SerializeField] private AudioMixerGroup _bgmMixerGroup; [SerializeField] private AudioMixerGroup _ambienceMixerGroup; - + [SerializeField] private AudioMixerGroup _sfxMixerGroup; + public AudioMixerGroup GetSfxMixerGroup => _sfxMixerGroup; private AudioSource _ambienceSource; void Awake() diff --git a/Assets/PerfectWorld/Scripts/Sound/SFXManager.cs b/Assets/PerfectWorld/Scripts/Sound/SFXManager.cs index bcdcef95da..676b68a131 100644 --- a/Assets/PerfectWorld/Scripts/Sound/SFXManager.cs +++ b/Assets/PerfectWorld/Scripts/Sound/SFXManager.cs @@ -264,5 +264,10 @@ namespace BrewMonster.Scripts _moveSoundSource.Play(); } } + public async UniTaskVoid StopMoveSoundAsync() + { + if (_moveSoundSource == null) return; + _moveSoundSource.Stop(); + } } } diff --git a/Assets/PerfectWorld/Scripts/UI/Login/BtnBackToSelectRole.cs b/Assets/PerfectWorld/Scripts/UI/Login/BtnBackToSelectRole.cs index 1c13540f72..5d5abc9835 100644 --- a/Assets/PerfectWorld/Scripts/UI/Login/BtnBackToSelectRole.cs +++ b/Assets/PerfectWorld/Scripts/UI/Login/BtnBackToSelectRole.cs @@ -11,17 +11,17 @@ namespace BrewMonster.UI public void OnClick() { // CECUIManager.Instance.ShowMessageBox( - // title: "Thoát", + // title: "Thoát", // message: "Đang rời khỏi Thế Giới Hoàn Mỹ", // messageBoxType: MessageBoxType.YesButton // ); - + // CECGameRun.Instance.GetPendingLogOut().AppendForSaveConfig(new CECPendingLogoutHalf()); // UnityGameSession.ReturnToSelectRole(); OnCommandRepick(); } - + // void CDlgSystem3::OnCommandRepick(const char *szCommand) // { // a_LogOutput(1, "CDlgSystem3::OnCommandRepick "); @@ -36,8 +36,8 @@ namespace BrewMonster.UI // pMsgBox->SetIsModal(false); // } // } - - + + void OnCommandRepick() { CECUIManager.Instance.ShowMessageBoxYes("Thoát", @@ -47,8 +47,13 @@ namespace BrewMonster.UI void OnClickYes() { CECGameRun.Instance.GetPendingLogOut().AppendForSaveConfig(new CECPendingLogoutHalf()); + if (!UnityGameSession.Instance.GameSession.IsConnectedInternet) + { + //force log out half + EC_Game.GetGameRun().SetLogoutFlag(1); + } } - + } } diff --git a/Assets/PerfectWorld/Scripts/UI/Login/LoginScreenUI.cs b/Assets/PerfectWorld/Scripts/UI/Login/LoginScreenUI.cs index e19fe6fe1a..5e2cbc3791 100644 --- a/Assets/PerfectWorld/Scripts/UI/Login/LoginScreenUI.cs +++ b/Assets/PerfectWorld/Scripts/UI/Login/LoginScreenUI.cs @@ -343,8 +343,9 @@ namespace BrewMonster.UI isDoneNPCRender = true; isDoneWorldRender = true; actLoadChar?.Invoke(); + AudioManager.Instance.StopBGM(1f); + WorldMusicController.Instance.InitForWorld(roleInfo.worldtag); UnityGameSession.EnterWorldAsync(roleInfo, OnEnterWorldComplete); - }); #endif }, null); diff --git a/Assets/PerfectWorld/Scripts/UI/SkillUI/CDlgSkillSubPool.cs b/Assets/PerfectWorld/Scripts/UI/SkillUI/CDlgSkillSubPool.cs index 6dd920d158..dbbe068e7f 100644 --- a/Assets/PerfectWorld/Scripts/UI/SkillUI/CDlgSkillSubPool.cs +++ b/Assets/PerfectWorld/Scripts/UI/SkillUI/CDlgSkillSubPool.cs @@ -28,6 +28,7 @@ namespace BrewMonster public override void OnEnable() { + _currentSelectSkill = null; UpdateView(); _skillSetUpComboWidget.ShowSetUpContent(false); _skillSetUpComboWidget.OnClickedSkillSlot += OnClickedSkillSlot; @@ -45,6 +46,7 @@ namespace BrewMonster public override void OnDisable() { + _currentSelectComboSlot = null; if (_currentSelectSkill is LearnedSkillUI learnedOnClose) { learnedOnClose.SetFocusFrame(false); diff --git a/Assets/PerfectWorld/Scripts/UI/WorldMap.meta b/Assets/PerfectWorld/Scripts/UI/WorldMap.meta new file mode 100644 index 0000000000..d30ed9d9f7 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/UI/WorldMap.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fce16fcbe8e82ec4588c7fba89c7cb64 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/PerfectWorld/Scripts/UI/DlgWorldMap.cs b/Assets/PerfectWorld/Scripts/UI/WorldMap/DlgWorldMap.cs similarity index 74% rename from Assets/PerfectWorld/Scripts/UI/DlgWorldMap.cs rename to Assets/PerfectWorld/Scripts/UI/WorldMap/DlgWorldMap.cs index a20a1728ca..425a0028da 100644 --- a/Assets/PerfectWorld/Scripts/UI/DlgWorldMap.cs +++ b/Assets/PerfectWorld/Scripts/UI/WorldMap/DlgWorldMap.cs @@ -1,3 +1,4 @@ +using BrewMonster.Network; using CSNetwork.Common; using UnityEngine; using UnityEngine.UI; @@ -54,10 +55,14 @@ namespace BrewMonster.UI public override bool Render() { - // UpdateHostPlayerPositionImage(); + UpdateHostPlayerPositionImage(); return base.Render(); } + + Vector3 _hostPlayerPosition; + Quaternion _hostPlayerRotation; + private void UpdateHostPlayerPositionImage() { if (_hostPlayerPositionImage == null) @@ -65,7 +70,7 @@ namespace BrewMonster.UI return; } - if (!TryGetHostPlayerPosition(out Vector3 hostPosition)) + if (!TryGetHostPlayerPosition(out _hostPlayerPosition, out _hostPlayerRotation)) { _hostPlayerPositionImage.enabled = false; return; @@ -81,13 +86,16 @@ namespace BrewMonster.UI _hostPlayerPositionImage.enabled = true; RectTransform hostPlayerRectTransform = _hostPlayerPositionImage.rectTransform; hostPlayerRectTransform.anchoredPosition = new Vector2( - hostPosition.x / _positionFactor, - hostPosition.z / _positionFactor); + _hostPlayerPosition.x / _positionFactor, + _hostPlayerPosition.z / _positionFactor); + + hostPlayerRectTransform.localRotation = Quaternion.Euler(0, 0, -_hostPlayerRotation.eulerAngles.y); } - private bool TryGetHostPlayerPosition(out Vector3 hostPlayerPosition) + private bool TryGetHostPlayerPosition(out Vector3 hostPlayerPosition, out Quaternion hostPlayerRotation) { hostPlayerPosition = Vector3.zero; + hostPlayerRotation = Quaternion.identity; CECHostPlayer hostPlayer = GetHostPlayer(); if (hostPlayer == null || hostPlayer.transform == null) @@ -96,6 +104,7 @@ namespace BrewMonster.UI } hostPlayerPosition = hostPlayer.transform.position; + hostPlayerRotation = hostPlayer.transform.rotation; return true; } @@ -139,6 +148,20 @@ namespace BrewMonster.UI } } + /// + /// When user click on the map texture. + /// We will calculate the world coordinates from the local cursor position. Then move the host player to the world coordinates. + /// + /// + public void OnMapClicked(Vector2 localCursorPosition) + { + var worldCoordinates = localCursorPosition * _positionFactor; + UnityGameSession.c2s_CmdGoto(worldCoordinates.x, 1.0f, worldCoordinates.y); + + // close the map + OnCloseButtonClicked(); + } + private void OnCloseButtonClicked() { CloseDialogue(); diff --git a/Assets/PerfectWorld/Scripts/UI/DlgWorldMap.cs.meta b/Assets/PerfectWorld/Scripts/UI/WorldMap/DlgWorldMap.cs.meta similarity index 100% rename from Assets/PerfectWorld/Scripts/UI/DlgWorldMap.cs.meta rename to Assets/PerfectWorld/Scripts/UI/WorldMap/DlgWorldMap.cs.meta diff --git a/Assets/PerfectWorld/Scripts/UI/WorldMap/WorldMapClickHandler.cs b/Assets/PerfectWorld/Scripts/UI/WorldMap/WorldMapClickHandler.cs new file mode 100644 index 0000000000..e051a5b058 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/UI/WorldMap/WorldMapClickHandler.cs @@ -0,0 +1,59 @@ +using UnityEngine; +using UnityEngine.EventSystems; + +namespace BrewMonster.UI +{ + public class WorldMapClickHandler : MonoBehaviour, IPointerClickHandler + { + [Tooltip("The RectTransform of the Map Image (Usually this GameObject)")] + private RectTransform mapRectTransform; + + [SerializeField] private RectTransform _hostPlayerPositionImage; + + public DlgWorldMap dlgWorldMap; + + // The host player player (0,0,0) is not at the center of the map. It usually has an offset that we have to calculate at Awake + private Vector2 _hostPlayerOffsetPosition; + + private void Awake() + { + // Get the RectTransform of the map + mapRectTransform = GetComponent(); + + CalculateHostPlayerOffsetPosition(); + } + + private void CalculateHostPlayerOffsetPosition() + { + _hostPlayerOffsetPosition = _hostPlayerPositionImage.anchoredPosition; + + // if the max/min of the anchor is 0.5 0.5, then the host player is at the center of the map + // however we have to calculate the offset of the player because it is not at the center of the map + // we can calculate the offset by the max/min of the anchor + var maxAnchor = _hostPlayerPositionImage.anchorMax; + var minAnchor = _hostPlayerPositionImage.anchorMin; + _hostPlayerOffsetPosition = new Vector2((maxAnchor.x - 0.5f) * mapRectTransform.rect.width, (maxAnchor.y - 0.5f) * mapRectTransform.rect.height); + } + + // This triggers automatically when the user clicks/taps on this Image + public void OnPointerClick(PointerEventData eventData) + { + Vector2 localCursorPosition; + + // Convert the screen click position to local anchored position inside the Map + bool isConverted = RectTransformUtility.ScreenPointToLocalPointInRectangle( + mapRectTransform, + eventData.position, + eventData.pressEventCamera, + out localCursorPosition + ); + + if (isConverted) + { + // convert the localCursorPosition to the local position of the host player position image + localCursorPosition -= _hostPlayerOffsetPosition; + dlgWorldMap.OnMapClicked(localCursorPosition); + } + } + } +} diff --git a/Assets/PerfectWorld/Scripts/UI/WorldMap/WorldMapClickHandler.cs.meta b/Assets/PerfectWorld/Scripts/UI/WorldMap/WorldMapClickHandler.cs.meta new file mode 100644 index 0000000000..9199d3ecf5 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/UI/WorldMap/WorldMapClickHandler.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 876ab9894018f2b4cb4a0b04bf534bc5 \ No newline at end of file diff --git a/Assets/Prefabs/ChatSystem/prefab_ChatSystemUI.prefab b/Assets/Prefabs/ChatSystem/prefab_ChatSystemUI.prefab index f1481018a6..11af5afd56 100644 --- a/Assets/Prefabs/ChatSystem/prefab_ChatSystemUI.prefab +++ b/Assets/Prefabs/ChatSystem/prefab_ChatSystemUI.prefab @@ -187,6 +187,7 @@ RectTransform: m_Children: - {fileID: 2739455247741079987} - {fileID: 1473246120053017968} + - {fileID: 3282421669272709967} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} @@ -234,6 +235,11 @@ MonoBehaviour: m_EditorClassIdentifier: inputField: {fileID: 3037472824809581303} chatSystem: {fileID: 11400000, guid: 43f54723aa074c74e83e5be28975bee5, type: 2} + typingPreview: + typingPreviewRoot: {fileID: 4018402239503345071} + typingPreviewText: {fileID: 1616725709352662407} + typingPreviewRect: {fileID: 3282421669272709967} + previewVerticalOffset: 100 _spriteMap: {fileID: 11400000, guid: f634ecf63ca3d004f82af9b17c966fc9, type: 2} channelButtons: - channel: 0 @@ -1110,6 +1116,163 @@ MonoBehaviour: m_OnValueChanged: m_PersistentCalls: m_Calls: [] +--- !u!1 &2902411919389723293 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 9105702282600116830} + - component: {fileID: 8286996527838887664} + - component: {fileID: 1830860820497748550} + - component: {fileID: 4544532093443431984} + m_Layer: 5 + m_Name: Placeholder + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &9105702282600116830 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2902411919389723293} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 3605044702849397252} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &8286996527838887664 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2902411919389723293} + m_CullTransparentMesh: 1 +--- !u!114 &1830860820497748550 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2902411919389723293} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: "Nh\u1EADp n\u1ED9i dung..." + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2} + m_sharedMaterial: {fileID: 9092487103257209053, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 2150773298 + m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 0.5} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 2 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 0 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 0 + m_ActiveFontFeatures: 6e72656b + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!114 &4544532093443431984 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2902411919389723293} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 1 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 --- !u!1 &3095457626805744279 GameObject: m_ObjectHideFlags: 0 @@ -1493,6 +1656,142 @@ MonoBehaviour: m_OnClick: m_PersistentCalls: m_Calls: [] +--- !u!1 &3569864358642720813 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6179475653333898123} + - component: {fileID: 3165768457449138107} + - component: {fileID: 4701185761014729773} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6179475653333898123 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3569864358642720813} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 3605044702849397252} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &3165768457449138107 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3569864358642720813} + m_CullTransparentMesh: 1 +--- !u!114 &4701185761014729773 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3569864358642720813} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: "\u200B" + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2} + m_sharedMaterial: {fileID: 9092487103257209053, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4281479730 + m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 3 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 0 + m_ActiveFontFeatures: 6e72656b + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} --- !u!1 &3646889256970119758 GameObject: m_ObjectHideFlags: 0 @@ -1671,6 +1970,184 @@ MonoBehaviour: isAlert: 0 m_InputValidator: {fileID: 0} m_ShouldActivateOnSelect: 1 +--- !u!1 &3775041254222000362 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4921631315982434735} + - component: {fileID: 682447300637418577} + - component: {fileID: 7576867370938653448} + - component: {fileID: 1616725709352662407} + m_Layer: 5 + m_Name: InputField (TMP) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4921631315982434735 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3775041254222000362} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 3605044702849397252} + m_Father: {fileID: 3282421669272709967} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &682447300637418577 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3775041254222000362} + m_CullTransparentMesh: 1 +--- !u!114 &7576867370938653448 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3775041254222000362} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!114 &1616725709352662407 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3775041254222000362} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2da0c512f12947e489f739169773d7ca, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 1, g: 1, b: 1, a: 1} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 0 + m_TargetGraphic: {fileID: 7576867370938653448} + m_TextViewport: {fileID: 3605044702849397252} + m_TextComponent: {fileID: 4701185761014729773} + m_Placeholder: {fileID: 1830860820497748550} + m_VerticalScrollbar: {fileID: 0} + m_VerticalScrollbarEventHandler: {fileID: 0} + m_LayoutGroup: {fileID: 0} + m_ScrollSensitivity: 1 + m_ContentType: 0 + m_InputType: 0 + m_AsteriskChar: 42 + m_KeyboardType: 0 + m_LineType: 0 + m_HideMobileInput: 0 + m_HideSoftKeyboard: 0 + m_CharacterValidation: 0 + m_RegexValue: + m_GlobalPointSize: 36 + m_CharacterLimit: 0 + m_OnEndEdit: + m_PersistentCalls: + m_Calls: [] + m_OnSubmit: + m_PersistentCalls: + m_Calls: [] + m_OnSelect: + m_PersistentCalls: + m_Calls: [] + m_OnDeselect: + m_PersistentCalls: + m_Calls: [] + m_OnTextSelection: + m_PersistentCalls: + m_Calls: [] + m_OnEndTextSelection: + m_PersistentCalls: + m_Calls: [] + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_OnTouchScreenKeyboardStatusChanged: + m_PersistentCalls: + m_Calls: [] + m_CaretColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_CustomCaretColor: 0 + m_SelectionColor: {r: 0.65882355, g: 0.80784315, b: 1, a: 0.7529412} + m_Text: + m_CaretBlinkRate: 0.85 + m_CaretWidth: 1 + m_ReadOnly: 0 + m_RichText: 1 + m_GlobalFontAsset: {fileID: 11400000, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2} + m_OnFocusSelectAll: 1 + m_ResetOnDeActivation: 1 + m_KeepTextSelectionVisible: 0 + m_RestoreOriginalTextOnEscape: 1 + m_isRichTextEditingAllowed: 0 + m_LineLimit: 0 + isAlert: 0 + m_InputValidator: {fileID: 0} + m_ShouldActivateOnSelect: 1 --- !u!1 &3878366334053570553 GameObject: m_ObjectHideFlags: 0 @@ -1869,6 +2346,82 @@ MonoBehaviour: m_OnClick: m_PersistentCalls: m_Calls: [] +--- !u!1 &4018402239503345071 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3282421669272709967} + - component: {fileID: 1622721548801034628} + - component: {fileID: 7848833373218203551} + m_Layer: 5 + m_Name: Typing Preview + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &3282421669272709967 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4018402239503345071} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 4921631315982434735} + m_Father: {fileID: 806170753671297629} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 15, y: -100} + m_SizeDelta: {x: -30, y: 450.9249} + m_Pivot: {x: 0.5, y: 1} +--- !u!222 &1622721548801034628 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4018402239503345071} + m_CullTransparentMesh: 1 +--- !u!114 &7848833373218203551 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4018402239503345071} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 --- !u!1 &4042949282556349356 GameObject: m_ObjectHideFlags: 0 @@ -4063,6 +4616,58 @@ MonoBehaviour: m_hasFontAssetChanged: 0 m_baseMaterial: {fileID: 0} m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!1 &6903426946426451281 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3605044702849397252} + - component: {fileID: 2373715959292045924} + m_Layer: 5 + m_Name: Text Area + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3605044702849397252 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6903426946426451281} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 9105702282600116830} + - {fileID: 6179475653333898123} + m_Father: {fileID: 4921631315982434735} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: -0.50001526} + m_SizeDelta: {x: -20, y: -13} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2373715959292045924 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6903426946426451281} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3312d7739989d2b4e91e6319e9a96d76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: {x: -8, y: -5, z: -8, w: -5} + m_Softness: {x: 0, y: 0} --- !u!1 &6957797720283583814 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Prefabs/UI/DlgWorldMap.prefab b/Assets/Prefabs/UI/DlgWorldMap.prefab index 245de697af..3eafab46a6 100644 --- a/Assets/Prefabs/UI/DlgWorldMap.prefab +++ b/Assets/Prefabs/UI/DlgWorldMap.prefab @@ -1,5 +1,80 @@ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: +--- !u!1 &191621185379502263 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 9142400375056319150} + - component: {fileID: 7949922842883969624} + - component: {fileID: 6790297770241223980} + m_Layer: 0 + m_Name: click_pos + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &9142400375056319150 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 191621185379502263} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 7169122999130120872} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 15, y: 15} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7949922842883969624 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 191621185379502263} + m_CullTransparentMesh: 1 +--- !u!114 &6790297770241223980 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 191621185379502263} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 --- !u!1 &936441858863998774 GameObject: m_ObjectHideFlags: 0 @@ -35,7 +110,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 403.03613, y: 341.03613} + m_AnchoredPosition: {x: 549, y: 465} m_SizeDelta: {x: 58, y: 58} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &6772256914059310038 @@ -286,7 +361,7 @@ MonoBehaviour: imageProgress: {fileID: 0} mapImage: {fileID: 1174346096914174862} _hostPlayerPositionImage: {fileID: 4036230907032538800} - _positionFactor: 2.5 + _positionFactor: 1.8 _closeButton: {fileID: 8858186809287203567} --- !u!1 &8308536083041954008 GameObject: @@ -363,6 +438,81 @@ MonoBehaviour: m_FillOrigin: 0 m_UseSpriteMesh: 0 m_PixelsPerUnitMultiplier: 1 +--- !u!1 &8900623989843312765 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1510574663178069641} + - component: {fileID: 5533213955690836106} + - component: {fileID: 7414570214724661608} + m_Layer: 0 + m_Name: hostplayerpos_debug + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &1510574663178069641 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8900623989843312765} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 7169122999130120872} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.518} + m_AnchorMax: {x: 0.5, y: 0.518} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 13, y: 16} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &5533213955690836106 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8900623989843312765} + m_CullTransparentMesh: 1 +--- !u!114 &7414570214724661608 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8900623989843312765} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 448046091, guid: 99520ceed6182dd408f2da040fe0c033, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 --- !u!1 &8924313797425690832 GameObject: m_ObjectHideFlags: 0 @@ -374,6 +524,7 @@ GameObject: - component: {fileID: 7169122999130120872} - component: {fileID: 7283747291599937432} - component: {fileID: 1174346096914174862} + - component: {fileID: 4521997594693838426} m_Layer: 0 m_Name: MapTexture m_TagString: Untagged @@ -394,12 +545,14 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: - {fileID: 5906545349664091413} + - {fileID: 1510574663178069641} + - {fileID: 9142400375056319150} m_Father: {fileID: 7323734624486819451} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 1024, y: 1024} + m_AnchoredPosition: {x: -6.0056, y: -6.0056} + m_SizeDelta: {x: 1408.0024, y: 1408.0024} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &7283747291599937432 CanvasRenderer: @@ -439,3 +592,17 @@ MonoBehaviour: m_FillOrigin: 0 m_UseSpriteMesh: 0 m_PixelsPerUnitMultiplier: 1 +--- !u!114 &4521997594693838426 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8924313797425690832} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 876ab9894018f2b4cb4a0b04bf534bc5, type: 3} + m_Name: + m_EditorClassIdentifier: + _hostPlayerPositionImage: {fileID: 5906545349664091413} + dlgWorldMap: {fileID: 135853640611757204} diff --git a/Assets/Prefabs/UI/Music.prefab.meta b/Assets/Prefabs/UI/Music.prefab.meta new file mode 100644 index 0000000000..ef403827e9 --- /dev/null +++ b/Assets/Prefabs/UI/Music.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2c6625b7f2f4bc2469813fb85db84114 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/ChatInputHandler.cs b/Assets/Scripts/ChatInputHandler.cs index 88371501f1..af0c5bca5b 100644 --- a/Assets/Scripts/ChatInputHandler.cs +++ b/Assets/Scripts/ChatInputHandler.cs @@ -3,14 +3,11 @@ using UnityEngine; using TMPro; using CSNetwork.GPDataType; using System.Collections.Generic; -using BrewMonster; using BrewMonster.Network; using BrewMonster.Scripts.Chat; using BrewMonster.Scripts.Chat.EmotionData; -using BrewMonster.Scripts.Managers; using BrewMonster.UI; using CSNetwork; -using PerfectWorld.Scripts.Managers; namespace BrewMonster.Scripts.ChatUI { @@ -31,6 +28,9 @@ namespace BrewMonster.Scripts.ChatUI public TMP_InputField inputField; public ChatSystemSO chatSystem; + [Header("Typing Preview")] + [SerializeField] private TypingPreviewController typingPreview = new(); + [Header("Emoji")] [Tooltip("SO ánh xạ emotion → TMP sprite tag. Gán EmotionLibrarySpriteMap đã build từ Emotion Atlas Converter.")] [SerializeField] EmotionLibrarySpriteMap _spriteMap; @@ -110,6 +110,8 @@ namespace BrewMonster.Scripts.ChatUI private float m_dwTickFarCry = 0; private float m_dwTickFarCry2 = 0; + private Vector2 _inputBarBaseAnchoredPos; + private bool _cachedAnchors; private void Awake() { @@ -172,6 +174,14 @@ namespace BrewMonster.Scripts.ChatUI } UpdateChatDropdownInteractable(); + UpdateTypingPreviewFromInput(); + } + + private void Update() + { + // Keyboard open/close does not always trigger input value changed, + // so refresh preview gate every frame. + UpdateTypingPreviewFromInput(); } // ===================================================== @@ -812,6 +822,8 @@ namespace BrewMonster.Scripts.ChatUI { inputField.text = ""; } + + UpdateTypingPreviewFromInput(); } private int GetEmotionSetForCurrentChannel() @@ -877,6 +889,7 @@ namespace BrewMonster.Scripts.ChatUI if (_syncingWireToDisplay) { _lastInputFieldText = newText; + UpdateTypingPreviewFromInput(); return; } @@ -884,6 +897,7 @@ namespace BrewMonster.Scripts.ChatUI { _lastInputFieldText = newText; SyncChatWireBodyFromInput(); + UpdateTypingPreviewFromInput(); return; } @@ -905,11 +919,13 @@ namespace BrewMonster.Scripts.ChatUI inputField.ForceLabelUpdate(); _lastInputFieldText = fixedText; SyncChatWireBodyFromInput(); + UpdateTypingPreviewFromInput(); return; } _lastInputFieldText = newText; SyncChatWireBodyFromInput(); + UpdateTypingPreviewFromInput(); } /// @@ -981,6 +997,15 @@ namespace BrewMonster.Scripts.ChatUI inputField.ActivateInputField(); } + void UpdateTypingPreviewFromInput() + { + if (inputField == null) + return; + + string body = ExtractMessageBodyFromVisual(inputField.text ?? ""); + typingPreview?.UpdatePreview(inputField.isFocused, body); + } + /// /// C++: GetHostPlayer()->GetPack()->GetItemTotalNum(id) — đếm túi chính. /// diff --git a/Assets/Scripts/TypingPreviewController.cs b/Assets/Scripts/TypingPreviewController.cs new file mode 100644 index 0000000000..fe81ac39b4 --- /dev/null +++ b/Assets/Scripts/TypingPreviewController.cs @@ -0,0 +1,76 @@ +using TMPro; +using UnityEngine; + +namespace BrewMonster.Scripts.ChatUI +{ + /// + /// Controls typing preview visibility/content and keyboard-anchored position. + /// Kept standalone so other chat/input UIs can reuse the same behavior. + /// + [System.Serializable] + public class TypingPreviewController + { + [Tooltip("Root của box xem trước nội dung đang gõ.")] + [SerializeField] private GameObject typingPreviewRoot; + [Tooltip("Text hiển thị nội dung đang gõ realtime.")] + [SerializeField] private TMP_InputField typingPreviewText; + [Tooltip("Rect của preview box để neo theo keyboard.")] + [SerializeField] private RectTransform typingPreviewRect; + [Tooltip("Khoảng cách dọc cộng thêm cho preview box.")] + [SerializeField] private float previewVerticalOffset = 8f; + + private Vector2 _baseAnchoredPos; + private bool _cachedAnchor; + + public void CacheInitialAnchor() + { + if (_cachedAnchor) + return; + + if (typingPreviewRect != null) + _baseAnchoredPos = typingPreviewRect.anchoredPosition; + + _cachedAnchor = true; + } + + public void ApplyKeyboardOffset(float yOffset) + { + if (typingPreviewRect == null) + return; + + CacheInitialAnchor(); + var previewPos = _baseAnchoredPos; + previewPos.y += yOffset + previewVerticalOffset; + typingPreviewRect.anchoredPosition = previewPos; + } + + public void UpdatePreview(bool isInputFocused, string body) + { + if (typingPreviewRoot == null || typingPreviewText == null) + return; + + string previewBody = body ?? string.Empty; + bool keyboardVisible = IsMobileKeyboardVisible(); + bool shouldShow = keyboardVisible && isInputFocused; + typingPreviewRoot.SetActive(shouldShow); + if (shouldShow) + typingPreviewText.text = previewBody; + } + + bool IsMobileKeyboardVisible() + { + if (!Application.isMobilePlatform) + return false; + return GetVisibleKeyboardHeight() > 0f || TouchScreenKeyboard.visible; + } + + float GetVisibleKeyboardHeight() + { + if (!TouchScreenKeyboard.visible) + return 0f; + + Rect area = TouchScreenKeyboard.area; + return area.height > 0f ? area.height : 0f; + } + } +} diff --git a/Assets/Scripts/TypingPreviewController.cs.meta b/Assets/Scripts/TypingPreviewController.cs.meta new file mode 100644 index 0000000000..d2f7801a37 --- /dev/null +++ b/Assets/Scripts/TypingPreviewController.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a9934ac12c563f746a3ba562e3de5bff \ No newline at end of file diff --git a/Assets/Scripts/typing-preview-summary.md b/Assets/Scripts/typing-preview-summary.md new file mode 100644 index 0000000000..b86b53a2d8 --- /dev/null +++ b/Assets/Scripts/typing-preview-summary.md @@ -0,0 +1,60 @@ +# Typing Preview - Summary + +## Muc tieu da thuc hien + +- Tach logic `typingPreview` ra class rieng de de tai su dung. +- Lien ket lai logic giua `ChatInputHandler` va `TypingPreviewController`. +- Dieu chinh co che hien/an theo yeu cau mobile keyboard. + +## Cac file da cap nhat + +- `Assets/Scripts/TypingPreviewController.cs` +- `Assets/Scripts/ChatInputHandler.cs` + +## Noi dung da lam + +### 1) Tach typing preview thanh class rieng + +- Tao class `TypingPreviewController` de quan ly: + - Hien/an preview (`typingPreviewRoot`) + - Cap nhat text preview realtime (`typingPreviewText`) + - Dinh vi preview theo offset keyboard (`typingPreviewRect`, `previewVerticalOffset`) + +### 2) Lien ket voi ChatInputHandler + +- `ChatInputHandler` giu `SerializeField`: + - `TypingPreviewController typingPreview` +- Moi khi input thay doi text, `ChatInputHandler` lay message body (bo prefix kenh/whisper) roi day sang controller de cap nhat preview. +- Khi clear input, preview duoc cap nhat lai ngay de an dung trang thai. + +### 3) Co che mobile keyboard (cap nhat moi nhat) + +- Da chuyen logic check keyboard vao thang `TypingPreviewController`: + - `IsMobileKeyboardVisible()` + - `GetVisibleKeyboardHeight()` +- `ChatInputHandler` da bo cac ham keyboard-check khong con dung. +- `ChatInputHandler` chi can goi `typingPreview.UpdatePreview(isFocused, body)`. +- `ChatInputHandler.Update()` van refresh moi frame de bat kip luc keyboard mo/dong. +- Rule hien moi nhat: + - Keyboard mobile vua mo la preview show ngay (neu input dang focus), khong can cho co ky tu. + +## Hanh vi hien tai + +- Preview chi hien khi: + - Dang o mobile + - Keyboard dang mo + - Input dang focus +- Khong con yeu cau body phai khong rong (show ngay khi keyboard mo). +- Khi tat keyboard, preview an ngay. +- Khi mo lai keyboard, noi dung da go truoc do van con trong input va preview hien lai dung noi dung. + +## Emoji tren preview + +- Hien tai preview duoc set text truc tiep tu `body`, nen neu `body` co TMP sprite tag thi co the hien emoji. +- Luu y cau hinh component: + - `typingPreviewText` dang de kieu `TMP_InputField` trong `TypingPreviewController`. + - Neu muon on dinh cho muc dich "preview display", nen doi sang `TMP_Text` hoac `TextMeshProUGUI`. + +## Ghi chu + +- Da kiem tra lint sau cac lan sua, khong phat hien loi lint moi tren cac file da chinh. diff --git a/Assets/Scripts/typing-preview-summary.md.meta b/Assets/Scripts/typing-preview-summary.md.meta new file mode 100644 index 0000000000..8304d161ef --- /dev/null +++ b/Assets/Scripts/typing-preview-summary.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 85a85257c23e84e41ba29cbc51455178 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: