116 lines
3.5 KiB
GDScript
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)
|