Better prints messages (#46)

This commit is contained in:
Rafał Mikrut 2021-04-24 17:53:09 +02:00 committed by GitHub
parent 4d82f9f873
commit 4a4a1543d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 317 additions and 171 deletions

View File

@ -2,28 +2,21 @@ extends Node
var regression_test_project : bool = true # Set it to true in RegressionTestProject var regression_test_project : bool = true # Set it to true in RegressionTestProject
# Contains info about disabled classes ### Contains info about disabled classes and allows to take info about allowed methods
# Also allows to get list of available classes
var properties_exceptions : Array = [ # Globablly disabled functions for all classes
"user_data",
"config_file",
"",
"",
]
var function_exceptions : Array = [ var function_exceptions : Array = [
"_set_user_data",
"get_packet", # TODO "get_packet", # TODO
"create_from_mesh", "_gui_input", # TODO probably missing cherrypick #GH 47636
"_input",
"_unhandled_input",
"_unhandled_key_input",
"connect_to_signal", # Should be chrrypicked
# They exists without assigment like Class.method, because they may be a parent of other objects and children also should have disabled child.method, its children also etc. which is too much to do # They exists without assigment like Class.method, because they may be a parent of other objects and children also should have disabled child.method, its children also etc. which is too much to do
"connect_to_signal", # GH 47572 #"connect_to_signal", # GH 47572
"set_config_file", # GH 45997
"class_get_property", # GH 47573
"class_set_property", # GH 47573
"_editor_settings_changed",# GH 45979 "_editor_settings_changed",# GH 45979
"_submenu_timeout", # GH 45981 "_submenu_timeout", # GH 45981
"_gui_input", # GH 45998
"_unhandled_key_input", # GH 45998
"_thread_done", #GH 46000 "_thread_done", #GH 46000
"generate", #GH 46001 "generate", #GH 46001
"_proximity_group_broadcast", #GH 46002 "_proximity_group_broadcast", #GH 46002
@ -31,13 +24,10 @@ var function_exceptions : Array = [
"create_from", #GH 46004 "create_from", #GH 46004
"create_from_blend_shape", #GH 46004 "create_from_blend_shape", #GH 46004
"append_from", #GH 46004 "append_from", #GH 46004
"_unhandled_input", # TODO
"_input", # TODO
"_set_tile_data", #GH 46015 "_set_tile_data", #GH 46015
"get", #GH 46019 "get", #GH 46019
"instance_has", #GH 46020 "instance_has", #GH 46020
"get_var", #GH 46096 "get_var", #GH 46096
"force_drag", #GH 46114
"set_script", #GH 46120 "set_script", #GH 46120
"getvar", #GH 46019 "getvar", #GH 46019
"get_available_chars", #GH 46118 "get_available_chars", #GH 46118
@ -47,22 +37,16 @@ var function_exceptions : Array = [
"set_editor_hint", #GH 46252 "set_editor_hint", #GH 46252
"get_item_at_position", #TODO hard to find "get_item_at_position", #TODO hard to find
"set_probe_data", #GH 46570 "set_probe_data", #GH 46570
"_range_click_timeout", "_range_click_timeout", #GH 46648
"draw", #GH 46648
"get_indexed", #GH 46019 "get_indexed", #GH 46019
"_vp_input", # TODO
"_vp_unhandled_input", # TODO
"remove_joy_mapping", #GH 46754
"add_joy_mapping", #GH 46754
"add_vertex", #GH 47066 "add_vertex", #GH 47066
"create_client", # TODO, strange memory leak "create_client", # TODO, strange memory leak
"create_shape_owner", #47135 "create_shape_owner", #47135
"shape_owner_get_owner", #47135 "shape_owner_get_owner", #47135
"collide", #GH 46137 "get_bind_bone", #GH 47358
"collide_and_get_contacts", #GH 46137 "get_bind_name", #GH 47358
"collide_with_motion", #GH 46137 "get_bind_pose", #GH 47358
"collide_with_motion_and_get_contacts", #GH 46137
# TODO Check this later # TODO Check this later
"propagate_notification", "propagate_notification",
@ -162,67 +146,10 @@ var function_exceptions : Array = [
"raise", "raise",
"add_child", "add_child",
"add_child_below_node", "add_child_below_node",
] "add_sibling",
var exported : Array = [
"get_bind_bone",
"get_bind_name",
"get_bind_pose",
] ]
# List of slow functions, which may frooze project(not simple executing each function alone) # Globally disabled classes which causes bugs or are very hard to us
var slow_functions : Array = [
"interpolate_baked",
"get_baked_length",
"get_baked_points",
"get_closest_offset",
"get_closest_point", # Only Curve, but looks that a lot of other classes uses this
"get_baked_up_vectors",
"interpolate_baked_up_vector",
"tessellate",
"get_baked_tilts",
"set_enabled_inputs",
"grow_mask",
"force_update_transform",
# In 3d view some options are really slow, needs to be limited
"set_rings",
"set_amount", # Particles
# Just a little slow functions
"is_enabler_enabled",
"set_enabler",
"get_aabb",
"set_aabb",
"is_on_screen"
]
# Specific classes which are initialized in specific way e.g. var undo_redo = get_undo_redo() instead var undo_redo = UndoRedo.new()
var only_instance : Array = [
"UndoRedo",
"Object",
"JSONRPC",
"MainLoop",
"SceneTree",
"ARVRPositionalTracker",
]
var invalid_signals : Array = [
"multi_selected",
"item_collapsed",
"button_pressed",
"",
"",
"",
# Probably Vararg
"tween_step",
"tween_completed",
"tween_started",
"data_channel_received",
"",
]
# Used only in ValueCreator
var disabled_classes : Array = [ var disabled_classes : Array = [
"ProjectSettings", # Don't mess with project settings, because they can broke entire your workflow "ProjectSettings", # Don't mess with project settings, because they can broke entire your workflow
"EditorSettings", # Also don't mess with editor settings "EditorSettings", # Also don't mess with editor settings
@ -239,6 +166,8 @@ var disabled_classes : Array = [
"IP_Unix", "IP_Unix",
"JNISingleton", "JNISingleton",
# Only one class - JavaClass returns Null when using JavaClass.new().get_class
"JavaClass",
# Just don't use these because they are not normal things # Just don't use these because they are not normal things
"_Thread", "_Thread",
@ -246,53 +175,63 @@ var disabled_classes : Array = [
"_Mutex", "_Mutex",
] ]
# GH 47358
func _init():
function_exceptions.append_array(exported)
# Checks if function can be executed # Checks if function can be executed
# Looks at its arguments an # Looks at its arguments an
func check_if_is_allowed(method_data : Dictionary) -> bool: func check_if_is_allowed(method_data : Dictionary) -> bool:
# Function is virtual, so we just skip it # Function is virtual or vararg, so we just skip it
if method_data["flags"] == method_data["flags"] | METHOD_FLAG_VIRTUAL: if method_data["flags"] == method_data["flags"] | METHOD_FLAG_VIRTUAL:
return false return false
if method_data["flags"] == method_data["flags"] | 128: # VARARG TODO, Godot issue, add missing flag binding
return false
for arg in method_data["args"]: for arg in method_data["args"]:
var name_of_class : String = arg["class_name"] var name_of_class : String = arg["class_name"]
if name_of_class.empty(): if name_of_class.empty():
continue continue
if !ClassDB.class_exists(name_of_class): # This is enum not object, but we allow it
continue
if name_of_class in disabled_classes: if name_of_class in disabled_classes:
return false return false
if name_of_class.find("Server") != -1 && ClassDB.class_exists(name_of_class) && !ClassDB.is_parent_class(name_of_class,"Reference"): if name_of_class.find("Server") != -1 && ClassDB.class_exists(name_of_class) && !ClassDB.is_parent_class(name_of_class,"Reference"):
return false return false
if name_of_class.find("Editor") != -1: # TODO not sure about it # Editor stuff usually aren't good choice for arhuments
if name_of_class.find("Editor") != -1 || name_of_class.find("SkinReference") != -1:
return false
# In case of adding new type, this prevents from crashing due not recognizing this type
# In case of removing/rename type, just comment e.g. TYPE_ARRAY and all occurencies on e.g. switch statement with it
var t : int = arg["type"]
if !(t == TYPE_NIL || t == TYPE_AABB || t == TYPE_ARRAY || t == TYPE_BASIS || t == TYPE_BOOL || t == TYPE_COLOR || t == TYPE_COLOR_ARRAY || t == TYPE_DICTIONARY || t == TYPE_INT || t == TYPE_INT_ARRAY || t == TYPE_NODE_PATH || t == TYPE_OBJECT || t == TYPE_PLANE || t == TYPE_QUAT || t == TYPE_RAW_ARRAY || t == TYPE_REAL || t == TYPE_REAL_ARRAY || t == TYPE_RECT2 || t == TYPE_RID || t == TYPE_STRING || t == TYPE_TRANSFORM || t == TYPE_TRANSFORM2D || t == TYPE_VECTOR2 || t == TYPE_VECTOR2_ARRAY || t == TYPE_VECTOR3 || t == TYPE_VECTOR3_ARRAY):
print("----------------------------------------------------------- TODO - MISSING TYPE, ADD SUPPORT IT") # Add assert here to get info which type is missing
return false return false
#This is only for RegressionTestProject, because it needs for now clear visual info what is going on screen, but some nodes broke view #This is only for RegressionTestProject, because it needs for now clear visual info what is going on screen, but some nodes broke view
if regression_test_project: if regression_test_project:
# That means that this is constant, not class
if !ClassDB.class_exists(name_of_class):
continue
if !ClassDB.is_parent_class(name_of_class, "Node") && !ClassDB.is_parent_class(name_of_class, "Reference"): if !ClassDB.is_parent_class(name_of_class, "Node") && !ClassDB.is_parent_class(name_of_class, "Reference"):
return false return false
# In case of adding new type, this prevents from crashing due not recognizing this type
var t : int = arg["type"]
if !(t == TYPE_NIL || t == TYPE_AABB || t == TYPE_ARRAY || t == TYPE_BASIS || t == TYPE_BOOL || t == TYPE_COLOR || t == TYPE_COLOR_ARRAY || t == TYPE_DICTIONARY || t == TYPE_INT || t == TYPE_INT_ARRAY || t == TYPE_NODE_PATH || t == TYPE_OBJECT || t == TYPE_PLANE || t == TYPE_QUAT || t == TYPE_RAW_ARRAY || t == TYPE_REAL || t == TYPE_REAL_ARRAY || t == TYPE_RECT2 || t == TYPE_RID || t == TYPE_STRING || t == TYPE_TRANSFORM || t == TYPE_TRANSFORM2D || t == TYPE_VECTOR2 || t == TYPE_VECTOR2_ARRAY || t == TYPE_VECTOR3 || t == TYPE_VECTOR3_ARRAY):
print("----------------------------------------------------------- TODO - MISSING TYPE, ADD SUPPORT IT")
return false
return true return true
# Return all available classes to instance and test func remove_disabled_methods(method_list : Array, exceptions : Array) -> void:
for exception in exceptions:
var index: int = -1
for method_index in range(method_list.size()):
if method_list[method_index]["name"] == exception:
index = method_index
break
if index != -1:
method_list.remove(index)
# Return all available classes which can be used
func get_list_of_available_classes(must_be_instantable : bool = true) -> Array: func get_list_of_available_classes(must_be_instantable : bool = true) -> Array:
var full_class_list : Array = Array(ClassDB.get_class_list()) var full_class_list : Array = Array(ClassDB.get_class_list())
var classes : Array = [] var classes : Array = []
full_class_list.sort() full_class_list.sort()
var c = 0 var c = 0
var rr = 0 # var rr = 0
for name_of_class in full_class_list: for name_of_class in full_class_list:
rr += 1 # rr += 1
if name_of_class in disabled_classes: if name_of_class in disabled_classes:
continue continue
@ -306,7 +245,7 @@ func get_list_of_available_classes(must_be_instantable : bool = true) -> Array:
if name_of_class.find("Server") != -1 && !ClassDB.is_parent_class(name_of_class,"Reference"): if name_of_class.find("Server") != -1 && !ClassDB.is_parent_class(name_of_class,"Reference"):
continue continue
if name_of_class.find("Editor") != -1: # TODO not sure about it if name_of_class.find("Editor") != -1 && regression_test_project:
continue continue

View File

@ -1,18 +1,32 @@
extends Node extends Node
# Execute every object function ### Script:
### - takes all available classes
### - checks if method is allowed
### - checks each argument if is allowed(in case e.g. adding new, to prevent crashes due not recognizing types)
### - print info if needed to console
### - execute function with parameters
var debug_print: bool = true var debug_print: bool = true
var add_to_tree: bool = false # Adds nodes to tree, freeze godot when removing a lot of nodes var add_to_tree: bool = false # Adds nodes to tree, freeze godot when removing a lot of nodes
var use_parent_methods: bool = false # Allows Node2D use Node methods etc. - it is a little slow option which rarely shows var use_parent_methods: bool = false # Allows Node2D use Node methods etc. - it is a little slow option which rarely shows
var use_always_new_object: bool = true # Don't allow to "remeber" other function effects var use_always_new_object: bool = true # Don't allow to "remeber" other function effects
var exiting: bool = true var exiting: bool = false
func _ready() -> void: func _ready() -> void:
if BasicData.regression_test_project:
ValueCreator.random = false # Results in RegressionTestProject must be always reproducible
else:
ValueCreator.random = true
ValueCreator.number = 100
ValueCreator.should_be_always_valid = false
if BasicData.regression_test_project: if BasicData.regression_test_project:
tests_all_functions() tests_all_functions()
func _process(_delta: float) -> void: func _process(_delta: float) -> void:
if !BasicData.regression_test_project: if !BasicData.regression_test_project:
tests_all_functions() tests_all_functions()
@ -23,44 +37,54 @@ func _process(_delta: float) -> void:
# Test all functions # Test all functions
func tests_all_functions() -> void: func tests_all_functions() -> void:
for name_of_class in BasicData.get_list_of_available_classes(): for name_of_class in BasicData.get_list_of_available_classes():
if debug_print:
print("\n#################### " + name_of_class + " ####################")
var object: Object = ClassDB.instance(name_of_class) var object: Object = ClassDB.instance(name_of_class)
assert(object != null, "Object must be instantable")
if add_to_tree: if add_to_tree:
if object is Node: if object is Node:
add_child(object) add_child(object)
var method_list: Array = ClassDB.class_get_method_list(name_of_class, !use_parent_methods) var method_list: Array = ClassDB.class_get_method_list(name_of_class, !use_parent_methods)
## Exception # Removes excluded methods
for exception in BasicData.function_exceptions: BasicData.remove_disabled_methods(method_list, BasicData.function_exceptions)
var index: int = -1
for method_index in range(method_list.size()):
if method_list[method_index]["name"] == exception:
index = method_index
break
if index != -1:
method_list.remove(index)
if debug_print:
print("#################### " + name_of_class +" ####################")
for _i in range(1): for _i in range(1):
for method_data in method_list: for method_data in method_list:
if !BasicData.check_if_is_allowed(method_data): if !BasicData.check_if_is_allowed(method_data):
continue continue
if debug_print: var arguments: Array = ParseArgumentType.parse_and_return_objects(method_data, name_of_class, debug_print)
print(name_of_class + "." + method_data["name"])
if debug_print:
var to_print: String = "GDSCRIPT CODE: "
if (
ClassDB.is_parent_class(name_of_class, "Object")
&& !ClassDB.is_parent_class(name_of_class, "Node")
&& !ClassDB.is_parent_class(name_of_class, "Reference")
&& !ClassDB.class_has_method(name_of_class, "new")
):
to_print += "ClassDB.instance(\"" + name_of_class + "\")." + method_data["name"] + "("
else:
to_print += name_of_class.trim_prefix("_") + ".new()." + method_data["name"] + "("
for i in arguments.size():
to_print += ParseArgumentType.return_gdscript_code_which_run_this_object(arguments[i])
if i != arguments.size() - 1:
to_print += ", "
to_print += ")"
print(to_print)
var arguments: Array = ParseArgumentType.parse_and_return_objects(method_data, debug_print)
object.callv(method_data["name"], arguments) object.callv(method_data["name"], arguments)
for argument in arguments: for argument in arguments:
if argument != null: if argument is Node:
if argument is Node: argument.queue_free()
argument.queue_free() elif argument is Object && !(argument is Reference):
elif argument is Object && !(argument is Reference): argument.free()
argument.free()
if use_always_new_object: if use_always_new_object:
assert(object != null, "Object must be instantable")
if object is Node: if object is Node:
object.queue_free() object.queue_free()
elif object is Object && !(object is Reference): elif object is Object && !(object is Reference):

View File

@ -1,7 +1,9 @@
extends Node extends Node
# Parse arguments and return needed info/objects etc. ### Scripts to arguments and return needed info about them.
### Class which contains informations about used
class SingleArgument: class SingleArgument:
var name: String # E.G. var roman, can be empty, so temp variable isn't created(nodes and objects must be created with temp_variable due to memory leaks) var name: String # E.G. var roman, can be empty, so temp variable isn't created(nodes and objects must be created with temp_variable due to memory leaks)
var type: String # np. Vector2 or Object var type: String # np. Vector2 or Object
@ -15,10 +17,6 @@ class SingleArgument:
func create_gdscript_arguments(arguments: Array) -> Array: func create_gdscript_arguments(arguments: Array) -> Array:
var argument_array: Array = [] var argument_array: Array = []
ValueCreator.number = 10
ValueCreator.random = true
ValueCreator.should_be_always_valid = true # DO NOT CHANGE, BECAUSE NON VALID VALUES WILL SHOW GDSCRIPT ERRORS!
var counter = 0 var counter = 0
for argument in arguments: for argument in arguments:
counter += 1 counter += 1
@ -122,17 +120,9 @@ func create_gdscript_arguments(arguments: Array) -> Array:
return argument_array return argument_array
func parse_and_return_objects(method_data: Dictionary, debug_print: bool = false) -> Array: func parse_and_return_objects(method_data: Dictionary, name_of_class: String, debug_print: bool = false) -> Array:
var arguments_array: Array = [] var arguments_array: Array = []
if BasicData.regression_test_project:
ValueCreator.number = 100
ValueCreator.random = false # Results in RegressionTestProject must be always reproducible
else:
ValueCreator.number = 1000
ValueCreator.random = true
ValueCreator.should_be_always_valid = false
for argument in method_data["args"]: for argument in method_data["args"]:
match argument.type: match argument.type:
TYPE_NIL: # Looks that this means VARIANT not null TYPE_NIL: # Looks that this means VARIANT not null
@ -213,5 +203,196 @@ func parse_and_return_objects(method_data: Dictionary, debug_print: bool = false
assert(false, "Missing type, needs to be added to project") assert(false, "Missing type, needs to be added to project")
if debug_print: if debug_print:
print("Parameters " + str(arguments_array)) print("\n" + name_of_class + "." + method_data["name"] + " --- executing with " + str(arguments_array.size()) + " parameters " + str(arguments_array))
return arguments_array return arguments_array
func return_gdscript_code_which_run_this_object(data) -> String:
if data == null:
return "null"
var return_string: String = ""
match typeof(data):
TYPE_NIL: # Looks that this means VARIANT not null
assert("false", "This is even possible?")
TYPE_AABB:
return_string = "AABB("
return_string += return_gdscript_code_which_run_this_object(data.position)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.size)
return_string += ")"
TYPE_ARRAY:
return_string = "Array(["
for i in data.size():
return_string += return_gdscript_code_which_run_this_object(data[i])
if i != data.size() - 1:
return_string += ", "
return_string += "])"
TYPE_BASIS:
return_string = "Basis("
return_string += return_gdscript_code_which_run_this_object(data.x)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.y)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.z)
return_string += ")"
TYPE_BOOL:
if data == true:
return_string = "true"
else:
return_string = "false"
TYPE_COLOR:
return_string = "Color("
return_string += return_gdscript_code_which_run_this_object(data.r)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.g)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.b)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.a)
return_string += ")"
TYPE_COLOR_ARRAY:
return_string = "PoolColorArray(["
for i in data.size():
return_string += return_gdscript_code_which_run_this_object(data[i])
if i != data.size() - 1:
return_string += ", "
return_string += "])"
TYPE_DICTIONARY:
return_string = "{"
for i in data.size():
return_string += return_gdscript_code_which_run_this_object(data.keys()[i])
return_string += " : "
return_string += return_gdscript_code_which_run_this_object(data.values()[i])
if i != data.size() - 1:
return_string += ", "
return_string += "}"
TYPE_INT:
return_string = str(data)
TYPE_INT_ARRAY:
return_string = "PoolIntArray(["
for i in data.size():
return_string += return_gdscript_code_which_run_this_object(data[i])
if i != data.size() - 1:
return_string += ", "
return_string += "])"
TYPE_NODE_PATH:
return_string = "NodePath("
return_string += return_gdscript_code_which_run_this_object(str(data))
return_string += ")"
TYPE_OBJECT:
if data == null:
return_string = "null"
else:
var name_of_class: String = data.get_class()
if (
ClassDB.is_parent_class(name_of_class, "Object")
&& !ClassDB.is_parent_class(name_of_class, "Node")
&& !ClassDB.is_parent_class(name_of_class, "Reference")
&& !ClassDB.class_has_method(name_of_class, "new")
):
return_string += "ClassDB.instance(\"" + name_of_class + "\")"
else:
return_string = name_of_class.trim_prefix("_")
return_string += ".new()"
TYPE_PLANE:
return_string = "Plane("
return_string += return_gdscript_code_which_run_this_object(data.x)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.y)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.z)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.d)
return_string += ")"
TYPE_QUAT:
return_string = "Quat("
return_string += return_gdscript_code_which_run_this_object(data.x)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.y)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.z)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.w)
return_string += ")"
TYPE_RAW_ARRAY:
return_string = "PoolByteArray(["
for i in data.size():
return_string += return_gdscript_code_which_run_this_object(data[i])
if i != data.size() - 1:
return_string += ", "
return_string += "])"
TYPE_REAL:
return_string = str(data)
TYPE_REAL_ARRAY:
return_string = "PoolRealArray(["
for i in data.size():
return_string += return_gdscript_code_which_run_this_object(data[i])
if i != data.size() - 1:
return_string += ", "
return_string += "])"
TYPE_RECT2:
return_string = "Rect2("
return_string += return_gdscript_code_which_run_this_object(data.position)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.size)
return_string += ")"
TYPE_RID:
return_string = "RID()"
TYPE_STRING:
return_string = "\"" + data + "\""
TYPE_STRING_ARRAY:
return_string = "PoolStringArray(["
for i in data.size():
return_string += return_gdscript_code_which_run_this_object(data[i])
if i != data.size() - 1:
return_string += ", "
return_string += "])"
TYPE_TRANSFORM:
return_string = "Transform("
return_string += return_gdscript_code_which_run_this_object(data.basis)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.origin)
return_string += ")"
TYPE_TRANSFORM2D:
return_string = "Transform2D("
return_string += return_gdscript_code_which_run_this_object(data.x)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.y)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.origin)
return_string += ")"
TYPE_VECTOR2:
return_string = "Vector2("
return_string += return_gdscript_code_which_run_this_object(data.x)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.y)
return_string += ")"
TYPE_VECTOR2_ARRAY:
return_string = "PoolVector2Array(["
for i in data.size():
return_string += return_gdscript_code_which_run_this_object(data[i])
if i != data.size() - 1:
return_string += ", "
return_string += "])"
TYPE_VECTOR3:
return_string = "Vector3("
return_string += return_gdscript_code_which_run_this_object(data.x)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.y)
return_string += ", "
return_string += return_gdscript_code_which_run_this_object(data.z)
return_string += ")"
TYPE_VECTOR3_ARRAY:
return_string = "PoolVector3Array(["
for i in data.size():
return_string += return_gdscript_code_which_run_this_object(data[i])
if i != data.size() - 1:
return_string += ", "
return_string += "])"
_:
assert(false, "Missing type, needs to be added to project")
return return_string

View File

@ -50,18 +50,19 @@ A scene that will probably give people a hard time quite often is `FunctionExecu
This is a fuzzer, but with removed ability to use random argument values (the arguments are identical every time it is run). This is a fuzzer, but with removed ability to use random argument values (the arguments are identical every time it is run).
When the engine crashes, in logs usually will be something like this: When the engine crashes, in logs usually will be something like this:
``` ```
#################### SkeletonModification2DPhysicalBones #################### #################### LineEdit ####################
SkeletonModification2DPhysicalBones.set_physical_bone_node
Parameters [100, ] LineEdit._text_changed --- executing with 0 parameters []
ERROR: Joint index out of range! GDSCRIPT CODE: LineEdit.new()._text_changed()
at: set_physical_bone_node (scene/resources/skeleton_modification_2d_physicalbones.cpp:259)
SkeletonModification2DPhysicalBones.get_physical_bone_node LineEdit._toggle_draw_caret --- executing with 0 parameters []
Parameters [100] GDSCRIPT CODE: LineEdit.new()._toggle_draw_caret()
ERROR: Joint index out of range!
at: get_physical_bone_node (scene/resources/skeleton_modification_2d_physicalbones.cpp:265) LineEdit.set_align --- executing with 1 parameters [100]
SkeletonModification2DPhysicalBones.fetch_physical_bones GDSCRIPT CODE: LineEdit.new().set_align(100)
Parameters [] ERROR: set_align: Index (int)p_align = 100 is out of bounds (4 = 4).
scene/resources/skeleton_modification_2d_physicalbones.cpp:186:2: runtime error: member access within null pointer of type 'struct SkeletonModificationStack2D' At: scene/gui/line_edit.cpp:592.
scene/resources/line_edit.cpp:186:2: runtime error: member access within null pointer of type 'struct LineEdit'
handle_crash: Program crashed with signal 11 handle_crash: Program crashed with signal 11
Dumping the backtrace. Please include this when reporting the bug on godotengine/godot/issues Dumping the backtrace. Please include this when reporting the bug on godotengine/godot/issues
[1] bin/godot.linuxbsd.tools.64s() [0x1e697d8] (/home/runner/work/godot/godot/platform/linuxbsd/crash_handler_linuxbsd.cpp:54) [1] bin/godot.linuxbsd.tools.64s() [0x1e697d8] (/home/runner/work/godot/godot/platform/linuxbsd/crash_handler_linuxbsd.cpp:54)
@ -70,24 +71,24 @@ Dumping the backtrace. Please include this when reporting the bug on godotengine
There are some interesting things to discuss here. There are some interesting things to discuss here.
This line shows what class we are testing now This line shows what class we are testing now
``` ```
#################### SkeletonModification2DPhysicalBones #################### #################### LineEdit ####################
``` ```
which method which method
``` ```
SkeletonModification2DPhysicalBones.set_physical_bone_node LineEdit.set_align
``` ```
and which parameters (here are two arguments - `100`, \` \`(empty string)) and which parameters
``` ```
Parameters [100, ] --- executing with 1 parameters [100]
``` ```
To make testing easier, each object is created from scratch and by looking at the class definition in Godot - `set_physical_bone_node(int, String)` we can create an expression that is executed on this line: Next you can see GDScript command which is executed and you can copy it and test manually in Godot
``` ```
SkeletonModification2DPhysicalBones.new().set_physical_bone_node(100,"") GDSCRIPT CODE: LineEdit.new()._toggle_draw_caret()
``` ```
Then you can see errors caused by invalid arguments, which you can ignore if they don't cause other crashes/leaks etc. Then you can see errors caused by invalid arguments, which you can ignore if they don't cause other crashes/leaks etc.
``` ```
ERROR: Joint index out of range! ERROR: set_align: Index (int)p_align = 100 is out of bounds (4 = 4).
at: get_physical_bone_node (scene/resources/skeleton_modification_2d_physicalbones.cpp:265) At: scene/gui/line_edit.cpp:592.
``` ```
At the end we can see Godot's crash log with additional information that tried to use null pointer incorrectly: At the end we can see Godot's crash log with additional information that tried to use null pointer incorrectly:
``` ```
@ -97,14 +98,14 @@ Dumping the backtrace. Please include this when reporting the bug on godotengine
[1] bin/godot.linuxbsd.tools.64s() [0x1e697d8] (/home/runner/work/godot/godot/platform/linuxbsd/crash_handler_linuxbsd.cpp:54) [1] bin/godot.linuxbsd.tools.64s() [0x1e697d8] (/home/runner/work/godot/godot/platform/linuxbsd/crash_handler_linuxbsd.cpp:54)
[2] /lib/x86_64-linux-gnu/libc.so.6(+0x46210) [0x7fd1ca5b0210] (??:0) [2] /lib/x86_64-linux-gnu/libc.so.6(+0x46210) [0x7fd1ca5b0210] (??:0)
``` ```
we can assume that this is caused by calling the function immediately before the crash: In most situations, the latest executed function/created object is responsible for crash
``` ```
SkeletonModification2DPhysicalBones.fetch_physical_bones LineEdit.set_align --- executing with 1 parameters [100]
Parameters [] GDSCRIPT CODE: LineEdit.new().set_align(100)
``` ```
We can test this by running a function in Godot that looks like this(just add `.new()` after class name and fill function arguments from `Parameters`): So we can just take GDScript code from above, copy it into Godot and test project, which should crash engine
``` ```
SkeletonModification2DPhysicalBones.new().fetch_physical_bones() LineEdit.new().set_align(100)
``` ```
## Nodes ## Nodes
@ -125,7 +126,8 @@ Scenes like `Physics2D.tscn` or `Lights3D.tscn` are normal scenes with specific
## 4.0 version limitations ## 4.0 version limitations
ReparentingDeleting is in 4.0 only Reparenting - bug https://github.com/godotengine/godot/issues/45471 ReparentingDeleting is in 4.0 only Reparenting - bug https://github.com/godotengine/godot/issues/45471
Some scenes available in 3.x branch, but due freezes and long loading times are disabled. Some scenes available in 3.x branch, but due freezes and long loading times are disabled(mostly Vulkan fault).
Some patches are applied to e.g. handle rename `OS` -> `Platform` or `Transform` -> `Transform3D`
## Epilepsy Warning ## Epilepsy Warning
Due using by project a lot of functions from each type of Node, screen may flicker, images and objects may change randomly color and size which may lead some users to health problems. Due using by project a lot of functions from each type of Node, screen may flicker, images and objects may change randomly color and size which may lead some users to health problems.