Skip to content

Commit 2bbe016

Browse files
authored
Merge pull request #107 from endlessm/variables-revamp
Revamp variable system
2 parents 296613e + aaf9f2d commit 2bbe016

File tree

19 files changed

+524
-162
lines changed

19 files changed

+524
-162
lines changed

addons/block_code/block_code_plugin.gd

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ const DISABLED_CLASSES := [
4444
"TitleBar",
4545
"MainPanel",
4646
"BlockCodePlugin",
47-
"BlockCategoryButton"
47+
"BlockCategoryButton",
48+
"CreateVariableButton",
49+
"VariableCategoryDisplay"
4850
]
4951

5052

addons/block_code/block_script_data/block_script_data.gd

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ extends Resource
33

44
@export var script_inherits: String
55
@export var block_trees: SerializedBlockTreeNodeArray
6+
@export var variables: Array[VariableResource]
67
@export var generated_script: String
78
@export var version: int
89

910

10-
func _init(p_script_inherits: String = "", p_block_trees: SerializedBlockTreeNodeArray = null, p_generated_script: String = "", p_version = 0):
11+
func _init(p_script_inherits: String = "", p_block_trees: SerializedBlockTreeNodeArray = null, p_variables: Array[VariableResource] = [], p_generated_script: String = "", p_version = 0):
1112
script_inherits = p_script_inherits
1213
block_trees = p_block_trees
1314
generated_script = p_generated_script
15+
variables = p_variables
1416
version = p_version

addons/block_code/examples/pong_game/pong_game.tscn

Lines changed: 139 additions & 110 deletions
Large diffs are not rendered by default.

addons/block_code/instruction_tree/instruction_tree.gd

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,34 @@ class TreeNode:
1414
children.append(node)
1515

1616

17+
class IDHandler:
18+
static var counts: Dictionary = {}
19+
20+
static func reset():
21+
counts = {}
22+
23+
static func get_unique_id(str: String) -> int:
24+
if not counts.has(str):
25+
counts[str] = 0
26+
27+
counts[str] += 1
28+
29+
return counts[str]
30+
31+
static func make_unique(formatted_string: String) -> String:
32+
var unique_string = formatted_string
33+
var regex = RegEx.new()
34+
regex.compile("\\b__[^\\s]+")
35+
var ids: Dictionary = {}
36+
for result in regex.search_all(formatted_string):
37+
var result_string = result.get_string()
38+
if not ids.has(result_string):
39+
ids[result_string] = get_unique_id(result_string)
40+
unique_string = unique_string.replace(result_string, result_string + "_%d" % ids[result_string])
41+
42+
return unique_string
43+
44+
1745
func generate_text(root_node: TreeNode, start_depth: int = 0) -> String:
1846
var out = PackedStringArray()
1947
generate_text_recursive(root_node, start_depth, out)

addons/block_code/types/types.gd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const cast_relationships = [
3636
[TYPE_INT, TYPE_STRING, "str(%s)"],
3737
[TYPE_FLOAT, TYPE_STRING, "str(%s)"],
3838
[TYPE_COLOR, TYPE_STRING, "str(%s)"],
39+
[TYPE_VECTOR2, TYPE_STRING, "str(%s)"],
3940
]
4041

4142
# Directed graph, edges are CastGraphEdge

addons/block_code/ui/block_canvas/node_block_canvas/node_block_canvas.gd

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ class_name NodeBlockCanvas
33
extends BlockCanvas
44

55

6-
func generate_script_from_current_window(script_inherits: String = ""):
6+
func generate_script_from_current_window(bsd: BlockScriptData):
77
# TODO: implement multiple windows
88
var current_window := _window
99

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

2222
var script: String = ""
2323

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

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

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

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

49+
InstructionTree.IDHandler.reset()
50+
4651
for entry_block in entry_blocks:
4752
var next_block := entry_block.bottom_snap.get_snapped_block()
4853

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class_name VariableResource
2+
extends Resource
3+
4+
@export var var_name: String
5+
@export var var_type: Variant.Type
6+
7+
8+
func _init(p_var_name: String = "", p_var_type: Variant.Type = TYPE_NIL):
9+
var_name = p_var_name
10+
var_type = p_var_type

addons/block_code/ui/blocks/control_block/control_block.gd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ func get_instruction_node() -> InstructionTree.TreeNode:
4545
for pair in param_name_input_pairs_array[i]:
4646
formatted_statement = formatted_statement.replace("{%s}" % pair[0], pair[1].get_string())
4747

48+
formatted_statement = InstructionTree.IDHandler.make_unique(formatted_statement)
49+
4850
var new_node := InstructionTree.TreeNode.new(formatted_statement)
4951
if i == 0:
5052
node = new_node

addons/block_code/ui/blocks/parameter_block/parameter_block.gd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ func get_parameter_string() -> String:
5555
for pair in param_name_input_pairs:
5656
formatted_statement = formatted_statement.replace("{%s}" % pair[0], pair[1].get_string())
5757

58+
formatted_statement = InstructionTree.IDHandler.make_unique(formatted_statement)
59+
5860
return formatted_statement
5961

6062

addons/block_code/ui/blocks/statement_block/statement_block.gd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ func get_instruction_node() -> InstructionTree.TreeNode:
5858
for pair in param_name_input_pairs:
5959
formatted_statement = formatted_statement.replace("{%s}" % pair[0], pair[1].get_string())
6060

61+
formatted_statement = InstructionTree.IDHandler.make_unique(formatted_statement)
62+
6163
var statement_lines := formatted_statement.split("\n")
6264

6365
var root: InstructionTree.TreeNode = InstructionTree.TreeNode.new(statement_lines[0])

addons/block_code/ui/main_panel.gd

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ var undo_redo: EditorUndoRedoManager:
3232

3333
func _ready():
3434
_picker.block_picked.connect(_drag_manager.copy_picked_block_and_drag)
35+
_picker.variable_created.connect(_create_variable)
3536
_block_canvas.reconnect_block.connect(_drag_manager.connect_block_canvas_signals)
3637
_drag_manager.block_dropped.connect(save_script)
3738
_drag_manager.block_modified.connect(save_script)
@@ -142,7 +143,7 @@ func save_script():
142143
undo_redo.add_undo_property(_current_block_code_node.block_script, "generated_script", _current_block_code_node.block_script.generated_script)
143144

144145
var block_trees := _block_canvas.get_canvas_block_trees()
145-
var generated_script = _block_canvas.generate_script_from_current_window(block_script.script_inherits)
146+
var generated_script = _block_canvas.generate_script_from_current_window(block_script)
146147
block_script.block_trees = block_trees
147148
block_script.generated_script = generated_script
148149
block_script.version = Constants.CURRENT_DATA_VERSION
@@ -174,7 +175,7 @@ func _print_generated_script():
174175
if _current_block_code_node == null:
175176
return
176177
var block_script: BlockScriptData = _current_block_code_node.block_script
177-
var script: String = _block_canvas.generate_script_from_current_window(block_script.script_inherits)
178+
var script: String = _block_canvas.generate_script_from_current_window(block_script)
178179
print(script)
179180
print("Debug script! (not saved)")
180181

@@ -252,3 +253,22 @@ func _set_selection(nodes: Array[Node]):
252253
EditorInterface.get_selection().clear()
253254
for node in nodes:
254255
EditorInterface.get_selection().add_node(node)
256+
257+
258+
func _create_variable(variable: VariableResource):
259+
if _current_block_code_node == null:
260+
print("No script loaded to add variable to.")
261+
return
262+
263+
var block_script: BlockScriptData = _current_block_code_node.block_script
264+
265+
undo_redo.create_action("Create variable %s in %s's block code script" % [variable.var_name, _current_block_code_node.get_parent().name])
266+
undo_redo.add_undo_property(_current_block_code_node.block_script, "variables", _current_block_code_node.block_script.variables)
267+
268+
var new_variables = block_script.variables.duplicate()
269+
new_variables.append(variable)
270+
271+
undo_redo.add_do_property(_current_block_code_node.block_script, "variables", new_variables)
272+
undo_redo.commit_action()
273+
274+
_picker.reload_variables(new_variables)

addons/block_code/ui/picker/categories/category_factory.gd

Lines changed: 37 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ static func get_general_blocks() -> Array[Block]:
204204

205205
b = BLOCKS["control_block"].instantiate()
206206
b.block_formats = ["repeat {number: INT}"]
207-
b.statements = ["for i in {number}:"]
207+
b.statements = ["for __i in {number}:"]
208208
b.category = "Loops"
209209
block_list.append(b)
210210

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

329329
#endregion
330330
#region Variables
331-
332-
b = BLOCKS["statement_block"].instantiate()
333-
b.block_format = "Set String {var: STRING} {value: STRING}"
334-
b.statement = "VAR_DICT[{var}] = {value}"
335-
b.category = "Variables"
336-
block_list.append(b)
337-
338-
b = BLOCKS["parameter_block"].instantiate()
339-
b.block_format = "Get String {var: STRING}"
340-
b.statement = "VAR_DICT[{var}]"
341-
b.category = "Variables"
342-
block_list.append(b)
343-
344-
b = BLOCKS["statement_block"].instantiate()
345-
b.block_format = "Set Int {var: STRING} {value: INT}"
346-
b.statement = "VAR_DICT[{var}] = {value}"
347-
b.category = "Variables"
348-
block_list.append(b)
349-
350-
b = BLOCKS["parameter_block"].instantiate()
351-
b.variant_type = TYPE_INT
352-
b.block_format = "Get Int {var: STRING}"
353-
b.statement = "VAR_DICT[{var}]"
354-
b.category = "Variables"
355-
block_list.append(b)
356-
357-
b = BLOCKS["parameter_block"].instantiate()
358-
b.block_format = "To String {int: INT}"
359-
b.statement = "str({int})"
360-
b.category = "Variables"
361-
block_list.append(b)
362-
363331
b = BLOCKS["parameter_block"].instantiate()
364332
b.variant_type = TYPE_VECTOR2
365333
b.block_format = "Vector2 x: {x: FLOAT} y: {y: FLOAT}"
@@ -455,10 +423,10 @@ static func get_general_blocks() -> Array[Block]:
455423
b.block_format = "Load file {file_path: STRING} as sound {name: STRING}"
456424
b.statement = (
457425
"""
458-
VAR_DICT[{name}] = AudioStreamPlayer.new()
459-
VAR_DICT[{name}].name = {name}
460-
VAR_DICT[{name}].set_stream(load({file_path}))
461-
add_child(VAR_DICT[{name}])
426+
var __sound = AudioStreamPlayer.new()
427+
__sound.name = {name}
428+
__sound.set_stream(load({file_path}))
429+
add_child(__sound)
462430
"""
463431
. dedent()
464432
)
@@ -471,9 +439,10 @@ static func get_general_blocks() -> Array[Block]:
471439
b.block_format = "Play the sound {name: STRING} with Volume dB {db: FLOAT} and Pitch Scale {pitch: FLOAT}"
472440
b.statement = (
473441
"""
474-
VAR_DICT[{name}].volume_db = {db}
475-
VAR_DICT[{name}].pitch_scale = {pitch}
476-
VAR_DICT[{name}].play()
442+
var __sound_node = get_node({name})
443+
__sound_node.volume_db = {db}
444+
__sound_node.pitch_scale = {pitch}
445+
__sound_node.play()
477446
"""
478447
. dedent()
479448
)
@@ -513,10 +482,10 @@ static func get_general_blocks() -> Array[Block]:
513482
static func property_to_blocklist(property: Dictionary) -> Array[Block]:
514483
var block_list: Array[Block] = []
515484

516-
var block_type = property.type
485+
var variant_type = property.type
517486

518-
if block_type:
519-
var type_string: String = Types.VARIANT_TYPE_TO_STRING[block_type]
487+
if variant_type:
488+
var type_string: String = Types.VARIANT_TYPE_TO_STRING[variant_type]
520489

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

533502
b = BLOCKS["parameter_block"].instantiate()
534-
b.block_type = block_type
503+
b.variant_type = variant_type
535504
b.block_format = "%s" % property.name.capitalize()
536505
b.statement = "%s" % property.name
537506
b.category = property.category
@@ -766,3 +735,27 @@ static func _get_input_blocks() -> Array[Block]:
766735
InputMap.action_add_event(action, event)
767736

768737
return block_list
738+
739+
740+
static func get_variable_blocks(variables: Array[VariableResource]):
741+
var block_list: Array[Block]
742+
743+
for variable in variables:
744+
var type_string: String = Types.VARIANT_TYPE_TO_STRING[variable.var_type]
745+
746+
var b = BLOCKS["parameter_block"].instantiate()
747+
b.variant_type = variable.var_type
748+
b.block_format = variable.var_name
749+
b.statement = variable.var_name
750+
# HACK: Color the blocks since they are outside of the normal picker system
751+
b.color = BUILTIN_PROPS["Variables"].color
752+
block_list.append(b)
753+
754+
b = BLOCKS["statement_block"].instantiate()
755+
b.block_type = Types.BlockType.EXECUTE
756+
b.block_format = "Set %s to {value: %s}" % [variable.var_name, type_string]
757+
b.statement = "%s = {value}" % [variable.var_name]
758+
b.color = BUILTIN_PROPS["Variables"].color
759+
block_list.append(b)
760+
761+
return block_list
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
@tool
2+
class_name CreateVariableButton
3+
extends MarginContainer
4+
5+
signal create_variable(var_name: String, var_type: String)
6+
7+
@onready var _create_variable_dialog := %CreateVariableDialog
8+
9+
10+
func _on_create_button_pressed():
11+
_create_variable_dialog.visible = true
12+
13+
14+
func _on_create_variable_dialog_create_variable(var_name, var_type):
15+
create_variable.emit(var_name, var_type)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[gd_scene load_steps=3 format=3 uid="uid://t0eoc4ekvjr1"]
2+
3+
[ext_resource type="Script" path="res://addons/block_code/ui/picker/categories/variable_category/create_variable_button.gd" id="1_cw6c3"]
4+
[ext_resource type="PackedScene" uid="uid://dbrm7wwkao0c0" path="res://addons/block_code/ui/picker/categories/variable_category/create_variable_dialog.tscn" id="2_udpg5"]
5+
6+
[node name="CreateVariableButton" type="MarginContainer"]
7+
size_flags_horizontal = 0
8+
theme_override_constants/margin_bottom = 12
9+
script = ExtResource("1_cw6c3")
10+
11+
[node name="CreateButton" type="Button" parent="."]
12+
layout_mode = 2
13+
text = "Create New Variable"
14+
15+
[node name="CreateVariableDialog" parent="." instance=ExtResource("2_udpg5")]
16+
unique_name_in_owner = true
17+
visible = false
18+
19+
[connection signal="pressed" from="CreateButton" to="." method="_on_create_button_pressed"]
20+
[connection signal="create_variable" from="CreateVariableDialog" to="." method="_on_create_variable_dialog_create_variable"]

0 commit comments

Comments
 (0)