diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs b/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs index 389d947ae2..8743a04f9c 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs @@ -15,6 +15,8 @@ using System.Text; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; +using BrewMonster.Scripts.UI.Inventory; +using CSNetwork.Protocols.RPCData; namespace BrewMonster.Scripts.Managers { @@ -166,6 +168,7 @@ namespace BrewMonster.Scripts.Managers ShowDetailPanel(false); ShowSplitPanel(false); RefreshAll(); + RefreshCharacterModelPreview(); } private void WireSplitUI() @@ -688,6 +691,7 @@ namespace BrewMonster.Scripts.Managers Debug.Log($"[InventoryUI] Equip request sent for item {currentSelectedItem.m_tid} from slot {currentSelectedSlot} to equip location {equipLocation}"); // Refresh inventory after equip RefreshAll(); + RefreshCharacterModelPreview(); }); } @@ -713,6 +717,7 @@ namespace BrewMonster.Scripts.Managers Debug.Log($"[InventoryUI] Unequip request sent for item {currentSelectedItem.m_tid} from equip location {equipLocation} to inventory slot {emptySlot}"); // Refresh inventory after unequip RefreshAll(); + RefreshCharacterModelPreview(); }); } @@ -738,6 +743,7 @@ namespace BrewMonster.Scripts.Managers // Refresh inventory after drop RefreshAll(); + RefreshCharacterModelPreview(); } /// @@ -1617,6 +1623,61 @@ namespace BrewMonster.Scripts.Managers return false; } + public void RefreshCharacterModelPreview() + { + var preview = PlayerModelPreview.Instance; + if (preview != null) + { + RoleInfo roleInfo = BuildCurrentPreviewRoleInfo(); + if (roleInfo != null) + { + preview.ReloadRoleModel(roleInfo); + } + } + + var inventoryPreview = FindFirstObjectByType(); + if (inventoryPreview != null) + { + inventoryPreview.QueueRefresh(); + } + } + + private RoleInfo BuildCurrentPreviewRoleInfo() + { + RoleInfo roleInfo = UnityGameSession.Instance != null ? UnityGameSession.Instance.GetRoleInfo() : null; + if (roleInfo == null) + return null; + + RoleInfo snapshot = roleInfo.Clone(); + if (snapshot.equipment == null) + snapshot.equipment = new List(); + else + snapshot.equipment.Clear(); + + CECHostPlayer host = CECGameRun.Instance?.GetHostPlayer(); + var equipInv = host?.GetInventory(InventoryConst.IVTRTYPE_EQUIPPACK); + if (equipInv == null) + return snapshot; + + int size = equipInv.GetSize(); + for (int i = 0; i < size; i++) + { + EC_IvtrItem item = equipInv.GetItem(i, false); + if (item == null) + continue; + + snapshot.equipment.Add(new GRoleInventory + { + id = (uint)item.GetTemplateID(), + pos = i, + count = item.GetCount(), + max_count = Math.Max(1, item.GetPileLimitInstance()) + }); + } + + return snapshot; + } + private bool IsPointerOverDetailPanel(Vector2 screenPosition) { var panelRect = detailPanelRoot.transform as RectTransform; diff --git a/Assets/PerfectWorld/Scripts/Players/PlayerModelPreview.cs b/Assets/PerfectWorld/Scripts/Players/PlayerModelPreview.cs index dbff7fb706..082a34a4d8 100644 --- a/Assets/PerfectWorld/Scripts/Players/PlayerModelPreview.cs +++ b/Assets/PerfectWorld/Scripts/Players/PlayerModelPreview.cs @@ -15,6 +15,9 @@ namespace BrewMonster.Scripts private int _loadVersion; + private bool _hasRequestedPlayerModelId; + private int _requestedPlayerModelId; + private void Awake() { if (modelRoot == null) @@ -50,20 +53,19 @@ namespace BrewMonster.Scripts if (version != _loadVersion) { - if (model != null) - Destroy(model); + Destroy(model); return; } - if (model == null) - continue; - model.transform.SetParent(modelRoot, false); model.transform.localPosition = Vector3.zero; model.transform.localRotation = Quaternion.identity; model.SetActive(false); + playerModels.Add(model); playerModelIds.Add(role.roleid); + + ApplyRequestedModelVisibility(); } } @@ -72,13 +74,36 @@ namespace BrewMonster.Scripts /// public void ShowPlayerModel(int playerModelId) { + //int n = Mathf.Min(playerModels.Count, playerModelIds.Count); + //for (int i = 0; i < n; i++) + //{ + // GameObject go = playerModels[i]; + // if (go == null) + // continue; + // go.SetActive(playerModelIds[i] == playerModelId); + //} + _hasRequestedPlayerModelId = true; + _requestedPlayerModelId = playerModelId; + + ApplyRequestedModelVisibility(); + } + + /// + /// Applies the visibility of player models based on the requested player model id. + /// + private void ApplyRequestedModelVisibility() + { + if(!_hasRequestedPlayerModelId) + return; + int n = Mathf.Min(playerModels.Count, playerModelIds.Count); for (int i = 0; i < n; i++) { GameObject go = playerModels[i]; - if (go == null) + if(go == null) continue; - go.SetActive(playerModelIds[i] == playerModelId); + + go.SetActive(playerModelIds[i] == _requestedPlayerModelId); } } @@ -307,5 +332,14 @@ namespace BrewMonster.Scripts } return skeletonBuilder; } + + public void ReloadRoleModel(RoleInfo roleInfo) + { + if (roleInfo == null) + return; + + ShowAllPlayerModels(new List { roleInfo }); + ShowPlayerModel(roleInfo.roleid); + } } } diff --git a/Assets/PerfectWorld/Scripts/UI/Inventory/InventoryCharacterPreview.cs b/Assets/PerfectWorld/Scripts/UI/Inventory/InventoryCharacterPreview.cs index 3ae85ac9ee..8b127d6206 100644 --- a/Assets/PerfectWorld/Scripts/UI/Inventory/InventoryCharacterPreview.cs +++ b/Assets/PerfectWorld/Scripts/UI/Inventory/InventoryCharacterPreview.cs @@ -27,21 +27,23 @@ namespace BrewMonster.Scripts.UI.Inventory [SerializeField] private Vector3 previewLocalPosition = Vector3.zero; [SerializeField] private Vector3 previewLocalEuler; [SerializeField] private Vector3 previewLocalScale = Vector3.one; - [SerializeField] private float previewHeightOffset = 0.12f; - [Tooltip("Copy the preview root layer onto the cloned hierarchy so the preview camera can isolate it.")] - [SerializeField] private bool inheritPreviewLayer = true; [Header("Camera Output")] [SerializeField] private RawImage previewFrame; [SerializeField] private RenderTexture previewRenderTexture; [SerializeField] private bool autoFocusCamera = true; - [SerializeField] private Vector3 cameraFocusOffset = new Vector3(0f, 1.5f, 0f); + [SerializeField] private Vector3 cameraFocusOffset = new Vector3(0f, 0f, 0f); [Header("Camera Framing")] - [SerializeField] private float previewCameraDistance = 1.4f; - [SerializeField] private Vector3 previewCameraOffset = new Vector3(0f, 0.5f, 0f); + [SerializeField] private float previewCameraDistance = 3.3f; + [SerializeField] private Vector3 previewCameraOffset = new Vector3(0.15f, 0.8f, 0f); [SerializeField] private bool overrideFieldOfView = true; - [SerializeField][Range(10f, 60f)] private float previewFieldOfView = 38f; + [SerializeField][Range(10f, 60f)] private float previewFieldOfView = 33f; + + [SerializeField] private bool autoFrameByBounds = true; + [SerializeField][Range(1f, 2f)] private float autoFramePadding = 1.15f; + [SerializeField] private float minAutoCameraDistance = 1.25f; + [SerializeField] private float maxAutoCameraDistance = 8f; private bool _cameraStateCached; private Vector3 _cachedCameraPosition; @@ -95,17 +97,27 @@ namespace BrewMonster.Scripts.UI.Inventory // Check if origin model structure has changed (equipment models are child objects) // This detects equipment changes in realtime since all equipment is attached as children Transform currentOriginRoot = ResolveSourceModelRoot(); - if (currentOriginRoot != null) + if (currentOriginRoot == null) { - int currentChildCount = CountAllChildren(currentOriginRoot); - - // Refresh if origin model changed or child count changed (equipment added/removed) - if (_lastOriginModelRoot != currentOriginRoot || _lastOriginModelChildCount != currentChildCount) + if (_previewInstance == null) { - _lastOriginModelRoot = currentOriginRoot; - _lastOriginModelChildCount = currentChildCount; QueueRefresh(); } + if(_refreshQueued) + { + _refreshQueued = false; + BuildPreviewModel(); + } + return; + } + + int currentChildCount = CountAllChildren(currentOriginRoot); + + if (_lastOriginModelRoot != currentOriginRoot || _lastOriginModelChildCount != currentChildCount) + { + _lastOriginModelRoot = currentOriginRoot; + _lastOriginModelChildCount = currentChildCount; + QueueRefresh(); } if (_refreshQueued) @@ -226,9 +238,19 @@ namespace BrewMonster.Scripts.UI.Inventory Transform sourceRoot = ResolveSourceModelRoot(); if (sourceRoot == null) { + _previewInstance = null; + _lastOriginModelRoot = null; + _lastOriginModelChildCount = 0; + + QueueRefresh(); return; } + if (!sourceRoot.gameObject.activeSelf) + { + sourceRoot.gameObject.SetActive(true); + } + // Use resolved source root, not sourceModelRoot field directly. _previewInstance = sourceRoot.gameObject; Transform instanceTransform = _previewInstance.transform; @@ -238,15 +260,11 @@ namespace BrewMonster.Scripts.UI.Inventory instanceTransform.SetParent(previewRoot, false); } - instanceTransform.localPosition = previewLocalPosition + Vector3.up * previewHeightOffset; + instanceTransform.localPosition = previewLocalPosition + Vector3.up; instanceTransform.localRotation = Quaternion.Euler(previewLocalEuler); instanceTransform.localScale = previewLocalScale; - if (inheritPreviewLayer) - { - ApplyLayerRecursive(instanceTransform, previewRoot.gameObject.layer); - } - + ApplyLayerRecursive(instanceTransform, previewRoot.gameObject.layer); EnsureCameraFocus(instanceTransform); EnsureCameraBindings(); } diff --git a/Assets/Prefabs/UI/InventoryUI.prefab b/Assets/Prefabs/UI/InventoryUI.prefab index aa4e06d0f5..d2316b9ab4 100644 --- a/Assets/Prefabs/UI/InventoryUI.prefab +++ b/Assets/Prefabs/UI/InventoryUI.prefab @@ -500,10 +500,10 @@ RectTransform: m_Children: [] m_Father: {fileID: 7166820878650541780} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 588.35, y: -59.5} + m_SizeDelta: {x: 85, y: 85} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &9112205963990496432 CanvasRenderer: @@ -907,10 +907,10 @@ RectTransform: m_Children: [] m_Father: {fileID: 7166820878650541780} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 479.18, y: -59.5} + m_SizeDelta: {x: 85, y: 85} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &3997873020355048166 CanvasRenderer: @@ -1238,10 +1238,10 @@ RectTransform: m_Children: [] m_Father: {fileID: 7166820878650541780} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 370.01, y: -59.5} + m_SizeDelta: {x: 85, y: 85} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &4479228720555407959 CanvasRenderer: @@ -4929,10 +4929,10 @@ RectTransform: m_Children: [] m_Father: {fileID: 7166820878650541780} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 42.5, y: -59.5} + m_SizeDelta: {x: 85, y: 85} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &7052320096474271168 CanvasRenderer: @@ -11098,16 +11098,14 @@ MonoBehaviour: previewLocalPosition: {x: 0, y: 0, z: 100} previewLocalEuler: {x: 0, y: 0, z: 0} previewLocalScale: {x: 1, y: 1, z: 1} - inheritPreviewLayer: 1 previewFrame: {fileID: 6707240765686952970} previewRenderTexture: {fileID: 8400000, guid: 42c3c43cd0c3b704cb6cf0dd1051d9ff, type: 2} autoFocusCamera: 1 cameraFocusOffset: {x: 0, y: 0, z: 0} - previewCameraDistance: 1.4 - previewCameraOffset: {x: 0, y: 0.1, z: 0} + previewCameraDistance: 3.3 + previewCameraOffset: {x: 0.06, y: 1.07, z: 0} overrideFieldOfView: 1 - previewFieldOfView: 25 - freezeAnimation: 1 + previewFieldOfView: 44 --- !u!1 &5473020210238587200 GameObject: m_ObjectHideFlags: 0 @@ -14072,10 +14070,10 @@ RectTransform: m_Children: [] m_Father: {fileID: 7166820878650541780} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 151.67, y: -59.5} + m_SizeDelta: {x: 85, y: 85} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &4452551064742165538 CanvasRenderer: @@ -19519,10 +19517,10 @@ RectTransform: m_Children: [] m_Father: {fileID: 7166820878650541780} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 260.84, y: -59.5} + m_SizeDelta: {x: 85, y: 85} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &5155025384962724770 CanvasRenderer: diff --git a/Assets/Scripts/CECHostPlayer.Inventory.cs b/Assets/Scripts/CECHostPlayer.Inventory.cs index 3bcf0669ed..678fdb5fb3 100644 --- a/Assets/Scripts/CECHostPlayer.Inventory.cs +++ b/Assets/Scripts/CECHostPlayer.Inventory.cs @@ -517,6 +517,7 @@ namespace BrewMonster if (ui != null) { ui.RefreshAll(); + ui.RefreshCharacterModelPreview(); } UpdateEquipSkins();