Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this do exactly? I want to make sure the extra syntax is really worth it since it seems like the regular input parameter would work fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This clears the in parameter's "visible" to avoid modify the value from users.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, if the in parameter shows up, it displays the full file path as a long text.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Without the input parameter in the display:
    Screenshot From 2024-11-27 17-10-07
  • With the input parameter in the display:
    Screenshot From 2024-11-27 17-12-16



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