Skip to content

Commit 3cfcf76

Browse files
authored
Merge pull request #316 from endlessm/T35649-fix-drag-drop-obj-property
BlockScriptSerialization: Re-generate block definition for object property blocks
2 parents b71d679 + 5c3358d commit 3cfcf76

File tree

4 files changed

+125
-57
lines changed

4 files changed

+125
-57
lines changed

addons/block_code/block_code_node/block_code.gd

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ extends Node
55

66
const TxUtils := preload("res://addons/block_code/translation/utils.gd")
77

8-
@export var block_script: BlockScriptSerialization = null
8+
@export var block_script: BlockScriptSerialization = null:
9+
set = _set_block_script
910

1011

1112
func _init():
@@ -37,6 +38,17 @@ func _enter_tree():
3738
block_script = new_block_script
3839

3940

41+
func _set_block_script(value):
42+
if value == null:
43+
# Wipe out the bidirectional link between this block code node and the
44+
# block script
45+
if block_script:
46+
block_script.block_code_node = null
47+
else:
48+
value.block_code_node = self
49+
block_script = value
50+
51+
4052
func _update_parent_script():
4153
if Engine.is_editor_hint():
4254
push_error("Updating the parent script must happen in game.")

addons/block_code/code_generation/blocks_catalog.gd

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -253,25 +253,52 @@ static func add_custom_blocks(
253253
static func get_variable_block_definitions(variables: Array[VariableDefinition]) -> Array[BlockDefinition]:
254254
var block_definitions: Array[BlockDefinition] = []
255255
for variable: VariableDefinition in variables:
256-
var type_string: String = Types.VARIANT_TYPE_TO_STRING[variable.var_type]
256+
var block_def: BlockDefinition
257257

258258
# Getter
259-
var block_def = BlockDefinition.new()
260-
block_def.name = "get_var_%s" % variable.var_name
261-
block_def.category = "Variables"
262-
block_def.type = Types.BlockType.VALUE
263-
block_def.variant_type = variable.var_type
264-
block_def.display_template = variable.var_name
265-
block_def.code_template = variable.var_name
259+
block_def = get_variable_getter_block_definition(variable)
266260
block_definitions.append(block_def)
267261

268262
# Setter
269-
block_def = BlockDefinition.new()
270-
block_def.name = "set_var_%s" % variable.var_name
271-
block_def.category = "Variables"
272-
block_def.type = Types.BlockType.STATEMENT
273-
block_def.display_template = "Set %s to {value: %s}" % [variable.var_name, type_string]
274-
block_def.code_template = "%s = {value}" % [variable.var_name]
263+
block_def = get_variable_setter_block_definition(variable)
275264
block_definitions.append(block_def)
276265

277266
return block_definitions
267+
268+
269+
static func get_variable_getter_block_definition(variable: VariableDefinition) -> BlockDefinition:
270+
var block_def := BlockDefinition.new()
271+
272+
block_def.name = "get_var_%s" % variable.var_name
273+
block_def.category = "Variables"
274+
block_def.type = Types.BlockType.VALUE
275+
block_def.variant_type = variable.var_type
276+
block_def.display_template = variable.var_name
277+
block_def.code_template = variable.var_name
278+
279+
return block_def
280+
281+
282+
static func get_variable_setter_block_definition(variable: VariableDefinition) -> BlockDefinition:
283+
var type_string: String = Types.VARIANT_TYPE_TO_STRING[variable.var_type]
284+
var block_def := BlockDefinition.new()
285+
286+
block_def.name = "set_var_%s" % variable.var_name
287+
block_def.category = "Variables"
288+
block_def.type = Types.BlockType.STATEMENT
289+
block_def.display_template = "Set %s to {value: %s}" % [variable.var_name, type_string]
290+
block_def.code_template = "%s = {value}" % variable.var_name
291+
292+
return block_def
293+
294+
295+
static func get_property_getter_block_definition(variable: VariableDefinition) -> BlockDefinition:
296+
var block_def := get_variable_getter_block_definition(variable)
297+
block_def.description = "The %s property" % variable.var_name
298+
return block_def
299+
300+
301+
static func get_property_setter_block_definition(variable: VariableDefinition) -> BlockDefinition:
302+
var block_def := get_variable_setter_block_definition(variable)
303+
block_def.description = "Set the %s property" % variable.var_name
304+
return block_def

addons/block_code/serialization/block_script_serialization.gd

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ const SCENE_PER_TYPE = {
2828
@export var generated_script: String
2929
@export var version: int
3030

31+
var block_code_node: BlockCode
32+
3133
var _available_blocks: Array[BlockDefinition]
3234
var _categories: Array[BlockCategory]
3335

@@ -81,22 +83,26 @@ func instantiate_block_by_name(block_name: String) -> Block:
8183

8284
func get_block_definition(block_name: String) -> BlockDefinition:
8385
var split := block_name.split(":", true, 1)
86+
var block_definition: BlockDefinition
8487

8588
if len(split) > 1:
8689
return _get_parameter_block_definition(split[0], split[1])
8790

88-
var block_definition = _get_base_block_definition(block_name)
91+
block_definition = _get_base_block_definition(block_name)
92+
if block_definition != null:
93+
return block_definition
8994

90-
if block_definition == null:
91-
# FIXME: This is a workaround for old-style output block references.
92-
# These were generated ahead of time using a block name that has
93-
# a "_" before the parameter name. Now, these parameter blocks
94-
# are generated on demand for any block name containing a ":".
95-
# Please remove this fallback when it is no longer necessary.
96-
split = block_name.rsplit("_", true, 1)
97-
return _get_parameter_block_definition(split[0], split[1])
95+
block_definition = _get_obj_property_block_definition(block_name)
96+
if block_definition != null:
97+
return block_definition
9898

99-
return block_definition
99+
# FIXME: This is a workaround for old-style output block references.
100+
# These were generated ahead of time using a block name that has
101+
# a "_" before the parameter name. Now, these parameter blocks
102+
# are generated on demand for any block name containing a ":".
103+
# Please remove this fallback when it is no longer necessary.
104+
split = block_name.rsplit("_", true, 1)
105+
return _get_parameter_block_definition(split[0], split[1])
100106

101107

102108
func _get_base_block_definition(block_name: String) -> BlockDefinition:
@@ -133,6 +139,49 @@ func _get_parameter_block_definition(block_name: String, parameter_name: String)
133139
return block_definition
134140

135141

142+
func _get_obj_property_block_definition(block_name: String) -> BlockDefinition:
143+
var block_definition: BlockDefinition
144+
var variable: VariableDefinition
145+
var property_name: String
146+
var is_getter = true
147+
148+
if block_name.begins_with("get_var_"):
149+
property_name = block_name.get_slice("get_var_", 1)
150+
elif block_name.begins_with("set_var_"):
151+
property_name = block_name.get_slice("set_var_", 1)
152+
is_getter = false
153+
else:
154+
return null
155+
156+
# Getter block needs the property's variant type information by visiting the
157+
# block_code_node's parent node because the type is not saved as a key of
158+
# the resource in the scene file
159+
var property_info := _get_parent_node_property_info(property_name)
160+
if not property_info.has("type"):
161+
return null
162+
163+
if is_getter:
164+
variable = VariableDefinition.new(property_name, property_info["type"])
165+
block_definition = BlocksCatalog.get_property_getter_block_definition(variable)
166+
else:
167+
variable = VariableDefinition.new(property_name, property_info["type"])
168+
block_definition = BlocksCatalog.get_property_setter_block_definition(variable)
169+
170+
return block_definition
171+
172+
173+
func _get_parent_node_property_info(property_name: String) -> Dictionary:
174+
if not block_code_node:
175+
return {}
176+
177+
var properties := block_code_node.get_parent().get_property_list()
178+
for property in properties:
179+
if property["name"] == property_name:
180+
return property
181+
182+
return {}
183+
184+
136185
func _update_block_definitions():
137186
_available_blocks.clear()
138187
_available_blocks.append_array(_get_inherited_block_definitions())

addons/block_code/ui/block_canvas/block_canvas.gd

Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ extends MarginContainer
33

44
const ASTList = preload("res://addons/block_code/code_generation/ast_list.gd")
55
const BlockAST = preload("res://addons/block_code/code_generation/block_ast.gd")
6+
const BlocksCatalog = preload("res://addons/block_code/code_generation/blocks_catalog.gd")
67
const BlockCodePlugin = preload("res://addons/block_code/block_code_plugin.gd")
78
const BlockDefinition = preload("res://addons/block_code/code_generation/block_definition.gd")
89
const BlockTreeUtil = preload("res://addons/block_code/ui/block_tree_util.gd")
910
const DragManager = preload("res://addons/block_code/drag_manager/drag_manager.gd")
1011
const ScriptGenerator = preload("res://addons/block_code/code_generation/script_generator.gd")
1112
const Types = preload("res://addons/block_code/types/types.gd")
1213
const Util = preload("res://addons/block_code/ui/util.gd")
14+
const VariableDefinition = preload("res://addons/block_code/code_generation/variable_definition.gd")
1315

1416
const EXTEND_MARGIN: float = 800
1517
const BLOCK_AUTO_PLACE_MARGIN: Vector2 = Vector2(25, 8)
@@ -79,8 +81,10 @@ func _can_drop_data(at_position: Vector2, data: Variant) -> bool:
7981
if typeof(data) != TYPE_DICTIONARY:
8082
return false
8183

82-
# Allow dropping property block
84+
# Allow dropping property block of the block code node's parent node
8385
if data.get("type", "") == "obj_property":
86+
if data["object"] != _context.parent_node:
87+
return false
8488
return true
8589

8690
var nodes: Array = data.get("nodes", [])
@@ -124,44 +128,20 @@ func _drop_node(at_position: Vector2, data: Variant) -> void:
124128

125129

126130
func _drop_obj_property(at_position: Vector2, data: Variant) -> void:
127-
var object_name = str(data["object"]).get_slice(":", 0)
128131
var property_name = data["property"]
129132
var property_value = data["value"]
133+
var is_getter = !_modifier_ctrl
130134

131135
# Prepare a Variable block to set / get the property's value according to
132136
# the modifier KEY_CTRL pressing.
137+
var variable := VariableDefinition.new(property_name, typeof(property_value))
133138
var block_definition: BlockDefinition
134-
var property_type = typeof(property_value)
135-
if _modifier_ctrl:
136-
var type_string: String = Types.VARIANT_TYPE_TO_STRING[property_type]
137-
block_definition = (
138-
BlockDefinition
139-
. new(
140-
&"%s_set_%s" % [object_name, property_name],
141-
object_name,
142-
"Set the %s property" % property_name,
143-
"Variables",
144-
Types.BlockType.STATEMENT,
145-
property_type,
146-
"set %s to {value: %s}" % [property_name.capitalize().to_lower(), type_string],
147-
"%s = {value}" % property_name,
148-
{"value": property_value},
149-
)
150-
)
139+
140+
if is_getter:
141+
block_definition = BlocksCatalog.get_property_getter_block_definition(variable)
151142
else:
152-
block_definition = (
153-
BlockDefinition
154-
. new(
155-
&"%s_get_%s" % [object_name, property_name],
156-
object_name,
157-
"The %s property" % property_name,
158-
"Variables",
159-
Types.BlockType.VALUE,
160-
property_type,
161-
"%s" % property_name.capitalize().to_lower(),
162-
"%s" % property_name,
163-
)
164-
)
143+
block_definition = BlocksCatalog.get_property_setter_block_definition(variable)
144+
block_definition.defaults = {"value": property_value}
165145

166146
var block = _context.block_script.instantiate_block(block_definition)
167147
add_block(block, at_position)

0 commit comments

Comments
 (0)