272 lines
7.3 KiB
GDScript
272 lines
7.3 KiB
GDScript
# ############################################################################ #
|
|
# Copyright © 2015-2021 inkle Ltd.
|
|
# Copyright © 2019-2022 Frédéric Maquin <fred@ephread.com>
|
|
# All Rights Reserved
|
|
#
|
|
# This file is part of inkgd.
|
|
# inkgd is licensed under the terms of the MIT license.
|
|
# ############################################################################ #
|
|
|
|
extends RefCounted
|
|
|
|
class_name InkUtils
|
|
|
|
# ############################################################################ #
|
|
# Imports
|
|
# ############################################################################ #
|
|
|
|
const ValueType = preload("res://addons/inkgd/runtime/values/value_type.gd").ValueType
|
|
|
|
# ############################################################################ #
|
|
# Exceptions
|
|
# ############################################################################ #
|
|
|
|
static func throw_exception(message: String) -> void:
|
|
InkRuntime().handle_exception(message)
|
|
|
|
static func throw_story_exception(
|
|
message: String,
|
|
use_end_line_number = false,
|
|
metadata = null
|
|
) -> void:
|
|
InkRuntime().handle_story_exception(message, use_end_line_number, metadata)
|
|
|
|
static func throw_argument_exception(message: String) -> void:
|
|
InkRuntime().handle_argument_exception(message)
|
|
|
|
# ############################################################################ #
|
|
# Assertions
|
|
# ############################################################################ #
|
|
|
|
static func __assert__(condition: bool, message = "") -> void:
|
|
if !condition && message != "":
|
|
printerr(message)
|
|
|
|
assert(condition)
|
|
|
|
# ############################################################################ #
|
|
# Type Assertion
|
|
# ############################################################################ #
|
|
|
|
static func as_or_null(variant, name_of_class: String):
|
|
if (
|
|
is_ink_class(variant, name_of_class) ||
|
|
(name_of_class == "Dictionary" && variant is Dictionary) ||
|
|
(name_of_class == "Array" && variant is Array)
|
|
):
|
|
return variant
|
|
else:
|
|
return null
|
|
|
|
static func cast(variant, name_of_class: String):
|
|
if is_ink_class(variant, name_of_class):
|
|
return variant
|
|
else:
|
|
push_error(
|
|
"Original implementation threw a RuntimeException here, because of a " +
|
|
"cast issue. Undefined behaviors should be expected."
|
|
)
|
|
|
|
assert(false)
|
|
return null
|
|
|
|
static func as_INamedContent_or_null(variant):
|
|
var properties = variant.get_property_list()
|
|
|
|
var has_has_valid_name = false
|
|
var has_name = false
|
|
|
|
for property in properties:
|
|
if property["name"] == "has_valid_name":
|
|
has_has_valid_name = true
|
|
|
|
if has_has_valid_name && has_name:
|
|
return variant
|
|
elif property["name"] == "name":
|
|
has_name = true
|
|
|
|
if has_has_valid_name && has_name:
|
|
return variant
|
|
|
|
return null
|
|
|
|
static func is_ink_class(object: Variant, name_of_class: String) -> bool:
|
|
return (object is Object) && object.is_ink_class(name_of_class)
|
|
|
|
static func are_of_same_type(object1: Variant, object2: Variant) -> bool:
|
|
if (object1 is Object) && (object2 is Object):
|
|
return object1.get_ink_class() == object2.get_ink_class()
|
|
|
|
return typeof(object1) == typeof(object2)
|
|
|
|
static func value_type_name(value_type: int) -> String:
|
|
match value_type:
|
|
ValueType.BOOL: return "Boolean"
|
|
|
|
ValueType.INT: return "Int"
|
|
ValueType.FLOAT: return "Float"
|
|
ValueType.LIST: return "List"
|
|
ValueType.STRING: return "String"
|
|
|
|
ValueType.DIVERT_TARGET: return "Divert Target"
|
|
ValueType.VARIABLE_POINTER: return "Variable Pointer"
|
|
|
|
_: return "unknown"
|
|
|
|
static func typename_of(variant) -> String:
|
|
match typeof(variant):
|
|
TYPE_NIL: return "null"
|
|
TYPE_BOOL: return "bool"
|
|
TYPE_INT: return "int"
|
|
TYPE_FLOAT: return "float"
|
|
TYPE_STRING: return "String"
|
|
TYPE_VECTOR2: return "Vector2"
|
|
TYPE_RECT2: return "Rect2"
|
|
TYPE_VECTOR3: return "Vector3"
|
|
TYPE_TRANSFORM2D: return "Transform2D"
|
|
TYPE_PLANE: return "Plane"
|
|
TYPE_QUATERNION: return "Quaternion"
|
|
TYPE_AABB: return "AABB"
|
|
TYPE_BASIS: return "Basis"
|
|
TYPE_TRANSFORM3D: return "Transform3D"
|
|
TYPE_COLOR: return "Color"
|
|
TYPE_NODE_PATH: return "NodePath"
|
|
TYPE_RID: return "RID"
|
|
TYPE_OBJECT: return variant.get_ink_class()
|
|
TYPE_DICTIONARY: return "Dictionary"
|
|
TYPE_ARRAY: return "Array"
|
|
TYPE_PACKED_BYTE_ARRAY: return "PackedByteArray"
|
|
TYPE_PACKED_INT32_ARRAY: return "PackedInt32Array"
|
|
TYPE_PACKED_FLOAT32_ARRAY: return "PackedFloat32Array"
|
|
TYPE_PACKED_STRING_ARRAY: return "PackedStringArray"
|
|
TYPE_PACKED_VECTOR2_ARRAY: return "PackedVector2Array"
|
|
TYPE_PACKED_VECTOR3_ARRAY: return "PackedVector3Array"
|
|
TYPE_PACKED_COLOR_ARRAY: return "PackedColorArray"
|
|
_: return "unknown"
|
|
|
|
# ############################################################################ #
|
|
# String Utils
|
|
# ############################################################################ #
|
|
|
|
static func trim(string_to_trim: String, characters = []) -> String:
|
|
if characters.is_empty():
|
|
return string_to_trim.strip_edges()
|
|
|
|
var length = string_to_trim.length()
|
|
var beginning = 0
|
|
var end = length
|
|
|
|
var i = 0
|
|
while i < string_to_trim.length():
|
|
var character = string_to_trim[i]
|
|
if characters.find(character) != -1:
|
|
beginning += 1
|
|
else:
|
|
break
|
|
|
|
i += 1
|
|
|
|
i = string_to_trim.length() - 1
|
|
while i >= 0:
|
|
var character = string_to_trim[i]
|
|
if characters.find(character) != -1:
|
|
end -= 1
|
|
else:
|
|
break
|
|
|
|
i -= 1
|
|
|
|
if beginning == 0 && end == length:
|
|
return string_to_trim
|
|
|
|
return string_to_trim.substr(beginning, end - beginning)
|
|
|
|
# ############################################################################ #
|
|
# Array Utils
|
|
# ############################################################################ #
|
|
|
|
static func join(joiner: String, array: Array) -> String:
|
|
var joined_string = ""
|
|
|
|
var i = 0
|
|
for element in array:
|
|
var element_string
|
|
if is_ink_class(element, "InkBase"):
|
|
element_string = element._to_string()
|
|
else:
|
|
element_string = str(element)
|
|
|
|
joined_string += element_string
|
|
|
|
if i >= 0 && i < array.size() - 1:
|
|
joined_string += joiner
|
|
|
|
i += 1
|
|
|
|
return joined_string
|
|
|
|
static func get_range(array: Array, index: int, count: int) -> Array:
|
|
if !(index >= 0 && index < array.size()):
|
|
printerr("get_range: index (%d) is out of bounds." % index)
|
|
return array.duplicate()
|
|
|
|
if index + count > array.size():
|
|
printerr("get_range: [index (%d) + count (%d)] is out of bounds." % [index, count])
|
|
return array.duplicate()
|
|
|
|
var new_array = []
|
|
var i = index
|
|
var c = 0
|
|
|
|
while (c < count):
|
|
new_array.append(array[i + c])
|
|
c += 1
|
|
|
|
return new_array
|
|
|
|
static func remove_range(array: Array, index: int, count: int) -> void:
|
|
if !(index >= 0 && index < array.size()):
|
|
printerr("get_range: index (%d) is out of bounds." % index)
|
|
return
|
|
|
|
if index + count > array.size():
|
|
printerr("get_range: [index (%d) + count (%d)] is out of bounds." % [index, count])
|
|
return
|
|
|
|
var i = index
|
|
var c = 0
|
|
|
|
while (c < count):
|
|
array.remove_at(i)
|
|
c += 1
|
|
|
|
static func array_equal(a1: Array, a2: Array, use_equals = false) -> bool:
|
|
if a1.size() != a2.size():
|
|
return false
|
|
|
|
var i = 0
|
|
while (i < a1.size()):
|
|
var first_element = a1[i]
|
|
var second_element = a2[i]
|
|
|
|
if use_equals:
|
|
if !first_element.equals(second_element):
|
|
return false
|
|
else:
|
|
i += 1
|
|
continue
|
|
else:
|
|
if first_element != second_element:
|
|
return false
|
|
else:
|
|
i += 1
|
|
continue
|
|
|
|
i += 1
|
|
|
|
return true
|
|
|
|
# ############################################################################ #
|
|
|
|
static func InkRuntime():
|
|
return Engine.get_main_loop().root.get_node("__InkRuntime")
|