├── .DS_Store
├── LICENSE
├── README.md
├── Reblocks.png
├── Reblocks.png.import
├── Reblocksv2.svg
├── Reblocksv2.svg.import
├── block_code_node
├── block_code.gd
├── block_code.gd.uid
├── block_code_node.svg
└── block_code_node.svg.import
├── block_code_plugin.gd
├── block_code_plugin.gd.uid
├── blocks
├── .DS_Store
├── communication
│ ├── add_node_to_group.tres
│ ├── add_to_group.tres
│ ├── area2d_on_entered.tres
│ ├── area2d_on_exited.tres
│ ├── call_method_group.tres
│ ├── call_method_node.tres
│ ├── define_method.tres
│ ├── get_node.gd
│ ├── get_node.gd.uid
│ ├── get_node.tres
│ ├── groups.gd
│ ├── groups.gd.uid
│ ├── is_in_group.tres
│ ├── is_node_in_group.tres
│ ├── remove_from_group.tres
│ ├── remove_node_from_group.tres
│ ├── rigidbody2d_on_entered.tres
│ ├── rigidbody2d_on_exited.tres
│ └── switch_scene.tres
├── graphics
│ ├── animationplayer_is_playing.tres
│ ├── animationplayer_pause.tres
│ ├── animationplayer_play.gd
│ ├── animationplayer_play.gd.uid
│ ├── animationplayer_play.tres
│ ├── animationplayer_stop.tres
│ ├── viewport_center.tres
│ ├── viewport_height.tres
│ └── viewport_width.tres
├── input
│ ├── characterbody2d_is_on_floor.tres
│ ├── characterbody2d_move.tres
│ ├── is_input_actioned.gd
│ ├── is_input_actioned.gd.uid
│ └── is_input_actioned.tres
├── lifecycle
│ ├── physics_process.tres
│ ├── process.tres
│ ├── queue_free.tres
│ ├── queue_free_node.tres
│ └── ready.tres
├── log
│ ├── breakpoint.tres
│ ├── comment.tres
│ ├── concat.tres
│ └── print.tres
├── logic
│ ├── and.tres
│ ├── compare.tres
│ ├── else.tres
│ ├── else_if.tres
│ ├── flip.tres
│ ├── if.tres
│ ├── not.tres
│ └── or.tres
├── loops
│ ├── await_scene_ready.tres
│ ├── break.tres
│ ├── continue.tres
│ ├── for.tres
│ └── while.tres
├── math
│ ├── add.tres
│ ├── cos.tres
│ ├── divide.tres
│ ├── multiply.tres
│ ├── pow.tres
│ ├── randf_range.tres
│ ├── randi_range.tres
│ ├── sin.tres
│ ├── subtract.tres
│ ├── tan.tres
│ ├── vector2_xy.tres
│ ├── vector3_multiply.tres
│ ├── vector3_xyz.tres
│ ├── vector_from_angle.tres
│ └── vector_multiply.tres
├── physics
│ ├── characterbody2d_move_and_slide.tres
│ └── characterbody3d_move_and_slide.tres
├── sounds
│ ├── audiostreamplayer_play.tres
│ ├── audiostreamplayer_stop.tres
│ ├── load_sound.tres
│ ├── pause_continue_sound.tres
│ ├── play_sound.tres
│ └── stop_sound.tres
├── spawn
│ └── cpuparticles2d_finished.tres
├── transform
│ └── rigidbody2d_physics_position.tres
├── ui
│ └── label_set_text.tres
└── variables
│ ├── vector2.tres
│ └── vector3.tres
├── code_generation
├── ast_list.gd
├── ast_list.gd.uid
├── block_ast.gd
├── block_ast.gd.uid
├── block_definition.gd
├── block_definition.gd.uid
├── block_extension.gd
├── block_extension.gd.uid
├── blocks_catalog.gd
├── blocks_catalog.gd.uid
├── option_data.gd
├── option_data.gd.uid
├── script_generator.gd
├── script_generator.gd.uid
├── util.gd
├── util.gd.uid
├── variable_definition.gd
└── variable_definition.gd.uid
├── drag_manager
├── drag.gd
├── drag.gd.uid
├── drag_manager.gd
├── drag_manager.gd.uid
└── drag_manager.tscn
├── image.png
├── image.png.import
├── inspector_plugin
├── block_script_inspector.gd
└── block_script_inspector.gd.uid
├── locale
├── ar.po
├── az.po
├── bg.po
├── bn.po
├── ca.po
├── cs.po
├── de.po
├── el.po
├── eo.po
├── es.po
├── et.po
├── fa.po
├── fi.po
├── fr.po
├── ga.po
├── gl.po
├── godot_block_coding.pot
├── he.po
├── hi.po
├── hu.po
├── id.po
├── it.po
├── ja.po
├── ka.po
├── ko.po
├── lt.po
├── lv.po
├── mr.po
├── ms.po
├── nb.po
├── nl.po
├── pl.po
├── pt.po
├── ro.po
├── ru.po
├── si.po
├── sk.po
├── sl.po
├── sq.po
├── sv.po
├── sw.po
├── ta.po
├── th.po
├── tr.po
├── uk.po
├── vi.po
├── zh_CN.po
└── zh_TW.po
├── plugin.cfg
├── serialization
├── block_script_serialization.gd
├── block_script_serialization.gd.uid
├── block_serialization.gd
├── block_serialization.gd.uid
├── block_serialization_tree.gd
├── block_serialization_tree.gd.uid
├── default_block_script.tres
├── value_block_serialization.gd
└── value_block_serialization.gd.uid
├── translation
├── parser.gd
├── parser.gd.uid
├── utils.gd
└── utils.gd.uid
├── types
├── types.gd
└── types.gd.uid
└── ui
├── block_canvas
├── block_canvas.gd
├── block_canvas.gd.uid
└── block_canvas.tscn
├── block_editor_context.gd
├── block_editor_context.gd.uid
├── block_tree_util.gd
├── block_tree_util.gd.uid
├── blocks
├── block
│ ├── block.gd
│ └── block.gd.uid
├── control_block
│ ├── control_block.gd
│ ├── control_block.gd.uid
│ └── control_block.tscn
├── entry_block
│ ├── entry_block.gd
│ ├── entry_block.gd.uid
│ └── entry_block.tscn
├── parameter_block
│ ├── parameter_block.gd
│ ├── parameter_block.gd.uid
│ └── parameter_block.tscn
├── statement_block
│ ├── statement_block.gd
│ ├── statement_block.gd.uid
│ └── statement_block.tscn
└── utilities
│ ├── background
│ ├── background.gd
│ ├── background.gd.uid
│ ├── gutter.gd
│ └── gutter.gd.uid
│ ├── drag_drop_area
│ ├── drag_drop_area.gd
│ ├── drag_drop_area.gd.uid
│ └── drag_drop_area.tscn
│ ├── parameter_input
│ ├── parameter_input.gd
│ ├── parameter_input.gd.uid
│ └── parameter_input.tscn
│ ├── parameter_output
│ ├── parameter_output.gd
│ ├── parameter_output.gd.uid
│ └── parameter_output.tscn
│ ├── snap_point
│ ├── snap_point.gd
│ ├── snap_point.gd.uid
│ └── snap_point.tscn
│ └── template_editor
│ ├── collapsable_settings.gd
│ ├── collapsable_settings.gd.uid
│ ├── collapsable_settings.tscn
│ ├── minus.svg
│ ├── minus.svg.import
│ ├── plus.svg
│ ├── plus.svg.import
│ ├── template_editor.gd
│ ├── template_editor.gd.uid
│ └── template_editor.tscn
├── constants.gd
├── constants.gd.uid
├── main_panel.gd
├── main_panel.gd.uid
├── main_panel.tscn
├── picker
├── categories
│ ├── block_category.gd
│ ├── block_category.gd.uid
│ ├── block_category_button.gd
│ ├── block_category_button.gd.uid
│ ├── block_category_button.tscn
│ ├── block_category_display.gd
│ ├── block_category_display.gd.uid
│ ├── block_category_display.tscn
│ ├── category_factory.gd
│ ├── category_factory.gd.uid
│ ├── icons
│ │ ├── communication.svg
│ │ ├── communication.svg.import
│ │ ├── file_broken.svg
│ │ ├── file_broken.svg.import
│ │ ├── graphics.svg
│ │ ├── graphics.svg.import
│ │ ├── info.svg
│ │ ├── info.svg.import
│ │ ├── input.svg
│ │ ├── input.svg.import
│ │ ├── lifecycle.svg
│ │ ├── lifecycle.svg.import
│ │ ├── log.svg
│ │ ├── log.svg.import
│ │ ├── logic.svg
│ │ ├── logic.svg.import
│ │ ├── loops.svg
│ │ ├── loops.svg.import
│ │ ├── math.svg
│ │ ├── math.svg.import
│ │ ├── physics.svg
│ │ ├── physics.svg.import
│ │ ├── sounds.svg
│ │ ├── sounds.svg.import
│ │ ├── transform.svg
│ │ ├── transform.svg.import
│ │ ├── ui.svg
│ │ ├── ui.svg.import
│ │ ├── variables.svg
│ │ └── variables.svg.import
│ └── variable_category
│ │ ├── create_variable_button.gd
│ │ ├── create_variable_button.gd.uid
│ │ ├── create_variable_button.tscn
│ │ ├── create_variable_dialog.gd
│ │ ├── create_variable_dialog.gd.uid
│ │ ├── create_variable_dialog.tscn
│ │ ├── variable_category_display.gd
│ │ ├── variable_category_display.gd.uid
│ │ └── variable_category_display.tscn
├── picker.gd
├── picker.gd.uid
└── picker.tscn
├── script_window
├── script_window.gd
├── script_window.gd.uid
├── script_window.tscn
├── split_script_window.gd
├── split_script_window.gd.uid
└── split_script_window.tscn
├── title_bar
├── title_bar.gd
├── title_bar.gd.uid
└── title_bar.tscn
├── tooltip
├── tooltip.gd
├── tooltip.gd.uid
└── tooltip.tscn
├── util.gd
└── util.gd.uid
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Redot-Experimental/reblocks/c80e8b09503556f4fba4c436dc7bb5dcb0c51804/.DS_Store
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Endless OS Foundation
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ReBlocks
2 |
3 | 
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | ReBlocks is a fork of the very good Block Coding plugin by [Endless OS Foundation](https://endlessos.org). While their mission is to provide a way to learn to program and eventually move to code, we want to provide a general use visual tool for making games, that will both enable users to make any kind of game they want without necessarily moving to code.
12 |
13 | ## Background
14 |
15 | From the very beginning of creating Redot, we've wanted both a community developed and supported, "official" visual scripting plugin that we could provide learning content, documentation, and examples for. Not to mention games. While this project is far from that goal, We fully intend to continue to develop and expand its capabilities, in order to eventually reach the goal of it being a solid, general use, game development alternative to coding.
16 |
17 | While there are other ways of visually programming a game, we feel that the block style is both an easy to learn, and closer to code-style where it does make it easier to pick up code if you wanted to. In that way, this tool will help people who want to learn to code but feel overwhelmed by code, to learn how to think logically and write in a more human way.
18 |
19 | On the other hand, there are plenty of people who just like the idea of visual scripting, have used other tools that are similar and would just like to continue with that paradigm.
20 |
21 | ## Current Status
22 |
23 | This plugin is under heavy development, and as such should not be used for general game development. we welcome anyone to download and give us feedback to help further development, as well as any help in the programming department. Currently the plugin is being developed by @Andevrs and @Takun.
24 |
25 | ## Feedback & Discussion
26 |
27 | Please join our [Discord](https://discord.gg/Z6WvTeN3kM) to provide feedback, share ideas, and ask questions. You can also join the general Redot [discord](https://discord.gg/redot)
28 |
29 |
--------------------------------------------------------------------------------
/Reblocks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Redot-Experimental/reblocks/c80e8b09503556f4fba4c436dc7bb5dcb0c51804/Reblocks.png
--------------------------------------------------------------------------------
/Reblocks.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://b74a25ua3bnur"
6 | path="res://.godot/imported/Reblocks.png-d1c246f0c6f1f875f87739ecd7c3dff5.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/reblocks/Reblocks.png"
14 | dest_files=["res://.godot/imported/Reblocks.png-d1c246f0c6f1f875f87739ecd7c3dff5.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 |
--------------------------------------------------------------------------------
/Reblocksv2.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://gpnxcfitxm68"
6 | path="res://.godot/imported/Reblocksv2.svg-34a916730e874b867a7afb18294be04a.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/reblocks/Reblocksv2.svg"
14 | dest_files=["res://.godot/imported/Reblocksv2.svg-34a916730e874b867a7afb18294be04a.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=0.01
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/block_code_node/block_code.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | @icon("res://addons/reblocks/block_code_node/block_code_node.svg")
3 | class_name BlockCode
4 | extends Node
5 |
6 | const TxUtils := preload("res://addons/reblocks/translation/utils.gd")
7 |
8 | @export var block_script: BlockScriptSerialization = null:
9 | set = _set_block_script
10 |
11 |
12 | func _init():
13 | TxUtils.set_block_translation_domain(self)
14 |
15 |
16 | func _ready():
17 | if Engine.is_editor_hint():
18 | return
19 |
20 | _update_parent_script()
21 |
22 |
23 | func _get_custom_or_native_class(node: Node):
24 | if node.has_method("get_custom_class"):
25 | return node.get_custom_class()
26 | return node.get_class()
27 |
28 |
29 | func _enter_tree():
30 | if not Engine.is_editor_hint():
31 | return
32 |
33 | # Create script
34 | if block_script == null:
35 | var new_block_script: BlockScriptSerialization = load("res://addons/reblocks/serialization/default_block_script.tres").duplicate(true)
36 | new_block_script.script_inherits = _get_custom_or_native_class(get_parent())
37 | new_block_script.generated_script = new_block_script.generated_script.replace("INHERIT_DEFAULT", new_block_script.script_inherits)
38 | block_script = new_block_script
39 |
40 |
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 |
52 | func _update_parent_script():
53 | if Engine.is_editor_hint():
54 | push_error("Updating the parent script must happen in game.")
55 | return
56 |
57 | var parent: Node = get_parent()
58 | var script := GDScript.new()
59 | script.set_source_code(block_script.generated_script)
60 | script.reload()
61 |
62 | # Persist export script variables (like SimpleCharacter exported texture)
63 | var persist_properties = {}
64 | var old_property_list = parent.get_property_list()
65 | for property in old_property_list:
66 | if property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE:
67 | persist_properties[property.name] = parent.get(property.name)
68 |
69 | parent.set_script(script)
70 | parent.set_process(true)
71 |
72 | # Set persisted script variables in new script
73 | for property_name in persist_properties:
74 | parent.set(property_name, persist_properties.get(property_name))
75 |
76 | # Run simple setup after node is ready
77 | if parent.has_method("simple_setup"):
78 | parent.call_deferred("simple_setup")
79 |
80 |
81 | func _get_configuration_warnings():
82 | var warnings = []
83 | if self.owner == null:
84 | warnings.append("A BlockCode must not be a root node.")
85 | if get_parent() is BlockCode:
86 | warnings.append("The parent must not be a BlockCode.")
87 | if get_parent().script:
88 | var parent_script_name: StringName = get_parent().script.get_global_name()
89 | if not (parent_script_name and block_script and parent_script_name == block_script.script_inherits):
90 | warnings.append("This BlockCode will override the existing script in the parent node.")
91 | if get_parent().find_children("*", "BlockCode", false).size() > 1:
92 | warnings.append("The parent should only contain one BlockCode.")
93 | if block_script and _get_custom_or_native_class(get_parent()) != block_script.script_inherits:
94 | var warning = "The parent is not a %s. Create a new BlockCode node and reattach." % block_script.script_inherits
95 | warnings.append(warning)
96 | return warnings
97 |
--------------------------------------------------------------------------------
/block_code_node/block_code.gd.uid:
--------------------------------------------------------------------------------
1 | uid://bh3nmc4c3kefq
2 |
--------------------------------------------------------------------------------
/block_code_node/block_code_node.svg:
--------------------------------------------------------------------------------
1 |
2 |
18 |
--------------------------------------------------------------------------------
/block_code_node/block_code_node.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cmusxj1ppspnp"
6 | path="res://.godot/imported/block_code_node.svg-c652aef58e872e066bb0462e7d6dc430.ctex"
7 | metadata={
8 | "has_editor_variant": true,
9 | "vram_texture": false
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://addons/reblocks/block_code_node/block_code_node.svg"
15 | dest_files=["res://.godot/imported/block_code_node.svg-c652aef58e872e066bb0462e7d6dc430.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=0
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=false
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=1
36 | svg/scale=1.0
37 | editor/scale_with_editor_scale=true
38 | editor/convert_colors_with_editor_theme=true
39 |
--------------------------------------------------------------------------------
/block_code_plugin.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cvhc6iqgs7rj2
2 |
--------------------------------------------------------------------------------
/blocks/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Redot-Experimental/reblocks/c80e8b09503556f4fba4c436dc7bb5dcb0c51804/blocks/.DS_Store
--------------------------------------------------------------------------------
/blocks/communication/add_node_to_group.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=5 format=3 uid="uid://bpvefei72nh3a"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_5qal7"]
4 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/option_data.gd" id="1_auf06"]
5 | [ext_resource type="Script" path="res://addons/reblocks/blocks/communication/groups.gd" id="1_p83c7"]
6 |
7 | [sub_resource type="Resource" id="Resource_sus0f"]
8 | script = ExtResource("1_auf06")
9 | selected = 0
10 | items = []
11 |
12 | [resource]
13 | script = ExtResource("1_5qal7")
14 | name = &"add_node_to_group"
15 | target_node_class = ""
16 | description = "Add the node into the group"
17 | category = "Communication | Groups"
18 | type = 2
19 | variant_type = 0
20 | display_template = "add {node: OBJECT} to group {group: STRING}"
21 | code_template = "{node}.add_to_group({group})"
22 | defaults = {
23 | "group": SubResource("Resource_sus0f")
24 | }
25 | signal_name = ""
26 | is_advanced = false
27 | extension_script = ExtResource("1_p83c7")
28 |
--------------------------------------------------------------------------------
/blocks/communication/add_to_group.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=5 format=3 uid="uid://bvrmau8atjx1x"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/option_data.gd" id="1_aom4j"]
4 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_bcm71"]
5 | [ext_resource type="Script" path="res://addons/reblocks/blocks/communication/groups.gd" id="2_42ixf"]
6 |
7 | [sub_resource type="Resource" id="Resource_fk0wa"]
8 | script = ExtResource("1_aom4j")
9 | selected = 0
10 | items = []
11 |
12 | [resource]
13 | script = ExtResource("1_bcm71")
14 | name = &"add_to_group"
15 | target_node_class = ""
16 | description = "Add this node into the group"
17 | category = "Communication | Groups"
18 | type = 2
19 | variant_type = 0
20 | display_template = "add to group {group: STRING}"
21 | code_template = "add_to_group({group})"
22 | defaults = {
23 | "group": SubResource("Resource_fk0wa")
24 | }
25 | signal_name = ""
26 | is_advanced = false
27 | extension_script = ExtResource("2_42ixf")
28 |
--------------------------------------------------------------------------------
/blocks/communication/area2d_on_entered.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://de4k7t7uqws1j"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_xotf5"]
4 |
5 | [resource]
6 | script = ExtResource("1_xotf5")
7 | name = &"area2d_on_entered"
8 | target_node_class = "Area2D"
9 | description = ""
10 | category = "Communication | Methods"
11 | type = 1
12 | variant_type = 0
13 | display_template = "when this node collides with [something: OBJECT]"
14 | code_template = "func _on_body_entered(something: Node2D):"
15 | defaults = {}
16 | signal_name = "body_entered"
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/communication/area2d_on_exited.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://b36nq4mau6lu6"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_21qth"]
4 |
5 | [resource]
6 | script = ExtResource("1_21qth")
7 | name = &"area2d_on_exited"
8 | target_node_class = "Area2D"
9 | description = ""
10 | category = "Communication | Methods"
11 | type = 1
12 | variant_type = 0
13 | display_template = "when this node stops colliding with [something: OBJECT]"
14 | code_template = "func _on_body_exited(something: Node2D):"
15 | defaults = {}
16 | signal_name = "body_exited"
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/communication/call_method_group.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=5 format=3 uid="uid://c15vtdfihdxb8"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/option_data.gd" id="1_3nuts"]
4 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_mlm68"]
5 | [ext_resource type="Script" path="res://addons/reblocks/blocks/communication/groups.gd" id="1_of577"]
6 |
7 | [sub_resource type="Resource" id="Resource_f4ctg"]
8 | script = ExtResource("1_3nuts")
9 | selected = 0
10 | items = []
11 |
12 | [resource]
13 | script = ExtResource("1_mlm68")
14 | name = &"call_method_group"
15 | target_node_class = ""
16 | description = "Calls the method/function on each member of the given group"
17 | category = "Communication | Methods"
18 | type = 2
19 | variant_type = 0
20 | display_template = "call method {method_name: STRING} in group {group: STRING}"
21 | code_template = "get_tree().call_group({group}, {method_name})"
22 | defaults = {
23 | "group": SubResource("Resource_f4ctg")
24 | }
25 | signal_name = ""
26 | is_advanced = false
27 | extension_script = ExtResource("1_of577")
28 |
--------------------------------------------------------------------------------
/blocks/communication/call_method_node.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://c04j5flmimjvf"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_pg363"]
4 |
5 | [resource]
6 | script = ExtResource("1_pg363")
7 | name = &"call_method_node"
8 | target_node_class = ""
9 | description = "Calls the method/function of the given node"
10 | category = "Communication | Methods"
11 | type = 2
12 | variant_type = 0
13 | display_template = "call method {method_name: STRING} on node {node: OBJECT}"
14 | code_template = "{node}.call({method_name})"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/communication/define_method.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://7r2b2griss3i"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_6e473"]
4 |
5 | [resource]
6 | script = ExtResource("1_6e473")
7 | name = &"define_method"
8 | target_node_class = ""
9 | description = "Define a method/function with following statements"
10 | category = "Communication | Methods"
11 | type = 1
12 | variant_type = 0
13 | display_template = "define method {method_name: STRING_NAME}"
14 | code_template = "func {method_name}():"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/communication/get_node.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends BlockExtension
3 |
4 | const OptionData = preload("res://addons/reblocks/code_generation/option_data.gd")
5 | const Util = preload("res://addons/reblocks/ui/util.gd")
6 |
7 |
8 | func _find_paths(paths: Array[NodePath], node: Node, path_root: Node, block_parent: Node):
9 | # Add any non-BlockCode nodes that aren't the parent of the current
10 | # BlockCode node.
11 | if not node is BlockCode:
12 | var node_path: NodePath = Util.node_scene_path(node, block_parent, path_root)
13 | if not node_path in [^"", ^"."]:
14 | paths.append(node_path)
15 |
16 | for child in node.get_children():
17 | _find_paths(paths, child, path_root, block_parent)
18 |
19 |
20 | func get_defaults_for_node(context_node: Node) -> Dictionary:
21 | # The default paths are only needed in the editor.
22 | if not Engine.is_editor_hint():
23 | return {}
24 |
25 | var scene_root: Node = EditorInterface.get_edited_scene_root()
26 | var path_root: Node = scene_root.get_parent()
27 | var paths: Array[NodePath]
28 | _find_paths(paths, scene_root, path_root, context_node)
29 |
30 | if not paths:
31 | return {}
32 |
33 | return {"path": OptionData.new(paths)}
34 |
--------------------------------------------------------------------------------
/blocks/communication/get_node.gd.uid:
--------------------------------------------------------------------------------
1 | uid://dqb1cqabkq52o
2 |
--------------------------------------------------------------------------------
/blocks/communication/get_node.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=5 format=3 uid="uid://canpdkahokjqs"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/option_data.gd" id="1_bk47y"]
4 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_d60g7"]
5 | [ext_resource type="Script" path="res://addons/reblocks/blocks/communication/get_node.gd" id="1_we5wl"]
6 |
7 | [sub_resource type="Resource" id="Resource_esr4a"]
8 | script = ExtResource("1_bk47y")
9 | selected = 0
10 | items = []
11 |
12 | [resource]
13 | script = ExtResource("1_d60g7")
14 | name = &"get_node"
15 | target_node_class = ""
16 | description = "Get the node at the given path"
17 | category = "Communication | Nodes"
18 | type = 3
19 | variant_type = 24
20 | display_template = "{path: NIL}"
21 | code_template = "get_node(\"{path}\")"
22 | defaults = {
23 | "path": SubResource("Resource_esr4a")
24 | }
25 | signal_name = ""
26 | is_advanced = false
27 | extension_script = ExtResource("1_we5wl")
28 |
29 |
--------------------------------------------------------------------------------
/blocks/communication/groups.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | ## Common BlockExtension for scene group options.
3 | extends BlockExtension
4 |
5 | const OptionData = preload("res://addons/reblocks/code_generation/option_data.gd")
6 |
7 |
8 | # Global groups are just project settings in the global_group group.
9 | # ProjectSettings doesn't offer an API to get the project groups or to get all
10 | # settings. Fortunately, settings are simply implemented as properties on the
11 | # ProjectSettings object.
12 | static func _add_global_groups(groups: Dictionary):
13 | for prop in ProjectSettings.get_property_list():
14 | var name: String = prop["name"]
15 | var parts := name.split("/", false, 1)
16 | if parts[0] == "global_group":
17 | groups[parts[1]] = null
18 |
19 |
20 | # Add all the groups in a node and its children, ignoring internal _ prefixed
21 | # groups.
22 | static func _add_node_groups(groups: Dictionary, node: Node):
23 | for group in node.get_groups():
24 | if not group.begins_with("_"):
25 | groups[String(group)] = null
26 |
27 | for child in node.get_children():
28 | _add_node_groups(groups, child)
29 |
30 |
31 | func _get_edited_scene_groups() -> Array[String]:
32 | var groups: Dictionary
33 | _add_global_groups(groups)
34 |
35 | var root := context_node.get_tree().edited_scene_root
36 | _add_node_groups(groups, root)
37 |
38 | var sorted_groups: Array[String]
39 | sorted_groups.assign(groups.keys())
40 | sorted_groups.sort()
41 | return sorted_groups
42 |
43 |
44 | func _init():
45 | # FIXME: Only global group changes are monitored. Scene local groups should
46 | # also be monitored, but godot does not have any reasonable API to do that.
47 | ProjectSettings.settings_changed.connect(_on_project_settings_changed)
48 |
49 |
50 | func _context_node_changed():
51 | # If the context node changed, the scene local groups need to be updated.
52 | changed.emit()
53 |
54 |
55 | func get_defaults() -> Dictionary:
56 | if not context_node:
57 | return {}
58 |
59 | # The default groups are only needed in the editor.
60 | if not context_node.is_part_of_edited_scene():
61 | return {}
62 |
63 | var groups: Array[String] = _get_edited_scene_groups()
64 | return {"group": OptionData.new(groups)}
65 |
66 |
67 | func _on_project_settings_changed():
68 | # FIXME: The global groups should be cached and compared so that the
69 | # defaults are only changed when the global groups actually change.
70 | changed.emit()
71 |
--------------------------------------------------------------------------------
/blocks/communication/groups.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cgegsolf0rww1
2 |
--------------------------------------------------------------------------------
/blocks/communication/is_in_group.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=5 format=3 uid="uid://q4cnstftvsiu"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/option_data.gd" id="1_cla3i"]
4 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_tjyq5"]
5 | [ext_resource type="Script" path="res://addons/reblocks/blocks/communication/groups.gd" id="2_o165d"]
6 |
7 | [sub_resource type="Resource" id="Resource_d0v0d"]
8 | script = ExtResource("1_cla3i")
9 | selected = 0
10 | items = []
11 |
12 | [resource]
13 | script = ExtResource("1_tjyq5")
14 | name = &"is_in_group"
15 | target_node_class = ""
16 | description = "Is this node in the group"
17 | category = "Communication | Groups"
18 | type = 3
19 | variant_type = 1
20 | display_template = "is in group {group: STRING}"
21 | code_template = "is_in_group({group})"
22 | defaults = {
23 | "group": SubResource("Resource_d0v0d")
24 | }
25 | signal_name = ""
26 | is_advanced = false
27 | extension_script = ExtResource("2_o165d")
28 |
--------------------------------------------------------------------------------
/blocks/communication/is_node_in_group.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=5 format=3 uid="uid://bbtdxeey74x67"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_5krrs"]
4 | [ext_resource type="Script" path="res://addons/reblocks/blocks/communication/groups.gd" id="1_r4prw"]
5 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/option_data.gd" id="1_y4j0k"]
6 |
7 | [sub_resource type="Resource" id="Resource_o38ym"]
8 | script = ExtResource("1_y4j0k")
9 | selected = 0
10 | items = []
11 |
12 | [resource]
13 | script = ExtResource("1_5krrs")
14 | name = &"is_node_in_group"
15 | target_node_class = ""
16 | description = "Is the node in the group"
17 | category = "Communication | Groups"
18 | type = 3
19 | variant_type = 1
20 | display_template = "{node: OBJECT} is in group {group: STRING}"
21 | code_template = "{node}.is_in_group({group})"
22 | defaults = {
23 | "group": SubResource("Resource_o38ym")
24 | }
25 | signal_name = ""
26 | is_advanced = false
27 | extension_script = ExtResource("1_r4prw")
28 |
--------------------------------------------------------------------------------
/blocks/communication/remove_from_group.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=5 format=3 uid="uid://dgenw5wyqorvq"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_cdwef"]
4 | [ext_resource type="Script" path="res://addons/reblocks/blocks/communication/groups.gd" id="1_i50fw"]
5 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/option_data.gd" id="1_mnxp7"]
6 |
7 | [sub_resource type="Resource" id="Resource_45b71"]
8 | script = ExtResource("1_mnxp7")
9 | selected = 0
10 | items = []
11 |
12 | [resource]
13 | script = ExtResource("1_cdwef")
14 | name = &"remove_from_group"
15 | target_node_class = ""
16 | description = "Remove this node from the group"
17 | category = "Communication | Groups"
18 | type = 2
19 | variant_type = 0
20 | display_template = "remove from group {group: STRING}"
21 | code_template = "remove_from_group({group})"
22 | defaults = {
23 | "group": SubResource("Resource_45b71")
24 | }
25 | signal_name = ""
26 | is_advanced = false
27 | extension_script = ExtResource("1_i50fw")
28 |
--------------------------------------------------------------------------------
/blocks/communication/remove_node_from_group.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=5 format=3 uid="uid://b2dwk77hnri8y"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/option_data.gd" id="1_clwhe"]
4 | [ext_resource type="Script" path="res://addons/reblocks/blocks/communication/groups.gd" id="1_h3lhb"]
5 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_pec24"]
6 |
7 | [sub_resource type="Resource" id="Resource_03rge"]
8 | script = ExtResource("1_clwhe")
9 | selected = 0
10 | items = []
11 |
12 | [resource]
13 | script = ExtResource("1_pec24")
14 | name = &"remove_node_from_group"
15 | target_node_class = ""
16 | description = "Remove the node from the group"
17 | category = "Communication | Groups"
18 | type = 2
19 | variant_type = 0
20 | display_template = "remove {node: OBJECT} from group {group: NIL}"
21 | code_template = "{node}.remove_from_group(\\\"{group}\\\")"
22 | defaults = {
23 | "group": SubResource("Resource_03rge")
24 | }
25 | signal_name = ""
26 | is_advanced = false
27 | extension_script = ExtResource("1_h3lhb")
28 |
--------------------------------------------------------------------------------
/blocks/communication/rigidbody2d_on_entered.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://dl1xd1jit2mlp"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_v2421"]
4 |
5 | [resource]
6 | script = ExtResource("1_v2421")
7 | name = &"rigidbody2d_on_entered"
8 | target_node_class = "RigidBody2D"
9 | description = ""
10 | category = "Communication | Methods"
11 | type = 1
12 | variant_type = 0
13 | display_template = "when this node collides with [something: OBJECT]"
14 | code_template = "func _on_body_entered(something: Node2D):"
15 | defaults = {}
16 | signal_name = "body_entered"
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/communication/rigidbody2d_on_exited.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://c15ymi1kxb570"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_sahiu"]
4 |
5 | [resource]
6 | script = ExtResource("1_sahiu")
7 | name = &"rigidbody2d_on_exited"
8 | target_node_class = "RigidBody2D"
9 | description = ""
10 | category = "Communication | Methods"
11 | type = 1
12 | variant_type = 0
13 | display_template = "when this node stops colliding with [something: OBJECT]"
14 | code_template = "func _on_body_exited(something: Node2D):"
15 | defaults = {}
16 | signal_name = "body_exited"
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/communication/switch_scene.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://dnc2555wnobks"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_rnqd5"]
4 |
5 | [resource]
6 | script = ExtResource("1_rnqd5")
7 | name = &"switch_scene"
8 | target_node_class = ""
9 | description = "Stop playing the current scene, and switch to a different one. You might use this to switch to a new level."
10 | category = "Communication | Methods"
11 | type = 2
12 | variant_type = 0
13 | display_template = "switch the scene to {file_path: STRING}"
14 | code_template = "get_tree().change_scene_to_file({file_path})
15 | "
16 | defaults = {}
17 | signal_name = ""
18 | scope = ""
19 |
--------------------------------------------------------------------------------
/blocks/graphics/animationplayer_is_playing.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://mg4y3o0rsqd5"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_xr50b"]
4 |
5 | [resource]
6 | script = ExtResource("1_xr50b")
7 | name = &"animationplayer_is_playing"
8 | target_node_class = "AnimationPlayer"
9 | description = "Check if an animation is currently playing."
10 | category = "Graphics | Animation"
11 | type = 3
12 | variant_type = 1
13 | display_template = "is playing"
14 | code_template = "is_playing()"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/graphics/animationplayer_pause.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://clopo7gmje5a"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_2enqv"]
4 |
5 | [resource]
6 | script = ExtResource("1_2enqv")
7 | name = &"animationplayer_pause"
8 | target_node_class = "AnimationPlayer"
9 | description = "Pause the currently playing animation."
10 | category = "Graphics | Animation"
11 | type = 2
12 | variant_type = 0
13 | display_template = "pause"
14 | code_template = "pause()"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/graphics/animationplayer_play.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends BlockExtension
3 |
4 | const OptionData = preload("res://addons/reblocks/code_generation/option_data.gd")
5 |
6 |
7 | func get_defaults() -> Dictionary:
8 | var animation_player = context_node as AnimationPlayer
9 |
10 | if not animation_player:
11 | return {}
12 |
13 | var animation_list = animation_player.get_animation_list()
14 |
15 | return {"animation": OptionData.new(animation_list)}
16 |
17 |
18 | func _context_node_changed():
19 | var animation_player = context_node as AnimationPlayer
20 |
21 | if not animation_player:
22 | return
23 |
24 | animation_player.animation_list_changed.connect(_on_animation_list_changed)
25 |
26 |
27 | func _on_animation_list_changed():
28 | _emit_changed()
29 |
--------------------------------------------------------------------------------
/blocks/graphics/animationplayer_play.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cx6c5ey7kmdcp
2 |
--------------------------------------------------------------------------------
/blocks/graphics/animationplayer_play.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=5 format=3 uid="uid://c5e1byehtxwc0"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_emeuv"]
4 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/option_data.gd" id="1_xu43h"]
5 | [ext_resource type="Script" path="res://addons/reblocks/blocks/graphics/animationplayer_play.gd" id="2_7ymgi"]
6 |
7 | [sub_resource type="Resource" id="Resource_qpxn2"]
8 | script = ExtResource("1_xu43h")
9 | selected = 0
10 | items = []
11 |
12 | [resource]
13 | script = ExtResource("1_emeuv")
14 | name = &"animationplayer_play"
15 | target_node_class = "AnimationPlayer"
16 | description = "Play the animation."
17 | category = "Graphics | Animation"
18 | type = 2
19 | variant_type = 0
20 | display_template = "play {animation: STRING}"
21 | code_template = "play({animation})
22 |
23 |
24 | "
25 | defaults = {
26 | "animation": SubResource("Resource_qpxn2")
27 | }
28 | signal_name = ""
29 | is_advanced = false
30 | extension_script = ExtResource("2_7ymgi")
31 |
--------------------------------------------------------------------------------
/blocks/graphics/animationplayer_stop.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://b4v00oxoxbfet"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_wp8gr"]
4 |
5 | [resource]
6 | script = ExtResource("1_wp8gr")
7 | name = &"animationplayer_stop"
8 | target_node_class = "AnimationPlayer"
9 | description = "Stop the currently playing animation."
10 | category = "Graphics | Animation"
11 | type = 2
12 | variant_type = 0
13 | display_template = "stop"
14 | code_template = "stop()"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/graphics/viewport_center.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://1536itmdu8yo"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_rc1so"]
4 |
5 | [resource]
6 | script = ExtResource("1_rc1so")
7 | name = &"viewport_center"
8 | target_node_class = ""
9 | description = "Coordinates of the middle of the viewable screen when playing."
10 | category = "Graphics | Viewport"
11 | type = 3
12 | variant_type = 5
13 | display_template = "viewport center"
14 | code_template = "(func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin / scale + get_viewport_rect().size / scale / 2).call()"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/graphics/viewport_height.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://bdm4yr68mdf4d"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_1debb"]
4 |
5 | [resource]
6 | script = ExtResource("1_1debb")
7 | name = &"viewport_height"
8 | target_node_class = ""
9 | description = "How tall the viewable screen is when playing."
10 | category = "Graphics | Viewport"
11 | type = 3
12 | variant_type = 3
13 | display_template = "viewport height"
14 | code_template = "(func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin.y / scale.y + get_viewport_rect().size.y / scale.y).call()"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/graphics/viewport_width.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://bt78ajp56ga24"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_ll4rh"]
4 |
5 | [resource]
6 | script = ExtResource("1_ll4rh")
7 | name = &"viewport_width"
8 | target_node_class = ""
9 | description = "How wide the viewable screen is when playing."
10 | category = "Graphics | Viewport"
11 | type = 3
12 | variant_type = 3
13 | display_template = "viewport width"
14 | code_template = "(func (): var transform: Transform2D = get_viewport_transform(); var scale: Vector2 = transform.get_scale(); return -transform.origin.x / scale.x + get_viewport_rect().size.x / scale.x).call()"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/input/characterbody2d_is_on_floor.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://cbpicqif1ddro"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_btxic"]
4 |
5 | [resource]
6 | script = ExtResource("1_btxic")
7 | name = &"characterbody2d_is_on_floor"
8 | target_node_class = "CharacterBody2D"
9 | description = "True if the character is on the floor."
10 | category = "Physics | Velocity"
11 | type = 3
12 | variant_type = 1
13 | display_template = "is on floor"
14 | code_template = "is_on_floor()"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/input/characterbody2d_move.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://cu3ru61vg6bx5"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_btxic"]
4 |
5 | [resource]
6 | script = ExtResource("1_btxic")
7 | name = &"characterbody2d_move"
8 | target_node_class = "CharacterBody2D"
9 | description = "Move the character up, down, left, and right with the keyboard using the given keys. The speed of movement can be adjusted separately for x (left and right) and y (up and down)."
10 | category = "Input"
11 | type = 2
12 | variant_type = 0
13 | display_template = "move with keys {up: STRING} {down: STRING} {left: STRING} {right: STRING} at speed {speed: VECTOR2}"
14 | code_template = "var dir = Vector2()
15 | dir.x += float(Input.is_key_pressed(OS.find_keycode_from_string({right})))
16 | dir.x -= float(Input.is_key_pressed(OS.find_keycode_from_string({left})))
17 | dir.y += float(Input.is_key_pressed(OS.find_keycode_from_string({down})))
18 | dir.y -= float(Input.is_key_pressed(OS.find_keycode_from_string({up})))
19 | dir = dir.normalized()
20 | velocity = dir*{speed}
21 | move_and_slide()
22 | "
23 | defaults = {
24 | "down": "S",
25 | "left": "A",
26 | "right": "D",
27 | "speed": Vector2(100, 100),
28 | "up": "W"
29 | }
30 | signal_name = ""
31 | scope = ""
32 |
--------------------------------------------------------------------------------
/blocks/input/is_input_actioned.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends BlockExtension
3 |
4 | const OptionData = preload("res://addons/reblocks/code_generation/option_data.gd")
5 |
6 |
7 | func get_defaults() -> Dictionary:
8 | var inputmap_actions = _get_inputmap_actions()
9 | return {"action_name": OptionData.new(inputmap_actions)}
10 |
11 |
12 | static func _get_inputmap_actions() -> Array[StringName]:
13 | var inputmap_actions: Array[StringName]
14 |
15 | var editor_input_actions: Dictionary = {}
16 | var editor_input_action_deadzones: Dictionary = {}
17 | if Engine.is_editor_hint():
18 | var actions := InputMap.get_actions()
19 | for action in actions:
20 | if action.begins_with("spatial_editor"):
21 | var events := InputMap.action_get_events(action)
22 | editor_input_actions[action] = events
23 | editor_input_action_deadzones[action] = InputMap.action_get_deadzone(action)
24 |
25 | InputMap.load_from_project_settings()
26 |
27 | inputmap_actions = InputMap.get_actions()
28 |
29 | if Engine.is_editor_hint():
30 | for action in editor_input_actions.keys():
31 | InputMap.add_action(action, editor_input_action_deadzones[action])
32 | for event in editor_input_actions[action]:
33 | InputMap.action_add_event(action, event)
34 |
35 | return inputmap_actions
36 |
--------------------------------------------------------------------------------
/blocks/input/is_input_actioned.gd.uid:
--------------------------------------------------------------------------------
1 | uid://dg44v8wyteiqi
2 |
--------------------------------------------------------------------------------
/blocks/input/is_input_actioned.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=5 format=3 uid="uid://86j17le5e58u"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/option_data.gd" id="1_d8i05"]
4 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_rprh7"]
5 | [ext_resource type="Script" path="res://addons/reblocks/blocks/input/is_input_actioned.gd" id="2_h11b7"]
6 |
7 | [sub_resource type="Resource" id="Resource_ai5in"]
8 | script = ExtResource("1_d8i05")
9 | selected = 0
10 | items = ["pressed", "just_pressed", "just_released"]
11 |
12 | [resource]
13 | script = ExtResource("1_rprh7")
14 | name = &"is_input_actioned"
15 | target_node_class = ""
16 | description = "True if the specified input action has been pressed or released."
17 | category = "Input"
18 | type = 3
19 | variant_type = 1
20 | display_template = "action {action_name: STRING_NAME} is {action: NIL}"
21 | code_template = "Input.is_action_{{action}}('{{action_name}}')"
22 | defaults = {
23 | "action": SubResource("Resource_ai5in")
24 | }
25 | signal_name = ""
26 | is_advanced = false
27 | extension_script = ExtResource("2_h11b7")
28 |
--------------------------------------------------------------------------------
/blocks/lifecycle/physics_process.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://3l8wefwlme2v"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_pmina"]
4 |
5 | [resource]
6 | script = ExtResource("1_pmina")
7 | name = &"physics_process"
8 | target_node_class = ""
9 | description = "Attached blocks will be executed before each physics step"
10 | category = "Lifecycle"
11 | type = 1
12 | variant_type = 0
13 | display_template = "every physics step"
14 | code_template = "func _physics_process(delta):"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 | is_advanced = true
19 |
--------------------------------------------------------------------------------
/blocks/lifecycle/process.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://chioedvp50013"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_pmina"]
4 |
5 | [resource]
6 | script = ExtResource("1_pmina")
7 | name = &"process"
8 | target_node_class = ""
9 | description = "Attached blocks will be executed during the processing step of the main loop"
10 | category = "Lifecycle"
11 | type = 1
12 | variant_type = 0
13 | display_template = "every frame"
14 | code_template = "func _process(delta):"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/lifecycle/queue_free.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://4hj5b3xaiuy8"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_75fle"]
4 |
5 | [resource]
6 | script = ExtResource("1_75fle")
7 | name = &"queue_free"
8 | target_node_class = ""
9 | description = "Queues this node to be deleted at the end of the current frame"
10 | category = "Lifecycle"
11 | type = 2
12 | variant_type = 0
13 | display_template = "remove"
14 | code_template = "queue_free()"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/lifecycle/queue_free_node.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://d31lkxkm5lww7"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_75fle"]
4 |
5 | [resource]
6 | script = ExtResource("1_75fle")
7 | name = &"queue_free_node"
8 | target_node_class = ""
9 | description = "Queues the given node to be deleted at the end of the current frame"
10 | category = "Lifecycle"
11 | type = 2
12 | variant_type = 0
13 | display_template = "remove {node: OBJECT}"
14 | code_template = "{node}.queue_free()"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/lifecycle/ready.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://dgwfoepoejlom"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_vk0xk"]
4 |
5 | [resource]
6 | script = ExtResource("1_vk0xk")
7 | name = &"ready"
8 | target_node_class = ""
9 | description = "Attached blocks will be executed once when the node is \"ready\""
10 | category = "Lifecycle"
11 | type = 1
12 | variant_type = 0
13 | display_template = "when starting"
14 | code_template = "func _ready():"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/log/breakpoint.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://bddy0d4xdv20c"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_xva04"]
4 |
5 | [resource]
6 | script = ExtResource("1_xva04")
7 | name = &"breakpoint"
8 | target_node_class = ""
9 | description = "Pause execution and show the current line of code in the debugger."
10 | category = "Log"
11 | type = 2
12 | variant_type = 0
13 | display_template = "breakpoint"
14 | code_template = "breakpoint"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/log/comment.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://c4qpkgyd7kfp4"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_44emg"]
4 |
5 | [resource]
6 | script = ExtResource("1_44emg")
7 | name = &"comment"
8 | target_node_class = ""
9 | description = "Add a comment to the code"
10 | category = "Log"
11 | type = 2
12 | variant_type = 0
13 | display_template = "comment {text}"
14 | code_template = "## {text}"
15 | defaults = {
16 | "text": "Hello"
17 | }
18 | signal_name = ""
19 | is_advanced = false
20 |
--------------------------------------------------------------------------------
/blocks/log/concat.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://cb6ux0amdhhlw"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_lstbo"]
4 |
5 | [resource]
6 | script = ExtResource("1_lstbo")
7 | name = &"concat"
8 | description = ""
9 | category = "Log"
10 | type = 3
11 | variant_type = 4
12 | display_template = "{string1: STRING} + {string2: STRING}"
13 | code_template = "{string1} + {string2}"
14 | defaults = {}
15 | signal_name = ""
16 |
--------------------------------------------------------------------------------
/blocks/log/print.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://barxsapb8tl0r"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_0lih2"]
4 |
5 | [resource]
6 | script = ExtResource("1_0lih2")
7 | name = &"print"
8 | target_node_class = ""
9 | description = "Print the text to output"
10 | category = "Log"
11 | type = 2
12 | variant_type = 0
13 | display_template = "log text {text: STRING}"
14 | code_template = "print({text})"
15 | defaults = {
16 | "text": "Hello"
17 | }
18 | signal_name = ""
19 | scope = ""
20 |
--------------------------------------------------------------------------------
/blocks/logic/and.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://d0g11cp3ff81i"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="2_lxlcw"]
4 |
5 | [resource]
6 | script = ExtResource("2_lxlcw")
7 | name = &"and"
8 | description = ""
9 | category = "Logic | Boolean"
10 | type = 3
11 | variant_type = 1
12 | display_template = "{bool1: BOOL} and {bool2: BOOL}"
13 | code_template = "{bool1} and {bool2}"
14 | defaults = {}
15 | signal_name = ""
16 | scope = ""
17 |
--------------------------------------------------------------------------------
/blocks/logic/compare.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=4 format=3 uid="uid://pr5wnn3ltkbo"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/option_data.gd" id="1_hcv2h"]
4 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_wp40r"]
5 |
6 | [sub_resource type="Resource" id="Resource_ie4sg"]
7 | script = ExtResource("1_hcv2h")
8 | selected = 0
9 | items = ["==", ">", "<", ">=", "<=", "!="]
10 |
11 | [resource]
12 | script = ExtResource("1_wp40r")
13 | name = &"compare"
14 | target_node_class = ""
15 | description = ""
16 | category = "Logic | Comparison"
17 | type = 3
18 | variant_type = 1
19 | display_template = "{float1: FLOAT} {op: NIL} {float2: FLOAT}"
20 | code_template = "{float1} {{op}} {float2}"
21 | defaults = {
22 | "float1": 1.0,
23 | "float2": 1.0,
24 | "op": SubResource("Resource_ie4sg")
25 | }
26 | signal_name = ""
27 | is_advanced = false
28 |
--------------------------------------------------------------------------------
/blocks/logic/else.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://dpgx8j3veifgl"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_x816c"]
4 |
5 | [resource]
6 | script = ExtResource("1_x816c")
7 | name = &"else"
8 | target_node_class = ""
9 | description = ""
10 | category = "Logic | Conditionals"
11 | type = 4
12 | variant_type = 0
13 | display_template = "else"
14 | code_template = "else:"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/logic/else_if.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://by53vmmn3wtny"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_kgjks"]
4 |
5 | [resource]
6 | script = ExtResource("1_kgjks")
7 | name = &"else_if"
8 | target_node_class = ""
9 | description = ""
10 | category = "Logic | Conditionals"
11 | type = 4
12 | variant_type = 0
13 | display_template = "else if {condition: BOOL}"
14 | code_template = "elif {condition}:"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/logic/flip.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://d3yr42a1ba0c8"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_nsxuk"]
4 |
5 | [resource]
6 | script = ExtResource("1_nsxuk")
7 | name = &"flip"
8 | target_node_class = ""
9 | description = ""
10 | category = "Logic | Conditionals"
11 | type = 2
12 | variant_type = 0
13 | display_template = "flip {condition: BOOL}"
14 | code_template = "flip_h = {condition}"
15 | defaults = {}
16 | signal_name = ""
17 | is_advanced = false
18 |
--------------------------------------------------------------------------------
/blocks/logic/if.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://cxvoo3jassq8c"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_c6ly3"]
4 |
5 | [resource]
6 | script = ExtResource("1_c6ly3")
7 | name = &"if"
8 | target_node_class = ""
9 | description = ""
10 | category = "Logic | Conditionals"
11 | type = 4
12 | variant_type = 0
13 | display_template = "if {condition: BOOL}"
14 | code_template = "if {condition}:"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/logic/not.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://d6asv53q6ok8"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_6igv6"]
4 |
5 | [resource]
6 | script = ExtResource("1_6igv6")
7 | name = &"not"
8 | target_node_class = ""
9 | description = ""
10 | category = "Logic | Boolean"
11 | type = 3
12 | variant_type = 1
13 | display_template = "not {bool: BOOL}"
14 | code_template = "not {bool}"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/logic/or.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://cyu2tntoqf85m"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_oets3"]
4 |
5 | [resource]
6 | script = ExtResource("1_oets3")
7 | name = &"or"
8 | description = ""
9 | category = "Logic | Boolean"
10 | type = 3
11 | variant_type = 1
12 | display_template = "{bool1: BOOL} or {bool2: BOOL}"
13 | code_template = "{bool1} or {bool2}"
14 | defaults = {}
15 | signal_name = ""
16 | scope = ""
17 |
--------------------------------------------------------------------------------
/blocks/loops/await_scene_ready.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://bkdmiqavhqrph"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_qy2t4"]
4 |
5 | [resource]
6 | script = ExtResource("1_qy2t4")
7 | name = &"await_scene_ready"
8 | target_node_class = ""
9 | description = ""
10 | category = "Loops"
11 | type = 2
12 | variant_type = 0
13 | display_template = "wait for the scene to be ready"
14 | code_template = "if not get_tree().root.is_node_ready():
15 | await get_tree().root.ready"
16 | defaults = {}
17 | signal_name = ""
18 | scope = ""
19 |
--------------------------------------------------------------------------------
/blocks/loops/break.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://dwteydig4c6hi"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_4rhsl"]
4 |
5 | [resource]
6 | script = ExtResource("1_4rhsl")
7 | name = &"break"
8 | target_node_class = ""
9 | description = ""
10 | category = "Loops"
11 | type = 2
12 | variant_type = 0
13 | display_template = "break"
14 | code_template = "break"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/loops/continue.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://srm0bee85n0d"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_junev"]
4 |
5 | [resource]
6 | script = ExtResource("1_junev")
7 | name = &"continue"
8 | target_node_class = ""
9 | description = ""
10 | category = "Loops"
11 | type = 2
12 | variant_type = 0
13 | display_template = "continue"
14 | code_template = "continue"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/loops/for.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://0g4njflvemaa"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_u01bi"]
4 |
5 | [resource]
6 | script = ExtResource("1_u01bi")
7 | name = &"for"
8 | target_node_class = ""
9 | description = "Run the connected blocks [i]number[/i] times"
10 | category = "Loops"
11 | type = 4
12 | variant_type = 0
13 | display_template = "repeat {number: INT}"
14 | code_template = "for __i in {number}:"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/loops/while.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://ccnjk5s5qb2xe"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_fxxh0"]
4 |
5 | [resource]
6 | script = ExtResource("1_fxxh0")
7 | name = &"while"
8 | target_node_class = ""
9 | description = "Run the connected blocks as long as [i]condition[/i] is true.
10 |
11 | Hint: snap a [b]Comparison[/b] block into the condition."
12 | category = "Loops"
13 | type = 4
14 | variant_type = 0
15 | display_template = "while {condition: BOOL}"
16 | code_template = "while {condition}:"
17 | defaults = {}
18 | signal_name = ""
19 | scope = ""
20 |
--------------------------------------------------------------------------------
/blocks/math/add.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://coy3o7q0x0y60"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_rks7c"]
4 |
5 | [resource]
6 | script = ExtResource("1_rks7c")
7 | name = &"add"
8 | target_node_class = ""
9 | description = ""
10 | category = "Math"
11 | type = 3
12 | variant_type = 3
13 | display_template = "{a: FLOAT} + {b: FLOAT}"
14 | code_template = "{a} + {b}"
15 | defaults = {
16 | "a": 1.0,
17 | "b": 1.0
18 | }
19 | signal_name = ""
20 | scope = ""
21 |
--------------------------------------------------------------------------------
/blocks/math/cos.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://c6g6ljp46lfrj"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_lxbvo"]
4 |
5 | [resource]
6 | script = ExtResource("1_lxbvo")
7 | name = &"cos"
8 | description = "Calculate the cosine of [i]angle[/i]"
9 | category = "Math"
10 | type = 3
11 | variant_type = 3
12 | display_template = "cos {angle: FLOAT}"
13 | code_template = "cos(deg_to_rad({angle}))"
14 | defaults = {
15 | "angle": 0.0
16 | }
17 | signal_name = ""
18 | scope = ""
19 |
--------------------------------------------------------------------------------
/blocks/math/divide.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://dwk6c70c4ta0"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_rhh7v"]
4 |
5 | [resource]
6 | script = ExtResource("1_rhh7v")
7 | name = &"divide"
8 | target_node_class = ""
9 | description = ""
10 | category = "Math"
11 | type = 3
12 | variant_type = 3
13 | display_template = "{a: FLOAT} / {b: FLOAT}"
14 | code_template = "{a} / {b}"
15 | defaults = {
16 | "a": 1.0,
17 | "b": 1.0
18 | }
19 | signal_name = ""
20 | scope = ""
21 |
--------------------------------------------------------------------------------
/blocks/math/multiply.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://yipjitb3p66q"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_c5vny"]
4 |
5 | [resource]
6 | script = ExtResource("1_c5vny")
7 | name = &"multiply"
8 | target_node_class = ""
9 | description = ""
10 | category = "Math"
11 | type = 3
12 | variant_type = 3
13 | display_template = "{a: FLOAT} * {b: FLOAT}"
14 | code_template = "{a} * {b}"
15 | defaults = {
16 | "a": 1.0,
17 | "b": 1.0
18 | }
19 | signal_name = ""
20 | scope = ""
21 |
--------------------------------------------------------------------------------
/blocks/math/pow.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://bib11ow5t44to"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_cx5g5"]
4 |
5 | [resource]
6 | script = ExtResource("1_cx5g5")
7 | name = &"pow"
8 | target_node_class = ""
9 | description = ""
10 | category = "Math"
11 | type = 3
12 | variant_type = 3
13 | display_template = "{base: FLOAT} ^ {exp: FLOAT}"
14 | code_template = "pow({base}, {exp})"
15 | defaults = {
16 | "base": 1.0,
17 | "exp": 1.0
18 | }
19 | signal_name = ""
20 | scope = ""
21 |
--------------------------------------------------------------------------------
/blocks/math/randf_range.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://u35glf576fue"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_03jps"]
4 |
5 | [resource]
6 | script = ExtResource("1_03jps")
7 | name = &"randf_range"
8 | target_node_class = ""
9 | description = "Generate a random floating point number between [i]from[/i] and [i]to[/i] inclusively"
10 | category = "Math"
11 | type = 3
12 | variant_type = 3
13 | display_template = "random floating point number between {from: FLOAT} and {to: FLOAT}"
14 | code_template = "randf_range({from}, {to})"
15 | defaults = {
16 | "from": -1.0,
17 | "to": 1.0
18 | }
19 | signal_name = ""
20 | scope = ""
21 |
--------------------------------------------------------------------------------
/blocks/math/randi_range.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://b3b1dyarh2hmo"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_hk574"]
4 |
5 | [resource]
6 | script = ExtResource("1_hk574")
7 | name = &"randi_range"
8 | target_node_class = ""
9 | description = "Generate a random signed 32-bits integer number between [i]from[/i] and [i]to[/i] inclusively. [i]from[/i] and [i]to[/i] can be a negative or positive number"
10 | category = "Math"
11 | type = 3
12 | variant_type = 2
13 | display_template = "random integer number between {from: INT} and {to: INT}"
14 | code_template = "randi_range({from}, {to})"
15 | defaults = {
16 | "from": 0,
17 | "to": 100
18 | }
19 | signal_name = ""
20 | scope = ""
21 |
--------------------------------------------------------------------------------
/blocks/math/sin.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://b1r7f06rfci6o"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_dlr47"]
4 |
5 | [resource]
6 | script = ExtResource("1_dlr47")
7 | name = &"sin"
8 | description = "Calculate the sine of [i]angle[/i]"
9 | category = "Math"
10 | type = 3
11 | variant_type = 3
12 | display_template = "sin {angle: FLOAT}"
13 | code_template = "sin(deg_to_rad({angle}))"
14 | defaults = {
15 | "angle": 0.0
16 | }
17 | signal_name = ""
18 | scope = ""
19 |
--------------------------------------------------------------------------------
/blocks/math/subtract.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://dkt135xfcklya"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_n0dmm"]
4 |
5 | [resource]
6 | script = ExtResource("1_n0dmm")
7 | name = &"subtract"
8 | target_node_class = ""
9 | description = ""
10 | category = "Math"
11 | type = 3
12 | variant_type = 3
13 | display_template = "{a: FLOAT} - {b: FLOAT}"
14 | code_template = "{a} - {b}"
15 | defaults = {
16 | "a": 1.0,
17 | "b": 1.0
18 | }
19 | signal_name = ""
20 | scope = ""
21 |
--------------------------------------------------------------------------------
/blocks/math/tan.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://blpo01pjjheqb"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_e2566"]
4 |
5 | [resource]
6 | script = ExtResource("1_e2566")
7 | name = &"tan"
8 | description = "Calculate the tangent of [i]angle[/i]"
9 | category = "Math"
10 | type = 3
11 | variant_type = 3
12 | display_template = "tan {angle: FLOAT}"
13 | code_template = "tan(deg_to_rad({angle}))"
14 | defaults = {
15 | "angle": 0.0
16 | }
17 | signal_name = ""
18 | scope = ""
19 |
--------------------------------------------------------------------------------
/blocks/math/vector2_xy.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=4 format=3 uid="uid://bpdjqy6oidfo4"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/option_data.gd" id="1_p8v57"]
4 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="2_207xo"]
5 |
6 | [sub_resource type="Resource" id="Resource_ie4sg"]
7 | script = ExtResource("1_p8v57")
8 | selected = 0
9 | items = ["x", "y"]
10 |
11 | [resource]
12 | script = ExtResource("2_207xo")
13 | name = &"vector2_xy"
14 | target_node_class = ""
15 | description = "Gives the x or y of a [b]Vector2[/b]"
16 | category = "Math"
17 | type = 3
18 | variant_type = 3
19 | display_template = "{xy: NIL} of {vector2: VECTOR2}"
20 | code_template = "{vector2}.{{xy}}"
21 | defaults = {
22 | "xy": SubResource("Resource_ie4sg")
23 | }
24 | signal_name = ""
25 | is_advanced = false
26 |
--------------------------------------------------------------------------------
/blocks/math/vector3_multiply.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://bff7cwmpisihj"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_52jwf"]
4 |
5 | [resource]
6 | script = ExtResource("1_52jwf")
7 | name = &"vector3_multiply"
8 | target_node_class = ""
9 | description = "Multiplies a Vector3 with a number. Use this, for example, to get a point some distance away along an angle."
10 | category = "Math"
11 | type = 3
12 | variant_type = 9
13 | display_template = "multiply {vector: VECTOR3} by {number: FLOAT}"
14 | code_template = "{vector} * {number}"
15 | defaults = {
16 | "number": 1.0,
17 | "vector": Vector3(1, 1, 1)
18 | }
19 | signal_name = ""
20 | scope = ""
21 |
--------------------------------------------------------------------------------
/blocks/math/vector3_xyz.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=4 format=3 uid="uid://s72tgtbci1ui"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/option_data.gd" id="1_0wc0o"]
4 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="2_e6ohf"]
5 |
6 | [sub_resource type="Resource" id="Resource_ie4sg"]
7 | script = ExtResource("1_0wc0o")
8 | selected = 0
9 | items = ["x", "y", "z"]
10 |
11 | [resource]
12 | script = ExtResource("2_e6ohf")
13 | name = &"vector3_xyz"
14 | target_node_class = ""
15 | description = "Gives the x, y, or z of a [b]Vector3[/b]"
16 | category = "Math"
17 | type = 3
18 | variant_type = 3
19 | display_template = "{xyz: NIL} of {vector3: VECTOR3}"
20 | code_template = "{vector3}.{{xyz}}"
21 | defaults = {
22 | "xyz": SubResource("Resource_ie4sg")
23 | }
24 | signal_name = ""
25 | is_advanced = false
26 |
--------------------------------------------------------------------------------
/blocks/math/vector_from_angle.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://c7a6wnxegkfd5"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_1p1ve"]
4 |
5 | [resource]
6 | script = ExtResource("1_1p1ve")
7 | name = &"from_angle"
8 | target_node_class = ""
9 | description = "Creates a unit Vector2 rotated to the given angle in radians."
10 | category = "Math"
11 | type = 3
12 | variant_type = 5
13 | display_template = "vector from {angle: FLOAT}"
14 | code_template = "Vector2.from_angle({angle})"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/math/vector_multiply.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://bff7cwmpisihj"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_52jwf"]
4 |
5 | [resource]
6 | script = ExtResource("1_52jwf")
7 | name = &"vector_multiply"
8 | target_node_class = ""
9 | description = "Multiplies a vector with a number. Use this, for example, to get a point some distance away along an angle."
10 | category = "Math"
11 | type = 3
12 | variant_type = 5
13 | display_template = "multiply {vector: VECTOR2} by {number: FLOAT}"
14 | code_template = "{vector} * {number}"
15 | defaults = {
16 | "number": 1.0,
17 | "vector": Vector2(1, 1)
18 | }
19 | signal_name = ""
20 | scope = ""
21 |
--------------------------------------------------------------------------------
/blocks/physics/characterbody2d_move_and_slide.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://cp6ak6wea8ogh"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_e3r2r"]
4 |
5 | [resource]
6 | script = ExtResource("1_e3r2r")
7 | name = &"characterbody2d_move_and_slide"
8 | target_node_class = "CharacterBody2D"
9 | description = ""
10 | category = "Physics | Velocity"
11 | type = 2
12 | variant_type = 0
13 | display_template = "move and slide"
14 | code_template = "move_and_slide()"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/physics/characterbody3d_move_and_slide.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://cp6ak6wea8ogh"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_e3r2r"]
4 |
5 | [resource]
6 | script = ExtResource("1_e3r2r")
7 | name = &"characterbody3d_move_and_slide"
8 | target_node_class = "CharacterBody3D"
9 | description = ""
10 | category = "Physics | Velocity"
11 | type = 2
12 | variant_type = 0
13 | display_template = "move and slide"
14 | code_template = "move_and_slide()"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/sounds/audiostreamplayer_play.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://bxjjml7u3rokv"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_vyl5w"]
4 |
5 | [resource]
6 | script = ExtResource("1_vyl5w")
7 | name = &"audiostreamplayer_play"
8 | target_node_class = "AudioStreamPlayer"
9 | description = "Play the audio stream"
10 | category = "Sounds"
11 | type = 2
12 | variant_type = 0
13 | display_template = "play"
14 | code_template = "play()"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/sounds/audiostreamplayer_stop.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://ib16grbtduab"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_db4g2"]
4 |
5 | [resource]
6 | script = ExtResource("1_db4g2")
7 | name = &"audiostreamplayer_stop"
8 | target_node_class = "AudioStreamPlayer"
9 | description = "Stop the audio stream"
10 | category = "Sounds"
11 | type = 2
12 | variant_type = 0
13 | display_template = "stop"
14 | code_template = "stop()"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/sounds/load_sound.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://coefocdmytg0j"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_4w4si"]
4 |
5 | [resource]
6 | script = ExtResource("1_4w4si")
7 | name = &"load_sound"
8 | target_node_class = ""
9 | description = "Load a resource file as the audio stream"
10 | category = "Sounds"
11 | type = 2
12 | variant_type = 0
13 | display_template = "load file {file_path: STRING} as sound {name: STRING}"
14 | code_template = "var __sound = AudioStreamPlayer.new()
15 | __sound.name = {name}
16 | __sound.set_stream(load({file_path}))
17 | add_child(__sound)
18 | "
19 | defaults = {}
20 | signal_name = ""
21 | scope = ""
22 |
--------------------------------------------------------------------------------
/blocks/sounds/pause_continue_sound.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=4 format=3 uid="uid://wpdspamg3f6g"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/option_data.gd" id="1_ilhdq"]
4 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_q04gm"]
5 |
6 | [sub_resource type="Resource" id="Resource_lalgp"]
7 | script = ExtResource("1_ilhdq")
8 | selected = 0
9 | items = ["pause", "continue"]
10 |
11 | [resource]
12 | script = ExtResource("1_q04gm")
13 | name = &"pause_continue_sound"
14 | target_node_class = ""
15 | description = "Pause/Continue the audio stream"
16 | category = "Sounds"
17 | type = 2
18 | variant_type = 0
19 | display_template = "{pause: NIL} the sound {name: STRING}"
20 | code_template = "var __sound_node = get_node({name})
21 | if {pause} == \"pause\":
22 | __sound_node.stream_paused = true
23 | else:
24 | __sound_node.stream_paused = false
25 | "
26 | defaults = {
27 | "pause": SubResource("Resource_lalgp")
28 | }
29 | signal_name = ""
30 | is_advanced = false
31 |
--------------------------------------------------------------------------------
/blocks/sounds/play_sound.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://dt022ilveapt5"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_llfp1"]
4 |
5 | [resource]
6 | script = ExtResource("1_llfp1")
7 | name = &"play_sound"
8 | target_node_class = ""
9 | description = "Play the audio stream with volume and pitch"
10 | category = "Sounds"
11 | type = 2
12 | variant_type = 0
13 | display_template = "play the sound {name: STRING} | with volume {db: FLOAT} dB and pitch scale {pitch: FLOAT}"
14 | code_template = "var __sound_node = get_node({name})
15 | __sound_node.volume_db = {db}
16 | __sound_node.pitch_scale = {pitch}
17 | __sound_node.play()
18 | "
19 | defaults = {
20 | "db": 0.0,
21 | "pitch": 1.0
22 | }
23 | signal_name = ""
24 | scope = ""
25 |
--------------------------------------------------------------------------------
/blocks/sounds/stop_sound.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://csg40u5awp1sy"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_rfujh"]
4 |
5 | [resource]
6 | script = ExtResource("1_rfujh")
7 | name = &"stop_sound"
8 | target_node_class = ""
9 | description = "Stop the audio stream"
10 | category = "Sounds"
11 | type = 2
12 | variant_type = 0
13 | display_template = "stop the sound {name: STRING}"
14 | code_template = "var __sound_node = get_node({name})
15 | __sound_node.stop()
16 | "
17 | defaults = {
18 | "db": 0.0,
19 | "pitch": 1.0
20 | }
21 | signal_name = ""
22 | scope = ""
23 |
--------------------------------------------------------------------------------
/blocks/spawn/cpuparticles2d_finished.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://c188gpgf4rpns"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_pmpup"]
4 |
5 | [resource]
6 | script = ExtResource("1_pmpup")
7 | name = &"cpuparticles2d_finished"
8 | target_node_class = "CPUParticles2D"
9 | description = "Emitted when all active particles have finished processing."
10 | category = "Lifecycle | Spawn"
11 | type = 1
12 | variant_type = 0
13 | display_template = "when particles are finished"
14 | code_template = "func _on_finished():"
15 | defaults = {}
16 | signal_name = "finished"
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/transform/rigidbody2d_physics_position.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://ses5486g56q"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_72i54"]
4 |
5 | [resource]
6 | script = ExtResource("1_72i54")
7 | name = &"rigidbody2d_physics_position"
8 | target_node_class = "RigidBody2D"
9 | description = ""
10 | category = "Transform | Position"
11 | type = 2
12 | variant_type = 0
13 | display_template = "set physics position {position: VECTOR2}"
14 | code_template = "PhysicsServer2D.body_set_state(
15 | get_rid(),
16 | PhysicsServer2D.BODY_STATE_TRANSFORM,
17 | Transform2D.IDENTITY.translated({position})
18 | )
19 | "
20 | defaults = {}
21 | signal_name = ""
22 | scope = ""
23 |
--------------------------------------------------------------------------------
/blocks/ui/label_set_text.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://ciqkywxdk4uht"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_bofov"]
4 |
5 | [resource]
6 | script = ExtResource("1_bofov")
7 | name = &"label_set_text"
8 | target_node_class = "Label"
9 | description = "Set the text for the label."
10 | category = "UI"
11 | type = 2
12 | variant_type = 0
13 | display_template = "set text to {text: STRING}"
14 | code_template = "text = {text}"
15 | defaults = {}
16 | signal_name = ""
17 | scope = ""
18 |
--------------------------------------------------------------------------------
/blocks/variables/vector2.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://ddj24k1fp0s82"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_ilw3v"]
4 |
5 | [resource]
6 | script = ExtResource("1_ilw3v")
7 | name = &"vector2"
8 | target_node_class = ""
9 | description = ""
10 | category = "Math"
11 | type = 3
12 | variant_type = 5
13 | display_template = "vector2 x: {x: FLOAT} y: {y: FLOAT}"
14 | code_template = "Vector2({x}, {y})"
15 | defaults = {
16 | "x": 0.0,
17 | "y": 0.0
18 | }
19 | signal_name = ""
20 | scope = ""
21 |
--------------------------------------------------------------------------------
/blocks/variables/vector3.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://ddj24k1fp0s82"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/block_definition.gd" id="1_ilw3v"]
4 |
5 | [resource]
6 | script = ExtResource("1_ilw3v")
7 | name = &"vector3"
8 | target_node_class = ""
9 | description = ""
10 | category = "Math"
11 | type = 3
12 | variant_type = 9
13 | display_template = "vector3 x: {x: FLOAT} y: {y: FLOAT}: z: {z: FLOAT}"
14 | code_template = "Vector3({x}, {y}, {z})"
15 | defaults = {
16 | "x": 0.0,
17 | "y": 0.0,
18 | "z": 0.0
19 | }
20 | signal_name = ""
21 | scope = ""
22 |
--------------------------------------------------------------------------------
/code_generation/ast_list.gd:
--------------------------------------------------------------------------------
1 | extends RefCounted
2 |
3 | const Types = preload("res://addons/reblocks/types/types.gd")
4 | const BlockAST = preload("res://addons/reblocks/code_generation/block_ast.gd")
5 |
6 | var array: Array[ASTPair]
7 |
8 |
9 | class ASTPair:
10 | var ast: BlockAST
11 | var canvas_position: Vector2
12 |
13 | func _init(p_ast: BlockAST, p_canvas_position: Vector2):
14 | ast = p_ast
15 | canvas_position = p_canvas_position
16 |
17 |
18 | func _init():
19 | array = []
20 |
21 |
22 | func append(ast: BlockAST, canvas_position: Vector2):
23 | array.append(ASTPair.new(ast, canvas_position))
24 |
25 |
26 | func clear():
27 | array.clear()
28 |
29 |
30 | func get_top_level_nodes_of_type(block_type: Types.BlockType) -> Array[BlockAST]:
31 | var asts: Array[BlockAST] = []
32 |
33 | for ast_pair in array:
34 | if ast_pair.ast.root.data.type == block_type:
35 | asts.append(ast_pair.ast)
36 |
37 | return asts
38 |
--------------------------------------------------------------------------------
/code_generation/ast_list.gd.uid:
--------------------------------------------------------------------------------
1 | uid://b5txthy46jhqc
2 |
--------------------------------------------------------------------------------
/code_generation/block_ast.gd.uid:
--------------------------------------------------------------------------------
1 | uid://b3v0lvdpx7tge
2 |
--------------------------------------------------------------------------------
/code_generation/block_definition.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cfmvxsm2ok4ek
2 |
--------------------------------------------------------------------------------
/code_generation/block_extension.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | ## Block extensions interface.
3 | ##
4 | ## A BlockExtension provides additional, context-sensitive information for the
5 | ## user interface of a particular type of block. An instance of BlockExtension
6 | ## belongs to a specific [Block] in the block canvas, but an extension does not
7 | ## have direct access to its block. Instead, it can use the [member context_node]
8 | ## property to draw information about the scene.[br]
9 | ## [br]
10 | ## To customize the user interface for a block, override public functions such
11 | ## as [method get_defaults].[br]
12 | ## [br]
13 | ## In some cases, an extension may need to monitor the scene to determine if it
14 | ## has changed. To achieve this, override [method _context_node_changed] to
15 | ## connect the relevant signals, and call [method _emit_changed] when a
16 | ## significant change has occurred.
17 | class_name BlockExtension
18 | extends RefCounted
19 |
20 | signal changed
21 |
22 | var context_node: Node:
23 | set(value):
24 | if context_node != value:
25 | context_node = value
26 | _context_node_changed()
27 |
28 |
29 | ## Called when the value of context_node changes. Use this for connecting
30 | ## signals to monitor for changes.
31 | func _context_node_changed():
32 | pass
33 |
34 |
35 | ## Generate a set of defaults for this block extension based on the current
36 | ## context. The return value will be merged with the defaults specified in the
37 | ## static block definition.
38 | func get_defaults() -> Dictionary:
39 | return get_defaults_for_node(context_node)
40 |
41 |
42 | ## @deprecated: Use [method get_defaults] instead.
43 | func get_defaults_for_node(context_node: Node) -> Dictionary:
44 | return {}
45 |
46 |
47 | ## Emit the "changed" signal. Use this when an event has occurred which may
48 | ## cause [method get_defaults] to return a different value.
49 | func _emit_changed():
50 | changed.emit()
51 |
--------------------------------------------------------------------------------
/code_generation/block_extension.gd.uid:
--------------------------------------------------------------------------------
1 | uid://g3dafc46bkmv
2 |
--------------------------------------------------------------------------------
/code_generation/blocks_catalog.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cjytr0p78b3x7
2 |
--------------------------------------------------------------------------------
/code_generation/option_data.gd:
--------------------------------------------------------------------------------
1 | extends Resource
2 |
3 | @export var selected: int
4 | @export var items: Array
5 |
6 |
7 | func _init(p_items: Array = [], p_selected: int = 0):
8 | items = p_items
9 | selected = p_selected
10 |
--------------------------------------------------------------------------------
/code_generation/option_data.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cteah6oqsmew0
2 |
--------------------------------------------------------------------------------
/code_generation/script_generator.gd:
--------------------------------------------------------------------------------
1 | extends Object
2 |
3 | const Types = preload("res://addons/reblocks/types/types.gd")
4 | const ASTList = preload("res://addons/reblocks/code_generation/ast_list.gd")
5 | const BlockAST = preload("res://addons/reblocks/code_generation/block_ast.gd")
6 | const BlockDefinition = preload("res://addons/reblocks/code_generation/block_definition.gd")
7 |
8 |
9 | static func generate_script(ast_list: ASTList, block_script: BlockScriptSerialization) -> String:
10 | var entry_asts: Array[BlockAST] = ast_list.get_top_level_nodes_of_type(Types.BlockType.ENTRY)
11 |
12 | var init_ast := BlockAST.new()
13 | init_ast.root = BlockAST.ASTNode.new()
14 | init_ast.root.data = BlockDefinition.new()
15 | init_ast.root.data.type = Types.BlockType.ENTRY
16 | init_ast.root.data.code_template = "func _init():"
17 |
18 | var combined_entry_asts = {}
19 |
20 | # Combine entry asts with same root statement
21 | for entry_ast in entry_asts:
22 | var statement = entry_ast.root.get_code(0)
23 | if not statement in combined_entry_asts:
24 | var new_ast := BlockAST.new()
25 | var root = BlockAST.ASTNode.new()
26 | root.data = entry_ast.root.data
27 | root.arguments = entry_ast.root.arguments
28 | root.children = entry_ast.root.children.duplicate()
29 | new_ast.root = root
30 | combined_entry_asts[statement] = new_ast
31 | else:
32 | combined_entry_asts[statement].root.children.append_array(entry_ast.root.children)
33 |
34 | # Connect signals on _init
35 | for entry_statement in combined_entry_asts:
36 | var entry_ast: BlockAST = combined_entry_asts[entry_statement]
37 | var signal_name = entry_ast.root.data.signal_name
38 | if signal_name != "":
39 | var signal_node := BlockAST.ASTNode.new()
40 | signal_node.data = BlockDefinition.new()
41 | signal_node.data.code_template = "{0}.connect(_on_{0})".format([signal_name])
42 | init_ast.root.children.append(signal_node)
43 |
44 | # Generate script extends statement
45 | var script := "extends %s\n\n" % block_script.script_inherits
46 |
47 | # Generate variables
48 | for variable in block_script.variables:
49 | script += "var %s: %s\n\n" % [variable.var_name, type_string(variable.var_type)]
50 |
51 | script += "\n"
52 |
53 | # Generate _init
54 | if not init_ast.root.children.is_empty():
55 | script += init_ast.get_code() + "\n"
56 |
57 | # Generate other entry methods
58 | for entry_statement in combined_entry_asts:
59 | var entry_ast: BlockAST = combined_entry_asts[entry_statement]
60 | script += entry_ast.get_code()
61 | script += "\n"
62 |
63 | return script
64 |
--------------------------------------------------------------------------------
/code_generation/script_generator.gd.uid:
--------------------------------------------------------------------------------
1 | uid://62nuwoymwimu
2 |
--------------------------------------------------------------------------------
/code_generation/util.gd:
--------------------------------------------------------------------------------
1 | extends Object
2 |
3 |
4 | static func get_files_in_dir_recursive(path: String, pattern: String) -> Array:
5 | var files = []
6 | var dir := DirAccess.open(path)
7 |
8 | if not dir:
9 | return files
10 |
11 | dir.list_dir_begin()
12 |
13 | var file_name = dir.get_next()
14 |
15 | while file_name != "":
16 | var file_path = path + "/" + file_name
17 | if dir.current_is_dir():
18 | files.append_array(get_files_in_dir_recursive(file_path, pattern))
19 | elif file_name.matchn(pattern):
20 | files.append(file_path)
21 |
22 | file_name = dir.get_next()
23 |
24 | return files
25 |
--------------------------------------------------------------------------------
/code_generation/util.gd.uid:
--------------------------------------------------------------------------------
1 | uid://b35g67ql6vfvl
2 |
--------------------------------------------------------------------------------
/code_generation/variable_definition.gd:
--------------------------------------------------------------------------------
1 | extends Resource
2 |
3 | @export var var_name: String
4 | @export var var_type: Variant.Type
5 |
6 |
7 | func _init(p_var_name: String = "", p_var_type: Variant.Type = TYPE_NIL):
8 | var_name = p_var_name
9 | var_type = p_var_type
10 |
--------------------------------------------------------------------------------
/code_generation/variable_definition.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cfnl76l82sw64
2 |
--------------------------------------------------------------------------------
/drag_manager/drag.gd.uid:
--------------------------------------------------------------------------------
1 | uid://2ota6mvwaf1k
2 |
--------------------------------------------------------------------------------
/drag_manager/drag_manager.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends Control
3 |
4 | signal block_dropped
5 | signal block_modified
6 |
7 | const BlockCanvas = preload("res://addons/reblocks/ui/block_canvas/block_canvas.gd")
8 | const BlockTreeUtil = preload("res://addons/reblocks/ui/block_tree_util.gd")
9 | const Drag = preload("res://addons/reblocks/drag_manager/drag.gd")
10 | const Picker = preload("res://addons/reblocks/ui/picker/picker.gd")
11 | const Util = preload("res://addons/reblocks/ui/util.gd")
12 |
13 | @export var picker_path: NodePath
14 | @export var block_canvas_path: NodePath
15 |
16 | const Constants = preload("res://addons/reblocks/ui/constants.gd")
17 |
18 | @onready var _context := BlockEditorContext.get_default()
19 |
20 | var _picker: Picker
21 | var _block_canvas: BlockCanvas
22 |
23 | var drag: Drag = null
24 |
25 |
26 | func _ready():
27 | _picker = get_node(picker_path)
28 | _block_canvas = get_node(block_canvas_path)
29 |
30 |
31 | func _process(_delta):
32 | if drag:
33 | drag.update_drag_state()
34 |
35 |
36 | func drag_block(block: Block, copied_from: Block = null, offset: Vector2 = Vector2.ZERO):
37 | if copied_from and copied_from.is_inside_tree():
38 | offset += get_global_mouse_position() - copied_from.global_position
39 | elif block.is_inside_tree():
40 | offset += get_global_mouse_position() - block.global_position
41 |
42 | if _block_canvas.is_ancestor_of(block):
43 | offset /= _block_canvas.zoom
44 |
45 | var parent = block.get_parent()
46 |
47 | if parent:
48 | parent.remove_child(block)
49 |
50 | block.disconnect_signals()
51 |
52 | var block_scope := BlockTreeUtil.get_tree_scope(block)
53 | if block_scope != "":
54 | _block_canvas.set_scope(block_scope)
55 |
56 | drag = Drag.new(block, block_scope, offset, _block_canvas)
57 | drag.set_snap_points(get_tree().get_nodes_in_group("snap_point"))
58 | drag.add_delete_area(_picker.get_global_rect())
59 | if block is ParameterBlock and block.spawned_by:
60 | drag.add_delete_area(block.spawned_by.get_global_rect())
61 | add_child(drag)
62 |
63 |
64 | func copy_block(block: Block) -> Block:
65 | if _context.block_script == null:
66 | return null
67 | return _context.block_script.instantiate_block(block.definition)
68 |
69 |
70 | func copy_picked_block_and_drag(block: Block, offset: Vector2):
71 | var new_block: Block = copy_block(block)
72 | drag_block(new_block, block, offset)
73 |
74 |
75 | func drag_ended():
76 | if not drag:
77 | return
78 |
79 | var block = drag.apply_drag()
80 |
81 | if block:
82 | connect_block_canvas_signals(block)
83 | block.grab_focus()
84 |
85 | # Allow the block to be deleted and edited now that it's on the canvas.
86 | block.can_delete = true
87 | block.editable = true
88 |
89 | _block_canvas.release_scope()
90 |
91 | drag.queue_free()
92 | drag = null
93 |
94 | block_dropped.emit()
95 |
96 |
97 | func connect_block_canvas_signals(block: Block):
98 | if block.drag_started.get_connections().size() == 0:
99 | block.drag_started.connect(_on_block_drag_started)
100 | if block.modified.get_connections().size() == 0:
101 | block.modified.connect(func(): block_modified.emit())
102 |
103 |
104 | func _on_block_drag_started(block: Block, offset: Vector2):
105 | drag_block(block, null, offset)
106 |
--------------------------------------------------------------------------------
/drag_manager/drag_manager.gd.uid:
--------------------------------------------------------------------------------
1 | uid://c00bv7tp7np7c
2 |
--------------------------------------------------------------------------------
/drag_manager/drag_manager.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=2 format=3 uid="uid://cph1k5cfximbf"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/drag_manager/drag_manager.gd" id="1_rif3x"]
4 |
5 | [node name="DragManager" type="Control"]
6 | layout_mode = 3
7 | anchors_preset = 0
8 | mouse_filter = 1
9 | script = ExtResource("1_rif3x")
10 |
--------------------------------------------------------------------------------
/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Redot-Experimental/reblocks/c80e8b09503556f4fba4c436dc7bb5dcb0c51804/image.png
--------------------------------------------------------------------------------
/image.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://wgc6ps8n8r8f"
6 | path="res://.godot/imported/image.png-89b02f89c22769258962765d13ebb6bd.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/reblocks/image.png"
14 | dest_files=["res://.godot/imported/image.png-89b02f89c22769258962765d13ebb6bd.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 |
--------------------------------------------------------------------------------
/inspector_plugin/block_script_inspector.gd:
--------------------------------------------------------------------------------
1 | extends EditorInspectorPlugin
2 |
3 | const BlockCodePlugin = preload("res://addons/reblocks/block_code_plugin.gd")
4 | const TxUtils := preload("res://addons/reblocks/translation/utils.gd")
5 |
6 |
7 | func _init():
8 | TxUtils.set_block_translation_domain(self)
9 |
10 |
11 | func _can_handle(object):
12 | return object is BlockCode
13 |
14 |
15 | func _parse_begin(object):
16 | var block_code := object as BlockCode
17 |
18 | var button := Button.new()
19 | button.text = tr("Open Block Script")
20 | button.pressed.connect(func(): BlockCodePlugin.main_panel.switch_block_code_node(block_code))
21 |
22 | var container := MarginContainer.new()
23 | container.add_theme_constant_override("margin_bottom", 10)
24 | container.add_child(button)
25 |
26 | add_custom_control(container)
27 |
--------------------------------------------------------------------------------
/inspector_plugin/block_script_inspector.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cfmu6utfadohw
2 |
--------------------------------------------------------------------------------
/plugin.cfg:
--------------------------------------------------------------------------------
1 | [plugin]
2 |
3 | name="ReBlocks"
4 | description="Create games using a high-level, block-based visual programming language."
5 | author="Redot"
6 | version="v0.1"
7 | script="block_code_plugin.gd"
8 |
--------------------------------------------------------------------------------
/serialization/block_script_serialization.gd.uid:
--------------------------------------------------------------------------------
1 | uid://chygx3dlf1fcl
2 |
--------------------------------------------------------------------------------
/serialization/block_serialization.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends Resource
3 |
4 | const BlockSerialization = preload("res://addons/reblocks/serialization/block_serialization.gd")
5 |
6 | @export var name: StringName:
7 | set = _set_name
8 | @export var children: Array[BlockSerialization]
9 | @export var arguments: Dictionary: # String, ValueBlockSerialization
10 | set = _set_arguments
11 |
12 |
13 | func _init(p_name: StringName = &"", p_children: Array[BlockSerialization] = [], p_arguments: Dictionary = {}):
14 | name = p_name
15 | children = p_children
16 | arguments = p_arguments
17 |
18 |
19 | # Block name and arguments backwards compatibility handling.
20 | const _renamed_blocks: Dictionary = {
21 | &"simplespawner_set_spawn_frequency": &"simplespawner_set_spawn_period",
22 | }
23 |
24 |
25 | func _set_name(value):
26 | var new_name = _renamed_blocks.get(value)
27 | if new_name:
28 | print("Migrating block %s to new name %s" % [value, new_name])
29 | name = new_name
30 | if Engine.is_editor_hint():
31 | EditorInterface.mark_scene_as_unsaved()
32 | else:
33 | name = value
34 |
35 |
36 | const _renamed_arguments: Dictionary = {
37 | &"simplespawner_set_spawn_period":
38 | {
39 | "new_frequency": "new_period",
40 | },
41 | }
42 |
43 |
44 | func _set_arguments(value):
45 | if not value is Dictionary:
46 | return
47 |
48 | var renamed_args = _renamed_arguments.get(name)
49 | if not renamed_args:
50 | # Try with the new block name if it hasn't been migrated yet.
51 | var new_block_name = _renamed_blocks.get(name)
52 | if new_block_name:
53 | renamed_args = _renamed_arguments.get(new_block_name)
54 |
55 | if renamed_args:
56 | var changed: bool = false
57 | value = value.duplicate()
58 | for old_arg in renamed_args.keys():
59 | if not old_arg in value:
60 | continue
61 |
62 | var new_arg = renamed_args[old_arg]
63 | print("Migrating block %s argument %s to new name %s" % [name, old_arg, new_arg])
64 | value[new_arg] = value[old_arg]
65 | value.erase(old_arg)
66 | changed = true
67 |
68 | if changed and Engine.is_editor_hint():
69 | EditorInterface.mark_scene_as_unsaved()
70 |
71 | arguments = value
72 |
--------------------------------------------------------------------------------
/serialization/block_serialization.gd.uid:
--------------------------------------------------------------------------------
1 | uid://wy5ivwnaavm
2 |
--------------------------------------------------------------------------------
/serialization/block_serialization_tree.gd:
--------------------------------------------------------------------------------
1 | extends Resource
2 |
3 | const BlockSerialization = preload("res://addons/reblocks/serialization/block_serialization.gd")
4 |
5 | @export var root: BlockSerialization
6 | @export var canvas_position: Vector2
7 |
8 |
9 | func _init(p_root: BlockSerialization = null, p_canvas_position: Vector2 = Vector2(0, 0)):
10 | root = p_root
11 | canvas_position = p_canvas_position
12 |
13 |
14 | func _to_string():
15 | return to_string_recursive(root, 0)
16 |
17 |
18 | func to_string_recursive(node: BlockSerialization, depth: int) -> String:
19 | var string: String = "%s %s\n" % ["-".repeat(depth), node.block_name]
20 |
21 | for c in node.children:
22 | string += to_string_recursive(c, depth + 1)
23 |
24 | return string
25 |
--------------------------------------------------------------------------------
/serialization/block_serialization_tree.gd.uid:
--------------------------------------------------------------------------------
1 | uid://dfuwu7thoved7
2 |
--------------------------------------------------------------------------------
/serialization/default_block_script.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="BlockScriptSerialization" load_steps=7 format=3 uid="uid://i7adsp6x51ml"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/serialization/block_serialization_tree.gd" id="1_opywe"]
4 | [ext_resource type="Script" path="res://addons/reblocks/serialization/block_serialization.gd" id="2_h8ehk"]
5 | [ext_resource type="Script" path="res://addons/reblocks/serialization/block_script_serialization.gd" id="2_yjlcv"]
6 | [ext_resource type="Script" path="res://addons/reblocks/code_generation/variable_definition.gd" id="3_wb2fg"]
7 |
8 | [sub_resource type="Resource" id="Resource_oalom"]
9 | script = ExtResource("2_h8ehk")
10 | name = &"ready"
11 | children = Array[ExtResource("2_h8ehk")]([])
12 | arguments = {}
13 |
14 | [sub_resource type="Resource" id="Resource_8sqy5"]
15 | script = ExtResource("1_opywe")
16 | root = SubResource("Resource_oalom")
17 | canvas_position = Vector2(54, 47)
18 |
19 | [resource]
20 | script = ExtResource("2_yjlcv")
21 | script_inherits = "INHERIT_DEFAULT"
22 | block_serialization_trees = Array[ExtResource("1_opywe")]([SubResource("Resource_8sqy5")])
23 | variables = Array[ExtResource("3_wb2fg")]([])
24 | generated_script = "extends INHERIT_DEFAULT"
25 | version = 0
26 |
--------------------------------------------------------------------------------
/serialization/value_block_serialization.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends Resource
3 |
4 | @export var name: StringName:
5 | set = _set_name
6 | @export var arguments: Dictionary: # String, ValueBlockSerialization
7 | set = _set_arguments
8 |
9 |
10 | func _init(p_name: StringName = &"", p_arguments: Dictionary = {}):
11 | name = p_name
12 | arguments = p_arguments
13 |
14 |
15 | # Block name and arguments backwards compatibility handling.
16 | const _renamed_blocks: Dictionary = {
17 | &"simplespawner_get_spawn_frequency": &"simplespawner_get_spawn_period",
18 | }
19 |
20 |
21 | func _set_name(value):
22 | var new_name = _renamed_blocks.get(value)
23 | if new_name:
24 | print("Migrating block %s to new name %s" % [value, new_name])
25 | name = new_name
26 | if Engine.is_editor_hint():
27 | EditorInterface.mark_scene_as_unsaved()
28 | else:
29 | name = value
30 |
31 |
32 | const _renamed_arguments: Dictionary = {}
33 |
34 |
35 | func _set_arguments(value):
36 | if not value is Dictionary:
37 | return
38 |
39 | var renamed_args = _renamed_arguments.get(name)
40 | if not renamed_args:
41 | # Try with the new block name if it hasn't been migrated yet.
42 | var new_block_name = _renamed_blocks.get(name)
43 | if new_block_name:
44 | renamed_args = _renamed_arguments.get(new_block_name)
45 |
46 | if renamed_args:
47 | var changed: bool = false
48 | value = value.duplicate()
49 | for old_arg in renamed_args.keys():
50 | if not old_arg in value:
51 | continue
52 |
53 | var new_arg = renamed_args[old_arg]
54 | print("Migrating block %s argument %s to new name %s" % [name, old_arg, new_arg])
55 | value[new_arg] = value[old_arg]
56 | value.erase(old_arg)
57 | changed = true
58 |
59 | if changed and Engine.is_editor_hint():
60 | EditorInterface.mark_scene_as_unsaved()
61 |
62 | arguments = value
63 |
--------------------------------------------------------------------------------
/serialization/value_block_serialization.gd.uid:
--------------------------------------------------------------------------------
1 | uid://ctw0ps1sk6d74
2 |
--------------------------------------------------------------------------------
/translation/parser.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | ## BlockCode translation parser plugin.
3 | ##
4 | ## Extracts translatable strings from BlockCode resources. Currently only
5 | ## BlockDefinition resources are handled.
6 | extends EditorTranslationParserPlugin
7 |
8 | const BLOCK_DEFINITION_SCRIPT_PATH := "res://addons/reblocks/code_generation/block_definition.gd"
9 |
10 | # BlockDefinition properties for translation
11 | const block_def_tx_properties: Array[String] = [
12 | "category",
13 | "description",
14 | "display_template",
15 | ]
16 |
17 |
18 | func _get_recognized_extensions() -> PackedStringArray:
19 | # BlockDefinition resources currently use the generic tres extension.
20 | return ["tres"]
21 |
22 |
23 | func _resource_is_block_definition(resource: Resource) -> bool:
24 | var script := resource.get_script()
25 | if not script:
26 | return false
27 | return script.resource_path == BLOCK_DEFINITION_SCRIPT_PATH
28 |
29 |
30 | func _parse_file(path: String, msgids: Array[String], msgids_context_plural: Array[Array]) -> void:
31 | # Only BlockDefinition resources are supported.
32 | var res = ResourceLoader.load(path, "Resource")
33 | if not res or not _resource_is_block_definition(res):
34 | return
35 | for prop in block_def_tx_properties:
36 | var value: String = res.get(prop)
37 | if value:
38 | # For now just the messages are used. It might be better to provide
39 | # context with msgids_context_plural to avoid conflicts.
40 | msgids.append(value)
41 |
--------------------------------------------------------------------------------
/translation/parser.gd.uid:
--------------------------------------------------------------------------------
1 | uid://lc46rs8la81q
2 |
--------------------------------------------------------------------------------
/translation/utils.gd.uid:
--------------------------------------------------------------------------------
1 | uid://ce0vcyai6vjvy
2 |
--------------------------------------------------------------------------------
/types/types.gd.uid:
--------------------------------------------------------------------------------
1 | uid://dmu5h51au2g1c
2 |
--------------------------------------------------------------------------------
/ui/block_canvas/block_canvas.gd.uid:
--------------------------------------------------------------------------------
1 | uid://5i4d33gig2gj
2 |
--------------------------------------------------------------------------------
/ui/block_editor_context.gd:
--------------------------------------------------------------------------------
1 | class_name BlockEditorContext
2 | extends Object
3 |
4 | signal changed
5 |
6 | static var _instance: BlockEditorContext
7 |
8 | var block_code_node: BlockCode:
9 | set(value):
10 | block_code_node = value
11 | changed.emit()
12 |
13 | var block_script: BlockScriptSerialization:
14 | get:
15 | if block_code_node == null:
16 | return null
17 | return block_code_node.block_script
18 |
19 | var parent_node: Node:
20 | get:
21 | if block_code_node == null:
22 | return null
23 | return block_code_node.get_parent()
24 |
25 |
26 | func force_update() -> void:
27 | changed.emit()
28 |
29 |
30 | static func get_default() -> BlockEditorContext:
31 | if _instance == null:
32 | _instance = BlockEditorContext.new()
33 | return _instance
34 |
--------------------------------------------------------------------------------
/ui/block_editor_context.gd.uid:
--------------------------------------------------------------------------------
1 | uid://8y6lwtx6tyjn
2 |
--------------------------------------------------------------------------------
/ui/block_tree_util.gd:
--------------------------------------------------------------------------------
1 | extends Object
2 |
3 |
4 | ## Returns the scope of the first non-empty scope child block
5 | static func get_tree_scope(node: Node) -> String:
6 | if node is Block:
7 | if node.definition.scope != "":
8 | return node.definition.scope
9 |
10 | for c in node.get_children():
11 | var scope := get_tree_scope(c)
12 | if scope != "":
13 | return scope
14 | return ""
15 |
16 |
17 | ## Get the nearest Block node that is a parent of the provided node.
18 | static func get_parent_block(node: Node) -> Block:
19 | var parent = node.get_parent()
20 | while parent and not parent is Block:
21 | parent = parent.get_parent()
22 | return parent as Block
23 |
--------------------------------------------------------------------------------
/ui/block_tree_util.gd.uid:
--------------------------------------------------------------------------------
1 | uid://w013b34y4cbd
2 |
--------------------------------------------------------------------------------
/ui/blocks/block/block.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cgc1aedsgtm8k
2 |
--------------------------------------------------------------------------------
/ui/blocks/control_block/control_block.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | class_name ControlBlock
3 | extends Block
4 |
5 | const Constants = preload("res://addons/reblocks/ui/constants.gd")
6 |
7 |
8 | func _ready():
9 | super()
10 |
11 | %TopBackground.color = color
12 | %BottomBackground.color = color
13 | %SnapPoint.add_theme_constant_override("margin_left", Constants.CONTROL_MARGIN)
14 | %SnapGutter.color = color
15 | %SnapGutter.custom_minimum_size.x = Constants.CONTROL_MARGIN
16 |
17 |
18 | func _on_drag_drop_area_drag_started(offset: Vector2) -> void:
19 | _drag_started(offset)
20 |
21 |
22 | static func get_block_class():
23 | return "ControlBlock"
24 |
25 |
26 | static func get_scene_path():
27 | return "res://addons/reblocks/ui/blocks/control_block/control_block.tscn"
28 |
--------------------------------------------------------------------------------
/ui/blocks/control_block/control_block.gd.uid:
--------------------------------------------------------------------------------
1 | uid://k4parnn65f1r
2 |
--------------------------------------------------------------------------------
/ui/blocks/entry_block/entry_block.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | class_name EntryBlock
3 | extends StatementBlock
4 |
5 | ## if non-empty, this block defines a callback that will be connected to the signal with this name
6 | @export var signal_name: String
7 |
8 |
9 | func _ready():
10 | super()
11 | bottom_snap = null
12 |
13 |
14 | static func get_block_class():
15 | return "EntryBlock"
16 |
17 |
18 | static func get_scene_path():
19 | return "res://addons/reblocks/ui/blocks/entry_block/entry_block.tscn"
20 |
--------------------------------------------------------------------------------
/ui/blocks/entry_block/entry_block.gd.uid:
--------------------------------------------------------------------------------
1 | uid://i1nt7sa7gn5r
2 |
--------------------------------------------------------------------------------
/ui/blocks/entry_block/entry_block.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=6 format=3 uid="uid://d2fibflv3ojys"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/ui/blocks/entry_block/entry_block.gd" id="2_3ik8h"]
4 | [ext_resource type="Script" path="res://addons/reblocks/ui/blocks/utilities/background/background.gd" id="2_yrw8l"]
5 | [ext_resource type="PackedScene" uid="uid://c7puyxpqcq6xo" path="res://addons/reblocks/ui/blocks/utilities/drag_drop_area/drag_drop_area.tscn" id="3_swkpp"]
6 | [ext_resource type="PackedScene" uid="uid://b1xvp3u11h41s" path="res://addons/reblocks/ui/blocks/utilities/template_editor/template_editor.tscn" id="4_1gwsm"]
7 | [ext_resource type="PackedScene" uid="uid://b1oge52xhjqnu" path="res://addons/reblocks/ui/blocks/utilities/snap_point/snap_point.tscn" id="4_yj206"]
8 |
9 | [node name="EntryBlock" type="MarginContainer" node_paths=PackedStringArray("child_snap", "template_editor")]
10 | size_flags_horizontal = 0
11 | focus_mode = 2
12 | mouse_filter = 2
13 | script = ExtResource("2_3ik8h")
14 | child_snap = NodePath("VBoxContainer/SnapPoint")
15 | template_editor = NodePath("VBoxContainer/TopMarginContainer/MarginContainer/TemplateEditor")
16 |
17 | [node name="VBoxContainer" type="VBoxContainer" parent="."]
18 | layout_mode = 2
19 | mouse_filter = 2
20 | theme_override_constants/separation = 0
21 |
22 | [node name="DragDropArea" parent="VBoxContainer" instance=ExtResource("3_swkpp")]
23 | custom_minimum_size = Vector2(80, 16)
24 | layout_mode = 2
25 | size_flags_horizontal = 0
26 | mouse_default_cursor_shape = 2
27 |
28 | [node name="TopMarginContainer" type="MarginContainer" parent="VBoxContainer"]
29 | custom_minimum_size = Vector2(0, 30)
30 | layout_mode = 2
31 | size_flags_horizontal = 0
32 | mouse_filter = 2
33 | theme_override_constants/margin_left = 0
34 | theme_override_constants/margin_top = 0
35 | theme_override_constants/margin_right = 0
36 | theme_override_constants/margin_bottom = 0
37 |
38 | [node name="Background" type="Control" parent="VBoxContainer/TopMarginContainer"]
39 | unique_name_in_owner = true
40 | layout_mode = 2
41 | mouse_filter = 1
42 | script = ExtResource("2_yrw8l")
43 | color = Color(1, 1, 1, 1)
44 | block_type = 1
45 |
46 | [node name="DragDropArea" parent="VBoxContainer/TopMarginContainer" instance=ExtResource("3_swkpp")]
47 | layout_mode = 2
48 | mouse_default_cursor_shape = 2
49 |
50 | [node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/TopMarginContainer"]
51 | layout_mode = 2
52 | mouse_filter = 2
53 | theme_override_constants/margin_left = 10
54 | theme_override_constants/margin_top = 6
55 | theme_override_constants/margin_right = 12
56 | theme_override_constants/margin_bottom = 6
57 |
58 | [node name="TemplateEditor" parent="VBoxContainer/TopMarginContainer/MarginContainer" instance=ExtResource("4_1gwsm")]
59 | unique_name_in_owner = true
60 | layout_mode = 2
61 |
62 | [node name="SnapPoint" parent="VBoxContainer" instance=ExtResource("4_yj206")]
63 | layout_mode = 2
64 |
65 | [connection signal="drag_started" from="VBoxContainer/DragDropArea" to="." method="_on_drag_drop_area_drag_started"]
66 | [connection signal="drag_started" from="VBoxContainer/TopMarginContainer/DragDropArea" to="." method="_on_drag_drop_area_drag_started"]
67 |
--------------------------------------------------------------------------------
/ui/blocks/parameter_block/parameter_block.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | class_name ParameterBlock
3 | extends Block
4 |
5 | const Constants = preload("res://addons/reblocks/ui/constants.gd")
6 | const Util = preload("res://addons/reblocks/ui/util.gd")
7 | const ParameterOutput = preload("res://addons/reblocks/ui/blocks/utilities/parameter_output/parameter_output.gd")
8 |
9 | @onready var _background := %Background
10 |
11 | var args_to_add_after_format: Dictionary # Only used when loading
12 | var spawned_by: ParameterOutput
13 |
14 |
15 | func _ready():
16 | super()
17 | _background.color = color
18 | _update_block_shape()
19 |
20 |
21 | func _on_definition_changed():
22 | super()
23 | _update_block_shape()
24 |
25 |
26 | func _update_block_shape():
27 | if not definition:
28 | return
29 | await ready
30 | _background.is_pointy_value = definition.variant_type == TYPE_BOOL
31 |
32 |
33 | func _on_drag_drop_area_drag_started(offset: Vector2) -> void:
34 | _drag_started(offset)
35 |
36 |
37 | static func get_block_class():
38 | return "ParameterBlock"
39 |
40 |
41 | static func get_scene_path():
42 | return "res://addons/reblocks/ui/blocks/parameter_block/parameter_block.tscn"
43 |
--------------------------------------------------------------------------------
/ui/blocks/parameter_block/parameter_block.gd.uid:
--------------------------------------------------------------------------------
1 | uid://b6w7djlymksvj
2 |
--------------------------------------------------------------------------------
/ui/blocks/parameter_block/parameter_block.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=5 format=3 uid="uid://clipm2dd28jde"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/ui/blocks/parameter_block/parameter_block.gd" id="1_0hajy"]
4 | [ext_resource type="PackedScene" uid="uid://c7puyxpqcq6xo" path="res://addons/reblocks/ui/blocks/utilities/drag_drop_area/drag_drop_area.tscn" id="2_0eadx"]
5 | [ext_resource type="Script" path="res://addons/reblocks/ui/blocks/utilities/background/background.gd" id="2_oimwh"]
6 | [ext_resource type="PackedScene" uid="uid://b1xvp3u11h41s" path="res://addons/reblocks/ui/blocks/utilities/template_editor/template_editor.tscn" id="3_shl1a"]
7 |
8 | [node name="ParameterBlock" type="MarginContainer" node_paths=PackedStringArray("template_editor")]
9 | offset_right = 16.0
10 | offset_bottom = 8.0
11 | size_flags_horizontal = 0
12 | focus_mode = 2
13 | mouse_filter = 2
14 | script = ExtResource("1_0hajy")
15 | template_editor = NodePath("MarginContainer/TemplateEditor")
16 |
17 | [node name="Background" type="Control" parent="."]
18 | unique_name_in_owner = true
19 | layout_mode = 2
20 | script = ExtResource("2_oimwh")
21 | color = Color(1, 1, 1, 1)
22 | block_type = 3
23 | is_pointy_value = null
24 |
25 | [node name="DragDropArea" parent="." instance=ExtResource("2_0eadx")]
26 | layout_mode = 2
27 | mouse_default_cursor_shape = 2
28 |
29 | [node name="MarginContainer" type="MarginContainer" parent="."]
30 | layout_mode = 2
31 | mouse_filter = 2
32 | theme_override_constants/margin_left = 10
33 | theme_override_constants/margin_right = 10
34 |
35 | [node name="TemplateEditor" parent="MarginContainer" instance=ExtResource("3_shl1a")]
36 | unique_name_in_owner = true
37 | layout_mode = 2
38 | size_flags_horizontal = 0
39 | theme_override_constants/margin_left = 10
40 | theme_override_constants/margin_top = 8
41 | theme_override_constants/margin_right = 10
42 | theme_override_constants/margin_bottom = 8
43 |
44 | [connection signal="focus_entered" from="." to="." method="_on_focus_entered"]
45 | [connection signal="focus_exited" from="." to="." method="_on_focus_exited"]
46 | [connection signal="drag_started" from="DragDropArea" to="." method="_on_drag_drop_area_drag_started"]
47 |
--------------------------------------------------------------------------------
/ui/blocks/statement_block/statement_block.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | class_name StatementBlock
3 | extends Block
4 |
5 | const Types = preload("res://addons/reblocks/types/types.gd")
6 |
7 | @onready var _background := %Background
8 |
9 | var arg_name_to_param_input_dict: Dictionary
10 | var args_to_add_after_format: Dictionary # Only used when loading
11 |
12 |
13 | func _ready():
14 | super()
15 | _background.color = color
16 |
17 |
18 | func _on_drag_drop_area_drag_started(offset: Vector2) -> void:
19 | _drag_started(offset)
20 |
21 |
22 | static func get_block_class():
23 | return "StatementBlock"
24 |
25 |
26 | static func get_scene_path():
27 | return "res://addons/reblocks/ui/blocks/statement_block/statement_block.tscn"
28 |
--------------------------------------------------------------------------------
/ui/blocks/statement_block/statement_block.gd.uid:
--------------------------------------------------------------------------------
1 | uid://di3niamt3587v
2 |
--------------------------------------------------------------------------------
/ui/blocks/statement_block/statement_block.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=6 format=3 uid="uid://c84vmg3odrtxt"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/ui/blocks/statement_block/statement_block.gd" id="1_6wvlf"]
4 | [ext_resource type="Script" path="res://addons/reblocks/ui/blocks/utilities/background/background.gd" id="2_lctqt"]
5 | [ext_resource type="PackedScene" uid="uid://b1oge52xhjqnu" path="res://addons/reblocks/ui/blocks/utilities/snap_point/snap_point.tscn" id="3_5vaov"]
6 | [ext_resource type="PackedScene" uid="uid://c7puyxpqcq6xo" path="res://addons/reblocks/ui/blocks/utilities/drag_drop_area/drag_drop_area.tscn" id="3_mbxhq"]
7 | [ext_resource type="PackedScene" uid="uid://b1xvp3u11h41s" path="res://addons/reblocks/ui/blocks/utilities/template_editor/template_editor.tscn" id="4_vky23"]
8 |
9 | [node name="StatementBlock" type="MarginContainer" node_paths=PackedStringArray("bottom_snap", "template_editor")]
10 | size_flags_horizontal = 0
11 | focus_mode = 2
12 | mouse_filter = 2
13 | script = ExtResource("1_6wvlf")
14 | bottom_snap = NodePath("VBoxContainer/SnapPoint")
15 | template_editor = NodePath("VBoxContainer/TopMarginContainer/MarginContainer/TemplateEditor")
16 |
17 | [node name="VBoxContainer" type="VBoxContainer" parent="."]
18 | layout_mode = 2
19 | mouse_filter = 2
20 | theme_override_constants/separation = 0
21 |
22 | [node name="TopMarginContainer" type="MarginContainer" parent="VBoxContainer"]
23 | custom_minimum_size = Vector2(0, 30)
24 | layout_mode = 2
25 | size_flags_horizontal = 0
26 | mouse_filter = 2
27 | theme_override_constants/margin_left = 0
28 | theme_override_constants/margin_top = 0
29 | theme_override_constants/margin_right = 0
30 | theme_override_constants/margin_bottom = 0
31 |
32 | [node name="Background" type="Control" parent="VBoxContainer/TopMarginContainer"]
33 | unique_name_in_owner = true
34 | layout_mode = 2
35 | mouse_filter = 1
36 | script = ExtResource("2_lctqt")
37 |
38 | [node name="DragDropArea" parent="VBoxContainer/TopMarginContainer" instance=ExtResource("3_mbxhq")]
39 | layout_mode = 2
40 | mouse_default_cursor_shape = 2
41 |
42 | [node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/TopMarginContainer"]
43 | layout_mode = 2
44 | mouse_filter = 2
45 | theme_override_constants/margin_left = 10
46 | theme_override_constants/margin_top = 6
47 | theme_override_constants/margin_right = 12
48 | theme_override_constants/margin_bottom = 6
49 |
50 | [node name="TemplateEditor" parent="VBoxContainer/TopMarginContainer/MarginContainer" instance=ExtResource("4_vky23")]
51 | unique_name_in_owner = true
52 | layout_mode = 2
53 |
54 | [node name="SnapPoint" parent="VBoxContainer" instance=ExtResource("3_5vaov")]
55 | layout_mode = 2
56 |
57 | [connection signal="drag_started" from="VBoxContainer/TopMarginContainer/DragDropArea" to="." method="_on_drag_drop_area_drag_started"]
58 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/background/background.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cv33xhf4grjdh
2 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/background/gutter.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends Control
3 |
4 | const BlockTreeUtil = preload("res://addons/reblocks/ui/block_tree_util.gd")
5 | const Constants = preload("res://addons/reblocks/ui/constants.gd")
6 |
7 | var outline_color: Color
8 | var parent_block: Block
9 |
10 | @export var color: Color:
11 | set = _set_color
12 |
13 |
14 | func _set_color(new_color):
15 | color = new_color
16 | outline_color = color.darkened(0.2)
17 | queue_redraw()
18 |
19 |
20 | func _ready():
21 | parent_block = BlockTreeUtil.get_parent_block(self)
22 | parent_block.focus_entered.connect(queue_redraw)
23 | parent_block.focus_exited.connect(queue_redraw)
24 |
25 |
26 | func _draw():
27 | var fill_polygon: PackedVector2Array
28 | fill_polygon.append(Vector2(0.0, 0.0))
29 | fill_polygon.append(Vector2(size.x, 0.0))
30 | fill_polygon.append(Vector2(size.x, size.y))
31 | fill_polygon.append(Vector2(0.0, size.y))
32 | fill_polygon.append(Vector2(0.0, 0.0))
33 |
34 | var left_polygon: PackedVector2Array
35 | var right_polygon: PackedVector2Array
36 |
37 | left_polygon.append(Vector2(0.0, 0.0))
38 | left_polygon.append(Vector2(0.0, size.y))
39 |
40 | right_polygon.append(Vector2(size.x, 0.0))
41 | right_polygon.append(Vector2(size.x, size.y))
42 |
43 | draw_colored_polygon(fill_polygon, color)
44 | draw_polyline(left_polygon, Constants.FOCUS_BORDER_COLOR if parent_block.has_focus() else outline_color, Constants.OUTLINE_WIDTH)
45 | draw_polyline(right_polygon, Constants.FOCUS_BORDER_COLOR if parent_block.has_focus() else outline_color, Constants.OUTLINE_WIDTH)
46 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/background/gutter.gd.uid:
--------------------------------------------------------------------------------
1 | uid://byvmxt4jx7ht6
2 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/drag_drop_area/drag_drop_area.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | ## Drag drop area.
3 | ##
4 | ## A Control which watches for click and drag gestures beginning from itself.
5 | ## It propagates events up to its parent, so it is possible to place this
6 | ## control inside a control which processes input events such as [LineEdit].
7 | ## If a drag occurs, it emits [signal drag_started].
8 | extends Control
9 |
10 | const Constants = preload("res://addons/reblocks/ui/constants.gd")
11 | const BlockTreeUtil = preload("res://addons/reblocks/ui/block_tree_util.gd")
12 |
13 | signal drag_started(offset: Vector2)
14 |
15 | ## True to require that the mouse move outside of the component before
16 | ## [signal drag_started] is emitted.
17 | @export var drag_outside: bool = false
18 |
19 | var _drag_start_position: Vector2 = Vector2.INF
20 | var parent_block: Block
21 |
22 |
23 | func _gui_input(event: InputEvent) -> void:
24 | # Watch for mouse clicks using _gui_input, so events are filtered based on
25 | # rules of the GUI system.
26 |
27 | if not event is InputEventMouseButton:
28 | return
29 |
30 | var button_event: InputEventMouseButton = event as InputEventMouseButton
31 |
32 | if button_event.button_index != MOUSE_BUTTON_LEFT and button_event.button_index != MOUSE_BUTTON_RIGHT:
33 | return
34 |
35 | if button_event.double_click:
36 | # Double click event (with the mouse released) has both pressed=true
37 | # and double_click=true, so ignore it as a special case.
38 | pass
39 | elif button_event.pressed:
40 | # Keep track of where the mouse click originated, but allow this
41 | # event to propagate to other nodes.
42 | if button_event.button_index == MOUSE_BUTTON_LEFT:
43 | _drag_start_position = event.global_position
44 | else:
45 | if not parent_block:
46 | parent_block = BlockTreeUtil.get_parent_block(self)
47 |
48 | if parent_block and parent_block.can_delete:
49 | # Accepts to avoid menu conflicts
50 | accept_event()
51 |
52 | # A new right-click menu with items
53 | var _context_menu := PopupMenu.new()
54 | _context_menu.add_icon_item(EditorInterface.get_editor_theme().get_icon("Duplicate", "EditorIcons"), "Duplicate")
55 | _context_menu.add_icon_item(EditorInterface.get_editor_theme().get_icon("Remove", "EditorIcons"), "Delete")
56 | _context_menu.popup_hide.connect(_cleanup)
57 | _context_menu.id_pressed.connect(_menu_pressed.bind(_context_menu))
58 |
59 | _context_menu.position = DisplayServer.mouse_get_position()
60 | add_child(_context_menu)
61 |
62 | _context_menu.show()
63 | else:
64 | _drag_start_position = Vector2.INF
65 |
66 |
67 | func _input(event: InputEvent) -> void:
68 | # Watch for mouse movements using _input. This way, we receive mouse
69 | # motion events that occur outside of the component before the GUI system
70 | # does.
71 |
72 | if not event is InputEventMouseMotion:
73 | return
74 |
75 | if _drag_start_position == Vector2.INF:
76 | return
77 |
78 | var motion_event: InputEventMouseMotion = event as InputEventMouseMotion
79 |
80 | if drag_outside and get_global_rect().has_point(motion_event.global_position):
81 | return
82 |
83 | if _drag_start_position.distance_to(motion_event.global_position) < Constants.MINIMUM_DRAG_THRESHOLD:
84 | return
85 |
86 | get_viewport().set_input_as_handled()
87 | drag_started.emit(_drag_start_position - motion_event.global_position)
88 | _drag_start_position = Vector2.INF
89 |
90 |
91 | func _menu_pressed(_index: int, _context_menu: PopupMenu):
92 | # Getting which item was pressed and the corresponding function
93 | var _pressed_label: String = _context_menu.get_item_text(_index)
94 |
95 | if _pressed_label == "Duplicate":
96 | parent_block.confirm_duplicate()
97 | elif _pressed_label == "Delete":
98 | parent_block.confirm_delete()
99 |
100 |
101 | func _cleanup():
102 | for child in get_children():
103 | remove_child(child)
104 | child.queue_free()
105 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/drag_drop_area/drag_drop_area.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cdhofr7vgp1tw
2 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/drag_drop_area/drag_drop_area.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=2 format=3 uid="uid://c7puyxpqcq6xo"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/ui/blocks/utilities/drag_drop_area/drag_drop_area.gd" id="1_5vdxp"]
4 |
5 | [node name="DragDropArea" type="Control"]
6 | layout_mode = 3
7 | anchors_preset = 15
8 | anchor_right = 1.0
9 | anchor_bottom = 1.0
10 | grow_horizontal = 2
11 | grow_vertical = 2
12 | mouse_filter = 1
13 | script = ExtResource("1_5vdxp")
14 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/parameter_input/parameter_input.gd.uid:
--------------------------------------------------------------------------------
1 | uid://ci3p07wpcslkb
2 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/parameter_output/parameter_output.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends MarginContainer
3 |
4 | const Types = preload("res://addons/reblocks/types/types.gd")
5 | const ParameterBlock = preload("res://addons/reblocks/ui/blocks/parameter_block/parameter_block.gd")
6 |
7 | var block: Block
8 | var parameter_name: String
9 | var _block_name: String:
10 | get:
11 | return block.definition.name if block else ""
12 |
13 | @export var block_params: Dictionary
14 |
15 | @onready var _context := BlockEditorContext.get_default()
16 |
17 | @onready var _snap_point := %SnapPoint
18 |
19 |
20 | func _ready():
21 | _update_parameter_block.call_deferred()
22 |
23 |
24 | func _update_parameter_block():
25 | if _snap_point == null:
26 | return
27 |
28 | if _snap_point.has_snapped_block():
29 | return
30 |
31 | if _context.block_script == null:
32 | return
33 |
34 | var block_name = &"%s:%s" % [_block_name, parameter_name]
35 | var parameter_block: ParameterBlock = _context.block_script.instantiate_block_by_name(block_name)
36 |
37 | if parameter_block == null:
38 | # FIXME: This sometimes occurs when a script is loaded but it is unclear why
39 | #push_error("Unable to create output block %s." % block_name)
40 | return
41 |
42 | _snap_point.add_child.call_deferred(parameter_block)
43 |
44 |
45 | func _on_parameter_block_drag_started(drag_block: Block, offset: Vector2):
46 | block.drag_started.emit(drag_block, offset)
47 |
48 |
49 | func _on_snap_point_snapped_block_changed(snap_block: Block):
50 | if snap_block == null:
51 | return
52 | # FIXME: The spawned_by property isn't serialized, so we'll set it here to
53 | # be sure. In the future, we should try to get rid of this property.
54 | snap_block.spawned_by = self
55 | snap_block.drag_started.connect(_on_parameter_block_drag_started)
56 |
57 |
58 | func _on_snap_point_snapped_block_removed(snap_block: Block):
59 | snap_block.drag_started.disconnect(_on_parameter_block_drag_started)
60 | _update_parameter_block.call_deferred()
61 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/parameter_output/parameter_output.gd.uid:
--------------------------------------------------------------------------------
1 | uid://bgx7kphxxwdtt
2 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/parameter_output/parameter_output.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://dp01u74qkty7r"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/ui/blocks/utilities/parameter_output/parameter_output.gd" id="1_eebb2"]
4 | [ext_resource type="PackedScene" uid="uid://b1oge52xhjqnu" path="res://addons/reblocks/ui/blocks/utilities/snap_point/snap_point.tscn" id="2_ngr7c"]
5 |
6 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_tn6h4"]
7 | bg_color = Color(1, 1, 1, 1)
8 | corner_radius_top_left = 40
9 | corner_radius_top_right = 40
10 | corner_radius_bottom_right = 40
11 | corner_radius_bottom_left = 40
12 |
13 | [node name="ParameterOutput" type="MarginContainer"]
14 | anchors_preset = 15
15 | anchor_right = 1.0
16 | anchor_bottom = 1.0
17 | offset_right = -1052.0
18 | offset_bottom = -617.0
19 | grow_horizontal = 2
20 | grow_vertical = 2
21 | mouse_filter = 2
22 | script = ExtResource("1_eebb2")
23 |
24 | [node name="Panel" type="Panel" parent="."]
25 | unique_name_in_owner = true
26 | layout_mode = 2
27 | mouse_filter = 2
28 | theme_override_styles/panel = SubResource("StyleBoxFlat_tn6h4")
29 |
30 | [node name="SnapPoint" parent="." instance=ExtResource("2_ngr7c")]
31 | unique_name_in_owner = true
32 | layout_mode = 2
33 | block_type = 0
34 | variant_type = 4
35 |
36 | [connection signal="snapped_block_changed" from="SnapPoint" to="." method="_on_snap_point_snapped_block_changed"]
37 | [connection signal="snapped_block_removed" from="SnapPoint" to="." method="_on_snap_point_snapped_block_removed"]
38 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/snap_point/snap_point.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | class_name SnapPoint
3 | extends MarginContainer
4 |
5 | const Types = preload("res://addons/reblocks/types/types.gd")
6 |
7 | @export var block_type: Types.BlockType = Types.BlockType.STATEMENT
8 |
9 | @export var snapped_block: Block:
10 | get:
11 | return snapped_block
12 | set(value):
13 | if value != snapped_block:
14 | var old_block = snapped_block
15 | snapped_block = value
16 | snapped_block_changed.emit(snapped_block)
17 | if value == null and old_block:
18 | snapped_block_removed.emit(old_block)
19 |
20 | ## When block_type is [enum Types.BlockType.VALUE], the type of the value that can be used at this snap point.
21 | @export var variant_type: Variant.Type
22 |
23 | signal drag_started(block: Block)
24 | signal snapped_block_changed(block: Block)
25 | signal snapped_block_removed(block: Block)
26 |
27 |
28 | func _ready():
29 | _update_snapped_block_from_children()
30 |
31 |
32 | func _update_snapped_block_from_children():
33 | # Temporary migration to set the snapped_block property based on children
34 | # of this node.
35 | if snapped_block:
36 | return
37 | for node in get_children():
38 | var child_block = node as Block
39 | if child_block:
40 | snapped_block = child_block
41 | return
42 |
43 |
44 | func get_snapped_block() -> Block:
45 | return snapped_block
46 |
47 |
48 | func has_snapped_block() -> bool:
49 | return snapped_block != null
50 |
51 |
52 | func replace_snapped_block(new_block: Block):
53 | var old_block = get_snapped_block()
54 |
55 | if old_block:
56 | remove_child(old_block)
57 |
58 | if new_block:
59 | add_child(new_block)
60 |
61 |
62 | func insert_snapped_block(new_block: Block) -> Block:
63 | var old_block = get_snapped_block()
64 |
65 | if old_block:
66 | remove_child(old_block)
67 |
68 | if new_block:
69 | add_child(new_block)
70 |
71 | if new_block and old_block:
72 | var last_snap = _get_last_snap(new_block)
73 | if last_snap:
74 | old_block = last_snap.insert_snapped_block(old_block)
75 |
76 | return old_block
77 |
78 |
79 | func _get_last_snap(next_block: Block) -> SnapPoint:
80 | var last_snap: SnapPoint
81 | while next_block:
82 | last_snap = next_block.bottom_snap
83 | next_block = last_snap.get_snapped_block() if last_snap else null
84 | return last_snap
85 |
86 |
87 | func _on_child_entered_tree(node):
88 | var new_block = node as Block
89 | if not new_block:
90 | return
91 | if new_block == snapped_block:
92 | return
93 | if snapped_block:
94 | # We only allow a single snapped block at a time
95 | push_warning("Attempted to add more than one Block node ({block}) to the same SnapPoint ({snap_point})".format({"block": new_block, "snap_point": self}))
96 | remove_child.call_deferred(snapped_block)
97 | snapped_block = new_block
98 |
99 |
100 | func _on_child_exiting_tree(node):
101 | var old_block = node as Block
102 | if old_block and old_block == snapped_block:
103 | snapped_block = null
104 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/snap_point/snap_point.gd.uid:
--------------------------------------------------------------------------------
1 | uid://be4hpnullwwgp
2 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/snap_point/snap_point.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=2 format=3 uid="uid://b1oge52xhjqnu"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/ui/blocks/utilities/snap_point/snap_point.gd" id="1_kseym"]
4 |
5 | [node name="SnapPoint" type="MarginContainer" groups=["snap_point"]]
6 | anchors_preset = 15
7 | anchor_right = 1.0
8 | anchor_bottom = 1.0
9 | offset_right = -1152.0
10 | offset_bottom = -648.0
11 | grow_horizontal = 2
12 | grow_vertical = 2
13 | mouse_filter = 2
14 | script = ExtResource("1_kseym")
15 |
16 | [connection signal="child_entered_tree" from="." to="." method="_on_child_entered_tree"]
17 | [connection signal="child_exiting_tree" from="." to="." method="_on_child_exiting_tree"]
18 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/template_editor/collapsable_settings.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | class_name CollapsableSettings
3 | extends HBoxContainer
4 |
5 | @onready var _expand_button: Button = %ExpandSettingsButton
6 | @onready var _collapse_button: Button = %CollapseSettingsButton
7 | var _collapsed := false
8 |
9 |
10 | func _ready() -> void:
11 | _collapse()
12 | move_child(_expand_button, 0)
13 | move_child(_collapse_button, -1)
14 | _expand_button.connect("button_up", _expand)
15 | _collapse_button.connect("button_up", _collapse)
16 |
17 |
18 | func _expand() -> void:
19 | if not _collapsed:
20 | return
21 | for child in get_children(true):
22 | child.visible = true
23 | _expand_button.visible = false
24 | _collapse_button.visible = true
25 | _collapsed = false
26 |
27 |
28 | func _collapse() -> void:
29 | if _collapsed:
30 | return
31 | for child in get_children(true):
32 | child.visible = false
33 | _expand_button.visible = true
34 | _collapsed = true
35 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/template_editor/collapsable_settings.gd.uid:
--------------------------------------------------------------------------------
1 | uid://b2ir1wey2qtyo
2 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/template_editor/collapsable_settings.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://1xfpd777g8pf"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/ui/blocks/utilities/template_editor/collapsable_settings.gd" id="1_f0ssn"]
4 | [ext_resource type="Texture2D" uid="uid://cd243la33evh" path="res://addons/reblocks/ui/blocks/utilities/template_editor/plus.svg" id="2_mp58d"]
5 | [ext_resource type="Texture2D" uid="uid://dmplpvmlpcdrk" path="res://addons/reblocks/ui/blocks/utilities/template_editor/minus.svg" id="3_adq5s"]
6 |
7 | [node name="CollapsableSettings" type="HBoxContainer"]
8 | offset_right = 36.0
9 | offset_bottom = 31.0
10 | script = ExtResource("1_f0ssn")
11 |
12 | [node name="ExpandSettingsButton" type="Button" parent="."]
13 | unique_name_in_owner = true
14 | layout_mode = 2
15 | icon = ExtResource("2_mp58d")
16 | flat = true
17 | icon_alignment = 1
18 |
19 | [node name="CollapseSettingsButton" type="Button" parent="."]
20 | unique_name_in_owner = true
21 | custom_minimum_size = Vector2(20, 20)
22 | layout_mode = 2
23 | icon = ExtResource("3_adq5s")
24 | flat = true
25 | icon_alignment = 1
26 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/template_editor/minus.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
57 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/template_editor/minus.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dmplpvmlpcdrk"
6 | path="res://.godot/imported/minus.svg-d7eb9fd8d189f35d0738132dd443fd4c.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/reblocks/ui/blocks/utilities/template_editor/minus.svg"
14 | dest_files=["res://.godot/imported/minus.svg-d7eb9fd8d189f35d0738132dd443fd4c.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/template_editor/plus.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
64 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/template_editor/plus.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cd243la33evh"
6 | path="res://.godot/imported/plus.svg-18d400f84cd1d85e41a3d9ade4846429.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/reblocks/ui/blocks/utilities/template_editor/plus.svg"
14 | dest_files=["res://.godot/imported/plus.svg-18d400f84cd1d85e41a3d9ade4846429.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/template_editor/template_editor.gd.uid:
--------------------------------------------------------------------------------
1 | uid://o6f8yps7ppb7
2 |
--------------------------------------------------------------------------------
/ui/blocks/utilities/template_editor/template_editor.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=2 format=3 uid="uid://b1xvp3u11h41s"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/ui/blocks/utilities/template_editor/template_editor.gd" id="1_7extq"]
4 |
5 | [node name="TemplateEditor" type="MarginContainer"]
6 | anchors_preset = 15
7 | anchor_right = 1.0
8 | anchor_bottom = 1.0
9 | grow_horizontal = 2
10 | grow_vertical = 2
11 | mouse_filter = 2
12 | script = ExtResource("1_7extq")
13 | editable = null
14 |
15 | [node name="Container" type="HBoxContainer" parent="."]
16 | unique_name_in_owner = true
17 | layout_mode = 2
18 | mouse_filter = 2
19 |
--------------------------------------------------------------------------------
/ui/constants.gd:
--------------------------------------------------------------------------------
1 | extends Object
2 |
3 | const CURRENT_DATA_VERSION = 0
4 |
5 | const KNOB_X = 10.0
6 | const KNOB_W = 20.0
7 | const KNOB_H = 5.0
8 | const KNOB_Z = 5.0
9 | const CONTROL_MARGIN = 20.0
10 | const OUTLINE_WIDTH = 3.0
11 | const MINIMUM_SNAP_DISTANCE = 80.0
12 | const MINIMUM_DRAG_THRESHOLD = 25
13 | const ROUND_RESOLUTION = 10
14 |
15 | const FOCUS_BORDER_COLOR = Color(225, 242, 0)
16 | const DRAG_REMOVE_COLOR = Color(1, 1, 1, 0.5)
17 | const DRAG_PREVIEW_COLOR = Color(225, 242, 0, 0.3)
18 |
19 | ## Properties for builtin categories. Order starts at 10 for the first
20 | ## category and then are separated by 10 to allow custom categories to
21 | ## be easily placed between builtin categories.
22 | const BUILTIN_CATEGORIES_PROPS: Dictionary = {
23 | "Lifecycle":
24 | {
25 | "color": Color("ff001aff"),
26 | "order": 10,
27 | },
28 | "Lifecycle | Game":
29 | {
30 | "color": Color("ff001aff"),
31 | "order": 12,
32 | },
33 | "Lifecycle | Spawn":
34 | {
35 | "color": Color("ff001aff"),
36 | "order": 15,
37 | },
38 | "Transform | Position":
39 | {
40 | "color": Color("773344ff"),
41 | "order": 20,
42 | },
43 | "Transform | Rotation":
44 | {
45 | "color": Color("773344ff"),
46 | "order": 30,
47 | },
48 | "Transform | Scale":
49 | {
50 | "color": Color("773344ff"),
51 | "order": 40,
52 | },
53 | "Graphics | Modulate":
54 | {
55 | "color": Color("a37276ff"),
56 | "order": 50,
57 | },
58 | "Graphics | Visibility":
59 | {
60 | "color": Color("a37276ff"),
61 | "order": 60,
62 | },
63 | "Graphics | Viewport":
64 | {
65 | "color": Color("a37276ff"),
66 | "order": 61,
67 | },
68 | "Graphics | Animation":
69 | {
70 | "color": Color("a37276ff"),
71 | "order": 62,
72 | },
73 | "UI":
74 | {
75 | "color": Color("03aa74"),
76 | "order": 65,
77 | },
78 | "Sounds":
79 | {
80 | "color": Color("7606B8"),
81 | "order": 70,
82 | },
83 | "Physics | Mass":
84 | {
85 | "color": Color("264653ff"),
86 | "order": 80,
87 | },
88 | "Physics | Velocity":
89 | {
90 | "color": Color("264653ff"),
91 | "order": 90,
92 | },
93 | "Input":
94 | {
95 | "color": Color("e76f51ff"),
96 | "order": 100,
97 | },
98 | "Communication | Methods":
99 | {
100 | "color": Color("2a9d8fff"),
101 | "order": 110,
102 | },
103 | "Communication | Nodes":
104 | {
105 | "color": Color("2a9d8fff"),
106 | "order": 115,
107 | },
108 | "Communication | Groups":
109 | {
110 | "color": Color("2a9d8fff"),
111 | "order": 120,
112 | },
113 | "Info | Score":
114 | {
115 | "color": Color("FF5000"),
116 | "order": 130,
117 | },
118 | "Loops":
119 | {
120 | "color": Color("e9c46aff"),
121 | "order": 140,
122 | },
123 | "Logic | Conditionals":
124 | {
125 | "color": Color("e9c46aff"),
126 | "order": 150,
127 | },
128 | "Logic | Comparison":
129 | {
130 | "color": Color("e9c46aff"),
131 | "order": 160,
132 | },
133 | "Logic | Boolean":
134 | {
135 | "color": Color("e9c46aff"),
136 | "order": 170,
137 | },
138 | "Variables":
139 | {
140 | "color": Color("e76f51ff"),
141 | "order": 180,
142 | },
143 | "Math":
144 | {
145 | "color": Color("f4a261ff"),
146 | "order": 190,
147 | },
148 | "Log":
149 | {
150 | "color": Color("002050"),
151 | "order": 200,
152 | },
153 | "Node | Properties":
154 | {
155 | "color": Color("002050"),
156 | "order": 210,
157 | }
158 | }
--------------------------------------------------------------------------------
/ui/constants.gd.uid:
--------------------------------------------------------------------------------
1 | uid://d0e278swld54t
2 |
--------------------------------------------------------------------------------
/ui/main_panel.gd.uid:
--------------------------------------------------------------------------------
1 | uid://b4f4roenpifgk
2 |
--------------------------------------------------------------------------------
/ui/picker/categories/block_category.gd:
--------------------------------------------------------------------------------
1 | extends RefCounted
2 |
3 | var name: String
4 | var color: Color
5 | var order: int
6 |
7 |
8 | func _init(p_name: String = "", p_color: Color = Color.WHITE, p_order: int = 0):
9 | name = p_name
10 | color = p_color
11 | order = p_order
12 |
13 |
14 | ## Compare block categories for sorting. Compare by order then name.
15 | static func sort_by_order(a, b) -> bool:
16 | if a.order != b.order:
17 | return a.order < b.order
18 | return a.name.naturalcasecmp_to(b.name) < 0
19 |
--------------------------------------------------------------------------------
/ui/picker/categories/block_category.gd.uid:
--------------------------------------------------------------------------------
1 | uid://crxpqbcd55h5a
2 |
--------------------------------------------------------------------------------
/ui/picker/categories/block_category_button.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends MarginContainer
3 |
4 | const BlockCategory = preload("res://addons/reblocks/ui/picker/categories/block_category.gd")
5 | const Util = preload("res://addons/reblocks/ui/util.gd")
6 |
7 | signal selected
8 |
9 | var category: BlockCategory
10 |
11 | @onready var _panel := %Panel
12 | @onready var _button := %Button
13 |
14 |
15 | func _ready():
16 | if not category:
17 | category = BlockCategory.new("Example", Color.RED)
18 | var category_title = category.name.get_slice(" |", 0)
19 |
20 | if not self.is_part_of_edited_scene():
21 | var texture = load("res://addons/reblocks/ui/picker/categories/icons/" + category_title.to_lower() + ".svg")
22 | _button.icon = texture
23 | _panel.modulate = category.color
24 |
25 | _button.tooltip_text = tr(category_title)
26 |
27 |
28 | func _on_button_pressed():
29 | selected.emit()
30 |
--------------------------------------------------------------------------------
/ui/picker/categories/block_category_button.gd.uid:
--------------------------------------------------------------------------------
1 | uid://y2srodxufo03
2 |
--------------------------------------------------------------------------------
/ui/picker/categories/block_category_button.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=8 format=3 uid="uid://bdtetj0gs45hv"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/ui/picker/categories/block_category_button.gd" id="1_pxxnl"]
4 | [ext_resource type="Texture2D" uid="uid://g10ct6m5goi6" path="res://addons/reblocks/ui/picker/categories/icons/file_broken.svg" id="2_0c1ke"]
5 |
6 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_w0e7p"]
7 | bg_color = Color(1, 1, 1, 1)
8 | corner_radius_top_left = 5
9 | corner_radius_top_right = 5
10 | corner_radius_bottom_right = 5
11 | corner_radius_bottom_left = 5
12 |
13 | [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_dgecf"]
14 |
15 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_fyk0j"]
16 | bg_color = Color(1, 1, 1, 0.196078)
17 | corner_radius_top_left = 5
18 | corner_radius_top_right = 5
19 | corner_radius_bottom_right = 5
20 | corner_radius_bottom_left = 5
21 |
22 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ha83k"]
23 | bg_color = Color(1, 1, 1, 0.392157)
24 | corner_radius_top_left = 5
25 | corner_radius_top_right = 5
26 | corner_radius_bottom_right = 5
27 | corner_radius_bottom_left = 5
28 |
29 | [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ousiv"]
30 |
31 | [node name="BlockCategoryButton" type="MarginContainer"]
32 | script = ExtResource("1_pxxnl")
33 |
34 | [node name="Panel" type="Panel" parent="."]
35 | unique_name_in_owner = true
36 | layout_mode = 2
37 | theme_override_styles/panel = SubResource("StyleBoxFlat_w0e7p")
38 |
39 | [node name="Button" type="Button" parent="."]
40 | unique_name_in_owner = true
41 | layout_mode = 2
42 | size_flags_horizontal = 4
43 | tooltip_text = "Example"
44 | mouse_default_cursor_shape = 2
45 | theme_override_styles/focus = SubResource("StyleBoxEmpty_dgecf")
46 | theme_override_styles/hover = SubResource("StyleBoxFlat_fyk0j")
47 | theme_override_styles/pressed = SubResource("StyleBoxFlat_ha83k")
48 | theme_override_styles/normal = SubResource("StyleBoxEmpty_ousiv")
49 | icon = ExtResource("2_0c1ke")
50 | icon_alignment = 1
51 |
52 | [connection signal="pressed" from="Button" to="." method="_on_button_pressed"]
53 |
--------------------------------------------------------------------------------
/ui/picker/categories/block_category_display.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends MarginContainer
3 |
4 | signal block_picked(block: Block, offset: Vector2)
5 |
6 | const BlockCategory = preload("res://addons/reblocks/ui/picker/categories/block_category.gd")
7 | const BlockDefinition = preload("res://addons/reblocks/code_generation/block_definition.gd")
8 | const Util = preload("res://addons/reblocks/ui/util.gd")
9 |
10 | @export var title: String:
11 | set = _set_title
12 | @export var block_definitions: Array[BlockDefinition]:
13 | set = _set_block_definitions
14 |
15 | @onready var _context := BlockEditorContext.get_default()
16 |
17 | @onready var _label := %Label
18 | @onready var _blocks_container := %BlocksContainer
19 |
20 | var _blocks: Dictionary # String, Block
21 |
22 |
23 | func _ready():
24 | _update_label()
25 | _update_blocks()
26 |
27 |
28 | func _set_title(value):
29 | title = value
30 | _update_label()
31 |
32 |
33 | func _set_block_definitions(value):
34 | block_definitions = value
35 | _update_blocks()
36 |
37 |
38 | func _update_label():
39 | if not _label:
40 | return
41 |
42 | _label.text = tr(title)
43 |
44 |
45 | func _update_blocks():
46 | if not _blocks_container:
47 | return
48 |
49 | if not _context:
50 | return
51 |
52 | for block in _blocks.values():
53 | block.hide()
54 |
55 | for block_definition in block_definitions:
56 | var block = _get_or_create_block(block_definition)
57 | _blocks_container.move_child(block, -1)
58 | block.show()
59 |
60 | _blocks_container.visible = not block_definitions.is_empty()
61 |
62 |
63 | func _get_or_create_block(block_definition: BlockDefinition) -> Block:
64 | var block: Block = _blocks.get(block_definition.name)
65 |
66 | if block == null:
67 | block = _context.block_script.instantiate_block(block_definition)
68 | block.can_delete = false
69 | block.editable = false
70 | block.drag_started.connect(func(block: Block, offset: Vector2): block_picked.emit(block, offset))
71 | _blocks_container.add_child(block)
72 | _blocks[block_definition.name] = block
73 | else:
74 | # If the block is being reused, make sure the context corresponds to
75 | # the current BlockCode node.
76 | block.refresh_context()
77 |
78 | return block
79 |
--------------------------------------------------------------------------------
/ui/picker/categories/block_category_display.gd.uid:
--------------------------------------------------------------------------------
1 | uid://bwwcj18bxjudi
2 |
--------------------------------------------------------------------------------
/ui/picker/categories/block_category_display.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=2 format=3 uid="uid://duhpwtfo3k0sk"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/ui/picker/categories/block_category_display.gd" id="1_wkdht"]
4 |
5 | [node name="BlockCategoryDisplay" type="MarginContainer"]
6 | anchors_preset = 15
7 | anchor_right = 1.0
8 | anchor_bottom = 1.0
9 | offset_right = -918.0
10 | offset_bottom = -246.0
11 | grow_horizontal = 2
12 | grow_vertical = 2
13 | theme_override_constants/margin_left = 4
14 | theme_override_constants/margin_bottom = 40
15 | script = ExtResource("1_wkdht")
16 |
17 | [node name="VBoxContainer" type="VBoxContainer" parent="."]
18 | layout_mode = 2
19 |
20 | [node name="MarginContainer" type="MarginContainer" parent="VBoxContainer"]
21 | layout_mode = 2
22 | theme_override_constants/margin_bottom = 4
23 |
24 | [node name="Label" type="Label" parent="VBoxContainer/MarginContainer"]
25 | unique_name_in_owner = true
26 | layout_mode = 2
27 | theme_override_font_sizes/font_size = 18
28 |
29 | [node name="BlocksContainer" type="VBoxContainer" parent="VBoxContainer"]
30 | unique_name_in_owner = true
31 | layout_mode = 2
32 | theme_override_constants/separation = 14
33 |
--------------------------------------------------------------------------------
/ui/picker/categories/category_factory.gd:
--------------------------------------------------------------------------------
1 | class_name CategoryFactory
2 | extends Object
3 |
4 | const BlockCategory = preload("res://addons/reblocks/ui/picker/categories/block_category.gd")
5 | const Constants = preload("res://addons/reblocks/ui/constants.gd")
6 |
7 |
8 | ## Returns a list of BlockCategory instances for all block categories.
9 | static func get_all_categories(custom_categories: Array[BlockCategory] = []) -> Array[BlockCategory]:
10 | var result: Array[BlockCategory]
11 |
12 | for category_name in Constants.BUILTIN_CATEGORIES_PROPS:
13 | var props: Dictionary = Constants.BUILTIN_CATEGORIES_PROPS.get(category_name, {})
14 | var color: Color = props.get("color", Color.SLATE_GRAY)
15 | var order: int = props.get("order", 0)
16 | result.append(BlockCategory.new(category_name, color, order))
17 |
18 | # TODO: Should we deduplicate custom_categories here?
19 | result.append_array(custom_categories)
20 |
21 | return result
22 |
--------------------------------------------------------------------------------
/ui/picker/categories/category_factory.gd.uid:
--------------------------------------------------------------------------------
1 | uid://bcdwygabsc65o
2 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/communication.svg:
--------------------------------------------------------------------------------
1 |
2 |
24 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/communication.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://d0agg8648xht3"
6 | path="res://.godot/imported/communication.svg-947c90ab31319a267db7fe17ba69d837.ctex"
7 | metadata={
8 | "has_editor_variant": true,
9 | "vram_texture": false
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://addons/reblocks/ui/picker/categories/icons/communication.svg"
15 | dest_files=["res://.godot/imported/communication.svg-947c90ab31319a267db7fe17ba69d837.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=0
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=false
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=1
36 | svg/scale=1.0
37 | editor/scale_with_editor_scale=true
38 | editor/convert_colors_with_editor_theme=false
39 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/file_broken.svg:
--------------------------------------------------------------------------------
1 |
2 |
24 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/file_broken.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://g10ct6m5goi6"
6 | path="res://.godot/imported/file_broken.svg-4eaab408643b07ce95d90d59c6c11ee5.ctex"
7 | metadata={
8 | "has_editor_variant": true,
9 | "vram_texture": false
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://addons/reblocks/ui/picker/categories/icons/file_broken.svg"
15 | dest_files=["res://.godot/imported/file_broken.svg-4eaab408643b07ce95d90d59c6c11ee5.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=0
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=false
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=1
36 | svg/scale=1.0
37 | editor/scale_with_editor_scale=true
38 | editor/convert_colors_with_editor_theme=false
39 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/graphics.svg:
--------------------------------------------------------------------------------
1 |
2 |
24 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/graphics.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bfvq21qp2l363"
6 | path="res://.godot/imported/graphics.svg-a28b663c4f820bd8c41e895b8bfaf874.ctex"
7 | metadata={
8 | "has_editor_variant": true,
9 | "vram_texture": false
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://addons/reblocks/ui/picker/categories/icons/graphics.svg"
15 | dest_files=["res://.godot/imported/graphics.svg-a28b663c4f820bd8c41e895b8bfaf874.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=0
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=false
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=1
36 | svg/scale=1.0
37 | editor/scale_with_editor_scale=true
38 | editor/convert_colors_with_editor_theme=false
39 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/info.svg:
--------------------------------------------------------------------------------
1 |
2 |
24 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/info.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bw76iiilnqfsn"
6 | path="res://.godot/imported/info.svg-9f3e9c8144e7ee8ec6ef26d98cf6f8af.ctex"
7 | metadata={
8 | "has_editor_variant": true,
9 | "vram_texture": false
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://addons/reblocks/ui/picker/categories/icons/info.svg"
15 | dest_files=["res://.godot/imported/info.svg-9f3e9c8144e7ee8ec6ef26d98cf6f8af.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=0
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=false
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=1
36 | svg/scale=1.0
37 | editor/scale_with_editor_scale=true
38 | editor/convert_colors_with_editor_theme=false
39 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/input.svg:
--------------------------------------------------------------------------------
1 |
2 |
24 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/input.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bqlh8yalvn3qt"
6 | path="res://.godot/imported/input.svg-8ff23e911a11ca01b6173c036b07dd03.ctex"
7 | metadata={
8 | "has_editor_variant": true,
9 | "vram_texture": false
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://addons/reblocks/ui/picker/categories/icons/input.svg"
15 | dest_files=["res://.godot/imported/input.svg-8ff23e911a11ca01b6173c036b07dd03.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=0
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=false
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=1
36 | svg/scale=1.0
37 | editor/scale_with_editor_scale=true
38 | editor/convert_colors_with_editor_theme=false
39 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/lifecycle.svg:
--------------------------------------------------------------------------------
1 |
2 |
27 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/lifecycle.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dtx1jvrk0xo6u"
6 | path="res://.godot/imported/lifecycle.svg-a03e82f944312da96cc3afcd5fe9b410.ctex"
7 | metadata={
8 | "has_editor_variant": true,
9 | "vram_texture": false
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://addons/reblocks/ui/picker/categories/icons/lifecycle.svg"
15 | dest_files=["res://.godot/imported/lifecycle.svg-a03e82f944312da96cc3afcd5fe9b410.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=0
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=false
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=1
36 | svg/scale=1.0
37 | editor/scale_with_editor_scale=true
38 | editor/convert_colors_with_editor_theme=false
39 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/log.svg:
--------------------------------------------------------------------------------
1 |
2 |
42 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/log.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://deb4kkgrd4ova"
6 | path="res://.godot/imported/log.svg-327c08a400b93a74d2b8236ea0898062.ctex"
7 | metadata={
8 | "has_editor_variant": true,
9 | "vram_texture": false
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://addons/reblocks/ui/picker/categories/icons/log.svg"
15 | dest_files=["res://.godot/imported/log.svg-327c08a400b93a74d2b8236ea0898062.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=0
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=false
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=1
36 | svg/scale=1.0
37 | editor/scale_with_editor_scale=true
38 | editor/convert_colors_with_editor_theme=false
39 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/logic.svg:
--------------------------------------------------------------------------------
1 |
2 |
28 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/logic.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://xs78uxfonid0"
6 | path="res://.godot/imported/logic.svg-944177754b8f54bab7f488e8345ce91f.ctex"
7 | metadata={
8 | "has_editor_variant": true,
9 | "vram_texture": false
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://addons/reblocks/ui/picker/categories/icons/logic.svg"
15 | dest_files=["res://.godot/imported/logic.svg-944177754b8f54bab7f488e8345ce91f.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=0
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=false
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=1
36 | svg/scale=1.0
37 | editor/scale_with_editor_scale=true
38 | editor/convert_colors_with_editor_theme=false
39 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/loops.svg:
--------------------------------------------------------------------------------
1 |
2 |
24 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/loops.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://xfxkkou3p0re"
6 | path="res://.godot/imported/loops.svg-316da2da589f07c3d0f5428710593245.ctex"
7 | metadata={
8 | "has_editor_variant": true,
9 | "vram_texture": false
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://addons/reblocks/ui/picker/categories/icons/loops.svg"
15 | dest_files=["res://.godot/imported/loops.svg-316da2da589f07c3d0f5428710593245.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=0
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=false
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=1
36 | svg/scale=1.0
37 | editor/scale_with_editor_scale=true
38 | editor/convert_colors_with_editor_theme=false
39 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/math.svg:
--------------------------------------------------------------------------------
1 |
2 |
20 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/math.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cjwntrfvngo35"
6 | path="res://.godot/imported/math.svg-c778437f6fc860eedd4f084b9d29355a.ctex"
7 | metadata={
8 | "has_editor_variant": true,
9 | "vram_texture": false
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://addons/reblocks/ui/picker/categories/icons/math.svg"
15 | dest_files=["res://.godot/imported/math.svg-c778437f6fc860eedd4f084b9d29355a.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=0
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=false
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=1
36 | svg/scale=1.0
37 | editor/scale_with_editor_scale=true
38 | editor/convert_colors_with_editor_theme=false
39 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/physics.svg:
--------------------------------------------------------------------------------
1 |
2 |
37 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/physics.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://8isr3pc5m4mi"
6 | path="res://.godot/imported/physics.svg-09ffe308a70b6e14c8f03dc392898be8.ctex"
7 | metadata={
8 | "has_editor_variant": true,
9 | "vram_texture": false
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://addons/reblocks/ui/picker/categories/icons/physics.svg"
15 | dest_files=["res://.godot/imported/physics.svg-09ffe308a70b6e14c8f03dc392898be8.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=0
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=false
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=1
36 | svg/scale=1.0
37 | editor/scale_with_editor_scale=true
38 | editor/convert_colors_with_editor_theme=false
39 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/sounds.svg:
--------------------------------------------------------------------------------
1 |
2 |
28 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/sounds.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://81pkn6w7wkba"
6 | path="res://.godot/imported/sounds.svg-355a120001ae628f9afecc29c867f10a.ctex"
7 | metadata={
8 | "has_editor_variant": true,
9 | "vram_texture": false
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://addons/reblocks/ui/picker/categories/icons/sounds.svg"
15 | dest_files=["res://.godot/imported/sounds.svg-355a120001ae628f9afecc29c867f10a.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=0
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=false
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=1
36 | svg/scale=1.0
37 | editor/scale_with_editor_scale=true
38 | editor/convert_colors_with_editor_theme=false
39 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/transform.svg:
--------------------------------------------------------------------------------
1 |
2 |
27 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/transform.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://rkbwr5ea2npu"
6 | path="res://.godot/imported/transform.svg-baaec2023e58f087ed2c55b9e83048bf.ctex"
7 | metadata={
8 | "has_editor_variant": true,
9 | "vram_texture": false
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://addons/reblocks/ui/picker/categories/icons/transform.svg"
15 | dest_files=["res://.godot/imported/transform.svg-baaec2023e58f087ed2c55b9e83048bf.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=0
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=false
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=1
36 | svg/scale=1.0
37 | editor/scale_with_editor_scale=true
38 | editor/convert_colors_with_editor_theme=false
39 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/ui.svg:
--------------------------------------------------------------------------------
1 |
2 |
27 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/ui.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cpdpycplq4kmp"
6 | path="res://.godot/imported/ui.svg-166cb4713f750fb9cec115a1d0a692ca.ctex"
7 | metadata={
8 | "has_editor_variant": true,
9 | "vram_texture": false
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://addons/reblocks/ui/picker/categories/icons/ui.svg"
15 | dest_files=["res://.godot/imported/ui.svg-166cb4713f750fb9cec115a1d0a692ca.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=0
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=false
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=1
36 | svg/scale=1.0
37 | editor/scale_with_editor_scale=true
38 | editor/convert_colors_with_editor_theme=false
39 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/variables.svg:
--------------------------------------------------------------------------------
1 |
2 |
20 |
--------------------------------------------------------------------------------
/ui/picker/categories/icons/variables.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://c0nt5beum2fx"
6 | path="res://.godot/imported/variables.svg-3dba899b1f7db7e9d53b46e5901f191a.ctex"
7 | metadata={
8 | "has_editor_variant": true,
9 | "vram_texture": false
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://addons/reblocks/ui/picker/categories/icons/variables.svg"
15 | dest_files=["res://.godot/imported/variables.svg-3dba899b1f7db7e9d53b46e5901f191a.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=0
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=false
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=1
36 | svg/scale=1.0
37 | editor/scale_with_editor_scale=true
38 | editor/convert_colors_with_editor_theme=false
39 |
--------------------------------------------------------------------------------
/ui/picker/categories/variable_category/create_variable_button.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends MarginContainer
3 |
4 | signal create_variable(var_name: String, var_type: String)
5 |
6 | @onready var _create_variable_dialog := %CreateVariableDialog
7 | @onready var _create_button := %CreateButton
8 | @onready var _create_variable_icon = _create_button.get_theme_icon("Add", "EditorIcons")
9 |
10 |
11 | func _ready() -> void:
12 | _create_button.icon = _create_variable_icon
13 |
14 |
15 | func _on_create_button_pressed():
16 | _create_variable_dialog.popup()
17 |
18 |
19 | func _on_create_variable_dialog_create_variable(var_name, var_type):
20 | create_variable.emit(var_name, var_type)
21 |
--------------------------------------------------------------------------------
/ui/picker/categories/variable_category/create_variable_button.gd.uid:
--------------------------------------------------------------------------------
1 | uid://dkhckmafib5pb
2 |
--------------------------------------------------------------------------------
/ui/picker/categories/variable_category/create_variable_button.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://t0eoc4ekvjr1"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/ui/picker/categories/variable_category/create_variable_button.gd" id="1_cw6c3"]
4 | [ext_resource type="PackedScene" uid="uid://dbrm7wwkao0c0" path="res://addons/reblocks/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 | unique_name_in_owner = true
13 | layout_mode = 2
14 | theme_type_variation = &"InspectorActionButton"
15 | text = "Create New Variable"
16 |
17 | [node name="CreateVariableDialog" parent="." instance=ExtResource("2_udpg5")]
18 | unique_name_in_owner = true
19 | visible = false
20 |
21 | [connection signal="pressed" from="CreateButton" to="." method="_on_create_button_pressed"]
22 | [connection signal="create_variable" from="CreateVariableDialog" to="." method="_on_create_variable_dialog_create_variable"]
23 |
--------------------------------------------------------------------------------
/ui/picker/categories/variable_category/create_variable_dialog.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends ConfirmationDialog
3 |
4 | const BlockCodePlugin = preload("res://addons/reblocks/block_code_plugin.gd")
5 |
6 | signal create_variable(var_name: String, var_type: String)
7 |
8 | @onready var _context := BlockEditorContext.get_default()
9 |
10 | @onready var _variable_input := %VariableInput
11 | @onready var _type_option := %TypeOption
12 | @onready var _messages := %Messages
13 |
14 | const available_types = ["STRING", "BOOL", "INT", "FLOAT", "VECTOR2", "COLOR"]
15 |
16 |
17 | func _ready():
18 | _type_option.clear()
19 | _type_option.focus_next = get_cancel_button().get_path()
20 | get_cancel_button().focus_previous = _type_option.get_path()
21 | get_ok_button().focus_next = _variable_input.get_path()
22 | _variable_input.focus_previous = get_ok_button().get_path()
23 |
24 | for type in available_types:
25 | _type_option.add_item(type)
26 |
27 | _clear()
28 |
29 |
30 | func _clear():
31 | # Workaround for POT generation extracting empty string.
32 | _variable_input.text = str("")
33 | get_ok_button().disabled = check_errors(_variable_input.text)
34 | _type_option.select(0)
35 |
36 |
37 | func _on_variable_input_text_changed(new_text):
38 | get_ok_button().disabled = check_errors(new_text)
39 |
40 |
41 | func check_errors(new_var_name: String) -> bool:
42 | if new_var_name.contains(" "):
43 | var caret_column = _variable_input.caret_column
44 | new_var_name = new_var_name.replace(" ", "_")
45 | _variable_input.text = new_var_name
46 | _variable_input.caret_column = caret_column
47 |
48 | _messages.clear()
49 |
50 | var errors: Array = []
51 |
52 | if new_var_name == "":
53 | errors.append("Variable requires a name")
54 | elif new_var_name == "_":
55 | errors.append("Variable name cannot be a single underscore")
56 | elif RegEx.create_from_string("^[0-9]").search(new_var_name) != null:
57 | errors.append("Variable name cannot start with numbers")
58 |
59 | if new_var_name.begins_with("__"):
60 | errors.append("Variable name cannot start with two underscores")
61 |
62 | if RegEx.create_from_string("[^_a-zA-Z0-9-]+").search(new_var_name) != null:
63 | errors.append("Variable name cannot contain special characters")
64 |
65 | var duplicate_variable_name := false
66 | if _context.block_script:
67 | for variable in _context.block_script.variables:
68 | if variable.var_name == new_var_name:
69 | duplicate_variable_name = true
70 | break
71 |
72 | if duplicate_variable_name:
73 | errors.append("Variable already exists")
74 |
75 | if errors.is_empty():
76 | _messages.push_context()
77 | _messages.push_color(Color("73F27F"))
78 | _messages.push_list(0, RichTextLabel.LIST_DOTS, false)
79 |
80 | _messages.add_text("Will create new variable")
81 |
82 | _messages.pop_context()
83 |
84 | return false
85 | else:
86 | _messages.push_context()
87 | _messages.push_color(Color("FF786B"))
88 | _messages.push_list(0, RichTextLabel.LIST_DOTS, false)
89 |
90 | for error in errors:
91 | _messages.add_text(error)
92 | _messages.newline()
93 |
94 | _messages.pop_context()
95 |
96 | return true
97 |
98 |
99 | func _on_confirmed():
100 | if check_errors(_variable_input.text):
101 | return
102 |
103 | create_variable.emit(_variable_input.text, _type_option.get_item_text(_type_option.selected))
104 | hide()
105 | _clear()
106 |
107 |
108 | func _on_canceled():
109 | _clear()
110 |
111 |
112 | func _on_about_to_popup() -> void:
113 | _variable_input.grab_focus()
114 |
115 |
116 | func _on_focus_entered() -> void:
117 | _variable_input.grab_focus()
118 |
119 |
120 | func _on_variable_input_text_submitted(new_text: String) -> void:
121 | _on_confirmed()
122 |
--------------------------------------------------------------------------------
/ui/picker/categories/variable_category/create_variable_dialog.gd.uid:
--------------------------------------------------------------------------------
1 | uid://drrvypmfse801
2 |
--------------------------------------------------------------------------------
/ui/picker/categories/variable_category/create_variable_dialog.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=2 format=3 uid="uid://dbrm7wwkao0c0"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/ui/picker/categories/variable_category/create_variable_dialog.gd" id="1_b52me"]
4 |
5 | [node name="CreateVariableDialog" type="ConfirmationDialog"]
6 | title = "Create New Variable"
7 | initial_position = 1
8 | size = Vector2i(300, 183)
9 | visible = true
10 | ok_button_text = "Create"
11 | dialog_hide_on_ok = false
12 | script = ExtResource("1_b52me")
13 |
14 | [node name="VBoxContainer" type="VBoxContainer" parent="."]
15 | offset_left = 8.0
16 | offset_top = 8.0
17 | offset_right = 292.0
18 | offset_bottom = 134.0
19 |
20 | [node name="GridContainer" type="GridContainer" parent="VBoxContainer"]
21 | layout_mode = 2
22 | columns = 2
23 |
24 | [node name="Label" type="Label" parent="VBoxContainer/GridContainer"]
25 | layout_mode = 2
26 | text = "Name "
27 |
28 | [node name="VariableInput" type="LineEdit" parent="VBoxContainer/GridContainer"]
29 | unique_name_in_owner = true
30 | auto_translate_mode = 2
31 | layout_mode = 2
32 | focus_neighbor_bottom = NodePath("../TypeOption")
33 | focus_next = NodePath("../TypeOption")
34 |
35 | [node name="Label2" type="Label" parent="VBoxContainer/GridContainer"]
36 | layout_mode = 2
37 | text = "Type "
38 |
39 | [node name="TypeOption" type="OptionButton" parent="VBoxContainer/GridContainer"]
40 | unique_name_in_owner = true
41 | auto_translate_mode = 2
42 | layout_mode = 2
43 | size_flags_horizontal = 3
44 | focus_neighbor_top = NodePath("../VariableInput")
45 | focus_previous = NodePath("../VariableInput")
46 | selected = 0
47 | item_count = 6
48 | popup/item_0/text = "STRING"
49 | popup/item_0/id = 0
50 | popup/item_1/text = "BOOL"
51 | popup/item_1/id = 1
52 | popup/item_2/text = "INT"
53 | popup/item_2/id = 2
54 | popup/item_3/text = "FLOAT"
55 | popup/item_3/id = 3
56 | popup/item_4/text = "VECTOR2"
57 | popup/item_4/id = 4
58 | popup/item_5/text = "COLOR"
59 | popup/item_5/id = 5
60 |
61 | [node name="ErrorsContainer" type="MarginContainer" parent="VBoxContainer"]
62 | layout_mode = 2
63 | size_flags_vertical = 3
64 | theme_override_constants/margin_top = 8
65 |
66 | [node name="Messages" type="RichTextLabel" parent="VBoxContainer/ErrorsContainer"]
67 | unique_name_in_owner = true
68 | custom_minimum_size = Vector2(0, 48)
69 | layout_mode = 2
70 | theme_override_constants/line_separation = 4
71 | fit_content = true
72 |
73 | [connection signal="about_to_popup" from="." to="." method="_on_about_to_popup"]
74 | [connection signal="canceled" from="." to="." method="_on_canceled"]
75 | [connection signal="confirmed" from="." to="." method="_on_confirmed"]
76 | [connection signal="focus_entered" from="." to="." method="_on_focus_entered"]
77 | [connection signal="text_changed" from="VBoxContainer/GridContainer/VariableInput" to="." method="_on_variable_input_text_changed"]
78 | [connection signal="text_submitted" from="VBoxContainer/GridContainer/VariableInput" to="." method="_on_variable_input_text_submitted"]
79 |
--------------------------------------------------------------------------------
/ui/picker/categories/variable_category/variable_category_display.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends "res://addons/reblocks/ui/picker/categories/block_category_display.gd"
3 |
4 | const Types = preload("res://addons/reblocks/types/types.gd")
5 | const VariableDefinition = preload("res://addons/reblocks/code_generation/variable_definition.gd")
6 |
7 | @onready var h_separator := %HSeparator
8 |
9 | signal variable_created(variable: VariableDefinition)
10 |
11 |
12 | func _ready():
13 | super()
14 |
15 |
16 | func _update_blocks():
17 | super()
18 |
19 | if h_separator:
20 | h_separator.visible = not block_definitions.is_empty()
21 |
22 |
23 | func _on_create_variable(var_name, var_type):
24 | variable_created.emit(VariableDefinition.new(var_name, Types.STRING_TO_VARIANT_TYPE[var_type]))
25 |
--------------------------------------------------------------------------------
/ui/picker/categories/variable_category/variable_category_display.gd.uid:
--------------------------------------------------------------------------------
1 | uid://b31vdisxgqpxb
2 |
--------------------------------------------------------------------------------
/ui/picker/categories/variable_category/variable_category_display.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=5 format=3 uid="uid://byne4g2yvdf3"]
2 |
3 | [ext_resource type="PackedScene" uid="uid://duhpwtfo3k0sk" path="res://addons/reblocks/ui/picker/categories/block_category_display.tscn" id="1_vermd"]
4 | [ext_resource type="Script" path="res://addons/reblocks/ui/picker/categories/variable_category/variable_category_display.gd" id="2_ggvi7"]
5 | [ext_resource type="PackedScene" uid="uid://t0eoc4ekvjr1" path="res://addons/reblocks/ui/picker/categories/variable_category/create_variable_button.tscn" id="3_gjvnq"]
6 |
7 | [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_0m6vh"]
8 |
9 | [node name="VariableCategoryDisplay" instance=ExtResource("1_vermd")]
10 | script = ExtResource("2_ggvi7")
11 |
12 | [node name="BlocksContainer" parent="VBoxContainer" index="1"]
13 | visible = false
14 |
15 | [node name="HSeparator" type="HSeparator" parent="VBoxContainer" index="2"]
16 | unique_name_in_owner = true
17 | visible = false
18 | layout_mode = 2
19 | theme_override_constants/separation = 30
20 | theme_override_styles/separator = SubResource("StyleBoxEmpty_0m6vh")
21 |
22 | [node name="CreateVariableButton" parent="VBoxContainer" index="3" instance=ExtResource("3_gjvnq")]
23 | layout_mode = 2
24 |
25 | [connection signal="create_variable" from="VBoxContainer/CreateVariableButton" to="." method="_on_create_variable"]
26 |
--------------------------------------------------------------------------------
/ui/picker/picker.gd.uid:
--------------------------------------------------------------------------------
1 | uid://b8fhdn4gigy8y
2 |
--------------------------------------------------------------------------------
/ui/picker/picker.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=2 format=3 uid="uid://dlabt3bgmpna2"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/ui/picker/picker.gd" id="1_tkt44"]
4 |
5 | [node name="Picker" type="MarginContainer"]
6 | offset_right = 251.0
7 | offset_bottom = 253.0
8 | script = ExtResource("1_tkt44")
9 |
10 | [node name="Panel" type="Panel" parent="."]
11 | layout_mode = 2
12 |
13 | [node name="WidgetContainer" type="HBoxContainer" parent="."]
14 | unique_name_in_owner = true
15 | layout_mode = 2
16 | size_flags_vertical = 3
17 | theme_override_constants/separation = 0
18 |
19 | [node name="CategoryMarginContainer" type="MarginContainer" parent="WidgetContainer"]
20 | layout_mode = 2
21 | size_flags_horizontal = 0
22 | theme_override_constants/margin_left = 4
23 | theme_override_constants/margin_top = 4
24 | theme_override_constants/margin_right = 4
25 | theme_override_constants/margin_bottom = 4
26 |
27 | [node name="CategoryScroll" type="ScrollContainer" parent="WidgetContainer/CategoryMarginContainer"]
28 | layout_mode = 2
29 | horizontal_scroll_mode = 0
30 |
31 | [node name="CategoryList" type="VBoxContainer" parent="WidgetContainer/CategoryMarginContainer/CategoryScroll"]
32 | unique_name_in_owner = true
33 | layout_mode = 2
34 | theme_override_constants/separation = 10
35 |
36 | [node name="BlockMarginContainer" type="MarginContainer" parent="WidgetContainer"]
37 | layout_mode = 2
38 | size_flags_horizontal = 3
39 |
40 | [node name="BlockScroll" type="ScrollContainer" parent="WidgetContainer/BlockMarginContainer"]
41 | unique_name_in_owner = true
42 | custom_minimum_size = Vector2(250, 0)
43 | layout_mode = 2
44 | size_flags_horizontal = 3
45 | horizontal_scroll_mode = 3
46 |
47 | [node name="BlockList" type="VBoxContainer" parent="WidgetContainer/BlockMarginContainer/BlockScroll"]
48 | unique_name_in_owner = true
49 | layout_mode = 2
50 | theme_override_constants/separation = 0
51 |
--------------------------------------------------------------------------------
/ui/script_window/script_window.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends Window
3 |
4 | @onready var script_label: CodeEdit = $"PanelContainer/VBox/Code"
5 |
6 | var script_content: String = ""
7 |
8 |
9 | ## Attempts to match the syntax highlighting for some open script in the
10 | ## editor, which is more likely to be appropriate for the editor theme
11 | ## than our hardcoded default
12 | func _apply_editor_syntax_highlighter() -> void:
13 | var script_editor: ScriptEditor = EditorInterface.get_script_editor()
14 | for x in script_editor.get_open_script_editors():
15 | var control: Control = x.get_base_editor()
16 | if control is TextEdit:
17 | script_label.syntax_highlighter = control.syntax_highlighter
18 | break
19 |
20 |
21 | ## Undoes the effect of the CodeEdit being read-only
22 | func _remove_font_color_alpha_clamp() -> void:
23 | var font_readonly_color = script_label.get_theme_color("font_readonly_color")
24 | font_readonly_color.a = 1
25 | script_label.add_theme_color_override("font_readonly_color", font_readonly_color)
26 |
27 |
28 | func update_script(script: String) -> void:
29 | _apply_editor_syntax_highlighter()
30 | _remove_font_color_alpha_clamp()
31 | script_content = script
32 | script_label.text = script_content.replace("\t", " ")
33 |
34 |
35 | func _on_copy_code_pressed() -> void:
36 | DisplayServer.clipboard_set(script_content)
37 |
--------------------------------------------------------------------------------
/ui/script_window/script_window.gd.uid:
--------------------------------------------------------------------------------
1 | uid://drgxnv88f3jyj
2 |
--------------------------------------------------------------------------------
/ui/script_window/script_window.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://c5qmyjwv7gaxl"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/ui/script_window/script_window.gd" id="1_iw5ag"]
4 |
5 | [sub_resource type="SystemFont" id="SystemFont_r6ct2"]
6 | font_names = PackedStringArray("DejaVu Sans Mono")
7 | subpixel_positioning = 0
8 |
9 | [sub_resource type="SyntaxHighlighter" id="SyntaxHighlighter_0wnrb"]
10 |
11 | [node name="ScriptWindow" type="Window"]
12 | title = "Block Code Generated GDScript"
13 | initial_position = 1
14 | size = Vector2i(750, 750)
15 | transient = true
16 | script = ExtResource("1_iw5ag")
17 |
18 | [node name="PanelContainer" type="PanelContainer" parent="."]
19 | anchors_preset = 15
20 | anchor_right = 1.0
21 | anchor_bottom = 1.0
22 | grow_horizontal = 2
23 | grow_vertical = 2
24 |
25 | [node name="Panel" type="Panel" parent="PanelContainer"]
26 | layout_mode = 2
27 |
28 | [node name="VBox" type="VBoxContainer" parent="PanelContainer"]
29 | layout_mode = 2
30 |
31 | [node name="Code" type="CodeEdit" parent="PanelContainer/VBox"]
32 | unique_name_in_owner = true
33 | layout_mode = 2
34 | size_flags_vertical = 3
35 | theme_override_colors/font_readonly_color = Color(0.875, 0.875, 0.875, 1)
36 | theme_override_fonts/font = SubResource("SystemFont_r6ct2")
37 | editable = false
38 | syntax_highlighter = SubResource("SyntaxHighlighter_0wnrb")
39 | highlight_all_occurrences = true
40 | highlight_current_line = true
41 |
42 | [node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/VBox"]
43 | layout_mode = 2
44 |
45 | [node name="MarginContainer" type="MarginContainer" parent="PanelContainer/VBox/HBoxContainer"]
46 | layout_mode = 2
47 | size_flags_horizontal = 3
48 | theme_override_constants/margin_left = 3
49 | theme_override_constants/margin_right = 3
50 | theme_override_constants/margin_bottom = 3
51 |
52 | [node name="CopyCode" type="Button" parent="PanelContainer/VBox/HBoxContainer/MarginContainer"]
53 | layout_mode = 2
54 | size_flags_horizontal = 4
55 | text = "Copy"
56 |
57 | [connection signal="pressed" from="PanelContainer/VBox/HBoxContainer/MarginContainer/CopyCode" to="." method="_on_copy_code_pressed"]
58 |
--------------------------------------------------------------------------------
/ui/script_window/split_script_window.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends HBoxContainer
3 |
4 | signal script_window_opened
5 |
6 | @onready var script_label: CodeEdit = $"PanelContainer/CodeContainer/Code"
7 | @onready var window_button: Button = %WindowButton
8 | @onready var code_container: VBoxContainer = $"PanelContainer/CodeContainer"
9 |
10 | var script_content: String = ""
11 | var window_mode: bool = false
12 |
13 |
14 | ## Attempts to match the syntax highlighting for some open script in the
15 | ## editor, which is more likely to be appropriate for the editor theme
16 | ## than our hardcoded default
17 | func _apply_editor_syntax_highlighter() -> void:
18 | var script_editor: ScriptEditor = EditorInterface.get_script_editor()
19 | for x in script_editor.get_open_script_editors():
20 | var control: Control = x.get_base_editor()
21 | if control is TextEdit:
22 | script_label.syntax_highlighter = control.syntax_highlighter
23 | break
24 |
25 |
26 | ## Undoes the effect of the CodeEdit being read-only
27 | func _remove_font_color_alpha_clamp() -> void:
28 | var font_readonly_color = script_label.get_theme_color("font_readonly_color")
29 | font_readonly_color.a = 1
30 | script_label.add_theme_color_override("font_readonly_color", font_readonly_color)
31 |
32 |
33 | func update_script(script: String) -> void:
34 | _apply_editor_syntax_highlighter()
35 | _remove_font_color_alpha_clamp()
36 | script_content = script
37 | script_label.text = script_content.replace("\t", " ")
38 |
39 |
40 | func _on_copy_code_pressed() -> void:
41 | DisplayServer.clipboard_set(script_content)
42 |
43 |
44 | func _on_window_button_pressed() -> void:
45 | script_window_opened.emit()
46 |
--------------------------------------------------------------------------------
/ui/script_window/split_script_window.gd.uid:
--------------------------------------------------------------------------------
1 | uid://c1esa7mkimtjv
2 |
--------------------------------------------------------------------------------
/ui/script_window/split_script_window.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://c2tvodrmli2ar"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/ui/script_window/split_script_window.gd" id="1_pcqlh"]
4 |
5 | [sub_resource type="SystemFont" id="SystemFont_r6ct2"]
6 | font_names = PackedStringArray("DejaVu Sans Mono")
7 | subpixel_positioning = 0
8 |
9 | [sub_resource type="CodeHighlighter" id="CodeHighlighter_3qk2k"]
10 |
11 | [node name="SplitScriptWindow" type="HBoxContainer"]
12 | custom_minimum_size = Vector2(400, 0)
13 | anchors_preset = 6
14 | anchor_left = 1.0
15 | anchor_top = 0.5
16 | anchor_right = 1.0
17 | anchor_bottom = 0.5
18 | offset_left = -484.0
19 | offset_top = -323.0
20 | offset_bottom = 323.0
21 | grow_horizontal = 0
22 | grow_vertical = 2
23 | size_flags_horizontal = 8
24 | size_flags_vertical = 3
25 | script = ExtResource("1_pcqlh")
26 |
27 | [node name="PanelContainer" type="PanelContainer" parent="."]
28 | layout_mode = 2
29 | size_flags_horizontal = 3
30 |
31 | [node name="Panel" type="Panel" parent="PanelContainer"]
32 | layout_mode = 2
33 |
34 | [node name="CodeContainer" type="VBoxContainer" parent="PanelContainer"]
35 | unique_name_in_owner = true
36 | layout_mode = 2
37 |
38 | [node name="Code" type="CodeEdit" parent="PanelContainer/CodeContainer"]
39 | unique_name_in_owner = true
40 | layout_mode = 2
41 | size_flags_vertical = 3
42 | theme_override_colors/font_readonly_color = Color(0.875, 0.875, 0.875, 1)
43 | theme_override_fonts/font = SubResource("SystemFont_r6ct2")
44 | text = " "
45 | editable = false
46 | syntax_highlighter = SubResource("CodeHighlighter_3qk2k")
47 | highlight_all_occurrences = true
48 | highlight_current_line = true
49 | draw_tabs = true
50 |
51 | [node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/CodeContainer"]
52 | layout_mode = 2
53 |
54 | [node name="MarginContainer" type="MarginContainer" parent="PanelContainer/CodeContainer/HBoxContainer"]
55 | layout_mode = 2
56 | size_flags_horizontal = 3
57 | theme_override_constants/margin_left = 3
58 | theme_override_constants/margin_right = 3
59 | theme_override_constants/margin_bottom = 3
60 |
61 | [node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/CodeContainer/HBoxContainer/MarginContainer"]
62 | layout_mode = 2
63 |
64 | [node name="CopyCode" type="Button" parent="PanelContainer/CodeContainer/HBoxContainer/MarginContainer/HBoxContainer"]
65 | layout_mode = 2
66 | size_flags_horizontal = 6
67 | text = "Copy"
68 |
69 | [node name="WindowButton" type="Button" parent="PanelContainer/CodeContainer/HBoxContainer/MarginContainer/HBoxContainer"]
70 | unique_name_in_owner = true
71 | layout_mode = 2
72 | size_flags_horizontal = 6
73 | text = "Open Window"
74 |
75 | [connection signal="pressed" from="PanelContainer/CodeContainer/HBoxContainer/MarginContainer/HBoxContainer/CopyCode" to="." method="_on_copy_code_pressed"]
76 | [connection signal="pressed" from="PanelContainer/CodeContainer/HBoxContainer/MarginContainer/HBoxContainer/WindowButton" to="." method="_on_window_button_pressed"]
77 |
--------------------------------------------------------------------------------
/ui/title_bar/title_bar.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends MarginContainer
3 |
4 | const BlockCodePlugin = preload("res://addons/reblocks/block_code_plugin.gd")
5 |
6 | signal node_name_changed(node_name: String)
7 |
8 | @onready var _context := BlockEditorContext.get_default()
9 |
10 | @onready var _block_code_icon = load("res://addons/reblocks/block_code_node/block_code_node.svg") as Texture2D
11 | @onready var _editor_inspector: EditorInspector = EditorInterface.get_inspector()
12 | @onready var _node_option_button: OptionButton = %NodeOptionButton
13 |
14 |
15 | func _ready():
16 | _context.changed.connect(_on_context_changed)
17 | _node_option_button.connect("item_selected", _on_node_option_button_item_selected)
18 |
19 |
20 | func _on_context_changed():
21 | # TODO: We should listen for property changes in all BlockCode nodes and
22 | # their parents. As a workaround for the UI displaying stale data,
23 | # we'll crudely update the list of BlockCode nodes whenever the
24 | # selection changes.
25 |
26 | _update_node_option_button_items()
27 |
28 | var select_index = _get_block_script_index(_context.block_script)
29 | if _node_option_button.selected != select_index:
30 | _node_option_button.select(select_index)
31 |
32 |
33 | func _update_node_option_button_items():
34 | _node_option_button.clear()
35 |
36 | var scene_root = EditorInterface.get_edited_scene_root()
37 |
38 | if not scene_root:
39 | return
40 |
41 | for block_code in BlockCodePlugin.list_block_code_nodes_for_node(scene_root, true):
42 | if not BlockCodePlugin.is_block_code_editable(block_code):
43 | continue
44 |
45 | var node_item_index = _node_option_button.item_count
46 | var node_label = "{name} ({type})".format({"name": scene_root.get_path_to(block_code).get_concatenated_names(), "type": block_code.block_script.script_inherits})
47 | _node_option_button.add_item(node_label)
48 | _node_option_button.set_item_icon(node_item_index, _block_code_icon)
49 | _node_option_button.set_item_metadata(node_item_index, block_code)
50 |
51 | _node_option_button.disabled = _node_option_button.item_count == 0
52 |
53 |
54 | func _get_block_script_index(block_script: BlockScriptSerialization) -> int:
55 | for index in range(_node_option_button.item_count):
56 | var block_code_node = _node_option_button.get_item_metadata(index)
57 | if block_code_node.block_script == block_script:
58 | return index
59 | return -1
60 |
61 |
62 | func _on_node_option_button_item_selected(index):
63 | var block_code_node = _node_option_button.get_item_metadata(index) as BlockCode
64 | _context.block_code_node = block_code_node
65 |
--------------------------------------------------------------------------------
/ui/title_bar/title_bar.gd.uid:
--------------------------------------------------------------------------------
1 | uid://dv1v5haqk3u58
2 |
--------------------------------------------------------------------------------
/ui/title_bar/title_bar.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=2 format=3 uid="uid://bm1183pm05p6a"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/ui/title_bar/title_bar.gd" id="1_hpvmt"]
4 |
5 | [node name="TitleBar" type="MarginContainer"]
6 | custom_minimum_size = Vector2(0, 40)
7 | offset_right = 1000.0
8 | offset_bottom = 40.0
9 | script = ExtResource("1_hpvmt")
10 |
11 | [node name="Panel" type="Panel" parent="."]
12 | layout_mode = 2
13 |
14 | [node name="HBoxContainer" type="HBoxContainer" parent="."]
15 | layout_mode = 2
16 |
17 | [node name="NodeOptionButton" type="OptionButton" parent="HBoxContainer"]
18 | unique_name_in_owner = true
19 | layout_mode = 2
20 | size_flags_horizontal = 3
21 |
--------------------------------------------------------------------------------
/ui/tooltip/tooltip.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | class_name Tooltip
3 | extends RichTextLabel
4 | ## Rich-text control for block tooltips that matches the built-in inspector's tooltips' font styles
5 |
6 | const Util = preload("res://addons/reblocks/ui/util.gd")
7 |
8 |
9 | func override_font(font_name: StringName, editor_font_name: StringName) -> Font:
10 | var font = get_theme_font(editor_font_name, &"EditorFonts")
11 | add_theme_font_override(font_name, font)
12 | return font
13 |
14 |
15 | func override_fonts():
16 | # Set fonts to match documentation tooltips in inspector
17 | override_font(&"normal_font", &"doc")
18 | override_font(&"mono_font", &"doc_source")
19 | override_font(&"bold_font", &"doc_bold")
20 | var italics = override_font(&"italics_font", &"doc_italic")
21 |
22 | # No doc_ style for bold italic; fake it by emboldening the italic style
23 | var bold_italics = FontVariation.new()
24 | bold_italics.set_base_font(italics)
25 | bold_italics.set_variation_embolden(1.2)
26 | add_theme_font_override(&"bold_italics_font", bold_italics)
27 |
28 |
29 | func _ready():
30 | if not self.is_part_of_edited_scene():
31 | override_fonts()
32 |
--------------------------------------------------------------------------------
/ui/tooltip/tooltip.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cmjwydpocd766
2 |
--------------------------------------------------------------------------------
/ui/tooltip/tooltip.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=2 format=3 uid="uid://bmxco03vqyq2t"]
2 |
3 | [ext_resource type="Script" path="res://addons/reblocks/ui/tooltip/tooltip.gd" id="1_4ko6a"]
4 |
5 | [node name="Tooltip" type="RichTextLabel"]
6 | custom_minimum_size = Vector2(360, 48)
7 | anchors_preset = 15
8 | anchor_right = 1.0
9 | anchor_bottom = 1.0
10 | grow_horizontal = 2
11 | grow_vertical = 2
12 | bbcode_enabled = true
13 | fit_content = true
14 | script = ExtResource("1_4ko6a")
15 |
--------------------------------------------------------------------------------
/ui/util.gd:
--------------------------------------------------------------------------------
1 | extends Object
2 |
3 |
4 | ## Get the path from [param reference] to [param node] within a scene.
5 | ##
6 | ## Returns the path from [param reference] to [param node] without referencing
7 | ## parent nodes. If [param node] is [param reference] or a child of it in the
8 | ## scene tree, a relative path is returned. If [param node] is an ancestor of
9 | ## [param reference] in the scene tree, an absolute path using [param
10 | ## path_root] is returned.
11 | ## [br]
12 | ## Both [param node] and [param reference] must be ancestors of [param
13 | ## path_root]. If [param path_root] is [constant null]
14 | ## [method EditorInterface.get_edited_scene_root().get_parent] is used.
15 | static func node_scene_path(node: Node, reference: Node, path_root: Node = null) -> NodePath:
16 | if path_root == null:
17 | path_root = EditorInterface.get_edited_scene_root().get_parent()
18 |
19 | if not path_root.is_ancestor_of(node):
20 | push_error("Node %s is not an ancestor of %s" % [path_root, node])
21 | return NodePath()
22 | if not path_root.is_ancestor_of(reference):
23 | push_error("Node %s is not an ancestor of %s" % [path_root, reference])
24 | return NodePath()
25 |
26 | if node.unique_name_in_owner:
27 | # With unique_name_in_owner, just use the % prefixed name.
28 | return NodePath("%%%s" % node.name)
29 | else:
30 | # The node is reference or a child of it. Use a relative path.
31 | return reference.get_path_to(node)
32 |
--------------------------------------------------------------------------------
/ui/util.gd.uid:
--------------------------------------------------------------------------------
1 | uid://bdhv40hm0im1l
2 |
--------------------------------------------------------------------------------