From 01a44db3998e4aea940c7a17ee7af2ae09656078 Mon Sep 17 00:00:00 2001 From: Jian-Hong Pan Date: Mon, 11 Nov 2024 18:27:29 +0800 Subject: [PATCH] BlockScriptSerialization: Re-generate block definition for object property blocks The drag & drop object property's blocks disappear after save & re-open the Godot project. And, shows error: core/variant/variant_utility.cpp:1092 - Cannot construct block from null block definition. res://addons/block_code/ui/block_canvas/block_canvas.gd:348 - Invalid call. Nonexistent function 'set_parameter_values_on_ready' in base 'Nil'. It is because the object property blocks are not the predefined blocks in the catalog. So, Block Coding plugin cannot find the block definition from the catalog when places the object property blocks into the cavas via _block_to_ast_node() after re-open the project. Therefore, introduce _get_obj_property_block_definition() generating object property's getter/setter block definition for get_block_definition(). Besides, it also needs the object property's value type. So, pass the AST node's arguments which is a Dictionary and may contain the "value" feild into get_block_definition(), too. https://phabricator.endlessm.com/T35649 --- .../block_script_serialization.gd | 62 ++++++++++++++----- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/addons/block_code/serialization/block_script_serialization.gd b/addons/block_code/serialization/block_script_serialization.gd index 5f3051e3..cc685c90 100644 --- a/addons/block_code/serialization/block_script_serialization.gd +++ b/addons/block_code/serialization/block_script_serialization.gd @@ -70,7 +70,7 @@ func instantiate_block(block_definition: BlockDefinition) -> Block: func instantiate_block_by_name(block_name: String) -> Block: - var block_definition := get_block_definition(block_name) + var block_definition := get_block_definition(block_name, {}) if block_definition == null: push_warning("Cannot find a block definition for %s" % block_name) @@ -79,24 +79,29 @@ func instantiate_block_by_name(block_name: String) -> Block: return instantiate_block(block_definition) -func get_block_definition(block_name: String) -> BlockDefinition: +func get_block_definition(block_name: String, arguments: Dictionary) -> BlockDefinition: var split := block_name.split(":", true, 1) + var block_definition: BlockDefinition if len(split) > 1: return _get_parameter_block_definition(split[0], split[1]) - var block_definition = _get_base_block_definition(block_name) + block_definition = _get_base_block_definition(block_name) + if block_definition != null: + return block_definition - if block_definition == null: - # FIXME: This is a workaround for old-style output block references. - # These were generated ahead of time using a block name that has - # a "_" before the parameter name. Now, these parameter blocks - # are generated on demand for any block name containing a ":". - # Please remove this fallback when it is no longer necessary. - split = block_name.rsplit("_", true, 1) - return _get_parameter_block_definition(split[0], split[1]) + var property_value = arguments.get("value", null) + block_definition = _get_obj_property_block_definition(block_name, property_value) + if block_definition != null: + return block_definition - return block_definition + # FIXME: This is a workaround for old-style output block references. + # These were generated ahead of time using a block name that has + # a "_" before the parameter name. Now, these parameter blocks + # are generated on demand for any block name containing a ":". + # Please remove this fallback when it is no longer necessary. + split = block_name.rsplit("_", true, 1) + return _get_parameter_block_definition(split[0], split[1]) func _get_base_block_definition(block_name: String) -> BlockDefinition: @@ -133,6 +138,33 @@ func _get_parameter_block_definition(block_name: String, parameter_name: String) return block_definition +func _get_obj_property_block_definition(block_name: String, property_value: Variant) -> BlockDefinition: + var block_definition: BlockDefinition + var variable: VariableDefinition + var property_name: String + var is_getter = true + + if block_name.find("get_var_") == 0: + property_name = block_name.get_slice("get_var_", 1) + elif block_name.find("set_var_") == 0: + property_name = block_name.get_slice("set_var_", 1) + is_getter = false + else: + return null + + if is_getter: + # Getter block needs the property name and variant type information by + # decoding block name + var split := property_name.rsplit("_", true, 1) + variable = VariableDefinition.new(split[0], int(split[1])) + block_definition = BlocksCatalog.get_property_getter_block_definition(variable) + else: + variable = VariableDefinition.new(property_name, typeof(property_value)) + block_definition = BlocksCatalog.get_property_setter_block_definition(variable) + + return block_definition + + func _update_block_definitions(): _available_blocks.clear() _available_blocks.append_array(_get_inherited_block_definitions()) @@ -202,7 +234,6 @@ func _tree_to_ast(tree: BlockSerializationTree) -> BlockAST: func _block_to_ast_node(node: BlockSerialization) -> BlockAST.ASTNode: var ast_node := BlockAST.ASTNode.new() - ast_node.data = get_block_definition(node.name) for arg_name in node.arguments: var argument = node.arguments[arg_name] @@ -210,6 +241,8 @@ func _block_to_ast_node(node: BlockSerialization) -> BlockAST.ASTNode: argument = _value_to_ast_value(argument) ast_node.arguments[arg_name] = argument + ast_node.data = get_block_definition(node.name, ast_node.arguments) + var children: Array[BlockAST.ASTNode] for c in node.children: children.append(_block_to_ast_node(c)) @@ -220,7 +253,6 @@ func _block_to_ast_node(node: BlockSerialization) -> BlockAST.ASTNode: func _value_to_ast_value(value_node: ValueBlockSerialization) -> BlockAST.ASTValueNode: var ast_value_node := BlockAST.ASTValueNode.new() - ast_value_node.data = get_block_definition(value_node.name) for arg_name in value_node.arguments: var argument = value_node.arguments[arg_name] @@ -228,6 +260,8 @@ func _value_to_ast_value(value_node: ValueBlockSerialization) -> BlockAST.ASTVal argument = _value_to_ast_value(argument) ast_value_node.arguments[arg_name] = argument + ast_value_node.data = get_block_definition(value_node.name, value_node.arguments) + return ast_value_node