Files
blockout/BlockOutReplica/Assets/Scripts/Presentation/BoardRimLayout.cs
T
2026-10-20 13:21:04 +08:00

71 lines
3.2 KiB
C#

using BlockOutReplica.Domain;
using UnityEngine;
namespace BlockOutReplica.Presentation
{
/// <summary>
/// Wall rectangles are specified by their visible bounds, not the Sprite's
/// pivot. Recovered Convex* art has a bottom-left pivot; extracted straight
/// cross-sections have a center pivot. Both must share the same grid edges.
/// </summary>
public static class BoardRimLayout
{
public const float SurfaceHeight = .1f;
public static string ProfileNameFor(DoorSide side)
{ return side == DoorSide.Right ? "ConvexRightTop" : side == DoorSide.Bottom ? "ConvexLeftBottom" : "ConvexLeftTop"; }
public static Sprite CreateStraightSprite(Sprite profile, bool horizontal)
{
Rect r = profile.textureRect;
Rect strip = horizontal ? new Rect(r.xMax - 3f, r.y, 2f, r.height)
: new Rect(r.x, r.y + 2f, r.width, 2f);
Sprite sprite = Sprite.Create(profile.texture, strip, Vector2.one * .5f,
profile.pixelsPerUnit, 0, SpriteMeshType.FullRect);
sprite.name = "Original Wall Cross Section " + profile.name;
return sprite;
}
public static Rect DoorBounds(LevelDefinition level, DoorDefinition door, Vector2 artSize)
{
if (door == null || door.Cells.Count == 0)
throw new System.ArgumentException("Door closure requires its original grid cells.", nameof(door));
bool horizontal = door.Side == DoorSide.Top || door.Side == DoorSide.Bottom;
GridPosition first = door.Cells[0];
foreach (GridPosition cell in door.Cells)
if (horizontal ? cell.X < first.X : cell.Y < first.Y) first = cell;
return WorldBounds(level, first, door.Cells.Count, artSize);
}
public static Rect WorldBounds(LevelDefinition level, GridPosition first, int length, Vector2 artSize)
{
Vector3 cell = level.GridToWorld(first);
bool left = first.X < level.MinX, right = first.X > level.MaxX;
bool bottom = first.Y < level.MinY, top = first.Y > level.MaxY;
bool corner = (left || right) && (top || bottom);
float x = cell.x, z = cell.z;
float width = corner || !(top || bottom) ? artSize.x : length;
float depth = corner || top || bottom ? artSize.y : length;
if (!corner)
{
if (top || bottom) x += (length - 1) * .5f;
else z += (length - 1) * .5f;
}
if (left) x += .5f - width * .5f;
if (right) x -= .5f - width * .5f;
if (top) z += depth * .5f - .5f;
if (bottom) z -= depth * .5f - .5f;
return new Rect(x - width * .5f, z - depth * .5f, width, depth);
}
public static Vector3 CenteredSpriteOrigin(Vector3 center, Vector2 targetSize,
Vector2 spriteSize, Vector2 spriteBoundsCenter)
{
// The XY sprite is rotated +90 degrees onto XZ by LevelViewFactory.
// Account for its local mesh center before that rotation.
return center - new Vector3(spriteBoundsCenter.x * targetSize.x / spriteSize.x,
0f, spriteBoundsCenter.y * targetSize.y / spriteSize.y);
}
}
}