279 lines
9.1 KiB
C#
279 lines
9.1 KiB
C#
using Cysharp.Threading.Tasks;
|
|
using System;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using UVC.UI;
|
|
|
|
namespace UVC.Factory.Playback.UI
|
|
{
|
|
/// <summary>
|
|
/// 재생 UI를 관리하는 클래스입니다.
|
|
/// - UI 요소의 표시/숨김, 버튼/슬라이더 등 UI 이벤트를 처리합니다.
|
|
/// - 실제 재생 로직은 UIPlaybackController에서 처리합니다.
|
|
/// </summary>
|
|
public class UIPlayback : MonoBehaviour
|
|
{
|
|
// 싱글톤 패턴: 어디서든 UIPlayback.Instance로 접근할 수 있습니다.
|
|
private static UIPlayback instance;
|
|
public static UIPlayback Instance
|
|
{
|
|
get
|
|
{
|
|
if (instance == null) instance = CreateUIPlayBack();
|
|
return instance;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// UIPlayback 프리팹을 동적으로 생성합니다.
|
|
/// </summary>
|
|
/// <returns>생성된 UIPlayback 인스턴스</returns>
|
|
private static UIPlayback CreateUIPlayBack()
|
|
{
|
|
// Resources 폴더에서 프리팹을 불러와 인스턴스화합니다.
|
|
GameObject prefab = Resources.Load<GameObject>("Factory/Prefabs/Playback/UIPlayback");
|
|
GameObject go = GameObject.Instantiate(prefab);
|
|
return go.GetComponent<UIPlayback>();
|
|
}
|
|
|
|
// Inspector에서 연결할 UI 컴포넌트들입니다.
|
|
[SerializeField]
|
|
[Tooltip("종료 버튼")]
|
|
private Button exitButton;
|
|
|
|
[SerializeField]
|
|
[Tooltip("종료 버튼")]
|
|
private TextMeshProUGUI dateTimeTxt0;
|
|
|
|
[SerializeField]
|
|
[Tooltip("종료 버튼")]
|
|
private TextMeshProUGUI dateTimeTxt1;
|
|
|
|
[SerializeField]
|
|
[Tooltip("play 버튼")]
|
|
private Button playButton;
|
|
|
|
[SerializeField]
|
|
[Tooltip("play 버튼 이미지")]
|
|
private Image playButtonImage;
|
|
|
|
[SerializeField]
|
|
[Tooltip("play 버튼 이미지 Sprite")]
|
|
private Sprite playButtonImagePlay;
|
|
|
|
[SerializeField]
|
|
[Tooltip("play 버튼 Puase 이미지 Sprite")]
|
|
private Sprite playButtonImagePause;
|
|
|
|
[SerializeField]
|
|
[Tooltip("Speed Slider")]
|
|
private UISliderWithLabel sliderSpeed;
|
|
|
|
[SerializeField]
|
|
[Tooltip("투명 조절 Slider")]
|
|
private SliderWithEvent opacitySlider;
|
|
|
|
[SerializeField]
|
|
[Tooltip("Progress Bar")]
|
|
private UIPlaybackProgressBar progressBar;
|
|
|
|
[SerializeField]
|
|
private CanvasGroup canvasGroup;
|
|
|
|
[SerializeField]
|
|
private UIDragger uiDragger;
|
|
|
|
// 컨트롤러: 실제 재생 로직을 담당합니다.
|
|
private UIPlaybackController controller;
|
|
|
|
// UI 이벤트를 외부(Controller)로 전달하기 위한 이벤트입니다.
|
|
public event Action OnClickExitButton;
|
|
public event Action OnClickPlayButton;
|
|
public event Action<int> OnChangeProgressValue;
|
|
public event Action<int> OnChangeSpeedValue;
|
|
public event Action<float> OnChangeOpacityValue;
|
|
|
|
/// <summary>
|
|
/// 오브젝트가 생성될 때 호출됩니다.
|
|
/// </summary>
|
|
private void Awake()
|
|
{
|
|
controller = new UIPlaybackController(this);
|
|
Init();
|
|
}
|
|
|
|
/// <summary>
|
|
/// UI 이벤트 리스너를 등록합니다.
|
|
/// </summary>
|
|
private void Init()
|
|
{
|
|
// 버튼 클릭 시 이벤트 발생
|
|
exitButton.onClick.AddListener(() => OnClickExitButton?.Invoke());
|
|
playButton.onClick.AddListener(() => OnClickPlayButton?.Invoke());
|
|
|
|
// 슬라이더/프로그레스바 값 변경 시 이벤트 발생
|
|
progressBar.OnChangeValue += (value) => OnChangeProgressValue?.Invoke(value);
|
|
sliderSpeed.OnChangeValue += (value) => OnChangeSpeedValue?.Invoke(value);
|
|
opacitySlider.onValueChanged.AddListener((value) => OnChangeOpacityValue?.Invoke(value));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 오브젝트가 파괴될 때 호출됩니다.
|
|
/// </summary>
|
|
private void OnDestroy()
|
|
{
|
|
// 모든 이벤트 리스너 해제
|
|
exitButton.onClick.RemoveAllListeners();
|
|
playButton.onClick.RemoveAllListeners();
|
|
progressBar.OnChangeValue = null;
|
|
sliderSpeed.OnChangeValue = null;
|
|
opacitySlider.onValueChanged.RemoveAllListeners();
|
|
controller.Dispose();
|
|
}
|
|
|
|
/// <summary>
|
|
/// UI를 화면에 표시합니다.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// // UIPlayback을 화면에 띄우는 예시
|
|
/// UIPlayback.Instance.Show();
|
|
/// </code>
|
|
/// </example>
|
|
public void Show()
|
|
{
|
|
if (playButton == null) Init();
|
|
gameObject.SetActive(true);
|
|
if (transform.parent == null)
|
|
{
|
|
// ModalCanvas에 붙여서 항상 위에 보이도록 설정
|
|
var canvases = GameObject.FindObjectsByType<Canvas>(FindObjectsSortMode.None);
|
|
foreach (var canvas in canvases)
|
|
{
|
|
if (canvas.name == "ModalCanvas")
|
|
{
|
|
transform.SetParent(canvas.transform, false);
|
|
uiDragger.SetDragArea(canvas.transform as RectTransform);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// UI를 화면에서 숨깁니다.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// // UIPlayback을 숨기는 예시
|
|
/// UIPlayback.Instance.Hide();
|
|
/// </code>
|
|
/// </example>
|
|
public void Hide()
|
|
{
|
|
controller.UpdateTimeScale(1);
|
|
controller.IsTick = false;
|
|
gameObject.SetActive(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 재생에 필요한 데이터를 설정합니다.
|
|
/// </summary>
|
|
/// <param name="date">날짜(예: "2024-07-29")</param>
|
|
/// <param name="time">시간(초 단위 문자열, 예: "3600")</param>
|
|
/// <param name="fileName">파일명</param>
|
|
/// <returns>비동기 작업(UniTask)</returns>
|
|
/// <example>
|
|
/// <code>
|
|
/// await UIPlayback.Instance.SetData("2024-07-29", "3600", "sample.sqlite");
|
|
/// </code>
|
|
/// </example>
|
|
public UniTask SetData(string date, string time, string fileName)
|
|
{
|
|
return controller.SetData(date, time, fileName);
|
|
}
|
|
|
|
#region View Update Methods
|
|
|
|
/// <summary>
|
|
/// 날짜/시간 텍스트를 갱신합니다.
|
|
/// </summary>
|
|
/// <param name="date">표시할 날짜 문자열</param>
|
|
public void UpdateDateTime(string date)
|
|
{
|
|
dateTimeTxt0.text = dateTimeTxt1.text = date;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 재생 진행 바를 초기화합니다.
|
|
/// </summary>
|
|
/// <param name="time">전체 재생 시간(초)</param>
|
|
public void InitProgressBar(int time) => progressBar.Init(time);
|
|
|
|
/// <summary>
|
|
/// 속도 슬라이더를 초기화합니다.
|
|
/// </summary>
|
|
public void InitSpeedSlider() => sliderSpeed.Init();
|
|
|
|
/// <summary>
|
|
/// 재생/일시정지 버튼 이미지를 갱신합니다.
|
|
/// </summary>
|
|
/// <param name="isPlaying">재생 중이면 true, 아니면 false</param>
|
|
public void UpdatePlayButtonState(bool isPlaying)
|
|
{
|
|
playButtonImage.sprite = isPlaying ? playButtonImagePause : playButtonImagePlay;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 재생 진행 바의 값을 설정합니다.
|
|
/// </summary>
|
|
/// <param name="value">설정할 값(초)</param>
|
|
public void SetProgressValue(int value)
|
|
{
|
|
if (progressBar.Value != value)
|
|
{
|
|
progressBar.Value = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 현재 재생 위치(초)를 반환합니다.
|
|
/// </summary>
|
|
public int GetProgressValue() => progressBar.Value;
|
|
|
|
/// <summary>
|
|
/// 전체 재생 시간(초)를 반환합니다.
|
|
/// </summary>
|
|
public int GetProgressMaxValue() => progressBar.MaxValue;
|
|
|
|
/// <summary>
|
|
/// 현재 선택된 재생 속도를 반환합니다.
|
|
/// </summary>
|
|
public int GetSpeedValue() => sliderSpeed.Value;
|
|
|
|
/// <summary>
|
|
/// UI의 투명도를 설정합니다.
|
|
/// </summary>
|
|
/// <param name="value">0(완전 투명) ~ 1(완전 불투명)</param>
|
|
public void SetOpacity(float value)
|
|
{
|
|
canvasGroup.alpha = value;
|
|
opacitySlider.value = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// UI의 상호작용 가능 여부를 설정합니다.
|
|
/// </summary>
|
|
/// <param name="isInteractable">true면 버튼/슬라이더 사용 가능</param>
|
|
public void SetUIInteractable(bool isInteractable)
|
|
{
|
|
playButton.enabled = isInteractable;
|
|
progressBar.Interactable = isInteractable;
|
|
}
|
|
#endregion
|
|
|
|
}
|
|
|
|
}
|