Files
przygody-pana-cegly/addons/rmsmartshape/lib/tuple.gd

143 lines
4.9 KiB
GDScript

@tool
extends RefCounted
class_name SS2D_IndexTuple
## Provides utility functions for handling and storing indices of two related points using Vector2i.
##
## Index tuples are considered equal if their elements are equal, regardless of their order:
## T(X, Y) <=> T(Y, X).
##
## For effectively working with containers, helper functions for arrays and dictionaries are
## provided that implement the above behavior.
## Returns the second tuple element that does not equal the given value.
## Returns -1 if neither element matches.
static func get_other_value(t: Vector2i, value: int) -> int:
if t.x == value:
return t.y
elif t.y == value:
return t.x
return -1
## Returns whether two tuples are equal. Two tuples are considered equal when both contain the same values regardless of order.
static func are_equal(t1: Vector2i, t2: Vector2i) -> bool:
return t1 == t2 or t1 == flip_elements(t2)
## Returns true when the tuple contains the given value.
static func has(t: Vector2i, value: int) -> bool:
return t.x == value or t.y == value
## Searches for an equal tuple in the given array and returns the index or -1 if not found.
## Incorporates the equality behavior.
static func array_find(tuple_array: Array[Vector2i], t: Vector2i) -> int:
for i in tuple_array.size():
if are_equal(tuple_array[i], t):
return i
return -1
## Returns whether the given tuple exists in the given array.
## Incorporates the equality behavior.
static func array_has(tuple_array: Array[Vector2i], t: Vector2i) -> bool:
return array_find(tuple_array, t) != -1
## Returns a list indices to tuples that contain the given value.
static func array_find_partial(tuple_array: Array[Vector2i], value: int) -> PackedInt32Array:
var out := PackedInt32Array()
for i in tuple_array.size():
if tuple_array[i].x == value or tuple_array[i].y == value:
out.push_back(i)
return out
## Transform the tuple into a normalized representation (elements in ascending order).
## Same as sort_ascending() at the moment.
## Useful in more optimized use-cases where certain assumptions can be made if all tuples share a
## normalized representation.
static func normalize_tuple(tuple: Vector2i) -> Vector2i:
return sort_ascending(tuple)
## Returns a tuple with elements in ascending order.
static func sort_ascending(tuple: Vector2i) -> Vector2i:
if tuple.x <= tuple.y:
return tuple
return flip_elements(tuple)
## Returns a tuple with x and y components switched.
static func flip_elements(tuple: Vector2i) -> Vector2i:
return Vector2i(tuple.y, tuple.x)
## Validates the keys of a dictionary to be correct tuple values and converts all Arrays to
## corresponding Vector2i values.
## Optionally also validates that values are of the given type.
## Exists mostly for backwards compatibility to allow a seamless transition from Array to Vector2i tuples.
static func dict_validate(dict: Dictionary, value_type: Variant = null) -> void:
# TODO: Maybe don't use asserts but push_warning and return true if successful
for key: Variant in dict.keys():
var value: Variant = dict[key]
if value_type != null:
assert(is_instance_of(value, value_type), "Incorrect value type in dictionary: " + var_to_str(value))
if key is Array or key is PackedInt32Array or key is PackedInt64Array:
var converted := Vector2i(int(key[0]), int(key[1]))
dict.erase(key)
dict[converted] = value
else:
assert(key is Vector2i, "Invalid tuple representation: %s. Should be Vector2i." % var_to_str(key))
## Get the value in a dictionary with the given tuple as key or a default value if it does not exist.
## Incorporates the equality behavior.
static func dict_get(dict: Dictionary, tuple: Vector2i, default: Variant = null) -> Variant:
if dict.has(tuple):
return dict[tuple]
return dict.get(flip_elements(tuple), default)
static func dict_has(dict: Dictionary, tuple: Vector2i) -> bool:
return dict.has(tuple) or dict.has(flip_elements(tuple))
static func dict_set(dict: Dictionary, tuple: Vector2i, value: Variant) -> void:
dict[dict_get_key(dict, tuple)] = value
## Removes the given entry from the dictionary. Returns true if a corresponding key existed, otherwise false.
static func dict_erase(dict: Dictionary, tuple: Vector2i) -> bool:
return dict.erase(dict_get_key(dict, tuple))
## Checks if there is an existing key for the given tuple or its flipped variant and returns it.
## If a key does not exist, returns the tuple as it is.
## Usually this function does not need to be invoked manually, as helpers for dictionary and array access exist.
static func dict_get_key(dict: Dictionary, tuple: Vector2i) -> Vector2i:
if not dict.has(tuple):
var flipped := flip_elements(tuple)
if dict.has(flipped):
return flipped
return tuple
## Returns a list of all dictionary keys (tuples) that contain the given value.
static func dict_find_partial(dict: Dictionary, value: int) -> Array[Vector2i]:
var out: Array[Vector2i] = []
for t: Vector2i in dict.keys():
if t.x == value or t.y == value:
out.push_back(t)
return out