Editor/Tileset/TilesetTools/Preview/RenderingWidget.cs
using Editor;
using Sandbox;
using System;
using System.Collections.Generic;
using System.Linq;
namespace SpriteTools.TilesetTool.Preview;
public class RenderingWidget : SpriteRenderingWidget
{
TilesetToolInspector Inspector;
AutotileBrush AutotileBrush;
float planeWidth;
float planeHeight;
float startX;
float startY;
float frameWidth;
float frameHeight;
float xSeparation;
float ySeparation;
Dictionary<Vector2, TilesetResource.Tile> tileDict;
protected override bool CanZoom => false;
public RenderingWidget ( TilesetToolInspector inspector, Widget parent ) : base( parent )
{
Inspector = inspector;
VerticalSizeMode = SizeMode.CanGrow;
}
[EditorEvent.Frame]
public void Frame ()
{
UpdateInputs();
var layer = TilesetTool.Active?.SelectedLayer;
if ( layer is null ) return;
var tileset = layer.TilesetResource;
if ( tileset is null ) return;
var tiles = tileset?.Tiles;
if ( tiles is null ) return;
tileDict = new();
foreach ( var tile in tiles )
{
for ( int i = 0; i < tile.Size.x; i++ )
{
for ( int j = 0; j < tile.Size.y; j++ )
{
var realTile = ( i == 0 && j == 0 ) ? tile : null;
tileDict[tile.Position + new Vector2( i, j )] = realTile;
}
}
}
AutotileBrush = AutotileWidget.Instance?.Brush;
using ( GizmoInstance.Push() )
{
var hasTiles = tiles.Count > 0;
planeWidth = 100f * TextureRect.Transform.Scale.y;
planeHeight = 100f * TextureRect.Transform.Scale.x;
startX = -( planeWidth / 2f );
startY = -( planeHeight / 2f );
frameWidth = tileset.TileSize.x / TextureSize.x * planeWidth;
frameHeight = tileset.TileSize.y / TextureSize.y * planeHeight;
xSeparation = tileset.TileSeparation.x / TextureSize.x * planeWidth;
ySeparation = tileset.TileSeparation.y / TextureSize.y * planeHeight;
{
int framesPerRow = tileset.CurrentTextureSize.x / tileset.CurrentTileSize.x;
int framesPerHeight = tileset.CurrentTextureSize.y / tileset.CurrentTileSize.y;
if ( !hasTiles )
{
framesPerRow = (int)TextureSize.x / tileset.TileSize.x;
framesPerHeight = (int)TextureSize.y / tileset.TileSize.y;
}
using ( Gizmo.Scope( "tiles" ) )
{
if ( AutotileBrush is null )
Gizmo.Draw.Color = new Color( 0.1f, 0.4f, 1f );
else
Gizmo.Draw.Color = Color.Yellow;
Gizmo.Draw.LineThickness = 3f;
int xi = 0;
int yi = 0;
if ( framesPerRow * framesPerHeight < 2048 )
{
while ( yi < framesPerHeight )
{
while ( xi < framesPerRow )
{
if ( tileDict.TryGetValue( new Vector2( xi, yi ), out var tile ) )
{
if ( tile is not null )
{
TileControl( xi, yi, tileDict[new Vector2( xi, yi )] );
}
}
xi++;
}
xi = 0;
yi++;
}
}
}
}
}
}
void TileControl ( int xi, int yi, TilesetResource.Tile tile )
{
if ( AutotileBrush is not null )
{
if ( !AutotileBrush.Tiles.Any( x => x?.Tiles?.Any( y => ( y?.Id ?? Guid.Empty ) == tile.Id ) ?? false ) ) return;
}
bool isSelected = TilesetTool.Active?.SelectedTile == tile;
using ( Gizmo.Scope( $"tile_{tile.Id}", Transform.Zero.WithPosition( isSelected ? ( Vector3.Up * 5f ) : Vector3.Zero ) ) )
{
float sizeX = tile.Size.x;
float sizeY = tile.Size.y;
var x = startX + ( xi * frameWidth + xi * xSeparation );
var y = startY + ( yi * frameHeight + yi * ySeparation );
var width = frameWidth * sizeX;
var height = frameHeight * sizeY;
var bbox = BBox.FromPositionAndSize( new Vector3( y + height / 2f, x + width / 2f, 1f ), new Vector3( height, width, 1f ) );
Gizmo.Hitbox.BBox( bbox );
if ( AutotileBrush is null )
{
if ( isSelected )
{
Gizmo.Draw.LineThickness = 4;
Gizmo.Draw.Color = Color.Yellow;
}
if ( Gizmo.IsHovered )
{
using ( Gizmo.Scope( "hover" ) )
{
Gizmo.Draw.Color = Gizmo.Draw.Color.WithAlpha( 0.5f );
Gizmo.Draw.SolidBox( bbox );
}
if ( Gizmo.WasLeftMousePressed )
{
TilesetTool.Active.SelectedTile = tile;
}
}
}
DrawBox( x, y, width, height );
}
}
void DrawBox ( float x, float y, float width, float height )
{
Gizmo.Draw.Line( new Vector3( y, x, 0 ), new Vector3( y, x + width, 0 ) );
Gizmo.Draw.Line( new Vector3( y, x, 0 ), new Vector3( y + height, x, 0 ) );
Gizmo.Draw.Line( new Vector3( y + height, x, 0 ), new Vector3( y + height, x + width, 0 ) );
Gizmo.Draw.Line( new Vector3( y + height, x + width, 0 ), new Vector3( y, x + width, 0 ) );
}
bool CanExpand ( TilesetResource.Tile tile, int x, int y )
{
int currentX = tile.Position.x;
int currentY = tile.Position.y;
if ( x != 0 )
{
int nextX = currentX + ( x > 0 ? ( x * (int)tile.Size.x ) : x );
if ( nextX < 0 || nextX >= ( TextureSize.x / tile.Tileset.CurrentTileSize.x ) ) return false;
else
{
for ( int i = 0; i < tile.Size.y; i++ )
{
int nextY = currentY + i;
if ( tileDict.ContainsKey( new Vector2( nextX, nextY ) ) )
{
return false;
}
}
}
}
if ( y != 0 )
{
int nextY = currentY + ( y > 0 ? ( y * (int)tile.Size.y ) : y );
if ( nextY < 0 || nextY >= ( TextureSize.y / tile.Tileset.CurrentTileSize.y ) ) return false;
else
{
for ( int i = 0; i < tile.Size.x; i++ )
{
int nextX = currentX + i;
if ( tileDict.ContainsKey( new Vector2( nextX, nextY ) ) )
{
return false;
}
}
}
}
return true;
}
}