107 lines
3.4 KiB
C#
107 lines
3.4 KiB
C#
using Godot;
|
|
using System;
|
|
|
|
using Rokojori.Extensions;
|
|
namespace Rokojori
|
|
{
|
|
/** One blit a layer contributes - where it goes, and how the shader should
|
|
read its content there.
|
|
|
|
A plain layer produces exactly one of these. A layer with
|
|
TextureStackStamps produces one per stamp, plus the extra copies edge
|
|
wrapping needs.
|
|
|
|
Layers fill in <code>rect</code> <marked>unclipped</marked> and leave
|
|
uvRect alone; TextureStackCompositor then clips the rect against the
|
|
output and derives uvRect from the two. That split is what lets a stamp
|
|
hang off the output's edge: the blit shrinks to the visible part, but
|
|
uvRect tells the shader which slice of the stamp that part is, so the
|
|
content and the masks stay aligned with the whole stamp instead of being
|
|
squeezed into the sliver. Without it, UV being rect-local (spike gate G6)
|
|
would silently scale every clipped placement.
|
|
*/
|
|
public struct TextureStackPlacement
|
|
{
|
|
/** Identity uvRect: this blit covers the whole placement. */
|
|
public static readonly Vector4 fullUVRect = new Vector4( 0, 0, 1, 1 );
|
|
|
|
/** Image space. Set by the layer unclipped, replaced by the compositor with
|
|
the part that actually lies inside the output.
|
|
*/
|
|
public Rect2I rect;
|
|
|
|
/** What rect was before clipping. Layers that generate content at the
|
|
placement's resolution - a nested stack - have to work at this size and
|
|
then show the uvRect slice of it, or their own full-texture layers would
|
|
fill the visible sliver instead of the whole placement.
|
|
*/
|
|
public Rect2I unclippedRect;
|
|
|
|
/** offset.xy / scale.zw - the slice of the placement that rect covers.
|
|
Filled in by the compositor.
|
|
*/
|
|
public Vector4 uvRect;
|
|
|
|
/** Extra content rotation in radians, on top of the layer's own. Non-zero
|
|
only for scattered stamps.
|
|
|
|
Note this rotates the content *inside* an axis-aligned rect, so a
|
|
non-square stamp gets cropped at its corners - keep scattered stamps
|
|
square, or leave rotation variation at 0.
|
|
*/
|
|
public float rotation;
|
|
|
|
/** Which stamp this is, 0 for a plain layer. Wrapped copies keep the index
|
|
of the stamp they belong to, so they draw identically.
|
|
*/
|
|
public int index;
|
|
|
|
|
|
public static TextureStackPlacement At( Rect2I rect, int index = 0, float rotation = 0 )
|
|
{
|
|
var placement = new TextureStackPlacement();
|
|
|
|
placement.rect = rect;
|
|
placement.unclippedRect = rect;
|
|
placement.uvRect = fullUVRect;
|
|
placement.rotation = rotation;
|
|
placement.index = index;
|
|
|
|
return placement;
|
|
}
|
|
|
|
/** Clips against the output and works out which slice of the original rect
|
|
survived. Returns false when nothing of it is visible.
|
|
*/
|
|
public bool ClipTo( Rect2I bounds )
|
|
{
|
|
var unclipped = rect;
|
|
|
|
unclippedRect = unclipped;
|
|
|
|
if ( unclipped.Size.X <= 0 || unclipped.Size.Y <= 0 )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var clipped = unclipped.Intersection( bounds );
|
|
|
|
if ( clipped.Size.X <= 0 || clipped.Size.Y <= 0 )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
rect = clipped;
|
|
|
|
uvRect = new Vector4(
|
|
( clipped.Position.X - unclipped.Position.X ) / (float) unclipped.Size.X,
|
|
( clipped.Position.Y - unclipped.Position.Y ) / (float) unclipped.Size.Y,
|
|
clipped.Size.X / (float) unclipped.Size.X,
|
|
clipped.Size.Y / (float) unclipped.Size.Y
|
|
);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|