선택한 모델 PropertyWindow 연결 완료
This commit is contained in:
@@ -59,6 +59,12 @@ namespace UVC.GLTF
|
||||
return instantiator.SceneTransform != null ? instantiator.SceneTransform.gameObject : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 여러 LOD 레벨의 glTF/glb 파일을 로드하고 LODGroup으로 설정합니다. 사용않함
|
||||
/// </summary>
|
||||
/// <param name="paths"></param>
|
||||
/// <param name="parentTransform"></param>
|
||||
/// <returns></returns>
|
||||
public static async UniTask<GameObject?> ImportWithLOD(List<string> paths, Transform parentTransform)
|
||||
{
|
||||
if (paths == null || paths.Count == 0) return null;
|
||||
|
||||
@@ -189,6 +189,16 @@ namespace UVC.UI.Window
|
||||
treeList.DeleteItem(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 아이템의 이름을 변경합니다.
|
||||
/// </summary>
|
||||
/// <param name="data">변경할 아이템 데이터</param>
|
||||
/// <param name="newName">새 이름</param>
|
||||
public void SetItemName(TreeListItemData data, string newName)
|
||||
{
|
||||
treeList.SetItemName(data, newName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 이름으로 아이템 선택
|
||||
/// </summary>
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace UVC.UI.Window.PropertyWindow
|
||||
FloatRange,
|
||||
DateRange,
|
||||
DateTimeRange,
|
||||
ColorState,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -331,5 +332,13 @@ namespace UVC.UI.Window.PropertyWindow
|
||||
}
|
||||
}
|
||||
|
||||
// --- 복합 타입 속성 ---
|
||||
public class ColorStateProperty : PropertyItem<Tuple<string, Color?>>
|
||||
{
|
||||
public override PropertyType PropertyType => PropertyType.ColorState;
|
||||
public ColorStateProperty(string id, string name, Tuple<string, Color?> initialValue) : base(id, name, initialValue) { }
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace UVC.UI.Window.PropertyWindow
|
||||
[SerializeField] private GameObject _numberRangePropertyPrefab;
|
||||
[SerializeField] private GameObject _dateRangePropertyPrefab;
|
||||
[SerializeField] private GameObject _dateTimeRangePropertyPrefab;
|
||||
[SerializeField] private GameObject _colorStatePropertyPrefab;
|
||||
|
||||
/// <summary>
|
||||
/// View가 상호작용할 Controller 인스턴스입니다.
|
||||
@@ -291,6 +292,8 @@ namespace UVC.UI.Window.PropertyWindow
|
||||
return _dateRangePropertyPrefab;
|
||||
case PropertyType.DateTimeRange:
|
||||
return _dateTimeRangePropertyPrefab;
|
||||
case PropertyType.ColorState:
|
||||
return _colorStatePropertyPrefab;
|
||||
default:
|
||||
Debug.LogWarning($"'{type}' 타입에 대한 프리팹이 정의되지 않았습니다.");
|
||||
return null;
|
||||
|
||||
@@ -402,6 +402,9 @@ namespace UVC.UI.Window.PropertyWindow
|
||||
_groupIndex.Clear();
|
||||
_itemIndex.Clear();
|
||||
EntriesCleared?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
// View 갱신하여 UI에서도 항목 제거
|
||||
Refresh();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
using System;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using UVC.Core;
|
||||
using UVC.Extention;
|
||||
using UVC.Studio.Manager;
|
||||
using UVC.UI.Modal.ColorPicker;
|
||||
using UVC.UI.Tooltip;
|
||||
using UVC.Util;
|
||||
|
||||
namespace UVC.UI.Window.PropertyWindow.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// ColorProperty를 위한 UI를 제어하는 스크립트입니다.
|
||||
/// Image 컴포넌트로 색상을 표시하고, Button으로 색상 선택기를 엽니다.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(LayoutElement))]
|
||||
public class ColorStatePropertyUI : MonoBehaviour, IPropertyUI
|
||||
{
|
||||
[Header("UI Components")]
|
||||
[SerializeField]
|
||||
private TextMeshProUGUI _nameLabel; // 속성 이름을 표시할 Text
|
||||
|
||||
[SerializeField]
|
||||
private TextMeshProUGUI _descriptionLabel;
|
||||
|
||||
[SerializeField]
|
||||
private TMP_InputField _stateLabel;
|
||||
|
||||
[SerializeField]
|
||||
private LayoutGroup _colorLayoutGroup;
|
||||
|
||||
[SerializeField]
|
||||
private Image _colorPreviewImage; // 현재 색상을 표시할 Image
|
||||
|
||||
[SerializeField]
|
||||
private TMP_InputField _colorLabel;
|
||||
|
||||
[SerializeField]
|
||||
private Button _colorPickerButton; // 색상 선택기를 열기 위한 Button
|
||||
|
||||
[SerializeField]
|
||||
private Button _previewButton; // 컬러를 미리보기 위한 Button
|
||||
|
||||
private ColorStateProperty _propertyItem;
|
||||
private PropertyWindow _controller;
|
||||
|
||||
private bool openningColorPickered = false;
|
||||
|
||||
/// <summary>
|
||||
/// PropertyView에 의해 호출되어 UI를 초기화하고 데이터를 설정합니다.
|
||||
/// </summary>
|
||||
/// <param name="item">UI에 표시할 속성 데이터(IPropertyItem)</param>
|
||||
/// <param name="controller">상호작용할 PropertyWindow</param>
|
||||
public void Setup(IPropertyItem item, PropertyWindow controller)
|
||||
{
|
||||
|
||||
if (!(item is ColorStateProperty typedItem))
|
||||
{
|
||||
Debug.LogError($"ColorStatePropertyUI에 잘못된 타입의 PropertyItem이 전달되었습니다. {item.GetType()}");
|
||||
return;
|
||||
}
|
||||
|
||||
_propertyItem = typedItem;
|
||||
_controller = controller;
|
||||
|
||||
// --- 데이터 바인딩 ---
|
||||
// 1. 속성 이름 설정
|
||||
_nameLabel.text = _propertyItem.Name;
|
||||
|
||||
// 툴팁 설정 (TooltipHandler 컴포넌트가 있다면 연동)
|
||||
TooltipHandler tooltipHandler = _nameLabel.GetComponent<TooltipHandler>();
|
||||
if (tooltipHandler != null && !_propertyItem.Tooltip.IsNullOrEmpty())
|
||||
{
|
||||
tooltipHandler.Tooltip = _propertyItem.Tooltip;
|
||||
}
|
||||
|
||||
if (_propertyItem.Description.IsNullOrEmpty())
|
||||
{
|
||||
_descriptionLabel.gameObject.SetActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_descriptionLabel.gameObject.SetActive(true);
|
||||
_descriptionLabel.text = _propertyItem.Description;
|
||||
}
|
||||
|
||||
_stateLabel.text = _propertyItem.Value.Item1;
|
||||
|
||||
// 2. 색상 미리보기 Image의 색상 설정
|
||||
if (_propertyItem.Value.Item2 == null)
|
||||
{
|
||||
_colorLayoutGroup.gameObject.SetActive(false);
|
||||
_previewButton.gameObject.SetActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_colorLayoutGroup.gameObject.SetActive(true);
|
||||
_colorPreviewImage.color = _propertyItem.Value.Item2.Value;
|
||||
|
||||
_colorLabel.text = ColorUtil.ToHex(_colorPreviewImage.color, true, false);
|
||||
_colorLabel.interactable = !_propertyItem.IsReadOnly;
|
||||
// 3. 읽기 전용 상태에 따라 버튼 상호작용 여부 결정
|
||||
_colorPickerButton.gameObject.SetActive(!_propertyItem.IsReadOnly);
|
||||
_colorPickerButton.onClick.RemoveAllListeners();
|
||||
if (!_propertyItem.IsReadOnly)
|
||||
{
|
||||
// --- 이벤트 리스너 등록 ---
|
||||
_colorPickerButton.onClick.AddListener(OpenColorPicker);
|
||||
}
|
||||
|
||||
_previewButton.gameObject.SetActive(true);
|
||||
|
||||
// PointerDown/PointerUp 핸들러 설정
|
||||
SetupPreviewButtonEvents();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PreviewButton에 PointerDown/PointerUp 이벤트를 설정합니다.
|
||||
/// </summary>
|
||||
private void SetupPreviewButtonEvents()
|
||||
{
|
||||
// 기존 PreviewButtonHandler가 있으면 제거
|
||||
var existingHandler = _previewButton.GetComponent<PreviewButtonHandler>();
|
||||
if (existingHandler != null)
|
||||
{
|
||||
Destroy(existingHandler);
|
||||
}
|
||||
|
||||
// 새 핸들러 추가
|
||||
var handler = _previewButton.gameObject.AddComponent<PreviewButtonHandler>();
|
||||
handler.Initialize(OnPreviewMouseDown, OnPreViewMouseUp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 색상 선택기 버튼을 클릭했을 때 호출됩니다.
|
||||
/// </summary>
|
||||
private async void OpenColorPicker()
|
||||
{
|
||||
if (openningColorPickered == true) return;
|
||||
openningColorPickered = true;
|
||||
CursorManager.Instance.SetCursor(CursorType.Wait);
|
||||
await ColorPicker.Create(_colorPreviewImage.color, "Color Picker", null, OnColorSelected, OnCloseColorPicker, true);
|
||||
CursorManager.Instance.SetDefaultCursor();
|
||||
Debug.LogWarning($"'{_propertyItem.Name}'의 색상 선택기 로직이 구현되지 않았습니다. 클릭 이벤트만 발생합니다.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 색상 선택기에서 새로운 색상이 선택되었을 때 호출되는 메서드입니다.
|
||||
/// </summary>
|
||||
/// <param name="newColor">선택된 새로운 색상</param>
|
||||
public void OnColorSelected(Color newColor)
|
||||
{
|
||||
|
||||
if (newColor == _propertyItem.Value.Item2.Value)
|
||||
{
|
||||
return; // 변경 사항이 없으므로 아무 작업도 하지 않음
|
||||
}
|
||||
|
||||
// 1. UI의 색상 미리보기를 업데이트합니다.
|
||||
_colorPreviewImage.color = newColor;
|
||||
|
||||
_colorLabel.text = ColorUtil.ToHex(_colorPreviewImage.color, true, false);
|
||||
|
||||
// 2. PropertyController를 통해 데이터 모델의 값을 업데이트합니다.
|
||||
_controller.UpdatePropertyValue(_propertyItem.Id, _propertyItem.PropertyType, new Tuple<string, string, Color?>(_propertyItem.Name, _stateLabel.text, newColor));
|
||||
|
||||
}
|
||||
|
||||
private void OnPreviewMouseDown()
|
||||
{
|
||||
// 미리보기 버튼 클릭 시 동작 구현 (필요시)
|
||||
SelectionManager selectionManager = InjectorAppContext.Instance.Get<SelectionManager>();
|
||||
if (selectionManager != null) selectionManager.PreviewColor(_propertyItem.Value.Item2!.Value);
|
||||
}
|
||||
|
||||
private void OnPreViewMouseUp()
|
||||
{
|
||||
// 미리보기 버튼 클릭 해제 시 동작 구현 (필요시)
|
||||
SelectionManager selectionManager = InjectorAppContext.Instance.Get<SelectionManager>();
|
||||
if (selectionManager != null) selectionManager.ClearPreviewColor();
|
||||
}
|
||||
|
||||
private void OnCloseColorPicker()
|
||||
{
|
||||
openningColorPickered = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UI의 읽기 전용 상태를 설정합니다.
|
||||
/// </summary>
|
||||
/// <param name="isReadOnly">읽기 전용 여부 (true: 비활성화, false: 활성화)</param>
|
||||
public void SetReadOnly(bool isReadOnly)
|
||||
{
|
||||
if (_propertyItem != null)
|
||||
{
|
||||
_propertyItem.IsReadOnly = isReadOnly;
|
||||
}
|
||||
if (_colorLabel != null) _colorLabel.interactable = !isReadOnly;
|
||||
if (_colorPickerButton != null) _colorPickerButton.gameObject.SetActive(!isReadOnly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 이 UI 오브젝트가 파괴될 때 Unity에 의해 호출됩니다.
|
||||
/// </summary>
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (_colorPickerButton != null && _colorPickerButton.onClick != null)
|
||||
{
|
||||
_colorPickerButton.onClick.RemoveAllListeners();
|
||||
}
|
||||
if (_previewButton != null)
|
||||
{
|
||||
var existingHandler = _previewButton.GetComponent<PreviewButtonHandler>();
|
||||
if (existingHandler != null)
|
||||
{
|
||||
Destroy(existingHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PreviewButton의 PointerDown/PointerUp 이벤트를 처리하는 핸들러
|
||||
/// </summary>
|
||||
public class PreviewButtonHandler : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
{
|
||||
private Action _onPointerDown;
|
||||
private Action _onPointerUp;
|
||||
|
||||
public void Initialize(Action onPointerDown, Action onPointerUp)
|
||||
{
|
||||
_onPointerDown = onPointerDown;
|
||||
_onPointerUp = onPointerUp;
|
||||
}
|
||||
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
_onPointerDown?.Invoke();
|
||||
}
|
||||
|
||||
public void OnPointerUp(PointerEventData eventData)
|
||||
{
|
||||
_onPointerUp?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 508447e589a88f149934d68ac57195ff
|
||||
Reference in New Issue
Block a user