using System.Collections; using System.Collections.Generic; using Godot; using System; namespace Rokojori { public class TextureCombinerBuffer { int _width; public int width => _width; int _height; public int height => _height; Color[] _pixels; public static TextureCombinerBuffer Create( int w, int h ) { var tb = new TextureCombinerBuffer(); tb._height = h; tb._width = w; tb._pixels = new Color[ w * h ]; return tb; } public static TextureCombinerBuffer From( Texture2D texture ) { var buffer = Create( texture.GetWidth(), texture.GetHeight() ); buffer.CopyFrom( texture.GetImage(), 0, 0, 0, 0, texture.GetWidth(), texture.GetHeight() ); return buffer; } public TextureCombinerBuffer Resize( int w, int h ) { var buffer = Create( w, h ); for ( int i = 0; i < w; i++ ) { for ( int j = 0; j < h; j++ ) { var uv = new Vector2( i / (float) w, j / (float) h ); var pixel = SampleBilinearUV( uv ); buffer.SetAt( i, j, pixel ); } } return buffer; } public void CopyFrom( Image image, int sourceX, int sourceY, int ownX, int ownY, int w, int h ) { for ( int i = 0; i < w; i++ ) { for ( int j = 0; j < h; j++ ) { var sourcePixel = image.GetPixel( sourceX + i, sourceY + j ); SetAt( ownX + i, ownY + j, sourcePixel ); } } } public void CopyTo( int ownX, int ownY, int targetX, int targetY, int w, int h, TextureCombinerBuffer output ) { for ( int i = 0; i < w; i++ ) { for ( int j = 0; j < h; j++ ) { var ownPixel = GetAt( ownX + i, ownY + j ); output.SetAt( targetX + i, targetY + j, ownPixel ); } } } public void CopyTo( int ownX, int ownY, int targetX, int targetY, int w, int h, Image image ) { for ( int i = 0; i < w; i++ ) { for ( int j = 0; j < h; j++ ) { var ownPixel = GetAt( ownX + i, ownY + j ); image.SetPixel( targetX + i, targetY + j, ownPixel ); } } } public int ComputeIndexFromPosition( int x, int y ) { return x + y * _width; } public void SetAt( int x, int y, Color value ) { SetIndexed( ComputeIndexFromPosition( x, y ), value ); } public void SetIndexed( int index, Color value ) { _pixels[ index ] = value; } public Color GetAt( int x, int y ) { return GetIndexed( ComputeIndexFromPosition( x, y ) ); } public Color GetIndexed( int index ) { return _pixels[ index ]; } public Color SampleNearestUV( Vector2 uv ) { return SampleNearestImage( uv.X * width, uv.Y * height ); } public Color SampleNearestImage( float imageDimensionsX, float imageDimensionsY ) { return GetAt( Mathf.RoundToInt( imageDimensionsX ), Mathf.RoundToInt( imageDimensionsY ) ); } public Color SampleBilinearUV( Vector2 uv ) { return SampleBilinearImage( uv.X * width, uv.Y * height ); } public Color SampleBilinearImage( float imageDimensionsX, float imageDimensionsY ) { var lowX = Mathf.FloorToInt( imageDimensionsX ); var highX = Mathf.Min( lowX + 1, width - 1 ); var lerpX = imageDimensionsX - lowX; var lowY = Mathf.FloorToInt( imageDimensionsY ); var highY = Mathf.Min( lowY + 1, height - 1 ); var lerpY = imageDimensionsY - lowY; var ll = GetAt( lowX, lowY ); var hl = GetAt( highX, lowY ); var lh = GetAt( lowX, highY ); var hh = GetAt( highX, highY ); var upper = ll.Lerp( hl, lerpX ); var lower = lh.Lerp( hh, lerpX ); return upper.Lerp( lower, lerpY ); } } }