Skip to content

Revamp variable system #107

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 16, 2024
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
4 changes: 3 additions & 1 deletion addons/block_code/block_code_plugin.gd
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ const DISABLED_CLASSES := [
"TitleBar",
"MainPanel",
"BlockCodePlugin",
"BlockCategoryButton"
"BlockCategoryButton",
"CreateVariableButton",
"VariableCategoryDisplay"
]


Expand Down
4 changes: 3 additions & 1 deletion addons/block_code/block_script_data/block_script_data.gd
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ extends Resource

@export var script_inherits: String
@export var block_trees: SerializedBlockTreeNodeArray
@export var variables: Array[VariableResource]
@export var generated_script: String
@export var version: int


func _init(p_script_inherits: String = "", p_block_trees: SerializedBlockTreeNodeArray = null, p_generated_script: String = "", p_version = 0):
func _init(p_script_inherits: String = "", p_block_trees: SerializedBlockTreeNodeArray = null, p_variables: Array[VariableResource] = [], p_generated_script: String = "", p_version = 0):
script_inherits = p_script_inherits
block_trees = p_block_trees
generated_script = p_generated_script
variables = p_variables
version = p_version
249 changes: 139 additions & 110 deletions addons/block_code/examples/pong_game/pong_game.tscn

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions addons/block_code/instruction_tree/instruction_tree.gd
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,34 @@ class TreeNode:
children.append(node)


class IDHandler:
static var counts: Dictionary = {}

static func reset():
counts = {}

static func get_unique_id(str: String) -> int:
if not counts.has(str):
counts[str] = 0

counts[str] += 1

return counts[str]

static func make_unique(formatted_string: String) -> String:
var unique_string = formatted_string
var regex = RegEx.new()
regex.compile("\\b__[^\\s]+")
var ids: Dictionary = {}
for result in regex.search_all(formatted_string):
var result_string = result.get_string()
if not ids.has(result_string):
ids[result_string] = get_unique_id(result_string)
unique_string = unique_string.replace(result_string, result_string + "_%d" % ids[result_string])

return unique_string


func generate_text(root_node: TreeNode, start_depth: int = 0) -> String:
var out = PackedStringArray()
generate_text_recursive(root_node, start_depth, out)
Expand Down
1 change: 1 addition & 0 deletions addons/block_code/types/types.gd
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const cast_relationships = [
[TYPE_INT, TYPE_STRING, "str(%s)"],
[TYPE_FLOAT, TYPE_STRING, "str(%s)"],
[TYPE_COLOR, TYPE_STRING, "str(%s)"],
[TYPE_VECTOR2, TYPE_STRING, "str(%s)"],
]

# Directed graph, edges are CastGraphEdge
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ class_name NodeBlockCanvas
extends BlockCanvas


func generate_script_from_current_window(script_inherits: String = ""):
func generate_script_from_current_window(bsd: BlockScriptData):
# TODO: implement multiple windows
var current_window := _window

Expand All @@ -21,9 +21,12 @@ func generate_script_from_current_window(script_inherits: String = ""):

var script: String = ""

script += "extends %s\n\n" % script_inherits
script += "extends %s\n\n" % bsd.script_inherits

script += "var VAR_DICT := {}\n\n"
for variable in bsd.variables:
script += "var %s: %s\n\n" % [variable.var_name, type_string(variable.var_type)]

script += "\n"

var init_func = InstructionTree.TreeNode.new("func _init():")

Expand All @@ -43,6 +46,8 @@ func _generate_script_from_entry_blocks(entry_statement: String, entry_blocks: A
var signal_node: InstructionTree.TreeNode
var is_empty = true

InstructionTree.IDHandler.reset()

for entry_block in entry_blocks:
var next_block := entry_block.bottom_snap.get_snapped_block()

Expand Down
10 changes: 10 additions & 0 deletions addons/block_code/ui/block_canvas/variable_resource.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class_name VariableResource
extends Resource

@export var var_name: String
@export var var_type: Variant.Type


func _init(p_var_name: String = "", p_var_type: Variant.Type = TYPE_NIL):
var_name = p_var_name
var_type = p_var_type
2 changes: 2 additions & 0 deletions addons/block_code/ui/blocks/control_block/control_block.gd
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ func get_instruction_node() -> InstructionTree.TreeNode:
for pair in param_name_input_pairs_array[i]:
formatted_statement = formatted_statement.replace("{%s}" % pair[0], pair[1].get_string())

formatted_statement = InstructionTree.IDHandler.make_unique(formatted_statement)

var new_node := InstructionTree.TreeNode.new(formatted_statement)
if i == 0:
node = new_node
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ func get_parameter_string() -> String:
for pair in param_name_input_pairs:
formatted_statement = formatted_statement.replace("{%s}" % pair[0], pair[1].get_string())

formatted_statement = InstructionTree.IDHandler.make_unique(formatted_statement)

return formatted_statement


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ func get_instruction_node() -> InstructionTree.TreeNode:
for pair in param_name_input_pairs:
formatted_statement = formatted_statement.replace("{%s}" % pair[0], pair[1].get_string())

formatted_statement = InstructionTree.IDHandler.make_unique(formatted_statement)

var statement_lines := formatted_statement.split("\n")

var root: InstructionTree.TreeNode = InstructionTree.TreeNode.new(statement_lines[0])
Expand Down
24 changes: 22 additions & 2 deletions addons/block_code/ui/main_panel.gd
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ var undo_redo: EditorUndoRedoManager:

func _ready():
_picker.block_picked.connect(_drag_manager.copy_picked_block_and_drag)
_picker.variable_created.connect(_create_variable)
_block_canvas.reconnect_block.connect(_drag_manager.connect_block_canvas_signals)
_drag_manager.block_dropped.connect(save_script)
_drag_manager.block_modified.connect(save_script)
Expand Down Expand Up @@ -142,7 +143,7 @@ func save_script():
undo_redo.add_undo_property(_current_block_code_node.block_script, "generated_script", _current_block_code_node.block_script.generated_script)

var block_trees := _block_canvas.get_canvas_block_trees()
var generated_script = _block_canvas.generate_script_from_current_window(block_script.script_inherits)
var generated_script = _block_canvas.generate_script_from_current_window(block_script)
block_script.block_trees = block_trees
block_script.generated_script = generated_script
block_script.version = Constants.CURRENT_DATA_VERSION
Expand Down Expand Up @@ -174,7 +175,7 @@ func _print_generated_script():
if _current_block_code_node == null:
return
var block_script: BlockScriptData = _current_block_code_node.block_script
var script: String = _block_canvas.generate_script_from_current_window(block_script.script_inherits)
var script: String = _block_canvas.generate_script_from_current_window(block_script)
print(script)
print("Debug script! (not saved)")

Expand Down Expand Up @@ -252,3 +253,22 @@ func _set_selection(nodes: Array[Node]):
EditorInterface.get_selection().clear()
for node in nodes:
EditorInterface.get_selection().add_node(node)


func _create_variable(variable: VariableResource):
if _current_block_code_node == null:
print("No script loaded to add variable to.")
return

var block_script: BlockScriptData = _current_block_code_node.block_script

undo_redo.create_action("Create variable %s in %s's block code script" % [variable.var_name, _current_block_code_node.get_parent().name])
undo_redo.add_undo_property(_current_block_code_node.block_script, "variables", _current_block_code_node.block_script.variables)

var new_variables = block_script.variables.duplicate()
new_variables.append(variable)

undo_redo.add_do_property(_current_block_code_node.block_script, "variables", new_variables)
undo_redo.commit_action()

_picker.reload_variables(new_variables)
81 changes: 37 additions & 44 deletions addons/block_code/ui/picker/categories/category_factory.gd
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ static func get_general_blocks() -> Array[Block]:

b = BLOCKS["control_block"].instantiate()
b.block_formats = ["repeat {number: INT}"]
b.statements = ["for i in {number}:"]
b.statements = ["for __i in {number}:"]
b.category = "Loops"
block_list.append(b)

Expand Down Expand Up @@ -328,38 +328,6 @@ static func get_general_blocks() -> Array[Block]:

#endregion
#region Variables

b = BLOCKS["statement_block"].instantiate()
b.block_format = "Set String {var: STRING} {value: STRING}"
b.statement = "VAR_DICT[{var}] = {value}"
b.category = "Variables"
block_list.append(b)

b = BLOCKS["parameter_block"].instantiate()
b.block_format = "Get String {var: STRING}"
b.statement = "VAR_DICT[{var}]"
b.category = "Variables"
block_list.append(b)

b = BLOCKS["statement_block"].instantiate()
b.block_format = "Set Int {var: STRING} {value: INT}"
b.statement = "VAR_DICT[{var}] = {value}"
b.category = "Variables"
block_list.append(b)

b = BLOCKS["parameter_block"].instantiate()
b.variant_type = TYPE_INT
b.block_format = "Get Int {var: STRING}"
b.statement = "VAR_DICT[{var}]"
b.category = "Variables"
block_list.append(b)

b = BLOCKS["parameter_block"].instantiate()
b.block_format = "To String {int: INT}"
b.statement = "str({int})"
b.category = "Variables"
block_list.append(b)

b = BLOCKS["parameter_block"].instantiate()
b.variant_type = TYPE_VECTOR2
b.block_format = "Vector2 x: {x: FLOAT} y: {y: FLOAT}"
Expand Down Expand Up @@ -455,10 +423,10 @@ static func get_general_blocks() -> Array[Block]:
b.block_format = "Load file {file_path: STRING} as sound {name: STRING}"
b.statement = (
"""
VAR_DICT[{name}] = AudioStreamPlayer.new()
VAR_DICT[{name}].name = {name}
VAR_DICT[{name}].set_stream(load({file_path}))
add_child(VAR_DICT[{name}])
var __sound = AudioStreamPlayer.new()
__sound.name = {name}
__sound.set_stream(load({file_path}))
add_child(__sound)
"""
. dedent()
)
Expand All @@ -471,9 +439,10 @@ static func get_general_blocks() -> Array[Block]:
b.block_format = "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"
b.statement = (
"""
VAR_DICT[{name}].volume_db = {db}
VAR_DICT[{name}].pitch_scale = {pitch}
VAR_DICT[{name}].play()
var __sound_node = get_node({name})
__sound_node.volume_db = {db}
__sound_node.pitch_scale = {pitch}
__sound_node.play()
"""
. dedent()
)
Expand Down Expand Up @@ -513,10 +482,10 @@ static func get_general_blocks() -> Array[Block]:
static func property_to_blocklist(property: Dictionary) -> Array[Block]:
var block_list: Array[Block] = []

var block_type = property.type
var variant_type = property.type

if block_type:
var type_string: String = Types.VARIANT_TYPE_TO_STRING[block_type]
if variant_type:
var type_string: String = Types.VARIANT_TYPE_TO_STRING[variant_type]

var b = BLOCKS["statement_block"].instantiate()
b.block_format = "Set %s to {value: %s}" % [property.name.capitalize(), type_string]
Expand All @@ -531,7 +500,7 @@ static func property_to_blocklist(property: Dictionary) -> Array[Block]:
block_list.append(b)

b = BLOCKS["parameter_block"].instantiate()
b.block_type = block_type
b.variant_type = variant_type
b.block_format = "%s" % property.name.capitalize()
b.statement = "%s" % property.name
b.category = property.category
Expand Down Expand Up @@ -766,3 +735,27 @@ static func _get_input_blocks() -> Array[Block]:
InputMap.action_add_event(action, event)

return block_list


static func get_variable_blocks(variables: Array[VariableResource]):
var block_list: Array[Block]

for variable in variables:
var type_string: String = Types.VARIANT_TYPE_TO_STRING[variable.var_type]

var b = BLOCKS["parameter_block"].instantiate()
b.variant_type = variable.var_type
b.block_format = variable.var_name
b.statement = variable.var_name
# HACK: Color the blocks since they are outside of the normal picker system
b.color = BUILTIN_PROPS["Variables"].color
block_list.append(b)

b = BLOCKS["statement_block"].instantiate()
b.block_type = Types.BlockType.EXECUTE
b.block_format = "Set %s to {value: %s}" % [variable.var_name, type_string]
b.statement = "%s = {value}" % [variable.var_name]
b.color = BUILTIN_PROPS["Variables"].color
block_list.append(b)

return block_list
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@tool
class_name CreateVariableButton
extends MarginContainer

signal create_variable(var_name: String, var_type: String)

@onready var _create_variable_dialog := %CreateVariableDialog


func _on_create_button_pressed():
_create_variable_dialog.visible = true


func _on_create_variable_dialog_create_variable(var_name, var_type):
create_variable.emit(var_name, var_type)
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[gd_scene load_steps=3 format=3 uid="uid://t0eoc4ekvjr1"]

[ext_resource type="Script" path="res://addons/block_code/ui/picker/categories/variable_category/create_variable_button.gd" id="1_cw6c3"]
[ext_resource type="PackedScene" uid="uid://dbrm7wwkao0c0" path="res://addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.tscn" id="2_udpg5"]

[node name="CreateVariableButton" type="MarginContainer"]
size_flags_horizontal = 0
theme_override_constants/margin_bottom = 12
script = ExtResource("1_cw6c3")

[node name="CreateButton" type="Button" parent="."]
layout_mode = 2
text = "Create New Variable"

[node name="CreateVariableDialog" parent="." instance=ExtResource("2_udpg5")]
unique_name_in_owner = true
visible = false

[connection signal="pressed" from="CreateButton" to="." method="_on_create_button_pressed"]
[connection signal="create_variable" from="CreateVariableDialog" to="." method="_on_create_variable_dialog_create_variable"]
Loading
Loading