Project_WL/Assets/Script/UI/WLBackgroundFit.cs

87 lines
4.0 KiB
C#
Raw Normal View History

WL 리뉴얼 세션 2026-09-06~07 (#760~#800) — 전투·배경·UI·타격감 (조직 PD 로그 #746~#800 · 대화로그 §14~§24) - 전투: Knight@Attack1~3_S 3콤보(4 컨트롤러·클래스별 서브클립) · 타겟팅 4규칙(정면 우선·재타겟·즉시 공격·어그로 금지 · WLTargetingSettings) · 대쉬 후 공격(Stander@Chase_Start · DashDriver · 5 m · 사정거리+0.8 · 근거리 적 우선) · 공격 이동 FrameTable(발 접지 실측 표 · AttackRootMotion) · 충돌 반경/투사체 0.3 배(WLCollisionTuning) · 무적(임시)·펫 금지(WLGameplaySettings) - 검기: NamuFX Slash_B 배리언트 Effect_WLSwingArc 원 피팅 정합 배치 + 캘리브레이션(SlashArcMeasure · SlashTrailSettings) · 찌르기 Effect_WLStab 대기 · 램프 리본(BladeTrail · WL_BladeRibbon.shader · T_WL_BladeRibbonRamp) 보존(drawRibbon 0) - 타격감: Assets/WL/Feel(WLHitFeel · 히트스톱 0.03 · 셰이크 0.10 m · 몹 펀치 1.12 · Actor.Get_Damage 훅 1줄 · 원본 RealCamera 셰이크 결함 대체) - 배경/맵: LMHPOLY Demo_01~10 → WL_Nature01~10(프리팹·씬·NavMesh·스포너·BattleMapConfig) · 물(ToonWaterU) · 포스트 블룸 0.9/0.3 · 잔디(BruteForce·드레싱) 제거 · 마젠타 머티리얼 URP 변환 - UI: 세로 HUD(WL_HUD · 하단 5메뉴 폭 전체 · 채팅/전투 패드 숨김 · WLIngameUiOverride) · Title/TitleInfo 1080×1920 Expand + 배경 높이 fit(WLBackgroundFit) · 로딩 SortOrder_5(WLRawImageAspectSync · 초점표 8장) · Loading1~8 ASTC 6×6 - 도구: AgentScripts/*(LightProbe · WL_MapSwitch · WL760~WL800 프로브/집행/검증 · 상단 사용법 주석) · 에디터 락 프로토콜 파일(staging) - 제외(별도 커밋 예정): Assets/LMHPOLY(703 MB) · Assets/Feel(422 MB) · Assets/Shinabro(300 MB) — 에셋 스토어/구 WL 팩 원본 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-06 23:24:25 +00:00
using UnityEngine;
/// <summary>
/// 전체화면 배경 이미지의 가로 위치를 결정한다. 크기는 같은 오브젝트의 AspectRatioFitter
/// (HeightControlsWidth) 가 잡고, 이 컴포넌트는 "어디를 보여줄지"만 정한다.
///
/// 왜 필요한가 (#795):
/// 16:9 배경을 9:19.5 세로 화면에 세로 맞춤하면 가로가 3.16배로 넘쳐 좌우가 잘린다.
/// 단순 중앙 크롭이면 화면 중앙에 오는 것은 원본의 정중앙뿐이라, 주인공이 왼쪽에 있는
/// 그림은 얼굴이 화면 밖으로 잘려 나간다.
/// 그렇다고 pivot 으로 밀어두면, 이번엔 이미지가 화면보다 좁아지는 가로 단말에서
/// 한쪽에만 검은 여백이 생기고 반대쪽은 잘리는 비대칭이 된다.
///
/// 해법: 원하는 초점(focusX)으로 밀되, 넘치는 양(overflow)을 넘어서까지는 밀지 않도록 clamp 한다.
/// - 이미지가 화면보다 넓을 때 : 초점이 화면 중앙에 오도록 이동 (단, 여백이 생기기 직전까지만)
/// - 이미지가 화면보다 좁을 때 : overflow 가 0 이므로 자동으로 정중앙 → 좌우 대칭 검은 여백
/// 즉 "여백은 항상 대칭, 잘림이 있을 때만 초점을 존중한다".
///
/// 비용: 레이아웃이 바뀔 때만 계산한다(매 프레임 Update 없음).
/// </summary>
[ExecuteAlways]
[RequireComponent(typeof(RectTransform))]
[DisallowMultipleComponent]
public class WLBackgroundFit : MonoBehaviour
{
[Tooltip("크롭이 생길 때 화면 중앙에 두고 싶은 원본 이미지의 가로 위치 (0 = 왼쪽 끝, 0.5 = 정중앙, 1 = 오른쪽 끝).")]
[Range(0f, 1f)]
public float focusX = 0.5f;
[Tooltip("세로도 같은 규칙으로 맞춘다. 세로 맞춤(HeightControlsWidth) 에서는 항상 0 이라 보통 꺼둔다.")]
public bool applyVertical = false;
[Range(0f, 1f)]
public float focusY = 0.5f;
RectTransform _rt;
RectTransform Rt => _rt != null ? _rt : (_rt = (RectTransform)transform);
// 이 컴포넌트가 값을 "구동"한다고 표시한다. 이렇게 해야 해상도가 바뀔 때마다
// 씬이 dirty 로 표시되지 않고(에디터에서 저장 안 한 변경으로 오인되지 않고),
// 인스펙터에서도 손으로 못 건드리게 잠긴다. AspectRatioFitter 등 레이아웃
// 컴포넌트가 쓰는 것과 같은 표준 방식이다.
DrivenRectTransformTracker _tracker;
void OnEnable()
{
_tracker.Clear();
_tracker.Add(this, Rt, DrivenTransformProperties.AnchoredPosition | DrivenTransformProperties.Pivot);
Apply();
}
void OnDisable() { _tracker.Clear(); }
void OnRectTransformDimensionsChange() { Apply(); }
#if UNITY_EDITOR
void OnValidate() { if (isActiveAndEnabled) Apply(); }
#endif
/// <summary>초점을 존중하되 여백이 생기지 않는 범위로 clamp 한 오프셋을 적용한다.</summary>
public void Apply()
{
var rt = Rt;
var parent = rt.parent as RectTransform;
if (parent == null) return;
// pivot 은 0.5 를 전제로 한다(중앙 기준 오프셋 계산). 다른 값이면 바로잡는다.
if (rt.pivot != new Vector2(0.5f, 0.5f)) rt.pivot = new Vector2(0.5f, 0.5f);
var pos = rt.anchoredPosition;
pos.x = Offset(rt.rect.width, parent.rect.width, focusX);
if (applyVertical) pos.y = Offset(rt.rect.height, parent.rect.height, focusY);
else pos.y = 0f;
if (pos != rt.anchoredPosition) rt.anchoredPosition = pos;
}
/// <summary>
/// size = 이미지가 차지하는 길이, avail = 화면(부모) 길이, focus = 중앙에 두고 싶은 정규화 위치.
/// 초점을 중앙에 두려면 size*(0.5-focus) 만큼 밀어야 하고, 넘치는 절반(overflow)까지만 허용된다.
/// </summary>
static float Offset(float size, float avail, float focus)
{
float overflow = Mathf.Max(0f, (size - avail) * 0.5f);
return Mathf.Clamp(size * (0.5f - focus), -overflow, overflow);
}
}