managems/tools/logical_grid.gd

116 lines
3.5 KiB
GDScript

extends Reference
class_name LogicalGrid
# Grid with a flow direction for the item added / removed
# The position on grid must be translated as the position in the array is different
enum FlowDirection { UP, DOWN, LEFT, RIGHT }
# Predicate on FlowDirection : vertical direction
static func isFlowDirectionVertical(dir):
match dir:
FlowDirection.UP:
return true
FlowDirection.DOWN:
return true
return false
# Predicate on FlowDirection : horizontal direction
static func isFlowDirectionHorizontal(dir):
match dir:
FlowDirection.LEFT:
return true
FlowDirection.RIGHT:
return true
return false
# Fields
var width: int # width
var height: int # height
var table: Array = [] # table = array of columns or rows depending on the direction
var flow_direction = FlowDirection.UP
# Constructor
func _init(width: int, height: int):
self.width = width
self.height = height
# By default, array is initialized with empty arrays
for x in range(0, width):
table.push_back(Array())
# Get flow direction
func get_flow_direction():
return self.flow_direction
# Set flow direction
func set_flow_direction(dir):
# Keep old values
var old_table = self.table
var old_dir = self.flow_direction
# Update the flow direction
self.flow_direction = dir
# Update the array to reflect the change in flow direction
self.table = []
if isFlowDirectionVertical(dir):
for nx in range(width):
self.table.push_back(Array())
for ny in range(height):
self.table[nx].push_back(false)
else:
for ny in range(height):
self.table.push_back(Array())
for nx in range(width):
self.table[ny].push_back(false)
# Set the real values
for i in range(width):
for j in range(height):
var old_idx = get_idx(i, j, old_dir)
var new_idx = get_idx(i, j, dir)
self.table[new_idx[0]][new_idx[1]] = old_table[old_idx[0]][old_idx[1]]
# Get the index in the table depending on the flow direction
func get_idx(x, y, dir = self.flow_direction):
match dir:
FlowDirection.UP:
return [x, y]
FlowDirection.DOWN:
return [x, height - 1 - y]
FlowDirection.LEFT:
return [y, x]
FlowDirection.RIGHT:
return [y, width - 1 - x]
# Get value at position
func at(x: int, y: int):
var idx = get_idx(x, y)
return self.table[idx[0]][idx[1]]
# Set value at position
func set_at(x: int, y: int, val):
var idx = get_idx(x, y)
self.table[idx[0]][idx[1]] = val
# Remove the values from a list of indexes
# To avoid problems, the items are removed from a descending lexicographical order of indexes
class IdxSorter:
static func higher_idx_first(a, b):
return (a[0] > b[0]) or ((a[0] == b[0]) and (a[1] > b[1]))
func remove_values(lst_idx: Array):
# Tranform the values
var new_idx = []
for idx in lst_idx:
new_idx.push_back(get_idx(idx[0], idx[1]))
new_idx.sort_custom(IdxSorter, "higher_idx_first")
for idx in new_idx:
self.table[idx[0]].remove(idx[1])
# Push a value to the grid, the position indicate the row or column to push to
func push_value(x: int, y: int, val):
var idx = get_idx(x, y)
self.table[idx[0]].push_back(val)
# Swap two values
func swap_values(x1: int, y1: int, x2: int, y2: int):
var v = self.at(x1, y1)
self.set_at(x1, y1, self.at(x2, y2))
self.set_at(x2, y2, v)