using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Unity.Collections;
using Unity.Mathematics;
using UnityEngine;
namespace GarmentButton.FlatenArray
{
public struct FlatenFloatArray2D
{
public int2 GridSize;
public float CellSize;
public float2 Center;
public FlatenFloatArray2D(int2 gridSize, float cellSize, float2 center)
{
GridSize = gridSize;
CellSize = cellSize;
Center = center;
}
private float2 HalfGridDimensions => new(GridSize.x * CellSize * 0.5f, GridSize.y * CellSize * 0.5f);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetCellAtPosition(float2 position)
{
var normalizedPosition = position - Center + HalfGridDimensions;
var cellCoordinates = new int2
{
x = (int)math.floor(normalizedPosition.x / CellSize),
y = (int)math.floor(normalizedPosition.y / CellSize),
};
cellCoordinates.x = math.clamp(cellCoordinates.x, 0, GridSize.x - 1);
cellCoordinates.y = math.clamp(cellCoordinates.y, 0, GridSize.y - 1);
return GridSize.x * cellCoordinates.y + cellCoordinates.x;
}
public int GetIndexSide(int index, Direction direction)
{
var coordinate = GetCorrdinate(index);
return GetIndexByCorredinate(direction, coordinate);
}
public NativeArray<int> GetAllIndexSide(int index, int howFar = 1)
{
var coordinate = GetCorrdinate(index);
const int NUMBER_OF_SIDES = 8;
NativeArray<int> sides = new NativeArray<int>(NUMBER_OF_SIDES * howFar, Allocator.Temp);
for (int distance = 1; distance <= howFar; distance++)
{
for (int direction = 0; direction < NUMBER_OF_SIDES; direction++)
{
int sideIndex = (distance - 1) * NUMBER_OF_SIDES + direction;
int valueSideIndex = GetIndexByCorredinate((Direction)direction, coordinate, distance);
if (valueSideIndex > GridSize.x * GridSize.y)
valueSideIndex = -1;
sides[sideIndex] = valueSideIndex;
}
}
return sides;
}
private int GetIndexByCorredinate(Direction direction, int2 coordinate, int howFar = 1)
{
switch (direction)
{
case Direction.Up_Left:
coordinate.x-= howFar;
coordinate.y+= howFar;
break;
case Direction.Up:
coordinate.y += howFar;
break;
case Direction.Up_Right:
coordinate.x += howFar;
coordinate.y += howFar;
break;
case Direction.Down_Left:
coordinate.x -= howFar;
coordinate.y -= howFar;
break;
case Direction.Down:
coordinate.y -= howFar;
break;
case Direction.Down_Right:
coordinate.y -= howFar;
coordinate.x += howFar;
break;
case Direction.Left:
coordinate.x -= howFar;
break;
case Direction.Right:
coordinate.x += howFar;
break;
}
return GridSize.x * coordinate.y + coordinate.x;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetIndexFromCoordinate(int x, int y)
{
return GridSize.x * y + x;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int2 GetCorrdinate(int result)
{
var y = result / GridSize.x; // Changed to GridSize.x
var x = result % GridSize.x;
return new int2(x, y);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float2 GetWorldPosition(int2 coord) =>
Center - HalfGridDimensions + ((float2)coord + 0.5f) * CellSize;
/// <summary>Convenience overload (tiny extra cost of constructing int2).</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float2 GetWorldPosition(int x, int y) =>
Center - HalfGridDimensions + (new float2(x + 0.5f, y + 0.5f)) * CellSize;
/// <summary>Slowest: takes a 1-D index, converts to coord, then to world.</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float2 GetWorldPosition(int index) =>
GetWorldPosition(GetCorrdinate(index));
}
public enum Direction : byte
{
Up_Left,Up, Up_Right,Down_Left, Down,Down_Right, Left, Right
}
}