diff --git a/Assets/PerfectWorld/Scripts/UI/Inventory/InventoryCharacterPreview.cs b/Assets/PerfectWorld/Scripts/UI/Inventory/InventoryCharacterPreview.cs index b83ef8114c..3ae85ac9ee 100644 --- a/Assets/PerfectWorld/Scripts/UI/Inventory/InventoryCharacterPreview.cs +++ b/Assets/PerfectWorld/Scripts/UI/Inventory/InventoryCharacterPreview.cs @@ -27,6 +27,7 @@ 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; @@ -47,9 +48,9 @@ namespace BrewMonster.Scripts.UI.Inventory private Quaternion _cachedCameraRotation; private float _cachedCameraFov; - [Header("Behaviour")] - [Tooltip("Disable PlayerVisual/Animancer components on the clone so it stays in a frozen idle pose.")] - [SerializeField] private bool freezeAnimation = true; + //[Header("Behaviour")] + //[Tooltip("Disable PlayerVisual/Animancer components on the clone so it stays in a frozen idle pose.")] + //[SerializeField] private bool freezeAnimation = true; private GameObject _previewInstance; private bool _refreshQueued; @@ -83,7 +84,7 @@ namespace BrewMonster.Scripts.UI.Inventory { RestoreCameraTargetTexture(); RestoreSharedCameraState(); - DestroyPreviewInstance(); + ReleasePreviewReference(); } private void LateUpdate() @@ -93,7 +94,7 @@ 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 - var currentOriginRoot = ResolveSourceModelRoot(); + Transform currentOriginRoot = ResolveSourceModelRoot(); if (currentOriginRoot != null) { int currentChildCount = CountAllChildren(currentOriginRoot); @@ -112,6 +113,11 @@ namespace BrewMonster.Scripts.UI.Inventory _refreshQueued = false; BuildPreviewModel(); } + + if(_previewInstance != null) + { + EnsureCameraFocus(_previewInstance.transform); + } } /// Allows manual binding from external UI scripts. @@ -217,19 +223,22 @@ namespace BrewMonster.Scripts.UI.Inventory return; } - var sourceRoot = ResolveSourceModelRoot(); + Transform sourceRoot = ResolveSourceModelRoot(); if (sourceRoot == null) { return; } - DestroyPreviewInstance(); + // Use resolved source root, not sourceModelRoot field directly. + _previewInstance = sourceRoot.gameObject; + Transform instanceTransform = _previewInstance.transform; - _previewInstance = Instantiate(sourceRoot.gameObject, previewRoot, false); - _previewInstance.name = $"{sourceRoot.name}_Preview"; + if (instanceTransform.parent != previewRoot) + { + instanceTransform.SetParent(previewRoot, false); + } - var instanceTransform = _previewInstance.transform; - instanceTransform.localPosition = previewLocalPosition; + instanceTransform.localPosition = previewLocalPosition + Vector3.up * previewHeightOffset; instanceTransform.localRotation = Quaternion.Euler(previewLocalEuler); instanceTransform.localScale = previewLocalScale; @@ -238,23 +247,11 @@ namespace BrewMonster.Scripts.UI.Inventory ApplyLayerRecursive(instanceTransform, previewRoot.gameObject.layer); } - if (freezeAnimation) - { - DisableComponentInChildren(_previewInstance); - DisableComponentInChildren(_previewInstance); - DisableComponentInChildren(_previewInstance); - FreezeAnimators(_previewInstance); - } - - if (cloneWholeHostHierarchy && stripRuntimeComponents) - { - StripRuntimeScripts(_previewInstance); - } - EnsureCameraFocus(instanceTransform); EnsureCameraBindings(); } + private Transform ResolveSourceModelRoot() { if (sourceModelRoot != null) @@ -262,54 +259,71 @@ namespace BrewMonster.Scripts.UI.Inventory return sourceModelRoot; } - if (hostPlayer == null) + if (_playerModelPreview == null) { return null; } - if (cloneWholeHostHierarchy) + // Prefer active model. + for (int i = 0; i < _playerModelPreview.playerModels.Count; i++) { - sourceModelRoot = hostPlayer.transform; - return sourceModelRoot; - } - - var playerVisual = hostPlayer.GetComponentInChildren(true); - sourceModelRoot = playerVisual != null ? playerVisual.transform : hostPlayer.transform; - return sourceModelRoot; - } - - private void DestroyPreviewInstance() - { - if (_previewInstance != null) - { - Destroy(_previewInstance); - _previewInstance = null; - } - } - - private static void DisableComponentInChildren(GameObject root) where T : Behaviour - { - if (root == null) - { - return; - } - - var components = root.GetComponentsInChildren(true); - for (int i = 0; i < components.Length; i++) - { - var component = components[i]; - if (component == null) - continue; - - component.enabled = false; - - if (component is PlayerVisual) + GameObject model = _playerModelPreview.playerModels[i]; + if (model != null && model.activeSelf) { - Destroy(component); + return model.transform; } } + + // Fallback to first available model. + for (int i = 0; i < _playerModelPreview.playerModels.Count; i++) + { + GameObject model = _playerModelPreview.playerModels[i]; + if (model != null) + { + return model.transform; + } + } + + return null; } + private void ReleasePreviewReference() + { + _previewInstance = null; + } + + //private void DestroyPreviewInstance() + //{ + // if (_previewInstance != null) + // { + // Destroy(_previewInstance); + // _previewInstance = null; + // } + //} + + //private static void DisableComponentInChildren(GameObject root) where T : Behaviour + //{ + // if (root == null) + // { + // return; + // } + + // var components = root.GetComponentsInChildren(true); + // for (int i = 0; i < components.Length; i++) + // { + // var component = components[i]; + // if (component == null) + // continue; + + // component.enabled = false; + + // if (component is PlayerVisual) + // { + // Destroy(component); + // } + // } + //} + private void ApplyLayerRecursive(Transform root, int layer) { if (root == null) @@ -326,7 +340,7 @@ namespace BrewMonster.Scripts.UI.Inventory private void EnsureCameraFocus(Transform modelRoot) { - if (!autoFocusCamera || _previewCamera == null || modelRoot == null) + if (_previewCamera == null) { return; } @@ -339,62 +353,69 @@ namespace BrewMonster.Scripts.UI.Inventory _cameraStateCached = true; } - var focusPoint = modelRoot.TransformPoint(cameraFocusOffset) + previewCameraOffset; + // Apply FOV override independently from auto focus. + if (overrideFieldOfView) + { + _previewCamera.fieldOfView = previewFieldOfView; + } - Vector3 viewDirection = -modelRoot.forward; + if (!autoFocusCamera || modelRoot == null) + { + return; + } + + Vector3 focusPoint = modelRoot.TransformPoint(cameraFocusOffset) + previewCameraOffset; + + Vector3 viewDirection = modelRoot.forward; viewDirection.y = 0f; if (viewDirection.sqrMagnitude < 0.0001f) { viewDirection = Vector3.back; } + viewDirection.Normalize(); _previewCamera.transform.position = focusPoint + viewDirection * previewCameraDistance; _previewCamera.transform.LookAt(focusPoint); - - if (overrideFieldOfView) - { - _previewCamera.fieldOfView = previewFieldOfView; - } } - private void StripRuntimeScripts(GameObject cloneRoot) - { - if (cloneRoot == null) - { - return; - } + //private void StripRuntimeScripts(GameObject cloneRoot) + //{ + // if (cloneRoot == null) + // { + // return; + // } - var monoBehaviours = cloneRoot.GetComponentsInChildren(true); - for (int i = 0; i < monoBehaviours.Length; i++) - { - var behaviour = monoBehaviours[i]; - if (behaviour == null) - continue; + // var monoBehaviours = cloneRoot.GetComponentsInChildren(true); + // for (int i = 0; i < monoBehaviours.Length; i++) + // { + // var behaviour = monoBehaviours[i]; + // if (behaviour == null) + // continue; - Destroy(behaviour); - } + // Destroy(behaviour); + // } - var colliders = cloneRoot.GetComponentsInChildren(true); - for (int i = 0; i < colliders.Length; i++) - { - var collider = colliders[i]; - if (collider == null) - continue; + // var colliders = cloneRoot.GetComponentsInChildren(true); + // for (int i = 0; i < colliders.Length; i++) + // { + // var collider = colliders[i]; + // if (collider == null) + // continue; - Destroy(collider); - } + // Destroy(collider); + // } - var rigidbodies = cloneRoot.GetComponentsInChildren(true); - for (int i = 0; i < rigidbodies.Length; i++) - { - var body = rigidbodies[i]; - if (body == null) - continue; + // var rigidbodies = cloneRoot.GetComponentsInChildren(true); + // for (int i = 0; i < rigidbodies.Length; i++) + // { + // var body = rigidbodies[i]; + // if (body == null) + // continue; - Destroy(body); - } - } + // Destroy(body); + // } + //} private void RestoreSharedCameraState() { @@ -409,23 +430,23 @@ namespace BrewMonster.Scripts.UI.Inventory _cameraStateCached = false; } - private void FreezeAnimators(GameObject cloneRoot) - { - if (cloneRoot == null) - { - return; - } + //private void FreezeAnimators(GameObject cloneRoot) + //{ + // if (cloneRoot == null) + // { + // return; + // } - var animators = cloneRoot.GetComponentsInChildren(true); - for (int i = 0; i < animators.Length; i++) - { - var animator = animators[i]; - if (animator == null) - continue; + // var animators = cloneRoot.GetComponentsInChildren(true); + // for (int i = 0; i < animators.Length; i++) + // { + // var animator = animators[i]; + // if (animator == null) + // continue; - animator.speed = 0f; - } - } + // animator.speed = 0f; + // } + //} /// /// Counts all children recursively in the transform hierarchy.