Files
XRLib/Assets/Sample/UIToolkit/UTKColorPickerSample.cs
2026-02-23 19:38:27 +09:00

396 lines
14 KiB
C#

#nullable enable
using System;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UIElements;
using UVC.UIToolkit;
namespace UVC.Sample.UIToolkit
{
/// <summary>
/// UTKColorPicker 샘플 코드
/// 버튼 클릭으로 컬러 피커를 열고 선택된 색상을 미리보기에 표시
/// </summary>
public class UTKColorPickerSample : MonoBehaviour
{
[SerializeField] private UIDocument? _uiDocument;
[SerializeField]
[Tooltip("시작 시 적용할 테마")]
private UTKTheme initialTheme = UTKTheme.Dark;
private UTKToggle _themeToggle;
private VisualElement? _root;
private VisualElement? _colorPreview;
private Label? _colorLabel;
private Toggle? _useAlphaToggle;
private Color _currentColor = Color.blue;
private UTKColorPicker? _currentPicker;
private void Start()
{
// UIDocument 참조 확인
var doc = GetComponent<UIDocument>();
if (doc == null)
{
Debug.LogError("UIDocument가 할당되지 않았습니다.");
return;
}
_uiDocument = doc;
var toggle = _uiDocument.rootVisualElement.Q<UTKToggle>("toggle");
if (toggle == null)
{
Debug.LogError("UXML에서 UTKToggle을 찾을 수 없습니다.");
return;
}
_themeToggle = toggle;
UTKThemeManager.Instance.RegisterRoot(_uiDocument.rootVisualElement);
UTKThemeManager.Instance.SetTheme(initialTheme);
_themeToggle.OnValueChanged += (isOn) =>
{
UTKThemeManager.Instance.SetTheme(!isOn ? UTKTheme.Dark : UTKTheme.Light);
};
_root = _uiDocument.rootVisualElement;
UTKColorPicker.SetRoot(_root);
CreateSampleUI();
}
private void CreateSampleUI()
{
if (_root == null) return;
// 메인 컨테이너
var container = new VisualElement();
container.style.position = Position.Absolute;
container.style.left = 20;
container.style.top = 20;
container.style.backgroundColor = new Color(0.2f, 0.2f, 0.2f);
container.style.borderTopLeftRadius = 8;
container.style.borderTopRightRadius = 8;
container.style.borderBottomLeftRadius = 8;
container.style.borderBottomRightRadius = 8;
container.style.paddingTop = 15;
container.style.paddingBottom = 15;
container.style.paddingLeft = 15;
container.style.paddingRight = 15;
container.style.width = 280;
// 타이틀
var title = new Label("UTKColorPicker Sample");
title.style.fontSize = 16;
title.style.unityFontStyleAndWeight = FontStyle.Bold;
title.style.color = Color.white;
title.style.marginBottom = 15;
container.Add(title);
// 색상 미리보기 영역
var previewRow = new VisualElement();
previewRow.style.flexDirection = FlexDirection.Row;
previewRow.style.alignItems = Align.Center;
previewRow.style.marginBottom = 15;
var previewLabel = new Label("Current Color:");
previewLabel.style.color = Color.white;
previewLabel.style.width = 100;
previewRow.Add(previewLabel);
_colorPreview = new VisualElement();
_colorPreview.style.width = 60;
_colorPreview.style.height = 30;
_colorPreview.style.backgroundColor = _currentColor;
_colorPreview.style.borderTopLeftRadius = 4;
_colorPreview.style.borderTopRightRadius = 4;
_colorPreview.style.borderBottomLeftRadius = 4;
_colorPreview.style.borderBottomRightRadius = 4;
_colorPreview.style.borderTopWidth = 1;
_colorPreview.style.borderBottomWidth = 1;
_colorPreview.style.borderLeftWidth = 1;
_colorPreview.style.borderRightWidth = 1;
_colorPreview.style.borderTopColor = new Color(0.4f, 0.4f, 0.4f);
_colorPreview.style.borderBottomColor = new Color(0.4f, 0.4f, 0.4f);
_colorPreview.style.borderLeftColor = new Color(0.4f, 0.4f, 0.4f);
_colorPreview.style.borderRightColor = new Color(0.4f, 0.4f, 0.4f);
previewRow.Add(_colorPreview);
_colorLabel = new Label(ColorToHex(_currentColor));
_colorLabel.style.color = new Color(0.7f, 0.7f, 0.7f);
_colorLabel.style.marginLeft = 10;
previewRow.Add(_colorLabel);
container.Add(previewRow);
// Alpha 사용 토글
var alphaRow = new VisualElement();
alphaRow.style.flexDirection = FlexDirection.Row;
alphaRow.style.alignItems = Align.Center;
alphaRow.style.marginBottom = 15;
_useAlphaToggle = new Toggle("Use Alpha Channel");
_useAlphaToggle.value = true;
_useAlphaToggle.style.color = Color.white;
alphaRow.Add(_useAlphaToggle);
container.Add(alphaRow);
// 버튼
var openPickerBtn = new Button(OpenColorPicker) { text = "Open Color Picker" };
openPickerBtn.style.height = 32;
openPickerBtn.style.marginBottom = 10;
container.Add(openPickerBtn);
// Async 버튼
var openPickerAsyncBtn = new Button(() => OpenColorPickerAsync().Forget()) { text = "Open Color Picker (Async)" };
openPickerAsyncBtn.style.height = 32;
openPickerAsyncBtn.style.marginBottom = 10;
container.Add(openPickerAsyncBtn);
// Alpha 프리셋 버튼들
var alphaPresetLabel = new Label("Alpha Presets:");
alphaPresetLabel.style.color = Color.white;
alphaPresetLabel.style.marginTop = 10;
alphaPresetLabel.style.marginBottom = 5;
container.Add(alphaPresetLabel);
var alphaPresetRow = new VisualElement();
alphaPresetRow.style.flexDirection = FlexDirection.Row;
alphaPresetRow.style.marginBottom = 10;
// Alpha 값이 다른 프리셋 버튼들
float[] alphaValues = { 1.0f, 0.75f, 0.5f, 0.25f };
foreach (var alpha in alphaValues)
{
var alphaBtn = new Button(() => SetColorWithAlpha(alpha));
alphaBtn.style.width = 50;
alphaBtn.style.height = 28;
alphaBtn.style.marginRight = 5;
alphaBtn.style.backgroundColor = new Color(0.3f, 0.3f, 0.3f);
alphaBtn.style.borderTopLeftRadius = 4;
alphaBtn.style.borderTopRightRadius = 4;
alphaBtn.style.borderBottomLeftRadius = 4;
alphaBtn.style.borderBottomRightRadius = 4;
alphaBtn.text = $"{(int)(alpha * 100)}%";
alphaBtn.style.fontSize = 11;
alphaPresetRow.Add(alphaBtn);
}
container.Add(alphaPresetRow);
// Alpha 활성화/비활성화 직접 호출 버튼들
var alphaControlLabel = new Label("Alpha Control Examples:");
alphaControlLabel.style.color = Color.white;
alphaControlLabel.style.marginTop = 5;
alphaControlLabel.style.marginBottom = 5;
container.Add(alphaControlLabel);
var alphaControlRow = new VisualElement();
alphaControlRow.style.flexDirection = FlexDirection.Row;
alphaControlRow.style.marginBottom = 10;
var withAlphaBtn = new Button(OpenColorPickerWithAlpha) { text = "With Alpha" };
withAlphaBtn.style.height = 28;
withAlphaBtn.style.flexGrow = 1;
withAlphaBtn.style.marginRight = 5;
alphaControlRow.Add(withAlphaBtn);
var withoutAlphaBtn = new Button(OpenColorPickerWithoutAlpha) { text = "Without Alpha" };
withoutAlphaBtn.style.height = 28;
withoutAlphaBtn.style.flexGrow = 1;
alphaControlRow.Add(withoutAlphaBtn);
container.Add(alphaControlRow);
// 프리셋 색상 버튼들
var presetLabel = new Label("Preset Colors:");
presetLabel.style.color = Color.white;
presetLabel.style.marginTop = 10;
presetLabel.style.marginBottom = 5;
container.Add(presetLabel);
var presetRow = new VisualElement();
presetRow.style.flexDirection = FlexDirection.Row;
presetRow.style.flexWrap = Wrap.Wrap;
Color[] presets = { Color.red, Color.green, Color.blue, Color.yellow, Color.cyan, Color.magenta, Color.white, Color.black };
foreach (var color in presets)
{
var presetBtn = new Button(() => SetColor(color));
presetBtn.style.width = 28;
presetBtn.style.height = 28;
presetBtn.style.marginRight = 5;
presetBtn.style.marginBottom = 5;
presetBtn.style.backgroundColor = color;
presetBtn.style.borderTopLeftRadius = 4;
presetBtn.style.borderTopRightRadius = 4;
presetBtn.style.borderBottomLeftRadius = 4;
presetBtn.style.borderBottomRightRadius = 4;
presetBtn.text = "";
presetRow.Add(presetBtn);
}
container.Add(presetRow);
_root.Add(container);
}
private void OpenColorPicker()
{
if (_root == null || _currentPicker != null) return;
bool useAlpha = _useAlphaToggle?.value ?? false;
_currentPicker = UTKColorPicker.Show(_currentColor, "Select Color", useAlpha);
_currentPicker.OnColorChanged += OnColorChanged;
_currentPicker.OnColorSelected += OnColorSelected;
}
/// <summary>
/// Alpha 채널 활성화 상태로 컬러 피커 열기
/// </summary>
private void OpenColorPickerWithAlpha()
{
if (_root == null || _currentPicker != null) return;
// useAlpha = true로 명시적 호출
_currentPicker = UTKColorPicker.Show(_currentColor, "Select Color (Alpha ON)", useAlpha: true);
_currentPicker.OnColorChanged += OnColorChanged;
_currentPicker.OnColorSelected += OnColorSelected;
Debug.Log("[Sample] ColorPicker opened with Alpha channel enabled");
}
/// <summary>
/// Alpha 채널 비활성화 상태로 컬러 피커 열기
/// </summary>
private void OpenColorPickerWithoutAlpha()
{
if (_root == null || _currentPicker != null) return;
// useAlpha = false로 명시적 호출
_currentPicker = UTKColorPicker.Show(_currentColor, "Select Color (Alpha OFF)", useAlpha: false);
_currentPicker.OnColorChanged += OnColorChanged;
_currentPicker.OnColorSelected += OnColorSelected;
Debug.Log("[Sample] ColorPicker opened without Alpha channel");
}
/// <summary>
/// 현재 색상의 Alpha 값을 변경
/// </summary>
private void SetColorWithAlpha(float alpha)
{
_currentColor = new Color(_currentColor.r, _currentColor.g, _currentColor.b, alpha);
if (_colorPreview != null)
{
_colorPreview.style.backgroundColor = _currentColor;
}
if (_colorLabel != null)
{
_colorLabel.text = ColorToHex(_currentColor);
}
Debug.Log($"[Sample] Alpha set to {(int)(alpha * 100)}% - Color: {ColorToHex(_currentColor)}");
}
private async UniTaskVoid OpenColorPickerAsync()
{
if (_root == null) return;
bool useAlpha = _useAlphaToggle?.value ?? true;
// ShowAsync를 사용하여 색상 선택 대기
// OK 클릭 시 선택된 색상 반환, 취소/닫기 시 _currentColor 반환
Color selectedColor = await UTKColorPicker.ShowAsync(_currentColor, "Select Color (Async)", useAlpha);
// 결과 처리
_currentColor = selectedColor;
if (_colorPreview != null)
{
_colorPreview.style.backgroundColor = selectedColor;
}
if (_colorLabel != null)
{
_colorLabel.text = ColorToHex(selectedColor);
}
Debug.Log($"[Async] Color Result: {ColorToHex(selectedColor)}");
}
private void OnColorChanged(Color color)
{
// 실시간 미리보기 업데이트
if (_colorPreview != null)
{
_colorPreview.style.backgroundColor = color;
}
if (_colorLabel != null)
{
_colorLabel.text = ColorToHex(color);
}
}
private void OnColorSelected(Color color)
{
_currentColor = color;
Debug.Log($"Color Selected: {ColorToHex(color)}");
// 피커 참조 정리
if (_currentPicker != null)
{
_currentPicker.OnColorChanged -= OnColorChanged;
_currentPicker.OnColorSelected -= OnColorSelected;
_currentPicker = null;
}
}
private void SetColor(Color color)
{
_currentColor = color;
if (_colorPreview != null)
{
_colorPreview.style.backgroundColor = color;
}
if (_colorLabel != null)
{
_colorLabel.text = ColorToHex(color);
}
Debug.Log($"Preset Color Set: {ColorToHex(color)}");
}
private string ColorToHex(Color color)
{
bool useAlpha = _useAlphaToggle?.value ?? false;
if (useAlpha)
{
return "#" + ColorUtility.ToHtmlStringRGBA(color);
}
return "#" + ColorUtility.ToHtmlStringRGB(color);
}
private void OnDestroy()
{
if (_currentPicker != null)
{
_currentPicker.OnColorChanged -= OnColorChanged;
_currentPicker.OnColorSelected -= OnColorSelected;
_currentPicker.Dispose();
_currentPicker = null;
}
}
}
}