Add stringify_variables method to misc.gd
This commit is contained in:
parent
97703eac04
commit
cacb5226bf
4 changed files with 170 additions and 1 deletions
2
dist/submodules/besseretests
vendored
2
dist/submodules/besseretests
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit cdd49246684d446c0115bc5cfbca289eaa5fe354
|
Subproject commit 4cd4f12f95f61a27d493c783e367008452745e8c
|
|
@ -45,6 +45,18 @@ class_name CoreConfiguration
|
||||||
@export var logui_background_color: Color
|
@export var logui_background_color: Color
|
||||||
## What font size the graphical log should have.
|
## What font size the graphical log should have.
|
||||||
@export var logui_font_size: int
|
@export var logui_font_size: int
|
||||||
|
|
||||||
|
@export_category("Miscellaneous")
|
||||||
|
## Shows or hides the type when calling [code]stringify_variables[/code].
|
||||||
|
@export var misc_stringify_show_type: bool
|
||||||
|
## Determines how [code]stringify_variables[/code] should display [class Color] variables.[br]
|
||||||
|
## Will display colors from [code]0[/code] to [code]255[/code] if [code]true[/code] or from [code]-1.0[/code] to [code]1.0[/code] if [code]false[/code].
|
||||||
|
@export var misc_stringify_color_range8: bool
|
||||||
|
## Determines if [class Array]s should be processed by [code]stringify_variables[/code].
|
||||||
|
@export var misc_stringify_array: bool
|
||||||
|
## Determines if [class Dictionary]s should be processed by [code]stringify_variables[/code].
|
||||||
|
@export var misc_stringify_dictionary: bool
|
||||||
|
|
||||||
@export_category("Easy Request Maker")
|
@export_category("Easy Request Maker")
|
||||||
## Determines how unsecure requests should be handled.
|
## Determines how unsecure requests should be handled.
|
||||||
@export var erm_unsecure_requests: CoreTypes.BlockadeLevel
|
@export var erm_unsecure_requests: CoreTypes.BlockadeLevel
|
||||||
|
@ -63,9 +75,17 @@ func _init() -> void:
|
||||||
logger_format = "%color%[%time%] [%level% %origin%] %message%"
|
logger_format = "%color%[%time%] [%level% %origin%] %message%"
|
||||||
logger_newlines_override = true
|
logger_newlines_override = true
|
||||||
logger_newlines_sizelimit = 40
|
logger_newlines_sizelimit = 40
|
||||||
|
|
||||||
# Log UI
|
# Log UI
|
||||||
logui_enabled = true
|
logui_enabled = true
|
||||||
logui_background_color = Color.BLACK # To disable the background, use Color.TRANSPARENT
|
logui_background_color = Color.BLACK # To disable the background, use Color.TRANSPARENT
|
||||||
logui_font_size = 14
|
logui_font_size = 14
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
misc_stringify_show_type = true
|
||||||
|
misc_stringify_color_range8 = true
|
||||||
|
misc_stringify_array = true
|
||||||
|
misc_stringify_dictionary = true
|
||||||
|
|
||||||
# Easy Request Maker
|
# Easy Request Maker
|
||||||
erm_unsecure_requests = CoreTypes.BlockadeLevel.BLOCK
|
erm_unsecure_requests = CoreTypes.BlockadeLevel.BLOCK
|
||||||
|
|
121
src/misc.gd
121
src/misc.gd
|
@ -21,6 +21,19 @@
|
||||||
## and generally make your life as a developer easier.
|
## and generally make your life as a developer easier.
|
||||||
extends CoreBaseModule
|
extends CoreBaseModule
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
var config_stringify_show_type: bool
|
||||||
|
var config_stringify_color_range8: bool
|
||||||
|
var config_stringify_array: bool
|
||||||
|
var config_stringify_dictionary: bool
|
||||||
|
|
||||||
|
# +++ module +++
|
||||||
|
func _pull_config() -> void:
|
||||||
|
config_stringify_show_type = core.config.misc_stringify_show_type
|
||||||
|
config_stringify_color_range8 = core.config.misc_stringify_color_range8
|
||||||
|
config_stringify_array = core.config.misc_stringify_array
|
||||||
|
config_stringify_dictionary = core.config.misc_stringify_dictionary
|
||||||
|
|
||||||
# +++ data type conversion +++
|
# +++ data type conversion +++
|
||||||
## Converts a number of bytes into mebibytes.[br]
|
## Converts a number of bytes into mebibytes.[br]
|
||||||
## [br]
|
## [br]
|
||||||
|
@ -125,6 +138,114 @@ func stringarray_to_array(array: Array[String]) -> Array:
|
||||||
func get_center(parent_size: Vector2, child_size: Vector2) -> Vector2:
|
func get_center(parent_size: Vector2, child_size: Vector2) -> Vector2:
|
||||||
return Vector2(parent_size.x/2-child_size.x/2, parent_size.y/2-child_size.y/2)
|
return Vector2(parent_size.x/2-child_size.x/2, parent_size.y/2-child_size.y/2)
|
||||||
|
|
||||||
|
## Makes variables as look correct inside strings.[br]
|
||||||
|
## Short examples:[br]
|
||||||
|
## [code]true[/code] -> [code]'true'[/code][br]
|
||||||
|
## [code]Vector2(69.064, PI)[/code] -> [code]'x=69.064 y=3.14159265358979'[/code][br]
|
||||||
|
## [code]"This is a test string"[/code] -> [code]'"This is a test string"'[/code][br]
|
||||||
|
## Full example:[br]
|
||||||
|
## [codeblock]
|
||||||
|
## Code:
|
||||||
|
## logger.diag(stringify_variables("Triggered %trigger% (pos=%position%, successful=%success%)", { "trigger": "shoot", "position": Vector2(5156.149, 581.69), "success": true }))
|
||||||
|
##
|
||||||
|
## Output:
|
||||||
|
## [16:44:35] [DIAG Test.gd] Triggered '"shoot"' (pos='x=5156.149 y=581.69', successful='true')
|
||||||
|
## [/codeblock]
|
||||||
|
func stringify_variables(template: String, variables: Dictionary, no_quotes: bool = false) -> String:
|
||||||
|
# To decrease allocations
|
||||||
|
var value
|
||||||
|
var type: String = ""
|
||||||
|
var replacement: String = ""
|
||||||
|
for placeholder in variables:
|
||||||
|
# Check key type
|
||||||
|
if typeof(placeholder) != TYPE_STRING:
|
||||||
|
logger.error("Invalid placeholder type '\"" + type_string(typeof(placeholder)) + "\", skipping")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Check for correct type
|
||||||
|
value = variables[placeholder]
|
||||||
|
|
||||||
|
match(typeof(value)):
|
||||||
|
# Primitives
|
||||||
|
Variant.Type.TYPE_NIL: replacement = "null"
|
||||||
|
Variant.Type.TYPE_BOOL: replacement = str(value)
|
||||||
|
Variant.Type.TYPE_INT: replacement = str(value)
|
||||||
|
Variant.Type.TYPE_FLOAT: replacement = str(value)
|
||||||
|
Variant.Type.TYPE_STRING: replacement = "\"" + value + "\""
|
||||||
|
Variant.Type.TYPE_STRING_NAME: replacement = "\"" + value + "\""
|
||||||
|
# Non-primitives
|
||||||
|
Variant.Type.TYPE_OBJECT: replacement = str(value)
|
||||||
|
Variant.Type.TYPE_COLOR:
|
||||||
|
if config_stringify_color_range8: replacement = "r=" + _sa(value.r8) + " g=" + _sa(value.g8) + " b=" + _sa(value.b8) + " a=" + _sa(value.a8)
|
||||||
|
else: replacement = "r=" + _sa(value.r) + " g=" + _sa(value.g) + " b=" + _sa(value.b) + " a=" + _sa(value.a)
|
||||||
|
Variant.Type.TYPE_RID: replacement = "id=" + _sa(value.get_id()) + " valid=" + _sa(value.is_valid())
|
||||||
|
Variant.Type.TYPE_ARRAY:
|
||||||
|
if config_stringify_array:
|
||||||
|
if value.size() == 0:
|
||||||
|
replacement = "[]"
|
||||||
|
else:
|
||||||
|
replacement = "[ "
|
||||||
|
for item in value:
|
||||||
|
if replacement == "[ ": replacement += _sa(item)
|
||||||
|
else: replacement += ", " + _sa(item)
|
||||||
|
replacement += " ]"
|
||||||
|
else: replacement = str(value)
|
||||||
|
Variant.Type.TYPE_DICTIONARY:
|
||||||
|
if config_stringify_dictionary:
|
||||||
|
if value.size() == 0: replacement = "{}"
|
||||||
|
else:
|
||||||
|
replacement = "{ "
|
||||||
|
for key in value:
|
||||||
|
if replacement == "{ ": replacement += _sa(key) + ": " + _sa(value[key])
|
||||||
|
else: replacement += ", " + _sa(key)
|
||||||
|
replacement += " }"
|
||||||
|
else: replacement = str(value)
|
||||||
|
# TODO: Packed Arrays
|
||||||
|
# Nodes & scripting
|
||||||
|
Variant.Type.TYPE_NODE_PATH: replacement = str(value)
|
||||||
|
Variant.Type.TYPE_CALLABLE: replacement = "valid=" + _sa(value.is_valid()) + " standard=" + _sa(value.is_standard()) + " object=" + _sa(value.get_object() ) + " method=" + value.get_method() + " args=" + _sa(value.get_bound_arguments())
|
||||||
|
Variant.Type.TYPE_SIGNAL: replacement = "name=" + _sa(value.get_name()) + " object=" + _sa(value.get_object())
|
||||||
|
# 2D
|
||||||
|
Variant.Type.TYPE_VECTOR2: replacement = "x=" + _sa(value.x) + " y=" + _sa(value.y)
|
||||||
|
Variant.Type.TYPE_VECTOR2I: replacement = "x=" + _sa(value.x) + " y=" + _sa(value.y)
|
||||||
|
Variant.Type.TYPE_RECT2: replacement = "size=" + _sa(value.size) + " pos=" + _sa(value.position) + " end=" + _sa(value.end)
|
||||||
|
Variant.Type.TYPE_RECT2I: replacement = "size=" + _sa(value.size) + " pos=" + _sa(value.position) + " end=" + _sa(value.end)
|
||||||
|
Variant.Type.TYPE_TRANSFORM2D: replacement = "x=" + _sa(value.x) + " y=" + _sa(value.y) + " origin=" + _sa(value.origin)
|
||||||
|
# 3D
|
||||||
|
Variant.Type.TYPE_VECTOR3: replacement = "x=" + _sa(value.x) + " y=" + _sa(value.y) + " z=" + _sa(value.z)
|
||||||
|
Variant.Type.TYPE_VECTOR3I: replacement = "x=" + _sa(value.x) + " y=" + _sa(value.y) + " z=" + _sa(value.z)
|
||||||
|
Variant.Type.TYPE_PLANE: replacement = "x=" + _sa(value.x) + " y=" + _sa(value.y) + " z=" + _sa(value.z) + " d=" + _sa(value.d) + " normal=" + _sa(value.normal)
|
||||||
|
Variant.Type.TYPE_QUATERNION: replacement = "x=" + _sa(value.x) + " y=" + _sa(value.y) + " z=" + _sa(value.z) + " w=" + _sa(value.w)
|
||||||
|
Variant.Type.TYPE_AABB: replacement = "size=" + _sa(value.size) + " pos=" + _sa(value.position) + " end=" + _sa(value.end)
|
||||||
|
Variant.Type.TYPE_TRANSFORM3D: replacement = "basis=" + _sa(value.basis) + " origin=" + _sa(value.origin)
|
||||||
|
Variant.Type.TYPE_BASIS: replacement = "x=" + _sa(value.x) + " y=" + _sa(value.y) + " z=" + _sa(value.z)
|
||||||
|
Variant.Type.TYPE_PROJECTION: replacement = "x=" + _sa(value.x) + " y=" + _sa(value.y) + " z=" + _sa(value.z) + " w=" + _sa(value.w)
|
||||||
|
# 4D
|
||||||
|
Variant.Type.TYPE_VECTOR4: replacement = "x=" + _sa(value.x) + " y=" + _sa(value.y) + " z=" + _sa(value.z) + " w=" + _sa(value.w)
|
||||||
|
Variant.Type.TYPE_VECTOR4I: replacement = "x=" + _sa(value.x) + " y=" + _sa(value.y) + " z=" + _sa(value.z) + " w=" + _sa(value.w)
|
||||||
|
# etc
|
||||||
|
Variant.Type.TYPE_MAX: replacement = str(value)
|
||||||
|
_:
|
||||||
|
replacement = str(value)
|
||||||
|
type = "(unknown) "
|
||||||
|
|
||||||
|
# Replace
|
||||||
|
if config_stringify_show_type and type == "":
|
||||||
|
match(typeof(value)):
|
||||||
|
Variant.Type.TYPE_NIL: type = ""
|
||||||
|
Variant.Type.TYPE_MAX: type = "(invalid) "
|
||||||
|
Variant.Type.TYPE_ARRAY:
|
||||||
|
if value.get_typed_builtin() != TYPE_NIL:
|
||||||
|
type = "(" + type_string(typeof(value)).to_lower() + "[" + type_string(typeof(value.get_typed_builtin())).to_lower() + "]) "
|
||||||
|
_: type = "(" + type_string(typeof(value)).to_lower() + ") " # something is causing almost everything to be displayed as a boolean, which is not true. i don't know what's the problem here however.
|
||||||
|
var quote: String = "'" if !no_quotes else ""
|
||||||
|
template = template.replace("%" + placeholder + "%", quote + type + replacement + quote)
|
||||||
|
return template
|
||||||
|
|
||||||
|
# Makes calls shorter
|
||||||
|
func _sa(value) -> String:
|
||||||
|
return stringify_variables("%var%", { "var": value }, true)
|
||||||
|
|
||||||
## Moved to [method Core.quit_safely].
|
## Moved to [method Core.quit_safely].
|
||||||
## @deprecated
|
## @deprecated
|
||||||
func quit_safely(exitcode: int = 0) -> void: await core.quit_safely(exitcode)
|
func quit_safely(exitcode: int = 0) -> void: await core.quit_safely(exitcode)
|
||||||
|
|
|
@ -156,3 +156,31 @@ func test_get_center() -> void:
|
||||||
return
|
return
|
||||||
|
|
||||||
rok()
|
rok()
|
||||||
|
|
||||||
|
# stringify_variables
|
||||||
|
func test_stringify_variables() -> void:
|
||||||
|
rskip("Unfinished")
|
||||||
|
return
|
||||||
|
# Init CORE
|
||||||
|
await load_framework()
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
var test_in_string: String = "[b]null[/b]=%null%\n[b]bool[/b]=%bool%\n[b]int[/b]=%int%\n[b]float[/b]=%float%\n[b]string[/b]=%string%\n[b]stringname[/b]=%stringname%\n[b]color[/b]=%color%\n[b]rid[/b]=%rid%\n[b]array[/b]=%array%\n[b]dict[/b]=%dictionary%\n[b]nodepath[/b]=%nodepath%\n[b]call[/b]=%callable%\n[b]signal[/b]=%signal%\n[b]vec2[/b]=%vector2%\n[b]vec2i[/b]=%vector2i%\n[b]rect2[/b]=%rect2%\n[b]rect2i[/b]=%rect2i%\n[b]trans2d[/b]=%transform2d%\n[b]vec3[/b]=%vector3%\n[b]vec3i[/b]=%vector3i%\n[b]plane[/b]=%plane%\n[b]quarternion[/b]=%quaternion%\n[b]aabb[/b]=%aabb%\n[b]trans3d[/b]=%transform3d%\n[b]basis[/b]=%basis%\n[b]projection[/b]=%projection%\n[b]vec4[/b]=%vector4%\n[b]vec4i[/b]=%vector4i%"
|
||||||
|
var test_in_args: Dictionary = { "null": null, "bool": true, "int": 505, "float": 505.69, "string": "some string", "stringname": "some string name", "color": Color("#d60532"), "rid": RenderingServer.get_white_texture(), "array": [ "item1", "item2", true, 4 ], "dictionary": { "key0": true, 1: "key2" }, "nodepath": NodePath("/root/CORE"), "callable": func() -> void: pass, "signal": core.logger.log_event, "vector2": Vector2(PI, TAU), "vector2i": Vector2i(505, 69), "rect2": Rect2(1.51, 2.56, 3.89, 4.11), "rect2i": Rect2i(1, 2, 3, 4), "transform2d": Transform2D(1.5, Vector2(2.1, 2.2), 3.6, Vector2(4.1, 4.2)), "vector3": Vector3(59.666, NAN, INF), "vector3i": Vector3i(505, 69, 1713208182), "plane": Plane(Vector3(1.5, 2.5, 3.5), 55.7777), "quaternion": Quaternion(1.55, 2.7812, 3.671, 4.8871), "aabb": AABB(Vector3(1.1, 1.2, 1.3), Vector3(2.1, 2.2, 2.3)), "transform3d": Transform3D(Basis(Vector3(1.11, 1.12, 1.13), Vector3(1.21, 1.22, 1.23), Vector3(1.31, 1.32, 1.33)), Vector3(2.1, 2.2, 2.3)), "basis": Basis(Vector3(1.1358, 1.268718, 1.35818), Vector3(2.1481, 2.258819, 2.3718), Vector3(3.1658581, 3.2581587, 3.357158)), "projection": Projection(Transform3D(Basis(Vector3(1.11, 1.12, 1.13), Vector3(1.21, 1.22, 1.23), Vector3(1.31, 1.32, 1.33)), Vector3(2.1, 2.2, 2.3))), "vector4": Vector4(1.55158, 2.517571, 3.58157, 4.51857185), "vector4i": Vector4i(1, 2, 3, 4) }
|
||||||
|
var test_out: String = "unfinished"
|
||||||
|
var test_result: String = core.misc.stringify_variables(test_in_string, test_in_args)
|
||||||
|
|
||||||
|
if test_result != test_out:
|
||||||
|
lerror("Got invalid test result:")
|
||||||
|
lerror("in (string) -> " + test_in_string.replace("\n", "\\n"))
|
||||||
|
await get_tree().create_timer(1).timeout # output overflow workaround
|
||||||
|
lerror("in (args) -> " + str(test_in_args))
|
||||||
|
await get_tree().create_timer(1).timeout # output overflow workaround
|
||||||
|
lerror("expected -> " + test_out.replace("\n", "\\n"))
|
||||||
|
await get_tree().create_timer(1).timeout # output overflow workaround
|
||||||
|
lerror("got -> " + test_result.replace("\n", "\\n"))
|
||||||
|
await get_tree().create_timer(1).timeout # output overflow workaround
|
||||||
|
rerror("Test did not return the right value (check logs)")
|
||||||
|
return
|
||||||
|
|
||||||
|
rok()
|
||||||
|
|
Loading…
Reference in a new issue