Skip to content

Commit

Permalink
Merge pull request #305 from endlessm/T35712-drag-drop-resource-file
Browse files Browse the repository at this point in the history
BlockCanvas: Implement drag & drop the file from resource FileSystem
  • Loading branch information
manuq authored Dec 5, 2024
2 parents 698a549 + 96a7da3 commit 2867d30
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 10 deletions.
5 changes: 4 additions & 1 deletion addons/block_code/code_generation/block_definition.gd
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ extends Resource

const Types = preload("res://addons/block_code/types/types.gd")

const FORMAT_STRING_PATTERN = "\\[(?<out_parameter>[^\\]]+)\\]|\\{(?<in_parameter>[^}]+)\\}|(?<label>[^\\{\\[]+)"
const FORMAT_STRING_PATTERN = "\\[(?<out_parameter>[^\\]]+)\\]|\\{const (?<const_parameter>[^}]+)\\}|\\{(?!const )(?<in_parameter>[^}]+)\\}|(?<label>[^\\{\\[]+)"

@export var name: StringName

Expand Down Expand Up @@ -102,6 +102,9 @@ static func parse_display_template(template_string: String):
elif regex_match.names.has("out_parameter"):
var parameter_string := regex_match.get_string("out_parameter")
items.append({"out_parameter": _parse_parameter_format(parameter_string)})
elif regex_match.names.has("const_parameter"):
var parameter_string := regex_match.get_string("const_parameter")
items.append({"const_parameter": _parse_parameter_format(parameter_string)})
return items


Expand Down
17 changes: 17 additions & 0 deletions addons/block_code/code_generation/blocks_catalog.gd
Original file line number Diff line number Diff line change
Expand Up @@ -302,3 +302,20 @@ static func get_property_setter_block_definition(variable: VariableDefinition) -
var block_def := get_variable_setter_block_definition(variable)
block_def.description = "Set the %s property" % variable.var_name
return block_def


static func get_resource_block_definition(file_path: String) -> BlockDefinition:
var block_def := BlockDefinition.new()
var file_name = file_path.get_file()

# Block Definition's name cannot work with '.'
block_def.name = &"get_resource_file_path"
block_def.description = "The full resource path of '%s'" % file_name
block_def.category = "Variables"
block_def.type = Types.BlockType.VALUE
block_def.variant_type = TYPE_STRING
block_def.display_template = "%s {const file_path: STRING}" % file_name
block_def.code_template = "{file_path}"
block_def.defaults = {"file_path": file_path}

return block_def
29 changes: 24 additions & 5 deletions addons/block_code/serialization/block_script_serialization.gd
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,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)
Expand All @@ -81,12 +81,14 @@ 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])
block_definition = _get_parameter_block_definition(split[0], split[1])
if block_definition:
return block_definition

block_definition = _get_base_block_definition(block_name)
if block_definition != null:
Expand All @@ -96,6 +98,11 @@ func get_block_definition(block_name: String) -> BlockDefinition:
if block_definition != null:
return block_definition

var file_path = arguments.get("file_path", "")
block_definition = _get_resource_block_definition(block_name, file_path)
if block_definition != null:
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
Expand Down Expand Up @@ -182,6 +189,16 @@ func _get_parent_node_property_info(property_name: String) -> Dictionary:
return {}


func _get_resource_block_definition(block_name: String, file_path: String) -> BlockDefinition:
if block_name != "get_resource_file_path":
return null

if file_path.is_empty() or not FileAccess.file_exists(file_path) or not ResourceLoader.exists(file_path):
return null

return BlocksCatalog.get_resource_block_definition(file_path)


func _update_block_definitions():
_available_blocks.clear()
_available_blocks.append_array(_get_inherited_block_definitions())
Expand Down Expand Up @@ -251,14 +268,15 @@ 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]
if argument is ValueBlockSerialization:
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))
Expand All @@ -269,14 +287,15 @@ 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]
if argument is ValueBlockSerialization:
argument = _value_to_ast_value(argument)
ast_value_node.arguments[arg_name] = argument

ast_value_node.data = get_block_definition(value_node.name, ast_value_node.arguments)

return ast_value_node


Expand Down
23 changes: 23 additions & 0 deletions addons/block_code/ui/block_canvas/block_canvas.gd
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ func _can_drop_data(at_position: Vector2, data: Variant) -> bool:
return false
return true

# Allow dropping resource file
if data.get("type", "") == "files":
return true

var nodes: Array = data.get("nodes", [])
if nodes.size() != 1:
return false
Expand All @@ -108,6 +112,8 @@ func _drop_data(at_position: Vector2, data: Variant) -> void:
_drop_node(at_position, data)
elif data["type"] == "obj_property":
_drop_obj_property(at_position, data)
elif data["type"] == "files":
_drop_files(at_position, data)


func _drop_node(at_position: Vector2, data: Variant) -> void:
Expand Down Expand Up @@ -148,6 +154,23 @@ func _drop_obj_property(at_position: Vector2, data: Variant) -> void:
reconnect_block.emit(block)


func _drop_files(at_position: Vector2, data: Variant) -> void:
var resource_files = data["files"]
var next_position = at_position
const bias = 20

for file_path in resource_files:
# Prepare a Variable block getting the file's resource path.
var block_definition = BlocksCatalog.get_resource_block_definition(file_path)
var block = _context.block_script.instantiate_block(block_definition)
add_block(block, next_position)
reconnect_block.emit(block)

# Shift next block's position a little bit to avoid overlap totally.
next_position.x += bias
next_position.y += bias


func add_block(block: Block, position: Vector2 = Vector2.ZERO) -> void:
if block is EntryBlock:
block.position = canvas_to_window(position).snapped(SNAP_GRID)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ const ParameterInputScene = preload("res://addons/block_code/ui/blocks/utilities
const ParameterOutput = preload("res://addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.gd")
const ParameterOutputScene = preload("res://addons/block_code/ui/blocks/utilities/parameter_output/parameter_output.tscn")

const FORMAT_STRING_PATTERN = "\\[(?<out_parameter>[^\\]]+)\\]|\\{(?<in_parameter>[^}]+)\\}|(?<label>[^\\{\\[]+)"

## A string describing a block's display format. For example:
## [br]
## [code]
Expand All @@ -41,7 +39,6 @@ var parent_block: Block
var _parameter_inputs_by_name: Dictionary

@onready var _container := %Container
@onready var _regex := RegEx.create_from_string(FORMAT_STRING_PATTERN)


func _ready() -> void:
Expand Down Expand Up @@ -97,6 +94,8 @@ func _update_from_format_string():
_append_input_parameter(item.get("in_parameter"), match_id)
elif item.has("out_parameter"):
_append_output_parameter(item.get("out_parameter"), match_id)
elif item.has("const_parameter"):
_append_const_parameter(item.get("const_parameter"), match_id)
match_id += 1


Expand All @@ -107,7 +106,7 @@ func _append_label(label_format: String):
_container.add_child(label)


func _append_input_parameter(parameter: Dictionary, id: int):
func _append_input_parameter(parameter: Dictionary, id: int) -> ParameterInput:
var default_value = parameter_defaults.get(parameter["name"])

var parameter_input: ParameterInput = ParameterInputScene.instantiate()
Expand All @@ -129,6 +128,8 @@ func _append_input_parameter(parameter: Dictionary, id: int):
_container.add_child(parameter_input)
_parameter_inputs_by_name[parameter["name"]] = parameter_input

return parameter_input


func _append_output_parameter(parameter: Dictionary, id: int):
var parameter_output: ParameterOutput
Expand All @@ -140,5 +141,12 @@ func _append_output_parameter(parameter: Dictionary, id: int):
_container.add_child(parameter_output)


func _append_const_parameter(parameter: Dictionary, id: int):
# const_parameter is a kind of in_parameter with default value, but never
# changes value.
var parameter_const := _append_input_parameter(parameter, id)
parameter_const.visible = false


func _on_parameter_input_drag_started(offset: Vector2):
drag_started.emit(offset)

0 comments on commit 2867d30

Please sign in to comment.