toolbar 코드 개선
This commit is contained in:
8
Assets/Scripts/UVC/UI/ToolBar/Model.meta
Normal file
8
Assets/Scripts/UVC/UI/ToolBar/Model.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c1fc3d4cc5339c429588952b08b1c0f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UVC.UI.Toolbar
|
||||
namespace UVC.UI.Toolbar.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 툴바에 추가될 수 있는 모든 항목(예: 버튼, 구분선, 드롭다운 메뉴 등)의
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using UVC.UI.Commands;
|
||||
|
||||
namespace UVC.UI.Toolbar
|
||||
namespace UVC.UI.Toolbar.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 툴바에 사용되는 모든 버튼(표준 버튼, 토글 버튼, 확장 버튼 등)의 기본 추상 클래스입니다.
|
||||
@@ -23,7 +23,7 @@ namespace UVC.UI.Toolbar
|
||||
/// Text = text; // 부모 클래스의 Text 속성 사용
|
||||
/// IconSpritePath = iconPath; // 부모 클래스의 IconSpritePath 속성 사용
|
||||
/// ClickCommand = command; // 부모 클래스의 ClickCommand 속성 사용
|
||||
/// TooltipKey = tooltip; // 부모 클래스의 TooltipKey 속성 사용
|
||||
/// Tooltip = tooltip; // 부모 클래스의 Tooltip 속성 사용
|
||||
/// IsEnabled = true; // 기본적으로 활성화 상태로 설정
|
||||
/// }
|
||||
///
|
||||
@@ -130,28 +130,28 @@ namespace UVC.UI.Toolbar
|
||||
}
|
||||
}
|
||||
|
||||
protected string _tooltipKey;
|
||||
protected string _tooltip;
|
||||
/// <summary>
|
||||
/// 버튼에 마우스를 올렸을 때 표시될 툴팁의 텍스트 또는 다국어 키입니다.
|
||||
/// TooltipKey 변경 시에는 기본적으로 OnStateChanged 이벤트가 발생하지 않지만,
|
||||
/// Tooltip 변경 시에는 기본적으로 OnStateChanged 이벤트가 발생하지 않지만,
|
||||
/// 필요에 따라 View에서 이 값을 직접 참조하여 툴팁을 업데이트할 수 있습니다.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// button.TooltipKey = "tooltip_save_button"; // 다국어 키 사용
|
||||
/// button.TooltipKey = "클릭하여 문서를 저장합니다."; // 직접 텍스트 사용
|
||||
/// button.Tooltip = "tooltip_save_button"; // 다국어 키 사용
|
||||
/// button.Tooltip = "클릭하여 문서를 저장합니다."; // 직접 텍스트 사용
|
||||
/// </code>
|
||||
/// </example>
|
||||
public string TooltipKey
|
||||
public string Tooltip
|
||||
{
|
||||
get => _tooltipKey;
|
||||
get => _tooltip;
|
||||
set
|
||||
{
|
||||
if (_tooltipKey != value)
|
||||
if (_tooltip != value)
|
||||
{
|
||||
_tooltipKey = value;
|
||||
// TooltipKey 변경 시 OnStateChanged를 호출할 필요는 일반적으로 없으나,
|
||||
// 만약 UI가 TooltipKey 자체를 표시하는 등의 로직이 있다면 필요할 수 있습니다.
|
||||
_tooltip = value;
|
||||
// Tooltip 변경 시 OnStateChanged를 호출할 필요는 일반적으로 없으나,
|
||||
// 만약 UI가 Tooltip 자체를 표시하는 등의 로직이 있다면 필요할 수 있습니다.
|
||||
// 여기서는 툴팁 내용이 동적으로 변경되는 경우가 적다고 가정하고 생략합니다.
|
||||
// 필요하다면 OnStateChanged?.Invoke(); 추가
|
||||
}
|
||||
@@ -216,5 +216,15 @@ namespace UVC.UI.Toolbar
|
||||
{
|
||||
OnStateChanged?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 이 버튼 모델에 연결된 모든 이벤트 핸들러를 정리(구독 해제)합니다.
|
||||
/// 주로 View가 파괴되거나 UI가 재생성될 때 호출되어 메모리 누수를 방지합니다.
|
||||
/// 파생 클래스에서는 이 메서드를 재정의하여 해당 클래스에 특화된 이벤트를 추가로 정리해야 합니다.
|
||||
/// </summary>
|
||||
public virtual void ClearEventHandlers()
|
||||
{
|
||||
OnStateChanged = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d8d1e1abfa138645b33ce2f969df756
|
||||
@@ -1,9 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine; // GameObject 사용을 위해 필요
|
||||
// using UnityEngine.UI; // Image 사용을 위해 필요할 수 있으나, 모델 클래스에서는 직접적인 UI 참조를 최소화하는 것이 좋음
|
||||
|
||||
namespace UVC.UI.Toolbar
|
||||
namespace UVC.UI.Toolbar.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 클릭 시 하위 버튼 목록(서브 메뉴)을 표시하거나 숨길 수 있는 확장형 버튼입니다.
|
||||
@@ -17,7 +16,7 @@ namespace UVC.UI.Toolbar
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// // ToolbarController 등에서 확장 버튼 생성 및 설정 예시
|
||||
/// // Toolbar 등에서 확장 버튼 생성 및 설정 예시
|
||||
/// var brushToolButton = mainToolbar.AddExpandableButton(
|
||||
/// "brush_tool_main", // 주 버튼 텍스트 (또는 다국어 키)
|
||||
/// "icons/brush_default", // 주 버튼 기본 아이콘 경로
|
||||
@@ -30,7 +29,7 @@ namespace UVC.UI.Toolbar
|
||||
/// {
|
||||
/// Text = "brush_small",
|
||||
/// IconSpritePath = "icons/brush_small_icon",
|
||||
/// TooltipKey = "tooltip_brush_small",
|
||||
/// Tooltip = "tooltip_brush_small",
|
||||
/// ClickCommand = new ActionCommand(() => Debug.Log("작은 브러시 선택됨"))
|
||||
/// };
|
||||
/// brushToolButton.SubButtons.Add(smallBrush);
|
||||
@@ -40,7 +39,7 @@ namespace UVC.UI.Toolbar
|
||||
/// {
|
||||
/// Text = "brush_medium",
|
||||
/// IconSpritePath = "icons/brush_medium_icon",
|
||||
/// TooltipKey = "tooltip_brush_medium",
|
||||
/// Tooltip = "tooltip_brush_medium",
|
||||
/// ClickCommand = new ActionCommand(() => Debug.Log("중간 브러시 선택됨"))
|
||||
/// };
|
||||
/// brushToolButton.SubButtons.Add(mediumBrush);
|
||||
@@ -141,5 +140,22 @@ namespace UVC.UI.Toolbar
|
||||
// 만약 여기서 실행해야 한다면: selectedSubButton.ExecuteClick();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 이 버튼 모델 및 모든 하위 버튼 모델에 연결된 이벤트 핸들러를 정리합니다.
|
||||
/// </summary>
|
||||
public override void ClearEventHandlers()
|
||||
{
|
||||
base.ClearEventHandlers(); // 부모 클래스의 이벤트 정리 (OnStateChanged)
|
||||
OnSubButtonSelected = null;
|
||||
|
||||
if (SubButtons != null)
|
||||
{
|
||||
foreach (var subButton in SubButtons)
|
||||
{
|
||||
subButton?.ClearEventHandlers(); // 각 하위 버튼의 이벤트 핸들러도 정리
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d7b463d85335feb4db9a045177ee9221
|
||||
@@ -1,7 +1,6 @@
|
||||
using UnityEngine;
|
||||
using UVC.UI.Commands;
|
||||
using UVC.UI.Commands;
|
||||
|
||||
namespace UVC.UI.Toolbar
|
||||
namespace UVC.UI.Toolbar.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 툴바의 전체적인 데이터 컨테이너 및 관리 클래스입니다.
|
||||
@@ -16,13 +15,13 @@ namespace UVC.UI.Toolbar
|
||||
/// - 라디오 버튼 그룹 관리: 동일한 그룹 이름을 가진 ToolbarRadioButton들을 내부적으로 ToolbarRadioButtonGroup으로 묶어 관리합니다.
|
||||
///
|
||||
/// 사용 흐름:
|
||||
/// 1. ToolbarController (또는 유사한 관리 클래스)에서 ToolbarModel의 인스턴스를 생성합니다.
|
||||
/// 1. Toolbar (또는 유사한 관리 클래스)에서 ToolbarModel의 인스턴스를 생성합니다.
|
||||
/// 2. 다양한 Add[ButtonType] 메서드 또는 AddItem 메서드를 호출하여 툴바 항목 모델들을 생성하고 ToolbarModel에 추가합니다.
|
||||
/// 3. 설정이 완료된 ToolbarModel 객체를 ToolbarView의 Initialize 메서드에 전달하여 UI를 렌더링하도록 합니다.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// // ToolbarController 등에서 ToolbarModel 사용 예시
|
||||
/// // Toolbar 등에서 ToolbarModel 사용 예시
|
||||
///
|
||||
/// // 1. ToolbarModel 인스턴스 생성
|
||||
/// ToolbarModel myToolbar = new ToolbarModel();
|
||||
@@ -118,11 +117,11 @@ namespace UVC.UI.Toolbar
|
||||
/// <param name="text">버튼에 표시될 텍스트 또는 다국어 키입니다.</param>
|
||||
/// <param name="iconSpritePath">버튼 아이콘의 Resources 경로입니다 (선택 사항).</param>
|
||||
/// <param name="command">버튼 클릭 시 실행될 ICommand 객체입니다 (선택 사항).</param>
|
||||
/// <param name="tooltipKey">버튼 툴팁의 텍스트 또는 다국어 키입니다 (선택 사항).</param>
|
||||
/// <param name="tooltip">버튼 툴팁의 텍스트 또는 다국어 키입니다 (선택 사항).</param>
|
||||
/// <returns>생성되고 추가된 ToolbarStandardButton 객체입니다.</returns>
|
||||
public ToolbarStandardButton AddStandardButton(string text, string iconSpritePath = null, ICommand command = null, string tooltipKey = null)
|
||||
public ToolbarStandardButton AddStandardButton(string text, string iconSpritePath = null, ICommand command = null, string tooltip = null)
|
||||
{
|
||||
var button = new ToolbarStandardButton { Text = text, IconSpritePath = iconSpritePath, ClickCommand = command, TooltipKey = tooltipKey };
|
||||
var button = new ToolbarStandardButton { Text = text, IconSpritePath = iconSpritePath, ClickCommand = command, Tooltip = tooltip };
|
||||
AddItem(button);
|
||||
return button;
|
||||
}
|
||||
@@ -136,9 +135,9 @@ namespace UVC.UI.Toolbar
|
||||
/// <param name="offIconSpritePath">버튼이 해제(Off) 상태일 때의 아이콘 경로입니다 (선택 사항).</param>
|
||||
/// <param name="onToggle">버튼의 선택 상태가 변경될 때 호출될 콜백 함수입니다 (선택 사항).</param>
|
||||
/// <param name="command">버튼 클릭 시 실행될 ICommand 객체입니다 (선택 사항).</param>
|
||||
/// <param name="tooltipKey">버튼 툴팁의 텍스트 또는 다국어 키입니다 (선택 사항).</param>
|
||||
/// <param name="tooltip">버튼 툴팁의 텍스트 또는 다국어 키입니다 (선택 사항).</param>
|
||||
/// <returns>생성되고 추가된 ToolbarToggleButton 객체입니다.</returns>
|
||||
public ToolbarToggleButton AddToggleButton(string text, bool initialState = false, string onIconSpritePath = null, string offIconSpritePath = null, System.Action<bool> onToggle = null, ICommand command = null, string tooltipKey = null)
|
||||
public ToolbarToggleButton AddToggleButton(string text, bool initialState = false, string onIconSpritePath = null, string offIconSpritePath = null, System.Action<bool> onToggle = null, ICommand command = null, string tooltip = null)
|
||||
{
|
||||
// ToolbarToggleButton의 IconSpritePath는 '선택된 상태'의 아이콘을 의미합니다.
|
||||
var button = new ToolbarToggleButton
|
||||
@@ -149,7 +148,7 @@ namespace UVC.UI.Toolbar
|
||||
OffIconSpritePath = offIconSpritePath, // 해제 시 아이콘
|
||||
OnToggle = onToggle,
|
||||
ClickCommand = command,
|
||||
TooltipKey = tooltipKey
|
||||
Tooltip = tooltip
|
||||
};
|
||||
AddItem(button);
|
||||
return button;
|
||||
@@ -166,9 +165,9 @@ namespace UVC.UI.Toolbar
|
||||
/// <param name="offIconSpritePath">버튼이 해제(Off) 상태일 때의 아이콘 경로입니다 (선택 사항).</param>
|
||||
/// <param name="onToggle">버튼의 선택 상태가 변경될 때 호출될 콜백 함수입니다 (선택 사항).</param>
|
||||
/// <param name="command">버튼 클릭(선택) 시 실행될 ICommand 객체입니다 (선택 사항).</param>
|
||||
/// <param name="tooltipKey">버튼 툴팁의 텍스트 또는 다국어 키입니다 (선택 사항).</param>
|
||||
/// <param name="tooltip">버튼 툴팁의 텍스트 또는 다국어 키입니다 (선택 사항).</param>
|
||||
/// <returns>생성되고 추가된 ToolbarRadioButton 객체입니다.</returns>
|
||||
public ToolbarRadioButton AddRadioButton(string groupName, string text, bool initialState = false, string iconSpritePath = null, string offIconSpritePath = null, System.Action<bool> onToggle = null, ICommand command = null, string tooltipKey = null)
|
||||
public ToolbarRadioButton AddRadioButton(string groupName, string text, bool initialState = false, string iconSpritePath = null, string offIconSpritePath = null, System.Action<bool> onToggle = null, ICommand command = null, string tooltip = null)
|
||||
{
|
||||
var button = new ToolbarRadioButton(groupName)
|
||||
{
|
||||
@@ -178,9 +177,9 @@ namespace UVC.UI.Toolbar
|
||||
OffIconSpritePath = offIconSpritePath,// 해제 시 아이콘
|
||||
OnToggle = onToggle,
|
||||
ClickCommand = command,
|
||||
TooltipKey = tooltipKey
|
||||
Tooltip = tooltip
|
||||
};
|
||||
|
||||
|
||||
// AddItem 내에서 그룹 등록 및 버튼에 그룹 참조 설정이 이루어집니다.
|
||||
AddItem(button);
|
||||
|
||||
@@ -200,11 +199,11 @@ namespace UVC.UI.Toolbar
|
||||
/// <param name="text">주 버튼에 표시될 텍스트 또는 다국어 키입니다.</param>
|
||||
/// <param name="iconSpritePath">주 버튼의 기본 아이콘 경로입니다 (선택 사항).</param>
|
||||
/// <param name="command">주 버튼 클릭 시 실행될 ICommand 객체입니다 (선택 사항, 하위 메뉴 토글과는 별개일 수 있음).</param>
|
||||
/// <param name="tooltipKey">주 버튼 툴팁의 텍스트 또는 다국어 키입니다 (선택 사항).</param>
|
||||
/// <param name="tooltip">주 버튼 툴팁의 텍스트 또는 다국어 키입니다 (선택 사항).</param>
|
||||
/// <returns>생성되고 추가된 ToolbarExpandableButton 객체입니다.</returns>
|
||||
public ToolbarExpandableButton AddExpandableButton(string text, string iconSpritePath = null, ICommand command = null, string tooltipKey = null)
|
||||
public ToolbarExpandableButton AddExpandableButton(string text, string iconSpritePath = null, ICommand command = null, string tooltip = null)
|
||||
{
|
||||
var button = new ToolbarExpandableButton { Text = text, IconSpritePath = iconSpritePath, ClickCommand = command, TooltipKey = tooltipKey };
|
||||
var button = new ToolbarExpandableButton { Text = text, IconSpritePath = iconSpritePath, ClickCommand = command, Tooltip = tooltip };
|
||||
AddItem(button);
|
||||
return button;
|
||||
}
|
||||
2
Assets/Scripts/UVC/UI/ToolBar/Model/ToolbarModel.cs.meta
Normal file
2
Assets/Scripts/UVC/UI/ToolBar/Model/ToolbarModel.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 27e53214281a62642adbdbf761ffd630
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace UVC.UI.Toolbar
|
||||
namespace UVC.UI.Toolbar.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 라디오 버튼 그룹 내에서 사용되는 버튼입니다. 동일한 GroupName을 가진 라디오 버튼들 중에서
|
||||
@@ -15,7 +15,7 @@ namespace UVC.UI.Toolbar
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// // ToolbarController 또는 ToolbarModel 등에서 ToolbarRadioButton 생성 및 사용 예시
|
||||
/// // Toolbar 또는 ToolbarModel 등에서 ToolbarRadioButton 생성 및 사용 예시
|
||||
///
|
||||
/// string cameraViewGroupName = "CameraViewOptions";
|
||||
///
|
||||
@@ -25,7 +25,7 @@ namespace UVC.UI.Toolbar
|
||||
/// Text = "view_top",
|
||||
/// IconSpritePath = "icons/toolbar/view_top_on",
|
||||
/// OffIconSpritePath = "icons/toolbar/view_top_off",
|
||||
/// TooltipKey = "tooltip_top_view",
|
||||
/// Tooltip = "tooltip_top_view",
|
||||
/// IsSelected = true, // 초기 선택 상태
|
||||
/// OnToggle = (isSelected) =>
|
||||
/// {
|
||||
@@ -44,7 +44,7 @@ namespace UVC.UI.Toolbar
|
||||
/// Text = "view_front",
|
||||
/// IconSpritePath = "icons/toolbar/view_front_on",
|
||||
/// OffIconSpritePath = "icons/toolbar/view_front_off",
|
||||
/// TooltipKey = "tooltip_front_view",
|
||||
/// Tooltip = "tooltip_front_view",
|
||||
/// IsSelected = false, // 초기 선택 안됨
|
||||
/// OnToggle = (isSelected) =>
|
||||
/// {
|
||||
@@ -149,5 +149,16 @@ namespace UVC.UI.Toolbar
|
||||
// 위 if(IsSelected) 조건을 제거하거나, 별도의 Command(예: DeselectCommand)를 고려해야 합니다.
|
||||
// 하지만 일반적인 라디오 버튼의 사용 패턴은 선택 시의 액션에 중점을 둡니다.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 이 버튼 모델에 연결된 모든 이벤트 핸들러를 정리합니다.
|
||||
/// ToolbarRadioButton은 ToolbarToggleButton에서 상속받은 이벤트 외에 추가적인 이벤트가 없으므로,
|
||||
/// 부모 클래스의 ClearEventHandlers를 호출합니다.
|
||||
/// </summary>
|
||||
public override void ClearEventHandlers()
|
||||
{
|
||||
base.ClearEventHandlers(); // 부모 클래스(ToolbarToggleButton)의 이벤트 정리
|
||||
// ToolbarRadioButton에 특화된 이벤트가 있다면 여기서 정리합니다.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 357d7605383a64d4cb43bd295b261c1a
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace UVC.UI.Toolbar
|
||||
namespace UVC.UI.Toolbar.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 여러 개의 ToolbarRadioButton 객체들을 하나의 그룹으로 관리합니다.
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UVC.UI.Toolbar
|
||||
namespace UVC.UI.Toolbar.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 툴바 내에서 항목들(예: 버튼 그룹)을 시각적으로 구분하는 구분선을 나타냅니다.
|
||||
@@ -11,7 +11,7 @@
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// // ToolbarController 또는 ToolbarModel 등에서 ToolbarSeparator 사용 예시
|
||||
/// // Toolbar 또는 ToolbarModel 등에서 ToolbarSeparator 사용 예시
|
||||
///
|
||||
/// // ToolbarModel 인스턴스가 있다고 가정
|
||||
/// // ToolbarModel toolbarModel = new ToolbarModel();
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2df7acabcce51f34c9495286bc8ed81b
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UVC.UI.Toolbar
|
||||
namespace UVC.UI.Toolbar.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 한 번 클릭으로 특정 동작을 수행하는 표준적인 버튼입니다.
|
||||
@@ -12,7 +12,7 @@
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// // ToolbarController 또는 ToolbarModel 등에서 ToolbarStandardButton 생성 및 사용 예시
|
||||
/// // Toolbar 또는 ToolbarModel 등에서 ToolbarStandardButton 생성 및 사용 예시
|
||||
///
|
||||
/// // 1. 버튼 클릭 시 실행될 커맨드 정의 (예: 간단한 로그 출력)
|
||||
/// ICommand saveCommand = new ActionCommand(() =>
|
||||
@@ -26,7 +26,7 @@
|
||||
/// {
|
||||
/// Text = "button_save", // 버튼 텍스트 (다국어 키 또는 실제 텍스트)
|
||||
/// IconSpritePath = "icons/toolbar/save_icon", // Resources 폴더 내 아이콘 경로
|
||||
/// TooltipKey = "tooltip_save_button_description", // 툴팁 (다국어 키 또는 실제 텍스트)
|
||||
/// Tooltip = "tooltip_save_button_description", // 툴팁 (다국어 키 또는 실제 텍스트)
|
||||
/// ClickCommand = saveCommand, // 위에서 정의한 커맨드 할당
|
||||
/// IsEnabled = true // 버튼 활성화 상태
|
||||
/// };
|
||||
@@ -53,13 +53,13 @@
|
||||
// /// <param name="text">버튼 텍스트 또는 다국어 키입니다.</param>
|
||||
// /// <param name="iconSpritePath">아이콘의 Resources 경로입니다.</param>
|
||||
// /// <param name="command">클릭 시 실행될 커맨드입니다.</param>
|
||||
// /// <param name="tooltipKey">툴팁 텍스트 또는 다국어 키입니다.</param>
|
||||
// public ToolbarStandardButton(string text, string iconSpritePath = null, ICommand command = null, string tooltipKey = null)
|
||||
// /// <param name="tooltip">툴팁 텍스트 또는 다국어 키입니다.</param>
|
||||
// public ToolbarStandardButton(string text, string iconSpritePath = null, ICommand command = null, string tooltip = null)
|
||||
// {
|
||||
// this.Text = text;
|
||||
// this.IconSpritePath = iconSpritePath;
|
||||
// this.ClickCommand = command;
|
||||
// this.TooltipKey = tooltipKey;
|
||||
// this.TooltipKey = tooltip;
|
||||
// }
|
||||
|
||||
// ToolbarButtonBase의 ExecuteClick 메서드를 그대로 사용합니다.
|
||||
@@ -80,5 +80,17 @@
|
||||
// // 여기에 ToolbarStandardButton만의 추가적인 로직이 있다면 작성
|
||||
// // 예를 들어, 클릭 후 특정 사운드 재생 등
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// 이 버튼 모델에 연결된 모든 이벤트 핸들러를 정리합니다.
|
||||
/// ToolbarStandardButton은 ToolbarButtonBase에서 상속받은 이벤트 외에 추가적인 이벤트가 없으므로,
|
||||
/// 기본 구현을 호출합니다.
|
||||
/// </summary>
|
||||
public override void ClearEventHandlers()
|
||||
{
|
||||
base.ClearEventHandlers();
|
||||
// ToolbarStandardButton에 특화된 이벤트가 있다면 여기서 정리합니다.
|
||||
// 예: CustomEvent = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce9fef59341116a46a731f2afe6a96f9
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UVC.UI.Toolbar
|
||||
namespace UVC.UI.Toolbar.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 클릭할 때마다 선택(On) 또는 해제(Off) 상태가 전환되는 토글 버튼입니다.
|
||||
@@ -16,7 +15,7 @@ namespace UVC.UI.Toolbar
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// // ToolbarController 또는 ToolbarModel 등에서 ToolbarToggleButton 생성 및 사용 예시
|
||||
/// // Toolbar 또는 ToolbarModel 등에서 ToolbarToggleButton 생성 및 사용 예시
|
||||
///
|
||||
/// // 1. 토글 상태 변경 시 실행될 액션 정의 (OnToggle 콜백용)
|
||||
/// Action<bool> handleMuteToggle = (isMuted) =>
|
||||
@@ -39,7 +38,7 @@ namespace UVC.UI.Toolbar
|
||||
/// Text = "button_mute", // 버튼 텍스트 (다국어 키)
|
||||
/// IconSpritePath = "icons/toolbar/sound_on_icon", // 선택(On) 상태 아이콘
|
||||
/// OffIconSpritePath = "icons/toolbar/sound_off_icon", // 해제(Off) 상태 아이콘
|
||||
/// TooltipKey = "tooltip_mute_button", // 툴팁 (다국어 키)
|
||||
/// Tooltip = "tooltip_mute_button", // 툴팁 (다국어 키)
|
||||
/// IsSelected = false, // 초기 상태는 해제(Off)
|
||||
/// OnToggle = handleMuteToggle, // 상태 변경 시 콜백 할당
|
||||
/// ClickCommand = muteCommand, // 클릭 커맨드 할당
|
||||
@@ -155,5 +154,16 @@ namespace UVC.UI.Toolbar
|
||||
ClickCommand.Execute(IsSelected);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 이 버튼 모델에 연결된 모든 이벤트 핸들러를 정리합니다.
|
||||
/// ToolbarButtonBase의 이벤트 외에 ToolbarToggleButton에 특화된 이벤트(OnToggleStateChanged, OnToggle)를 추가로 정리합니다.
|
||||
/// </summary>
|
||||
public override void ClearEventHandlers()
|
||||
{
|
||||
base.ClearEventHandlers(); // 부모 클래스의 이벤트 정리 (OnStateChanged)
|
||||
OnToggleStateChanged = null;
|
||||
OnToggle = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9530db2a5b423bf4eb8c5d8e4f9dd5ed
|
||||
@@ -1,10 +1,12 @@
|
||||
using UnityEngine;
|
||||
using UVC.Locale;
|
||||
using UVC.UI.Commands;
|
||||
using UVC.UI.Toolbar.Model;
|
||||
using UVC.UI.Toolbar.View;
|
||||
|
||||
namespace UVC.UI.Toolbar
|
||||
{
|
||||
public class ToolbarController : MonoBehaviour
|
||||
public class Toolbar : MonoBehaviour
|
||||
{
|
||||
protected ToolbarModel mainToolbar;
|
||||
protected ToolbarView mainToolbarView;
|
||||
@@ -100,7 +102,7 @@ namespace UVC.UI.Toolbar
|
||||
|
||||
// 9. 화면 캡처
|
||||
mainToolbar.AddStandardButton("button_capture_screen",
|
||||
"Prefabs/UI/Toolbar/images/ic_chapture_white",
|
||||
"Prefabs/UI/Toolbar/images/ic_capture_white",
|
||||
new ActionCommand(() => Debug.Log("화면 캡처 버튼 클릭됨")),
|
||||
"tooltip_capture_screen");
|
||||
|
||||
@@ -124,7 +126,7 @@ namespace UVC.UI.Toolbar
|
||||
{
|
||||
Text = "brush_size_small",
|
||||
IconSpritePath = "Prefabs/UI/Toolbar/images/ic_brush_small_white",
|
||||
TooltipKey = "tooltip_brush_small",
|
||||
Tooltip = "tooltip_brush_small",
|
||||
ClickCommand = smallBrushCmd
|
||||
};
|
||||
expandableBtnModel.SubButtons.Add(smallBrush);
|
||||
@@ -133,7 +135,7 @@ namespace UVC.UI.Toolbar
|
||||
{
|
||||
Text = "brush_size_medium",
|
||||
IconSpritePath = "Prefabs/UI/Toolbar/images/ic_brush_medium_white",
|
||||
TooltipKey = "tooltip_brush_medium",
|
||||
Tooltip = "tooltip_brush_medium",
|
||||
ClickCommand = new ActionCommand(() => Debug.Log("중간 브러시 선택됨 (Sub-Command 실행)"))
|
||||
};
|
||||
expandableBtnModel.SubButtons.Add(mediumBrush);
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 49e156554491e3c4fb49243701695feb
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c71e02eeca4e94e4b8dedd8f9fb7e4a7
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 451c776768fed71479e8c7a4a73818ea
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41943a25123704b4f82ec6417863d158
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d7cc1da90c7117449ff98ba4600c3ce
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6407c881188c7c04c9cb4efb1dd7b4ce
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60240c8d04420604681084344d3a0253
|
||||
@@ -2,6 +2,8 @@
|
||||
using UVC.Locale;
|
||||
using UVC.UI.Commands;
|
||||
using UVC.UI.Toolbar;
|
||||
using UVC.UI.Toolbar.Model;
|
||||
using UVC.UI.Toolbar.View;
|
||||
|
||||
namespace UVC.UI.ToolBar
|
||||
{
|
||||
@@ -21,7 +23,7 @@ namespace UVC.UI.ToolBar
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// // Unity 에디터에서 GameObject를 생성하고 이 ToolboxController 스크립트를 추가합니다.
|
||||
/// // Unity 에디터에서 GameObject를 생성하고 이 Toolbox 스크립트를 추가합니다.
|
||||
/// // 또한, ToolbarView 스크립트도 해당 GameObject 또는 자식 GameObject에 추가하고,
|
||||
/// // ToolbarView의 프리팹 필드들(standardButtonPrefab 등)을 Inspector에서 할당해야 합니다.
|
||||
///
|
||||
@@ -31,7 +33,7 @@ namespace UVC.UI.ToolBar
|
||||
/// // private void OpenFile() { Debug.Log("파일 열기 기능 실행"); }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public class ToolboxController : MonoBehaviour
|
||||
public class Toolbox : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// 툴바의 데이터 모델입니다. 툴바 항목들의 정보와 구조를 담고 있습니다.
|
||||
@@ -62,7 +64,7 @@ namespace UVC.UI.ToolBar
|
||||
|
||||
if (mainToolbarView == null)
|
||||
{
|
||||
Debug.LogError("ToolboxController: ToolbarView 컴포넌트를 찾을 수 없습니다. GameObject에 ToolbarView를 추가하고 연결해주세요.");
|
||||
Debug.LogError("Toolbox: ToolbarView 컴포넌트를 찾을 수 없습니다. GameObject에 ToolbarView를 추가하고 연결해주세요.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +82,7 @@ namespace UVC.UI.ToolBar
|
||||
if (mainToolbarView == null)
|
||||
{
|
||||
// Awake에서 이미 로그를 남겼을 수 있지만, 한 번 더 확인하여 Start 로직 중단
|
||||
Debug.LogError("ToolboxController: ToolbarView가 할당되지 않아 툴바를 초기화할 수 없습니다.");
|
||||
Debug.LogError("Toolbox: ToolbarView가 할당되지 않아 툴바를 초기화할 수 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -156,7 +158,7 @@ namespace UVC.UI.ToolBar
|
||||
|
||||
// 예시 4: 화면 캡처 버튼 (텍스트가 다국어 키일 수 있음)
|
||||
mainToolbar.AddStandardButton("button_capture_screen", // 다국어 키로 사용될 수 있는 텍스트
|
||||
"Prefabs/UI/Toolbar/images/ic_chapture_white",
|
||||
"Prefabs/UI/Toolbar/images/ic_capture_white",
|
||||
new ActionCommand(() => Debug.Log("화면 캡처 버튼 클릭됨")),
|
||||
"tooltip_capture_screen"); // 툴팁도 다국어 키 사용 가능
|
||||
|
||||
@@ -184,7 +186,7 @@ namespace UVC.UI.ToolBar
|
||||
{
|
||||
Text = "brush_size_small", // 하위 버튼 텍스트/키
|
||||
IconSpritePath = "Prefabs/UI/Toolbar/images/ic_brush_small_white", // 하위 버튼 아이콘
|
||||
TooltipKey = "tooltip_brush_small", // 하위 버튼 툴팁
|
||||
Tooltip = "tooltip_brush_small", // 하위 버튼 툴팁
|
||||
ClickCommand = smallBrushCmd
|
||||
};
|
||||
expandableBtnModel.SubButtons.Add(smallBrush); // 확장 버튼 모델에 하위 버튼 추가
|
||||
@@ -194,7 +196,7 @@ namespace UVC.UI.ToolBar
|
||||
{
|
||||
Text = "brush_size_medium",
|
||||
IconSpritePath = "Prefabs/UI/Toolbar/images/ic_brush_medium_white",
|
||||
TooltipKey = "tooltip_brush_medium",
|
||||
Tooltip = "tooltip_brush_medium",
|
||||
ClickCommand = new ActionCommand(() => Debug.Log("중간 브러시 선택됨 (Sub-Command 실행)"))
|
||||
};
|
||||
expandableBtnModel.SubButtons.Add(mediumBrush);
|
||||
8
Assets/Scripts/UVC/UI/ToolBar/View.meta
Normal file
8
Assets/Scripts/UVC/UI/ToolBar/View.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3981414c9998a846bad8e35456a3979
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
51
Assets/Scripts/UVC/UI/ToolBar/View/IButtonViewProcessor.cs
Normal file
51
Assets/Scripts/UVC/UI/ToolBar/View/IButtonViewProcessor.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using UnityEngine;
|
||||
using UVC.UI.Toolbar.Model;
|
||||
using UVC.UI.Toolbar.View;
|
||||
|
||||
namespace UVC.UI.ToolBar.View
|
||||
{
|
||||
/// <summary>
|
||||
/// 툴바 버튼의 UI 생성, 설정 및 업데이트 로직을 처리하는 인터페이스입니다.
|
||||
/// 각 버튼 타입(표준, 토글, 라디오, 확장 등)에 대한 구체적인 UI 처리 클래스가 이 인터페이스를 구현합니다.
|
||||
/// </summary>
|
||||
public interface IButtonViewProcessor
|
||||
{
|
||||
/// <summary>
|
||||
/// 지정된 버튼 모델에 대한 UI GameObject를 생성하고 초기화합니다.
|
||||
/// </summary>
|
||||
/// <param name="buttonModel">UI를 생성할 버튼의 데이터 모델입니다.</param>
|
||||
/// <param name="parentContainer">생성된 UI GameObject가 자식으로 추가될 부모 Transform입니다.</param>
|
||||
/// <param name="viewContext">현재 ToolbarView의 컨텍스트입니다. 프리팹 참조, 헬퍼 메서드 접근 등에 사용됩니다.</param>
|
||||
/// <returns>생성된 UI GameObject입니다. 생성 실패 시 null을 반환할 수 있습니다.</returns>
|
||||
GameObject CreateButtonUI(ToolbarButtonBase buttonModel, Transform parentContainer, ToolbarView viewContext);
|
||||
|
||||
/// <summary>
|
||||
/// 생성된 버튼 UI GameObject에 대해 초기 시각적 요소(텍스트, 아이콘 등)를 설정하고,
|
||||
/// 사용자 상호작용(예: 클릭 이벤트) 시 모델의 메서드가 호출되도록 이벤트를 바인딩합니다.
|
||||
/// 또한, 모델의 상태 변경 이벤트(OnStateChanged, OnToggleStateChanged 등)를 구독하여 UI가 업데이트되도록 설정합니다.
|
||||
/// </summary>
|
||||
/// <param name="buttonModel">설정할 버튼의 데이터 모델입니다.</param>
|
||||
/// <param name="buttonUIObject">모델에 해당하는, 화면에 표시될 UI GameObject입니다.</param>
|
||||
/// <param name="viewContext">현재 ToolbarView의 컨텍스트입니다.</param>
|
||||
void SetupButtonInteractions(ToolbarButtonBase buttonModel, GameObject buttonUIObject, ToolbarView viewContext);
|
||||
|
||||
/// <summary>
|
||||
/// 버튼 모델의 공통적인 상태(텍스트, 아이콘, 활성화 상태 등)가 변경되었을 때,
|
||||
/// 해당 버튼 UI의 시각적 요소를 업데이트합니다.
|
||||
/// </summary>
|
||||
/// <param name="buttonModel">상태가 변경된 버튼의 모델입니다.</param>
|
||||
/// <param name="buttonUIObject">업데이트할 UI GameObject입니다.</param>
|
||||
/// <param name="viewContext">현재 ToolbarView의 컨텍스트입니다.</param>
|
||||
void UpdateCommonButtonVisuals(ToolbarButtonBase buttonModel, GameObject buttonUIObject, ToolbarView viewContext);
|
||||
|
||||
/// <summary>
|
||||
/// 토글 가능한 버튼(ToolbarToggleButton, ToolbarRadioButton)의 선택 상태(IsSelected)가 모델에서 변경되었을 때 호출됩니다.
|
||||
/// 해당 UI Toggle 컴포넌트의 isOn 상태를 모델의 IsSelected 값과 동기화합니다.
|
||||
/// </summary>
|
||||
/// <param name="toggleButtonModel">IsSelected 상태가 변경된 토글/라디오 버튼의 모델입니다.</param>
|
||||
/// <param name="buttonUIObject">업데이트할 UI GameObject입니다.</param>
|
||||
/// <param name="isSelected">모델의 새로운 IsSelected 값입니다.</param>
|
||||
/// <param name="viewContext">현재 ToolbarView의 컨텍스트입니다.</param>
|
||||
void UpdateToggleStateVisuals(ToolbarToggleButton toggleButtonModel, GameObject buttonUIObject, bool isSelected, ToolbarView viewContext);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 813fbe357e2233d49beaf93864c6bfd8
|
||||
@@ -0,0 +1,51 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UVC.UI.Toolbar.Model;
|
||||
using UVC.UI.ToolBar.View;
|
||||
|
||||
namespace UVC.UI.Toolbar.View
|
||||
{
|
||||
public class ToolbarExpandableButtonViewProcessor : IButtonViewProcessor
|
||||
{
|
||||
public GameObject CreateButtonUI(ToolbarButtonBase buttonModel, Transform parentContainer, ToolbarView viewContext)
|
||||
{
|
||||
if (viewContext.expandableButtonPrefab == null)
|
||||
{
|
||||
Debug.LogError("ExpandableButtonViewProcessor: expandableButtonPrefab이 ToolbarView에 할당되지 않았습니다.", viewContext);
|
||||
return null;
|
||||
}
|
||||
return Object.Instantiate(viewContext.expandableButtonPrefab, parentContainer);
|
||||
}
|
||||
|
||||
public void SetupButtonInteractions(ToolbarButtonBase buttonModel, GameObject buttonUIObject, ToolbarView viewContext)
|
||||
{
|
||||
ToolbarExpandableButton expandableModel = buttonModel as ToolbarExpandableButton;
|
||||
if (expandableModel == null) return;
|
||||
|
||||
Button uiButton = buttonUIObject.GetComponent<Button>();
|
||||
if (uiButton != null)
|
||||
{
|
||||
uiButton.onClick.AddListener(() =>
|
||||
{
|
||||
expandableModel.ExecuteClick();
|
||||
viewContext.ToggleSubMenu(expandableModel, buttonUIObject);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"ExpandableButtonViewProcessor: ExpandableButton '{expandableModel.Text}'의 GameObject에 Button 컴포넌트가 없습니다.", buttonUIObject);
|
||||
}
|
||||
UpdateCommonButtonVisuals(buttonModel, buttonUIObject, viewContext);
|
||||
}
|
||||
|
||||
public void UpdateCommonButtonVisuals(ToolbarButtonBase buttonModel, GameObject buttonUIObject, ToolbarView viewContext)
|
||||
{
|
||||
viewContext.InternalUpdateCommonButtonVisuals(buttonModel, buttonUIObject);
|
||||
}
|
||||
|
||||
public void UpdateToggleStateVisuals(ToolbarToggleButton toggleButtonModel, GameObject buttonUIObject, bool isSelected, ToolbarView viewContext)
|
||||
{
|
||||
// 확장 버튼은 기본 토글 상태가 없음 (하위 메뉴 표시 여부는 다른 메커니즘으로 관리)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91d4340b73cb5a84d91986ba644d398f
|
||||
@@ -0,0 +1,70 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UVC.UI.Toolbar.Model;
|
||||
using UVC.UI.ToolBar.View;
|
||||
|
||||
namespace UVC.UI.Toolbar.View
|
||||
{
|
||||
public class ToolbarRadioButtonViewProcessor : IButtonViewProcessor
|
||||
{
|
||||
public GameObject CreateButtonUI(ToolbarButtonBase buttonModel, Transform parentContainer, ToolbarView viewContext)
|
||||
{
|
||||
if (viewContext.radioButtonPrefab == null)
|
||||
{
|
||||
Debug.LogError("RadioButtonViewProcessor: radioButtonPrefab이 ToolbarView에 할당되지 않았습니다.", viewContext);
|
||||
return null;
|
||||
}
|
||||
return Object.Instantiate(viewContext.radioButtonPrefab, parentContainer);
|
||||
}
|
||||
|
||||
public void SetupButtonInteractions(ToolbarButtonBase buttonModel, GameObject buttonUIObject, ToolbarView viewContext)
|
||||
{
|
||||
ToolbarRadioButton radioModel = buttonModel as ToolbarRadioButton;
|
||||
if (radioModel == null) return;
|
||||
|
||||
Toggle toggleComponent = buttonUIObject.GetComponent<Toggle>();
|
||||
if (toggleComponent != null)
|
||||
{
|
||||
ToggleGroup uiToggleGroup = viewContext.GetOrCreateToggleGroup(radioModel.GroupName);
|
||||
toggleComponent.group = uiToggleGroup;
|
||||
toggleComponent.SetIsOnWithoutNotify(radioModel.IsSelected);
|
||||
|
||||
toggleComponent.onValueChanged.AddListener((isSelected) =>
|
||||
{
|
||||
if (isSelected)
|
||||
{
|
||||
radioModel.ExecuteClick(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"RadioButtonViewProcessor: RadioButton '{radioModel.Text}'의 GameObject에 Toggle 컴포넌트가 없습니다.", buttonUIObject);
|
||||
}
|
||||
UpdateCommonButtonVisuals(buttonModel, buttonUIObject, viewContext);
|
||||
UpdateToggleStateVisuals(radioModel, buttonUIObject, radioModel.IsSelected, viewContext);
|
||||
}
|
||||
|
||||
public void UpdateCommonButtonVisuals(ToolbarButtonBase buttonModel, GameObject buttonUIObject, ToolbarView viewContext)
|
||||
{
|
||||
viewContext.InternalUpdateCommonButtonVisuals(buttonModel, buttonUIObject);
|
||||
}
|
||||
|
||||
public void UpdateToggleStateVisuals(ToolbarToggleButton toggleButtonModel, GameObject buttonUIObject, bool isSelected, ToolbarView viewContext)
|
||||
{
|
||||
// ToolbarToggleButton 타입으로 캐스팅 시도
|
||||
ToolbarRadioButton radioModel = toggleButtonModel as ToolbarRadioButton;
|
||||
if (radioModel == null) return;
|
||||
|
||||
Toggle toggleComponent = buttonUIObject.GetComponent<Toggle>();
|
||||
if (toggleComponent != null)
|
||||
{
|
||||
if (toggleComponent.isOn != isSelected)
|
||||
{
|
||||
toggleComponent.SetIsOnWithoutNotify(isSelected);
|
||||
}
|
||||
}
|
||||
viewContext.InternalUpdateCommonButtonVisuals(radioModel, buttonUIObject); // 아이콘 업데이트를 위해 호출
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1e8beeab960cbd549ad03e44b366896e
|
||||
@@ -0,0 +1,54 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UVC.UI.Toolbar.Model;
|
||||
using UVC.UI.ToolBar.View;
|
||||
|
||||
namespace UVC.UI.Toolbar.View
|
||||
{
|
||||
public class ToolbarStandardButtonViewProcessor : IButtonViewProcessor
|
||||
{
|
||||
public GameObject CreateButtonUI(ToolbarButtonBase buttonModel, Transform parentContainer, ToolbarView viewContext)
|
||||
{
|
||||
if (viewContext.standardButtonPrefab == null)
|
||||
{
|
||||
Debug.LogError("StandardButtonViewProcessor: standardButtonPrefab이 ToolbarView에 할당되지 않았습니다.", viewContext);
|
||||
return null;
|
||||
}
|
||||
return Object.Instantiate(viewContext.standardButtonPrefab, parentContainer);
|
||||
}
|
||||
|
||||
public void SetupButtonInteractions(ToolbarButtonBase buttonModel, GameObject buttonUIObject, ToolbarView viewContext)
|
||||
{
|
||||
ToolbarStandardButton standardModel = buttonModel as ToolbarStandardButton;
|
||||
if (standardModel == null) return;
|
||||
|
||||
Button uiButton = buttonUIObject.GetComponent<Button>();
|
||||
if (uiButton != null)
|
||||
{
|
||||
uiButton.onClick.AddListener(() =>
|
||||
{
|
||||
standardModel.ExecuteClick(standardModel.Text);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"StandardButtonViewProcessor: StandardButton '{standardModel.Text}'의 GameObject에 Button 컴포넌트가 없습니다.", buttonUIObject);
|
||||
}
|
||||
|
||||
// 공통적인 모델 상태 변경 구독은 ToolbarView의 RenderToolbar에서 처리하거나,
|
||||
// 각 Processor가 viewContext를 통해 UpdateCommonButtonVisuals 등을 직접 호출하도록 할 수 있습니다.
|
||||
// 여기서는 ToolbarView에서 공통 구독을 처리한다고 가정합니다.
|
||||
UpdateCommonButtonVisuals(buttonModel, buttonUIObject, viewContext);
|
||||
}
|
||||
|
||||
public void UpdateCommonButtonVisuals(ToolbarButtonBase buttonModel, GameObject buttonUIObject, ToolbarView viewContext)
|
||||
{
|
||||
viewContext.InternalUpdateCommonButtonVisuals(buttonModel, buttonUIObject);
|
||||
}
|
||||
|
||||
public void UpdateToggleStateVisuals(ToolbarToggleButton toggleButtonModel, GameObject buttonUIObject, bool isSelected, ToolbarView viewContext)
|
||||
{
|
||||
// 표준 버튼은 토글 상태가 없음
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a22df99b306444429b5c67ec0e8d46b
|
||||
@@ -0,0 +1,60 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UVC.UI.Toolbar.Model;
|
||||
using UVC.UI.ToolBar.View;
|
||||
|
||||
namespace UVC.UI.Toolbar.View
|
||||
{
|
||||
public class ToolbarToggleButtonViewProcessor : IButtonViewProcessor
|
||||
{
|
||||
public GameObject CreateButtonUI(ToolbarButtonBase buttonModel, Transform parentContainer, ToolbarView viewContext)
|
||||
{
|
||||
if (viewContext.toggleButtonPrefab == null)
|
||||
{
|
||||
Debug.LogError("ToggleButtonViewProcessor: toggleButtonPrefab이 ToolbarView에 할당되지 않았습니다.", viewContext);
|
||||
return null;
|
||||
}
|
||||
return Object.Instantiate(viewContext.toggleButtonPrefab, parentContainer);
|
||||
}
|
||||
|
||||
public void SetupButtonInteractions(ToolbarButtonBase buttonModel, GameObject buttonUIObject, ToolbarView viewContext)
|
||||
{
|
||||
ToolbarToggleButton toggleModel = buttonModel as ToolbarToggleButton;
|
||||
if (toggleModel == null) return;
|
||||
|
||||
Toggle toggleComponent = buttonUIObject.GetComponent<Toggle>();
|
||||
if (toggleComponent != null)
|
||||
{
|
||||
toggleComponent.SetIsOnWithoutNotify(toggleModel.IsSelected);
|
||||
toggleComponent.onValueChanged.AddListener((isSelected) =>
|
||||
{
|
||||
toggleModel.ExecuteClick();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"ToggleButtonViewProcessor: ToggleButton '{toggleModel.Text}'의 GameObject에 Toggle 컴포넌트가 없습니다.", buttonUIObject);
|
||||
}
|
||||
UpdateCommonButtonVisuals(buttonModel, buttonUIObject, viewContext);
|
||||
UpdateToggleStateVisuals(toggleModel, buttonUIObject, toggleModel.IsSelected, viewContext);
|
||||
}
|
||||
|
||||
public void UpdateCommonButtonVisuals(ToolbarButtonBase buttonModel, GameObject buttonUIObject, ToolbarView viewContext)
|
||||
{
|
||||
viewContext.InternalUpdateCommonButtonVisuals(buttonModel, buttonUIObject);
|
||||
}
|
||||
|
||||
public void UpdateToggleStateVisuals(ToolbarToggleButton toggleButtonModel, GameObject buttonUIObject, bool isSelected, ToolbarView viewContext)
|
||||
{
|
||||
Toggle toggleComponent = buttonUIObject.GetComponent<Toggle>();
|
||||
if (toggleComponent != null)
|
||||
{
|
||||
if (toggleComponent.isOn != isSelected)
|
||||
{
|
||||
toggleComponent.SetIsOnWithoutNotify(isSelected);
|
||||
}
|
||||
}
|
||||
viewContext.InternalUpdateCommonButtonVisuals(toggleButtonModel, buttonUIObject); // 아이콘 업데이트를 위해 호출
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d7a0ee99f42c57745b899b45fd7dad30
|
||||
@@ -4,9 +4,12 @@ using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UVC.Extension;
|
||||
using UVC.Locale;
|
||||
using UVC.UI.Toolbar.Model;
|
||||
using UVC.UI.ToolBar;
|
||||
using UVC.UI.ToolBar.View;
|
||||
using UVC.UI.Tooltip;
|
||||
|
||||
namespace UVC.UI.Toolbar
|
||||
namespace UVC.UI.Toolbar.View
|
||||
{
|
||||
/// <summary>
|
||||
/// ToolbarModel에 정의된 데이터를 기반으로 실제 툴바 UI를 생성하고 관리하는 MonoBehaviour 클래스입니다.
|
||||
@@ -41,9 +44,9 @@ namespace UVC.UI.Toolbar
|
||||
/// // - Layout Group: Toolbar Container에 연결된 LayoutGroup (예: VerticalLayoutGroup, HorizontalLayoutGroup)
|
||||
/// // - Root Canvas: (선택 사항, TooltipManager 초기화에 필요하며 보통 자동으로 찾음)
|
||||
/// //
|
||||
/// // 3. ToolbarController (또는 유사 클래스)에서 ToolbarModel을 설정한 후,
|
||||
/// // 3. Toolbar (또는 유사 클래스)에서 ToolbarModel을 설정한 후,
|
||||
/// // ToolbarView의 Initialize 메서드를 호출하여 툴바 UI를 생성합니다.
|
||||
/// // ToolbarController controller = GetComponent<ToolbarController>(); // 또는 다른 방식으로 참조
|
||||
/// // Toolbar controller = GetComponent<Toolbar>(); // 또는 다른 방식으로 참조
|
||||
/// // ToolbarModel model = controller.GetConfiguredModel(); // 가정: 컨트롤러가 모델을 반환
|
||||
/// // Initialize(model);
|
||||
/// </code>
|
||||
@@ -52,28 +55,52 @@ namespace UVC.UI.Toolbar
|
||||
{
|
||||
/// <summary>
|
||||
/// 현재 툴바 UI의 기반이 되는 데이터 모델입니다.
|
||||
/// Initialize 메서드를 통해 외부(주로 ToolbarController)에서 주입받습니다.
|
||||
/// Initialize 메서드를 통해 외부(주로 Toolbar)에서 주입받습니다.
|
||||
/// </summary>
|
||||
protected ToolbarModel ToolbarModel { get; private set; }
|
||||
|
||||
// --- Inspector에서 할당할 프리팹 및 UI 요소들 ---
|
||||
[Header("UI Prefabs")]
|
||||
/// <summary>
|
||||
/// 표준 버튼 UI에 사용될 프리팹입니다. Inspector를 통해 할당해야 합니다.
|
||||
/// </summary>
|
||||
[Tooltip("표준 버튼 UI에 사용될 프리팹입니다.")]
|
||||
public GameObject standardButtonPrefab;
|
||||
/// <summary>
|
||||
/// 토글 버튼 UI에 사용될 프리팹입니다. Inspector를 통해 할당해야 합니다.
|
||||
/// </summary>
|
||||
[Tooltip("토글 버튼 UI에 사용될 프리팹입니다.")]
|
||||
public GameObject toggleButtonPrefab;
|
||||
/// <summary>
|
||||
/// 라디오 버튼 UI에 사용될 프리팹입니다. Inspector를 통해 할당해야 합니다.
|
||||
/// </summary>
|
||||
[Tooltip("라디오 버튼 UI에 사용될 프리팹입니다.")]
|
||||
public GameObject radioButtonPrefab;
|
||||
/// <summary>
|
||||
/// 확장 가능한 버튼 UI에 사용될 프리팹입니다. Inspector를 통해 할당해야 합니다.
|
||||
/// </summary>
|
||||
[Tooltip("확장 가능한 버튼 UI에 사용될 프리팹입니다.")]
|
||||
public GameObject expandableButtonPrefab;
|
||||
/// <summary>
|
||||
/// 구분선 UI에 사용될 프리팹입니다. Inspector를 통해 할당해야 합니다.
|
||||
/// </summary>
|
||||
[Tooltip("구분선 UI에 사용될 프리팹입니다.")]
|
||||
public GameObject separatorPrefab;
|
||||
/// <summary>
|
||||
/// 확장 버튼의 하위 메뉴 패널 UI에 사용될 프리팹입니다. Inspector를 통해 할당해야 합니다.
|
||||
/// </summary>
|
||||
[Tooltip("확장 버튼의 하위 메뉴 패널 UI에 사용될 프리팹입니다.")]
|
||||
public GameObject subMenuPanelPrefab;
|
||||
|
||||
[Header("UI Layout")]
|
||||
/// <summary>
|
||||
/// 생성된 툴바 항목 UI들이 자식으로 추가될 부모 Transform입니다. Inspector를 통해 할당해야 합니다.
|
||||
/// </summary>
|
||||
[Tooltip("생성된 툴바 항목 UI들이 자식으로 추가될 부모 Transform입니다.")]
|
||||
public Transform toolbarContainer;
|
||||
/// <summary>
|
||||
/// 툴바 항목들의 자동 배치를 담당하는 LayoutGroup 컴포넌트입니다. Inspector를 통해 할당해야 합니다.
|
||||
/// </summary>
|
||||
[Tooltip("툴바 항목들의 자동 배치를 담당하는 LayoutGroup 컴포넌트입니다 (예: VerticalLayoutGroup).")]
|
||||
public LayoutGroup layoutGroup;
|
||||
|
||||
@@ -83,6 +110,11 @@ namespace UVC.UI.Toolbar
|
||||
/// </summary>
|
||||
protected Dictionary<ToolbarButtonBase, GameObject> _modelToGameObjectMap = new Dictionary<ToolbarButtonBase, GameObject>();
|
||||
|
||||
/// <summary>
|
||||
/// 버튼 타입별 UI 처리기를 저장하는 딕셔너리입니다.
|
||||
/// </summary>
|
||||
private Dictionary<System.Type, IButtonViewProcessor> _buttonViewProcessors = new Dictionary<System.Type, IButtonViewProcessor>();
|
||||
|
||||
/// <summary>
|
||||
/// 툴팁 표시에 사용될 루트 Canvas입니다.
|
||||
/// Inspector에서 할당하거나, Awake에서 자동으로 찾으려고 시도합니다.
|
||||
@@ -97,6 +129,12 @@ namespace UVC.UI.Toolbar
|
||||
protected virtual void Awake()
|
||||
{
|
||||
|
||||
if (standardButtonPrefab == null || toggleButtonPrefab == null || radioButtonPrefab == null ||
|
||||
expandableButtonPrefab == null || separatorPrefab == null || subMenuPanelPrefab == null)
|
||||
{
|
||||
Debug.LogError("ToolbarView: 필수 프리팹이 할당되지 않았습니다. Inspector에서 모든 프리팹을 설정해주세요.", this);
|
||||
}
|
||||
|
||||
// toolbarContainer 자동 할당 (Inspector에서 할당되지 않은 경우)
|
||||
if (toolbarContainer == null) toolbarContainer = GetComponent<Transform>();
|
||||
if (toolbarContainer == null) toolbarContainer = GetComponentInChildren<Transform>(true); // 비활성 자식도 포함
|
||||
@@ -128,12 +166,19 @@ namespace UVC.UI.Toolbar
|
||||
// TooltipManager 초기화
|
||||
if (rootCanvas != null)
|
||||
{
|
||||
if(!TooltipManager.Instance.IsInitialized) TooltipManager.Instance.Initialize(rootCanvas.transform, rootCanvas);
|
||||
if (!TooltipManager.Instance.IsInitialized) TooltipManager.Instance.Initialize(rootCanvas.transform, rootCanvas);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("ToolbarView: rootCanvas를 찾을 수 없어 TooltipVisualManager를 초기화할 수 없습니다.");
|
||||
}
|
||||
|
||||
// 버튼 뷰 처리기 등록
|
||||
_buttonViewProcessors[typeof(ToolbarStandardButton)] = new ToolbarStandardButtonViewProcessor();
|
||||
_buttonViewProcessors[typeof(ToolbarToggleButton)] = new ToolbarToggleButtonViewProcessor();
|
||||
_buttonViewProcessors[typeof(ToolbarRadioButton)] = new ToolbarRadioButtonViewProcessor();
|
||||
_buttonViewProcessors[typeof(ToolbarExpandableButton)] = new ToolbarExpandableButtonViewProcessor();
|
||||
// 새로운 버튼 타입이 추가되면 여기에 처리기를 등록합니다.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -145,6 +190,13 @@ namespace UVC.UI.Toolbar
|
||||
{
|
||||
this.ToolbarModel = toolbarModel;
|
||||
|
||||
if (standardButtonPrefab == null || toggleButtonPrefab == null || radioButtonPrefab == null ||
|
||||
expandableButtonPrefab == null || separatorPrefab == null || subMenuPanelPrefab == null)
|
||||
{
|
||||
Debug.LogError("ToolbarView: 필수 프리팹이 할당되지 않았습니다. Inspector에서 모든 프리팹을 설정해주세요.", this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (toolbarContainer == null)
|
||||
{
|
||||
Debug.LogError("ToolbarView: Initialize 실패. toolbarContainer가 할당되지 않았습니다.", this);
|
||||
@@ -178,11 +230,9 @@ namespace UVC.UI.Toolbar
|
||||
{
|
||||
if (pair.Key != null) // 모델(버튼)에 연결된 이벤트 구독 해제
|
||||
{
|
||||
pair.Key.OnStateChanged -= () => UpdateItemVisuals(pair.Key);
|
||||
if (pair.Key is ToolbarToggleButton toggleButton)
|
||||
{
|
||||
toggleButton.OnToggleStateChanged -= (isSelected) => UpdateToggleVisuals(toggleButton, isSelected);
|
||||
}
|
||||
// ToolbarButtonBase 및 파생 클래스에 정의된 ClearEventHandlers를 호출하여
|
||||
// 모델에 연결된 모든 이벤트 구독을 명시적으로 해제합니다.
|
||||
pair.Key.ClearEventHandlers();
|
||||
}
|
||||
if (pair.Value != null) // UI GameObject 파괴
|
||||
{
|
||||
@@ -219,10 +269,29 @@ namespace UVC.UI.Toolbar
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 지정된 버튼 모델 타입에 맞는 IButtonViewProcessor를 반환합니다.
|
||||
/// </summary>
|
||||
/// <param name="buttonModelType">버튼 모델의 System.Type 객체입니다.</param>
|
||||
/// <returns>해당 타입의 처리기. 없으면 null을 반환합니다.</returns>
|
||||
protected IButtonViewProcessor GetButtonViewProcessor(System.Type buttonModelType)
|
||||
{
|
||||
if (_buttonViewProcessors.TryGetValue(buttonModelType, out var processor))
|
||||
{
|
||||
return processor;
|
||||
}
|
||||
// 상속 관계를 고려하여 부모 타입의 처리기를 찾을 수도 있습니다.
|
||||
// 예를 들어, MyCustomButton : ToolbarStandardButton 인 경우, ToolbarStandardButton 처리기를 반환할 수 있습니다.
|
||||
// 이 로직은 필요에 따라 확장할 수 있습니다.
|
||||
// 현재는 정확한 타입 매칭만 지원합니다.
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ToolbarModel에 정의된 항목들을 기반으로 실제 UI 요소들을 생성하여 툴바를 구성합니다.
|
||||
/// 먼저 ClearToolbar를 호출하여 기존 UI를 정리한 후, 모델의 각 항목에 대해 적절한 프리팹을 사용하여
|
||||
/// UI GameObject를 생성하고, 필요한 설정(이벤트 바인딩, 툴팁 등)을 수행합니다.
|
||||
/// 버튼 항목의 경우 IButtonViewProcessor 구현체에 UI 생성을 위임합니다.
|
||||
/// </summary>
|
||||
protected void RenderToolbar()
|
||||
{
|
||||
@@ -239,53 +308,55 @@ namespace UVC.UI.Toolbar
|
||||
{
|
||||
GameObject itemUIObject = null;// 생성될 UI GameObject
|
||||
|
||||
// 1. 모델 타입에 따라 적절한 프리팹 선택 및 인스턴스화
|
||||
if (itemModel is ToolbarSeparator)
|
||||
{
|
||||
if (separatorPrefab != null) itemUIObject = Instantiate(separatorPrefab, toolbarContainer);
|
||||
else Debug.LogError("ToolbarView: separatorPrefab이 할당되지 않았습니다.", this);
|
||||
}
|
||||
else if (itemModel is ToolbarButtonBase buttonModel) // 모든 버튼 타입의 기본 처리
|
||||
else if (itemModel is ToolbarButtonBase buttonModel)
|
||||
{
|
||||
GameObject prefabToUse = null;
|
||||
if (buttonModel is ToolbarRadioButton) prefabToUse = radioButtonPrefab;
|
||||
else if (buttonModel is ToolbarToggleButton) prefabToUse = toggleButtonPrefab; // 라디오 버튼보다 먼저 와야 함 (상속 관계)
|
||||
else if (buttonModel is ToolbarExpandableButton) prefabToUse = expandableButtonPrefab;
|
||||
else if (buttonModel is ToolbarStandardButton) prefabToUse = standardButtonPrefab;
|
||||
// else: 다른 커스텀 버튼 타입이 있다면 여기에 추가
|
||||
|
||||
if (prefabToUse != null)
|
||||
IButtonViewProcessor processor = GetButtonViewProcessor(buttonModel.GetType());
|
||||
if (processor != null)
|
||||
{
|
||||
itemUIObject = Instantiate(prefabToUse, toolbarContainer);
|
||||
itemUIObject = processor.CreateButtonUI(buttonModel, toolbarContainer, this);
|
||||
if (itemUIObject != null)
|
||||
{
|
||||
_modelToGameObjectMap[buttonModel] = itemUIObject;
|
||||
processor.SetupButtonInteractions(buttonModel, itemUIObject, this);
|
||||
|
||||
// 모델 상태 변경 이벤트 구독 (공통)
|
||||
buttonModel.OnStateChanged += () => processor.UpdateCommonButtonVisuals(buttonModel, itemUIObject, this);
|
||||
|
||||
// 토글 버튼/라디오 버튼의 경우 추가적인 이벤트 구독
|
||||
if (buttonModel is ToolbarToggleButton toggleModel) // ToolbarRadioButton도 ToolbarToggleButton을 상속
|
||||
{
|
||||
toggleModel.OnToggleStateChanged += (isSelected) => processor.UpdateToggleStateVisuals(toggleModel, itemUIObject, isSelected, this);
|
||||
}
|
||||
|
||||
// 툴팁 핸들러 추가 및 설정
|
||||
if (!string.IsNullOrEmpty(buttonModel.Tooltip))
|
||||
{
|
||||
TooltipHandler tooltipHandler = itemUIObject.GetComponent<TooltipHandler>();
|
||||
if (tooltipHandler == null) tooltipHandler = itemUIObject.AddComponent<TooltipHandler>();
|
||||
|
||||
tooltipHandler.Tooltip = buttonModel.Tooltip;
|
||||
if (TooltipManager.Instance != null && TooltipManager.Instance.IsInitialized)
|
||||
{
|
||||
tooltipHandler.OnPointerEnterAction = TooltipManager.Instance.HandlePointerEnter;
|
||||
tooltipHandler.OnPointerExitAction = TooltipManager.Instance.HandlePointerExit;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"ToolbarView: {buttonModel.GetType().Name}의 UI를 생성하지 못했습니다 (Processor 반환 null).", this);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"ToolbarView: {buttonModel.GetType().Name}에 대한 프리팹이 할당되지 않았거나 알 수 없는 버튼 타입입니다.", this);
|
||||
continue; // 이 버튼은 건너뜀
|
||||
}
|
||||
|
||||
// 2. 모델-UI 매핑 및 모델 상태 변경 구독
|
||||
_modelToGameObjectMap[buttonModel] = itemUIObject;
|
||||
// 모델의 OnStateChanged 이벤트가 발생하면 UpdateItemVisuals 메서드를 호출하여 UI를 업데이트합니다.
|
||||
// 람다 표현식에서 buttonModel을 직접 클로저로 캡처합니다.
|
||||
buttonModel.OnStateChanged += () => UpdateItemVisuals(buttonModel);
|
||||
|
||||
// 3. 버튼 UI 초기 설정 및 사용자 상호작용(이벤트) 바인딩
|
||||
SetupButtonVisualsAndInteractions(buttonModel, itemUIObject);
|
||||
|
||||
// 4. 툴팁 핸들러 추가 및 설정
|
||||
if (!string.IsNullOrEmpty(buttonModel.TooltipKey))
|
||||
{
|
||||
TooltipHandler tooltipHandler = itemUIObject.GetComponent<TooltipHandler>();
|
||||
if (tooltipHandler == null) tooltipHandler = itemUIObject.AddComponent<TooltipHandler>();
|
||||
|
||||
tooltipHandler.Tooltip = buttonModel.TooltipKey; // 툴팁 내용 또는 키 전달
|
||||
// TooltipManager의 이벤트 핸들러 연결
|
||||
if (TooltipManager.Instance != null && TooltipManager.Instance.IsInitialized)
|
||||
{
|
||||
tooltipHandler.OnPointerEnterAction = TooltipManager.Instance.HandlePointerEnter;
|
||||
tooltipHandler.OnPointerExitAction = TooltipManager.Instance.HandlePointerExit;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -308,213 +379,56 @@ namespace UVC.UI.Toolbar
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 버튼 모델(ToolbarButtonBase)과 해당 UI GameObject를 받아,
|
||||
/// 버튼의 초기 시각적 요소(텍스트, 아이콘, 활성화 상태)를 설정하고,
|
||||
/// UI 상호작용(예: 클릭) 시 모델의 메서드가 호출되도록 이벤트를 연결합니다.
|
||||
/// </summary>
|
||||
/// <param name="model">설정할 버튼의 데이터 모델입니다.</param>
|
||||
/// <param name="itemObj">모델에 해당하는, 화면에 표시될 UI GameObject입니다.</param>
|
||||
protected void SetupButtonVisualsAndInteractions(ToolbarButtonBase model, GameObject itemObj)
|
||||
{
|
||||
// 1. 공통 UI 요소(텍스트, 아이콘, 활성화 상태) 초기 업데이트
|
||||
UpdateCommonButtonVisuals(model, itemObj);
|
||||
|
||||
// 2. 버튼 타입별 특화된 UI 요소 설정 및 이벤트 바인딩// 2. 버튼 타입별 특화된 UI 요소 설정 및 이벤트 바인딩
|
||||
if (model is ToolbarRadioButton radioModel)
|
||||
{
|
||||
Toggle toggleComponent = itemObj.GetComponent<Toggle>(); // 라디오 버튼 프리팹에는 Toggle 컴포넌트가 있어야 함
|
||||
if (toggleComponent != null)
|
||||
{
|
||||
// UnityEngine.UI.ToggleGroup 가져오거나 생성하여 할당
|
||||
ToggleGroup uiToggleGroup = GetOrCreateToggleGroup(radioModel.GroupName);
|
||||
toggleComponent.group = uiToggleGroup;
|
||||
|
||||
// 초기 선택 상태 설정 (UI 이벤트 발생 없이)
|
||||
toggleComponent.SetIsOnWithoutNotify(radioModel.IsSelected);
|
||||
|
||||
// UI 토글 값 변경(사용자 클릭) 시 모델 업데이트
|
||||
toggleComponent.onValueChanged.AddListener((isSelected) =>
|
||||
{
|
||||
// 사용자가 UI를 직접 클릭하여 상태를 변경한 경우
|
||||
if (isSelected) // 라디오 버튼은 선택될 때만 모델 업데이트 요청
|
||||
{
|
||||
// 모델의 ExecuteClick을 호출하여 그룹 내 선택 로직 및 커맨드 실행을 트리거합니다.
|
||||
// 파라미터로 true (선택됨) 또는 모델 자체를 전달할 수 있습니다.
|
||||
radioModel.ExecuteClick(true);
|
||||
}
|
||||
});
|
||||
|
||||
// 모델의 IsSelected 상태 변경(OnToggleStateChanged 이벤트) 시 UI 업데이트
|
||||
// 이 이벤트는 모델의 IsSelected 속성이 코드에 의해 변경될 때 발생합니다.
|
||||
radioModel.OnToggleStateChanged += (isSelected) => UpdateToggleVisuals(radioModel, isSelected);
|
||||
}
|
||||
else Debug.LogError($"ToolbarView: RadioButton '{model.Text}'의 GameObject에 Toggle 컴포넌트가 없습니다.", itemObj);
|
||||
}
|
||||
else if (model is ToolbarToggleButton toggleModel)
|
||||
{
|
||||
Toggle toggleComponent = itemObj.GetComponent<Toggle>(); // 토글 버튼 프리팹에도 Toggle 컴포넌트 필요
|
||||
if (toggleComponent != null)
|
||||
{
|
||||
toggleComponent.SetIsOnWithoutNotify(toggleModel.IsSelected);
|
||||
toggleComponent.onValueChanged.AddListener((isSelected) =>
|
||||
{
|
||||
// 사용자가 UI 토글을 클릭하면 모델의 ExecuteClick을 호출합니다.
|
||||
// ExecuteClick 내부에서 IsSelected가 변경되고 관련 이벤트/콜백이 호출됩니다.
|
||||
toggleModel.ExecuteClick();
|
||||
});
|
||||
toggleModel.OnToggleStateChanged += (isSelected) => UpdateToggleVisuals(toggleModel, isSelected);
|
||||
}
|
||||
else Debug.LogError($"ToolbarView: ToggleButton '{model.Text}'의 GameObject에 Toggle 컴포넌트가 없습니다.", itemObj);
|
||||
}
|
||||
else if (model is ToolbarExpandableButton expandableModel)
|
||||
{
|
||||
Button uiButton = itemObj.GetComponent<Button>(); // 확장 버튼 프리팹에는 Button 컴포넌트 필요
|
||||
if (uiButton != null)
|
||||
{
|
||||
uiButton.onClick.AddListener(() =>
|
||||
{
|
||||
expandableModel.ExecuteClick(); // 주 버튼의 커맨드 실행 (있다면)
|
||||
ToggleSubMenu(expandableModel, itemObj); // 하위 메뉴 토글 (itemObj는 위치 기준으로 사용)
|
||||
});
|
||||
}
|
||||
else Debug.LogError($"ToolbarView: ExpandableButton '{model.Text}'의 GameObject에 Button 컴포넌트가 없습니다.", itemObj);
|
||||
}
|
||||
else if (model is ToolbarStandardButton standardModel)
|
||||
{
|
||||
Button uiButton = itemObj.GetComponent<Button>(); // 표준 버튼 프리팹에도 Button 컴포넌트 필요
|
||||
if (uiButton != null)
|
||||
{
|
||||
uiButton.onClick.AddListener(() =>
|
||||
{
|
||||
// 표준 버튼 클릭 시 모델의 ExecuteClick 호출.
|
||||
// 파라미터로 버튼 텍스트(또는 다른 식별자)를 전달할 수 있으나,
|
||||
// ClickCommand가 파라미터를 받는 형태로 정의되어 있어야 합니다.
|
||||
// 여기서는 standardModel.Text를 전달하는 예시입니다.
|
||||
standardModel.ExecuteClick(standardModel.Text);
|
||||
});
|
||||
}
|
||||
else Debug.LogError($"ToolbarView: StandardButton '{model.Text}'의 GameObject에 Button 컴포넌트가 없습니다.", itemObj);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 버튼 모델의 상태(Text, IconSpritePath, IsEnabled 등)가 변경되었을 때 호출되어,
|
||||
/// 해당 버튼의 모든 관련 UI 시각적 요소를 업데이트합니다.
|
||||
/// 이 메서드는 주로 모델의 OnStateChanged 이벤트에 의해 호출됩니다.
|
||||
/// </summary>
|
||||
/// <param name="model">상태가 변경된 버튼의 모델입니다.</param>
|
||||
protected void UpdateItemVisuals(ToolbarButtonBase model)
|
||||
{
|
||||
if (_modelToGameObjectMap.TryGetValue(model, out GameObject itemObj))
|
||||
{
|
||||
// 1. 공통 시각적 요소(텍스트, 아이콘, 활성화 상태) 업데이트
|
||||
UpdateCommonButtonVisuals(model, itemObj);
|
||||
|
||||
// 2. 타입별 특화된 UI 업데이트 (예: Toggle 컴포넌트의 isOn 상태)
|
||||
if (model is ToolbarToggleButton tb) // ToolbarRadioButton도 ToolbarToggleButton을 상속하므로 여기에 해당
|
||||
{
|
||||
Toggle toggleComponent = itemObj.GetComponent<Toggle>();
|
||||
if (toggleComponent != null)
|
||||
{
|
||||
// UI의 현재 상태와 모델의 상태가 다를 때만 UI를 업데이트하여 불필요한 이벤트 발생 방지
|
||||
if (toggleComponent.isOn != tb.IsSelected)
|
||||
{
|
||||
toggleComponent.SetIsOnWithoutNotify(tb.IsSelected);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 다른 버튼 타입에 대한 추가적인 시각적 업데이트 로직이 필요하면 여기에 추가
|
||||
}
|
||||
// else: 모델에 해당하는 GameObject를 찾지 못한 경우 (오류 상황일 수 있음)
|
||||
// Debug.LogWarning($"ToolbarView: UpdateItemVisuals - 모델 '{model.Text}'에 대한 GameObject를 찾을 수 없습니다.", this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 특정 토글 버튼 또는 라디오 버튼의 IsSelected 상태가 모델에서 변경되었을 때 호출됩니다.
|
||||
/// 해당 UI Toggle 컴포넌트의 isOn 상태를 모델의 IsSelected 값과 동기화합니다.
|
||||
/// 이 메서드는 주로 모델의 OnToggleStateChanged 이벤트에 의해 호출됩니다.
|
||||
/// </summary>
|
||||
/// <param name="model">IsSelected 상태가 변경된 토글/라디오 버튼의 모델입니다.</param>
|
||||
/// <param name="isSelected">모델의 새로운 IsSelected 값입니다.</param>
|
||||
protected void UpdateToggleVisuals(ToolbarToggleButton model, bool isSelected)
|
||||
{
|
||||
if (_modelToGameObjectMap.TryGetValue(model, out GameObject itemObj))
|
||||
{
|
||||
Toggle toggleComponent = itemObj.GetComponent<Toggle>();
|
||||
if (toggleComponent != null)
|
||||
{
|
||||
if (toggleComponent.isOn != isSelected) // UI와 모델 상태가 다를 때만 업데이트
|
||||
{
|
||||
toggleComponent.SetIsOnWithoutNotify(isSelected);
|
||||
}
|
||||
}
|
||||
}
|
||||
// else: Debug.LogWarning($"ToolbarView: UpdateToggleVisuals - 모델 '{model.Text}'에 대한 GameObject를 찾을 수 없습니다.", this);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 버튼 모델과 UI GameObject를 기반으로 공통적인 시각적 요소(텍스트, 아이콘, 활성화 상태)를 업데이트합니다.
|
||||
/// 이 메서드는 각 IButtonViewProcessor 구현체에서 호출됩니다.
|
||||
/// </summary>
|
||||
/// <param name="model">업데이트할 버튼의 데이터 모델입니다.</param>
|
||||
/// <param name="itemObj">업데이트할 UI GameObject입니다.</param>
|
||||
protected void UpdateCommonButtonVisuals(ToolbarButtonBase model, GameObject itemObj)
|
||||
internal void InternalUpdateCommonButtonVisuals(ToolbarButtonBase model, GameObject itemObj)
|
||||
{
|
||||
if (model == null || itemObj == null) return;
|
||||
|
||||
// 1. 텍스트 업데이트 (TextMeshProUGUI 사용 가정)
|
||||
// 프리팹 내부에 TextMeshProUGUI 컴포넌트를 가진 자식 오브젝트가 있다고 가정합니다.
|
||||
// 이름으로 찾거나, GetComponentInChildren을 사용할 수 있습니다. 여기서는 후자를 사용합니다.
|
||||
TextMeshProUGUI buttonTextComponent = itemObj.GetComponentInChildren<TextMeshProUGUI>(true); // true: 비활성 자식도 검색
|
||||
// 1. 텍스트 업데이트
|
||||
TextMeshProUGUI buttonTextComponent = itemObj.GetComponentInChildren<TextMeshProUGUI>(true);
|
||||
if (buttonTextComponent != null)
|
||||
{
|
||||
string displayText = model.Text;
|
||||
// LocalizationManager가 있고, model.Text가 비어있지 않다면 다국어 처리 시도
|
||||
if (LocalizationManager.Instance != null && !string.IsNullOrEmpty(model.Text))
|
||||
{
|
||||
displayText = LocalizationManager.Instance.GetString(model.Text, model.Text); // 키가 없으면 키 자체를 반환하도록 설정
|
||||
displayText = LocalizationManager.Instance.GetString(model.Text, model.Text);
|
||||
}
|
||||
buttonTextComponent.text = displayText;
|
||||
// 텍스트가 없으면 비활성화 (선택적)
|
||||
// buttonTextComponent.gameObject.SetActive(!string.IsNullOrEmpty(displayText));
|
||||
}
|
||||
|
||||
// 2. 아이콘 업데이트 (Image 컴포넌트 사용 가정)
|
||||
// 프리팹 내부에 "Icon"이라는 이름을 가진 자식 GameObject에 Image 컴포넌트가 있다고 가정합니다.
|
||||
// 또는 GetComponentInChildren<Image>를 사용하여 첫 번째 Image 컴포넌트를 찾을 수도 있습니다.
|
||||
// 2. 아이콘 업데이트
|
||||
Image iconImageComponent = null;
|
||||
Transform iconTransform = itemObj.transform.Find("Icon"); // 이름으로 먼저 찾아봄
|
||||
Transform iconTransform = itemObj.transform.Find("Icon");
|
||||
if (iconTransform != null) iconImageComponent = iconTransform.GetComponent<Image>();
|
||||
if (iconImageComponent == null) iconImageComponent = itemObj.GetComponentInChildren<Image>(true); // 못찾으면 자식에서 검색
|
||||
if (iconImageComponent == null) iconImageComponent = itemObj.GetComponentInChildren<Image>(true);
|
||||
|
||||
if (iconImageComponent != null)
|
||||
{
|
||||
string iconPathToLoad = model.IconSpritePath; // 기본적으로 선택/활성 상태 아이콘 경로
|
||||
|
||||
// 토글 버튼 또는 라디오 버튼의 경우, IsSelected 상태에 따라 다른 아이콘 경로 사용
|
||||
if (model is ToolbarToggleButton toggleButton) // ToolbarRadioButton도 ToolbarToggleButton을 상속
|
||||
string iconPathToLoad = model.IconSpritePath;
|
||||
if (model is ToolbarToggleButton toggleButton)
|
||||
{
|
||||
iconPathToLoad = toggleButton.IsSelected ? toggleButton.IconSpritePath : toggleButton.OffIconSpritePath;
|
||||
}
|
||||
// (ToolbarRadioButton에 대한 특별 처리는 ToolbarToggleButton에서 이미 커버됨)
|
||||
|
||||
if (!string.IsNullOrEmpty(iconPathToLoad))
|
||||
{
|
||||
Sprite iconSprite = LoadSpriteFromResources(iconPathToLoad);
|
||||
iconImageComponent.sprite = iconSprite;
|
||||
iconImageComponent.enabled = (iconSprite != null); // 스프라이트가 있어야 활성화
|
||||
iconImageComponent.enabled = (iconSprite != null);
|
||||
}
|
||||
else
|
||||
{
|
||||
iconImageComponent.sprite = null; // 아이콘 경로 없으면 스프라이트 제거
|
||||
iconImageComponent.enabled = false; // 비활성화
|
||||
iconImageComponent.sprite = null;
|
||||
iconImageComponent.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 활성화 상태(interactable) 업데이트
|
||||
// 버튼 UI GameObject에 Selectable (Button, Toggle 등) 컴포넌트가 있다고 가정합니다.
|
||||
Selectable selectableComponent = itemObj.GetComponent<Selectable>();
|
||||
if (selectableComponent != null)
|
||||
{
|
||||
@@ -529,7 +443,7 @@ namespace UVC.UI.Toolbar
|
||||
/// </summary>
|
||||
/// <param name="groupName">찾거나 생성할 토글 그룹의 이름입니다.</param>
|
||||
/// <returns>해당 이름의 ToggleGroup 컴포넌트입니다.</returns>
|
||||
protected ToggleGroup GetOrCreateToggleGroup(string groupName)
|
||||
internal ToggleGroup GetOrCreateToggleGroup(string groupName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(groupName))
|
||||
{
|
||||
@@ -577,7 +491,7 @@ namespace UVC.UI.Toolbar
|
||||
/// </summary>
|
||||
/// <param name="expandableButtonModel">하위 버튼 목록을 가진 확장 버튼 모델입니다.</param>
|
||||
/// <param name="expandableButtonObj">주 확장 버튼의 UI GameObject로, 하위 메뉴 위치 결정에 사용됩니다.</param>
|
||||
protected void ToggleSubMenu(ToolbarExpandableButton expandableButtonModel, GameObject expandableButtonObj)
|
||||
internal void ToggleSubMenu(ToolbarExpandableButton expandableButtonModel, GameObject expandableButtonObj)
|
||||
{
|
||||
// 이미 다른 하위 메뉴가 열려있거나, 현재 클릭한 버튼의 하위 메뉴가 열려있다면 닫습니다.
|
||||
if (currentSubMenu != null)
|
||||
@@ -648,13 +562,13 @@ namespace UVC.UI.Toolbar
|
||||
|
||||
// 패널 위치를 확장 버튼의 위치에 맞춥니다.
|
||||
Vector2 offset = new Vector2(expandableButtonRect.anchoredPosition.x, expandableButtonRect.anchoredPosition.y);
|
||||
if(layoutGroup is VerticalLayoutGroup)
|
||||
if (layoutGroup is VerticalLayoutGroup)
|
||||
{
|
||||
offset.x += expandableButtonRect.rect.width; // 수직 레이아웃인 경우 버튼 오른쪽에 표시 되도록
|
||||
}
|
||||
else
|
||||
{
|
||||
if(subMenuLayoutGroup != null) offset.x -= subMenuLayoutGroup.padding.left; // 수평 레이아웃인 경우 패딩을 고려
|
||||
{
|
||||
if (subMenuLayoutGroup != null) offset.x -= subMenuLayoutGroup.padding.left; // 수평 레이아웃인 경우 패딩을 고려
|
||||
offset.y -= expandableButtonRect.rect.height; // 수평 레이아웃인 경우 버튼 아래에 표시 되도록
|
||||
}
|
||||
panelRect.anchoredPosition = offset; // 위치 조정
|
||||
@@ -664,62 +578,83 @@ namespace UVC.UI.Toolbar
|
||||
{
|
||||
if (subItemBase is ToolbarButtonBase subItemModel) // 모든 하위 아이템은 ToolbarButtonBase라고 가정
|
||||
{
|
||||
IButtonViewProcessor subProcessor = GetButtonViewProcessor(subItemModel.GetType());
|
||||
// 하위 버튼도 적절한 프리팹을 사용해야 합니다.
|
||||
// 여기서는 모든 하위 버튼이 standardButtonPrefab을 사용한다고 가정합니다.
|
||||
// 실제로는 subItemModel의 타입에 따라 다른 프리팹을 선택할 수 있습니다.
|
||||
GameObject subButtonPrefabToUse = standardButtonPrefab; // 기본값
|
||||
if (subItemModel is ToolbarToggleButton) subButtonPrefabToUse = toggleButtonPrefab;
|
||||
// ... 다른 타입에 대한 처리 ...
|
||||
|
||||
if (subButtonPrefabToUse == null)
|
||||
if (subProcessor != null) // 하위 버튼도 Processor를 통해 생성 시도
|
||||
{
|
||||
Debug.LogError($"ToolbarView: 하위 버튼 '{subItemModel.Text}'에 대한 프리팹을 결정할 수 없습니다 (standardButtonPrefab 사용 시도).", this);
|
||||
continue;
|
||||
}
|
||||
if (subItemModel is ToolbarToggleButton) subButtonPrefabToUse = toggleButtonPrefab;
|
||||
else subButtonPrefabToUse = standardButtonPrefab; // 기본은 표준 버튼
|
||||
|
||||
GameObject subButtonObj = Instantiate(subButtonPrefabToUse, panelRect); // 하위 메뉴 패널의 자식으로 생성
|
||||
subButtonObj.name = $"SubItem_{subItemModel.Text}";
|
||||
|
||||
// 하위 버튼의 시각적 요소 설정 및 상호작용 연결
|
||||
UpdateCommonButtonVisuals(subItemModel, subButtonObj); // 공통 UI 업데이트
|
||||
|
||||
// 하위 버튼 클릭 이벤트 연결
|
||||
Button subUiButton = subButtonObj.GetComponent<Button>(); // 또는 Toggle 등 타입에 맞는 컴포넌트
|
||||
if (subUiButton != null)
|
||||
{
|
||||
subUiButton.interactable = subItemModel.IsEnabled; // 상호작용 상태 설정
|
||||
subUiButton.onClick.AddListener(() =>
|
||||
// ... 다른 타입에 대한 처리 ...
|
||||
if (subButtonPrefabToUse == null)
|
||||
{
|
||||
// 1. 주 확장 버튼 모델에 하위 버튼 선택 알림 (주 버튼 모양 업데이트 등)
|
||||
// SelectSubButton의 두 번째 파라미터(GameObject)는 제거되었으므로, 모델만 전달
|
||||
expandableButtonModel.SelectSubButton(subItemModel); // 모델 업데이트 및 주 버튼 외형 변경 요청
|
||||
Debug.LogError($"ToolbarView: 하위 버튼 '{subItemModel.Text}'에 대한 프리팹을 결정할 수 없습니다 (standardButtonPrefab 사용 시도).", this);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2. 선택된 하위 버튼 자체의 커맨드 실행
|
||||
subItemModel.ExecuteClick(subItemModel.Text); // 하위 버튼의 Command 실행
|
||||
GameObject subButtonObj = Instantiate(subButtonPrefabToUse, panelRect); // 하위 메뉴 패널의 자식으로 생성
|
||||
subButtonObj.name = $"SubItem_{subItemModel.Text}";
|
||||
|
||||
// 3. 하위 메뉴 닫기
|
||||
Destroy(currentSubMenu);
|
||||
currentSubMenu = null;
|
||||
// 하위 버튼의 시각적 요소 설정 및 상호작용 연결
|
||||
InternalUpdateCommonButtonVisuals(subItemModel, subButtonObj); // 공통 UI 업데이트
|
||||
|
||||
// 4. 툴팁 숨기기 (하위 메뉴가 닫힐 때 관련 툴팁도 숨김)
|
||||
if (TooltipManager.Instance != null && TooltipManager.Instance.IsInitialized) TooltipManager.Instance.HandlePointerExit();
|
||||
});
|
||||
// 하위 버튼 클릭 이벤트 연결
|
||||
Button subUiButton = subButtonObj.GetComponent<Button>(); // 또는 Toggle 등 타입에 맞는 컴포넌트
|
||||
Toggle subUiToggle = subButtonObj.GetComponent<Toggle>();
|
||||
if (subUiButton != null)
|
||||
{
|
||||
subUiButton.interactable = subItemModel.IsEnabled; // 상호작용 상태 설정
|
||||
subUiButton.onClick.AddListener(() =>
|
||||
{
|
||||
// 1. 주 확장 버튼 모델에 하위 버튼 선택 알림 (주 버튼 모양 업데이트 등)
|
||||
// SelectSubButton의 두 번째 파라미터(GameObject)는 제거되었으므로, 모델만 전달
|
||||
expandableButtonModel.SelectSubButton(subItemModel); // 모델 업데이트 및 주 버튼 외형 변경 요청
|
||||
|
||||
// 2. 선택된 하위 버튼 자체의 커맨드 실행
|
||||
subItemModel.ExecuteClick(subItemModel.Text); // 하위 버튼의 Command 실행
|
||||
|
||||
// 3. 하위 메뉴 닫기
|
||||
Destroy(currentSubMenu);
|
||||
currentSubMenu = null;
|
||||
|
||||
// 4. 툴팁 숨기기 (하위 메뉴가 닫힐 때 관련 툴팁도 숨김)
|
||||
if (TooltipManager.Instance != null && TooltipManager.Instance.IsInitialized) TooltipManager.Instance.HandlePointerExit();
|
||||
});
|
||||
}
|
||||
else if (subUiToggle != null && subItemModel is ToolbarToggleButton subToggleModel) // 하위 아이템이 토글 버튼인 경우
|
||||
{
|
||||
subUiToggle.interactable = subToggleModel.IsEnabled;
|
||||
subUiToggle.SetIsOnWithoutNotify(subToggleModel.IsSelected);
|
||||
subUiToggle.onValueChanged.AddListener((isSelected) =>
|
||||
{
|
||||
// 하위 토글 버튼은 보통 클릭 시 바로 액션 실행 및 메뉴 닫힘
|
||||
expandableButtonModel.SelectSubButton(subToggleModel); // 주 버튼 모양 업데이트
|
||||
subToggleModel.ExecuteClick(); // 하위 버튼 커맨드 실행 (내부에서 IsSelected 변경)
|
||||
Destroy(currentSubMenu);
|
||||
currentSubMenu = null;
|
||||
if (TooltipManager.Instance != null) TooltipManager.Instance.HideTooltip();
|
||||
});
|
||||
}
|
||||
|
||||
// 하위 버튼 툴팁 처리
|
||||
if (!string.IsNullOrEmpty(subItemModel.Tooltip))
|
||||
{
|
||||
TooltipHandler tooltipHandler = subButtonObj.GetComponent<TooltipHandler>();
|
||||
if (tooltipHandler == null) tooltipHandler = subButtonObj.AddComponent<TooltipHandler>();
|
||||
|
||||
tooltipHandler.Tooltip = subItemModel.Tooltip;
|
||||
tooltipHandler.OnPointerEnterAction = TooltipManager.Instance.HandlePointerEnter;
|
||||
tooltipHandler.OnPointerExitAction = TooltipManager.Instance.HandlePointerExit;
|
||||
}
|
||||
|
||||
// 하위 버튼 모델의 상태 변경도 구독하여 UI 업데이트 (선택적 확장)
|
||||
// subItemModel.OnStateChanged += () => UpdateCommonButtonVisuals(subItemModel, subButtonObj);
|
||||
// 이 경우, _modelToGameObjectMap에 하위 버튼도 추가하고 ClearToolbar에서 정리해야 함.
|
||||
}
|
||||
|
||||
// 하위 버튼 툴팁 처리
|
||||
if (!string.IsNullOrEmpty(subItemModel.TooltipKey))
|
||||
{
|
||||
TooltipHandler tooltipHandler = subButtonObj.GetComponent<TooltipHandler>();
|
||||
if (tooltipHandler == null) tooltipHandler = subButtonObj.AddComponent<TooltipHandler>();
|
||||
|
||||
tooltipHandler.Tooltip = subItemModel.TooltipKey;
|
||||
tooltipHandler.OnPointerEnterAction = TooltipManager.Instance.HandlePointerEnter;
|
||||
tooltipHandler.OnPointerExitAction = TooltipManager.Instance.HandlePointerExit;
|
||||
}
|
||||
|
||||
// 하위 버튼 모델의 상태 변경도 구독하여 UI 업데이트 (선택적 확장)
|
||||
// subItemModel.OnStateChanged += () => UpdateCommonButtonVisuals(subItemModel, subButtonObj);
|
||||
// 이 경우, _modelToGameObjectMap에 하위 버튼도 추가하고 ClearToolbar에서 정리해야 함.
|
||||
}
|
||||
}
|
||||
|
||||
2
Assets/Scripts/UVC/UI/ToolBar/View/ToolbarView.cs.meta
Normal file
2
Assets/Scripts/UVC/UI/ToolBar/View/ToolbarView.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2eb6cd37a2c94ca48b031d1a9c160e46
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d72ec0e29e760440b1badbdf4b051f2
|
||||
@@ -89,13 +89,13 @@ namespace UVC.UI.Tooltip
|
||||
/// <summary>
|
||||
/// 지정된 시간(TooltipDelay)만큼 대기한 후, OnPointerEnterAction을 호출하여 툴팁 표시를 요청하는 코루틴입니다.
|
||||
/// </summary>
|
||||
/// <param name="tooltipKey">표시할 툴팁 내용 또는 다국어 키입니다.</param>
|
||||
/// <param name="tooltip">표시할 툴팁 내용 또는 다국어 키입니다.</param>
|
||||
/// <param name="mousePosition">현재 마우스 포인터의 화면 좌표입니다.</param>
|
||||
private IEnumerator ShowTooltipAfterDelayCoroutine(string tooltipKey, Vector3 mousePosition)
|
||||
private IEnumerator ShowTooltipAfterDelayCoroutine(string tooltip, Vector3 mousePosition)
|
||||
{
|
||||
yield return new WaitForSeconds(TooltipDelay); // 지정된 시간만큼 대기
|
||||
_showTooltipCoroutine = null; // 코루틴 완료 후 참조 null 처리
|
||||
OnPointerEnterAction?.Invoke(tooltipKey, mousePosition); // 연결된 액션 호출 (TooltipManager.HandlePointerEnter)
|
||||
OnPointerEnterAction?.Invoke(tooltip, mousePosition); // 연결된 액션 호출 (TooltipManager.HandlePointerEnter)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user