227 lines
7.6 KiB
C#
227 lines
7.6 KiB
C#
namespace Gpm.Ui
|
|
{
|
|
using UnityEngine;
|
|
using MoveToType = InfiniteScroll.MoveToType;
|
|
|
|
/// <summary>
|
|
/// 스크롤 위치를 제어하기 위한 인터페이스입니다.
|
|
/// InfiniteScroll과 같이 스크롤 기능이 있는 클래스에서 이 인터페이스를 구현합니다.
|
|
/// </summary>
|
|
public interface IMoveScroll
|
|
{
|
|
/// <summary>
|
|
/// 현재 스크롤 위치를 반환합니다.
|
|
/// </summary>
|
|
Vector2 GetScrollPosition();
|
|
|
|
/// <summary>
|
|
/// 스크롤 위치를 설정합니다.
|
|
/// </summary>
|
|
void SetScrollPosition(Vector2 position);
|
|
|
|
/// <summary>
|
|
/// 특정 아이템 인덱스로 이동할 위치를 계산하여 반환합니다.
|
|
/// </summary>
|
|
/// <param name="itemIndex">이동할 아이템의 인덱스</param>
|
|
/// <param name="moveToType">아이템을 정렬할 위치(상단, 중앙, 하단)</param>
|
|
Vector2 GetMovePosition(int itemIndex, MoveToType moveToType);
|
|
|
|
/// <summary>
|
|
/// 전체 스크롤 범위의 특정 비율로 이동할 위치를 계산하여 반환합니다.
|
|
/// </summary>
|
|
/// <param name="scrollRate">이동할 비율 (0.0 ~ 1.0)</param>
|
|
Vector2 GetMovePosition(float scrollRate);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 특정 위치로 스크롤을 애니메이션과 함께 부드럽게 이동시키는 컴포넌트입니다.
|
|
/// InfiniteScroll과 같이 IMoveScroll 인터페이스를 구현한 컴포넌트가 있는 게임 오브젝트에 추가하여 사용합니다.
|
|
///
|
|
/// --- 샘플 코드 ---
|
|
/// <code>
|
|
/// // 이동을 원하는 스크롤이 있는 GameObject를 찾습니다.
|
|
/// GameObject scrollObject = GameObject.Find("InfiniteScroll");
|
|
///
|
|
/// // ScrollMoveTo 컴포넌트가 없으면 추가하고, 있으면 가져옵니다.
|
|
/// ScrollMoveTo moveTo = scrollObject.GetComponent<ScrollMoveTo>();
|
|
/// if (moveTo == null)
|
|
/// {
|
|
/// moveTo = scrollObject.AddComponent<ScrollMoveTo>();
|
|
/// }
|
|
///
|
|
/// // 예제 1: 10번 아이템의 중앙으로 0.5초 동안 이동
|
|
/// moveTo.Set(10, MoveToType.MOVE_TO_CENTER, 0.5f);
|
|
/// moveTo.Play();
|
|
///
|
|
/// // 예제 2: 스크롤 전체의 80% 위치로 0.3초 동안 이동
|
|
/// moveTo.Set(0.8f, 0.3f);
|
|
/// moveTo.Play();
|
|
/// </code>
|
|
/// </summary>
|
|
[DisallowMultipleComponent]
|
|
public class ScrollMoveTo : MonoBehaviour
|
|
{
|
|
/// <summary>
|
|
/// 스크롤 이동 목표를 지정하는 방식입니다.
|
|
/// </summary>
|
|
public enum ScrollType
|
|
{
|
|
/// <summary>
|
|
/// 아이템의 인덱스를 기준으로 이동합니다.
|
|
/// </summary>
|
|
INDEX,
|
|
/// <summary>
|
|
/// 전체 스크롤의 비율(0.0~1.0)을 기준으로 이동합니다.
|
|
/// </summary>
|
|
RATE
|
|
}
|
|
|
|
private IMoveScroll scroll;
|
|
|
|
private void OnEnable()
|
|
{
|
|
if (scroll == null)
|
|
{
|
|
scroll = GetComponent<IMoveScroll>();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 스크롤 이동 목표를 설정합니다. (인덱스 또는 비율)
|
|
/// </summary>
|
|
[Tooltip("스크롤 이동 목표를 설정합니다. (인덱스 또는 비율)")]
|
|
public ScrollType scrollType;
|
|
|
|
/// <summary>
|
|
/// 이동할 대상 아이템의 인덱스입니다. (scrollType이 INDEX일 때 사용)
|
|
/// </summary>
|
|
[Tooltip("이동할 대상 아이템의 인덱스입니다. (scrollType이 INDEX일 때 사용)")]
|
|
public int itemIndex;
|
|
|
|
/// <summary>
|
|
/// 아이템을 화면의 어느 위치에 맞출지 결정합니다. (scrollType이 INDEX일 때 사용)
|
|
/// </summary>
|
|
[Tooltip("아이템을 화면의 어느 위치에 맞출지 결정합니다. (scrollType이 INDEX일 때 사용)")]
|
|
public MoveToType moveToType;
|
|
|
|
/// <summary>
|
|
/// 이동할 스크롤의 비율입니다. (0.0 = 시작, 1.0 = 끝) (scrollType이 RATE일 때 사용)
|
|
/// </summary>
|
|
[Tooltip("이동할 스크롤의 비율입니다. (0.0 = 시작, 1.0 = 끝) (scrollType이 RATE일 때 사용)")]
|
|
[Range(0f, 1f)]
|
|
public float scrollRate = 0;
|
|
|
|
/// <summary>
|
|
/// 목표 위치까지 이동하는 데 걸리는 시간(초)입니다.
|
|
/// </summary>
|
|
[Tooltip("목표 위치까지 이동하는 데 걸리는 시간(초)입니다.")]
|
|
public float time = 0.3f;
|
|
|
|
/// <summary>
|
|
/// 이동 애니메이션의 속도 변화를 제어하는 커브입니다.
|
|
/// </summary>
|
|
[Tooltip("이동 애니메이션의 속도 변화를 제어하는 커브입니다.")]
|
|
public AnimationCurve curve = AnimationCurve.EaseInOut(0, 0, 1, 1);
|
|
|
|
/// <summary>
|
|
/// 이동이 완료된 후 이 컴포넌트를 자동으로 파괴할지 여부입니다.
|
|
/// </summary>
|
|
[Tooltip("이동이 완료된 후 이 컴포넌트를 자동으로 파괴할지 여부입니다.")]
|
|
public bool autoDestory = false;
|
|
|
|
private float rate = 0;
|
|
|
|
private Vector2 start;
|
|
|
|
/// <summary>
|
|
/// 특정 아이템 인덱스로 이동하도록 설정합니다.
|
|
/// </summary>
|
|
/// <param name="itemIndex">이동할 아이템 인덱스</param>
|
|
/// <param name="moveToType">아이템 정렬 위치</param>
|
|
/// <param name="time">이동 시간(초)</param>
|
|
public void Set(int itemIndex, MoveToType moveToType, float time)
|
|
{
|
|
this.scrollType = ScrollType.INDEX;
|
|
this.itemIndex = itemIndex;
|
|
this.moveToType = moveToType;
|
|
|
|
this.time = time;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 특정 비율 위치로 이동하도록 설정합니다.
|
|
/// </summary>
|
|
/// <param name="scrollRate">이동할 비율 (0.0 ~ 1.0)</param>
|
|
/// <param name="time">이동 시간(초)</param>
|
|
public void Set(float scrollRate, float time)
|
|
{
|
|
this.scrollType = ScrollType.RATE;
|
|
this.scrollRate = scrollRate;
|
|
|
|
this.time = time;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 설정된 값에 따라 스크롤 이동 애니메이션을 시작합니다.
|
|
/// </summary>
|
|
public void Play()
|
|
{
|
|
rate = 0;
|
|
enabled = true;
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
if (scroll == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (rate == 0)
|
|
{
|
|
start = scroll.GetScrollPosition();
|
|
}
|
|
|
|
if (time > 0)
|
|
{
|
|
rate += Time.deltaTime / time;
|
|
}
|
|
else
|
|
{
|
|
rate = 1;
|
|
}
|
|
|
|
Vector2 end;
|
|
if (scrollType == ScrollType.INDEX)
|
|
{
|
|
end = scroll.GetMovePosition(itemIndex, moveToType);
|
|
}
|
|
else if (scrollType == ScrollType.RATE)
|
|
{
|
|
end = scroll.GetMovePosition(scrollRate);
|
|
}
|
|
else
|
|
{
|
|
end = start;
|
|
rate = 1;
|
|
|
|
}
|
|
|
|
if (rate < 1)
|
|
{
|
|
scroll.SetScrollPosition(Vector2.Lerp(start, end, curve.Evaluate(rate)));
|
|
}
|
|
else
|
|
{
|
|
scroll.SetScrollPosition(end);
|
|
rate = 0;
|
|
|
|
if (autoDestory == true)
|
|
{
|
|
Destroy(this);
|
|
}
|
|
enabled = false;
|
|
}
|
|
}
|
|
}
|
|
} |