└── addons
└── event_system_plugin
├── LICENSE
├── assets
├── icons
│ ├── event_icons
│ │ ├── call.svg
│ │ ├── call.svg.import
│ │ ├── condition.svg
│ │ ├── condition.svg.import
│ │ ├── custom.svg
│ │ ├── custom.svg.import
│ │ ├── emit_signal.svg
│ │ ├── emit_signal.svg.import
│ │ ├── goto.svg
│ │ ├── goto.svg.import
│ │ ├── hidden.png
│ │ ├── hidden.png.import
│ │ ├── label.svg
│ │ ├── label.svg.import
│ │ ├── outline.svg
│ │ ├── outline.svg.import
│ │ ├── set_value.svg
│ │ ├── set_value.svg.import
│ │ ├── solid.svg
│ │ ├── solid.svg.import
│ │ ├── visible.png
│ │ ├── visible.png.import
│ │ ├── wait.svg
│ │ └── wait.svg.import
│ ├── timeline_icon.png
│ ├── timeline_icon.png.import
│ ├── warning.svg
│ └── warning.svg.import
└── themes
│ ├── event_node
│ └── event_node.tres
│ ├── timeline_editor.tres
│ └── timeline_editor
│ └── timeline_editor_d.tres
├── core
├── event_inspector.gd
├── inspector_tools.gd
├── shortcuts.gd
└── utils.gd
├── events
├── call_from.gd
├── comment.gd
├── condition.gd
├── emit_signal.gd
├── end_timeline.gd
├── goto.gd
├── hide.gd
├── set.gd
├── show.gd
└── wait.gd
├── godot_plugin.gd
├── icon.png
├── icon.png.import
├── nodes
├── editor
│ ├── category_manager.gd
│ ├── event_node
│ │ ├── event_condition_node.gd
│ │ ├── event_node.gd
│ │ └── event_popup_menu.gd
│ ├── event_selector
│ │ ├── event_selector.gd
│ │ └── event_selector.tscn
│ ├── flow_container.gd
│ ├── playground
│ │ ├── event_manager_demo.tscn
│ │ └── in_game_editor.tscn
│ ├── subtimeline.gd
│ ├── timeline_displayer.gd
│ ├── timeline_drawer.gd
│ ├── timeline_editor.gd
│ ├── timeline_list.gd
│ └── welcome
│ │ ├── main_panel.gd
│ │ └── main_panel.tscn
└── event_manager
│ └── event_manager.gd
├── plugin.cfg
├── plugin_script.gd
└── resources
├── event_class
└── event_class.gd
├── registered_events
├── _.gd
└── registered_events.tres
└── timeline_class
└── timeline_class.gd
/addons/event_system_plugin/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 AnidemDex
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 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/call.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/call.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/call.svg-fcdd23d46a12116186f791edf9462815.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/event_system_plugin/assets/icons/event_icons/call.svg"
13 | dest_files=[ "res://.import/call.svg-fcdd23d46a12116186f791edf9462815.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/condition.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/condition.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/condition.svg-579187d50a8d87875312075e1a14293c.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/event_system_plugin/assets/icons/event_icons/condition.svg"
13 | dest_files=[ "res://.import/condition.svg-579187d50a8d87875312075e1a14293c.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/custom.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/custom.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/custom.svg-59e2fe8ffe62fc955b993462f3466265.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/event_system_plugin/assets/icons/event_icons/custom.svg"
13 | dest_files=[ "res://.import/custom.svg-59e2fe8ffe62fc955b993462f3466265.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/emit_signal.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/emit_signal.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/emit_signal.svg-f1e8e658a5abcf471929727d8464bbbe.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/event_system_plugin/assets/icons/event_icons/emit_signal.svg"
13 | dest_files=[ "res://.import/emit_signal.svg-f1e8e658a5abcf471929727d8464bbbe.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/goto.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/goto.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/goto.svg-cf34756d48e0fa3017e79ddc4f206c33.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/event_system_plugin/assets/icons/event_icons/goto.svg"
13 | dest_files=[ "res://.import/goto.svg-cf34756d48e0fa3017e79ddc4f206c33.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/hidden.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:22c7cb90e975f2affe859327a0220059c4addb863bdaa846298dd11752c29393
3 | size 350
4 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/hidden.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/hidden.png-da303d5e7240bd64d6960f6154b2d56a.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/event_system_plugin/assets/icons/event_icons/hidden.png"
13 | dest_files=[ "res://.import/hidden.png-da303d5e7240bd64d6960f6154b2d56a.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/label.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/label.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/label.svg-04a81bdfdbc5fd4b90f6b68a75c0e04e.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/event_system_plugin/assets/icons/event_icons/label.svg"
13 | dest_files=[ "res://.import/label.svg-04a81bdfdbc5fd4b90f6b68a75c0e04e.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/outline.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/outline.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/outline.svg-80b64523e937bd316725c9fce70a2da7.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/event_system_plugin/assets/icons/event_icons/outline.svg"
13 | dest_files=[ "res://.import/outline.svg-80b64523e937bd316725c9fce70a2da7.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/set_value.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/set_value.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/set_value.svg-96015dc53b42e43f938bbe0cb70a49c4.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/event_system_plugin/assets/icons/event_icons/set_value.svg"
13 | dest_files=[ "res://.import/set_value.svg-96015dc53b42e43f938bbe0cb70a49c4.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/solid.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/solid.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/solid.svg-1e2db139c93da3bfad4b54110345d3c0.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/event_system_plugin/assets/icons/event_icons/solid.svg"
13 | dest_files=[ "res://.import/solid.svg-1e2db139c93da3bfad4b54110345d3c0.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/visible.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:298df18f88878a09d39cdcd0d7c217249b853a87781c92ac73cc1283a69be0f2
3 | size 364
4 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/visible.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/visible.png-538e566050bb4faf2b8f2c1eff052afe.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/event_system_plugin/assets/icons/event_icons/visible.png"
13 | dest_files=[ "res://.import/visible.png-538e566050bb4faf2b8f2c1eff052afe.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/wait.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/event_icons/wait.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/wait.svg-1fc38f1e456deb8d5521fdfa9f9c5133.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/event_system_plugin/assets/icons/event_icons/wait.svg"
13 | dest_files=[ "res://.import/wait.svg-1fc38f1e456deb8d5521fdfa9f9c5133.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/timeline_icon.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:140dca20a9c1784f1e0b854219ff913380ed5f73c5f1f2cf02af654ab8dca3c0
3 | size 173
4 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/timeline_icon.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/timeline_icon.png-18a80ece71c9c4e87e5312d030cdeba2.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/event_system_plugin/assets/icons/timeline_icon.png"
13 | dest_files=[ "res://.import/timeline_icon.png-18a80ece71c9c4e87e5312d030cdeba2.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/warning.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/icons/warning.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/warning.svg-8a96b0f48377176c4d03aea4fefa1c18.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/event_system_plugin/assets/icons/warning.svg"
13 | dest_files=[ "res://.import/warning.svg-8a96b0f48377176c4d03aea4fefa1c18.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/themes/event_node/event_node.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Theme" load_steps=6 format=2]
2 |
3 | [sub_resource type="StyleBoxEmpty" id=5]
4 |
5 | [sub_resource type="StyleBoxFlat" id=2]
6 |
7 | [sub_resource type="StyleBoxFlat" id=3]
8 | content_margin_left = 8.0
9 | content_margin_right = 4.0
10 | content_margin_top = 4.0
11 | content_margin_bottom = 4.0
12 | corner_radius_top_left = 32
13 | corner_radius_bottom_left = 32
14 |
15 | [sub_resource type="StyleBoxFlat" id=4]
16 | content_margin_left = 12.0
17 | content_margin_right = 8.0
18 | content_margin_top = 4.0
19 | content_margin_bottom = 4.0
20 | corner_radius_top_right = 32
21 | corner_radius_bottom_right = 32
22 | shadow_offset = Vector2( 2, 0 )
23 |
24 | [sub_resource type="StyleBoxFlat" id=1]
25 | content_margin_left = 8.0
26 | content_margin_right = 8.0
27 | content_margin_top = 4.0
28 | content_margin_bottom = 4.0
29 | draw_center = false
30 | border_width_left = 2
31 | border_width_top = 2
32 | border_width_right = 2
33 | border_width_bottom = 2
34 | border_color = Color( 0.0980392, 0.113725, 0.156863, 1 )
35 | corner_radius_top_left = 16
36 | corner_radius_top_right = 16
37 | corner_radius_bottom_right = 16
38 | corner_radius_bottom_left = 16
39 |
40 | [resource]
41 | Button/styles/disabled = SubResource( 5 )
42 | Button/styles/focus = SubResource( 5 )
43 | Button/styles/hover = SubResource( 5 )
44 | Button/styles/normal = SubResource( 5 )
45 | Button/styles/pressed = SubResource( 5 )
46 | EventNode/colors/default = Color( 0.6, 0.6, 0.6, 1 )
47 | EventNode/colors/event = Color( 0.984314, 0.694118, 0.235294, 1 )
48 | EventNode/colors/hover = Color( 0.156863, 0.572549, 0.843137, 1 )
49 | EventNode/colors/outline = Color( 0.0980392, 0.113725, 0.156863, 1 )
50 | EventNode/styles/bg = SubResource( 2 )
51 | EventNode/styles/bg_left = SubResource( 3 )
52 | EventNode/styles/bg_right = SubResource( 4 )
53 | EventNode/styles/outline = SubResource( 1 )
54 | HBoxContainer/constants/separation = 0
55 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/themes/timeline_editor.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Theme" load_steps=19 format=2]
2 |
3 | [ext_resource path="res://addons/event_system_plugin/assets/icons/event_icons/outline.svg" type="Texture" id=1]
4 | [ext_resource path="res://addons/event_system_plugin/assets/icons/warning.svg" type="Texture" id=2]
5 | [ext_resource path="res://addons/event_system_plugin/assets/icons/event_icons/wait.svg" type="Texture" id=3]
6 | [ext_resource path="res://addons/event_system_plugin/assets/icons/event_icons/goto.svg" type="Texture" id=4]
7 | [ext_resource path="res://addons/event_system_plugin/assets/icons/event_icons/set_value.svg" type="Texture" id=5]
8 | [ext_resource path="res://addons/event_system_plugin/assets/icons/event_icons/emit_signal.svg" type="Texture" id=6]
9 | [ext_resource path="res://addons/event_system_plugin/assets/icons/event_icons/call.svg" type="Texture" id=7]
10 | [ext_resource path="res://addons/event_system_plugin/assets/icons/event_icons/condition.svg" type="Texture" id=9]
11 | [ext_resource path="res://addons/event_system_plugin/assets/icons/event_icons/label.svg" type="Texture" id=10]
12 | [ext_resource path="res://addons/event_system_plugin/assets/icons/event_icons/visible.png" type="Texture" id=11]
13 | [ext_resource path="res://addons/event_system_plugin/assets/icons/event_icons/hidden.png" type="Texture" id=12]
14 |
15 | [sub_resource type="StyleBoxFlat" id=6]
16 | bg_color = Color( 1, 1, 1, 1 )
17 | border_width_left = 1
18 | border_width_top = 1
19 | border_width_right = 1
20 | border_width_bottom = 1
21 | border_color = Color( 1, 1, 1, 0 )
22 | corner_radius_top_left = 4
23 | corner_radius_bottom_left = 4
24 |
25 | [sub_resource type="StyleBoxFlat" id=4]
26 | content_margin_right = 6.0
27 | draw_center = false
28 | border_width_left = 1
29 | border_width_top = 1
30 | border_width_right = 1
31 | border_width_bottom = 1
32 | border_color = Color( 0.0980392, 0.0980392, 0.0980392, 0.784314 )
33 | corner_radius_top_left = 4
34 | corner_radius_top_right = 4
35 | corner_radius_bottom_right = 4
36 | corner_radius_bottom_left = 4
37 |
38 | [sub_resource type="StyleBoxFlat" id=9]
39 | content_margin_top = 4.0
40 | content_margin_bottom = 4.0
41 | bg_color = Color( 0.509804, 0.509804, 0.509804, 0.207843 )
42 | border_color = Color( 1, 1, 1, 1 )
43 |
44 | [sub_resource type="StyleBoxFlat" id=1]
45 | content_margin_left = 8.0
46 | content_margin_right = 8.0
47 | content_margin_top = 4.0
48 | content_margin_bottom = 4.0
49 | draw_center = false
50 | border_width_left = 2
51 | border_width_top = 2
52 | border_width_right = 2
53 | border_width_bottom = 2
54 | border_color = Color( 0.0980392, 0.113725, 0.156863, 1 )
55 | corner_radius_top_left = 16
56 | corner_radius_top_right = 16
57 | corner_radius_bottom_right = 16
58 | corner_radius_bottom_left = 16
59 |
60 | [sub_resource type="StyleBoxFlat" id=10]
61 | bg_color = Color( 0.509804, 0.509804, 0.509804, 0.207843 )
62 | border_width_left = 5
63 | border_color = Color( 1, 1, 1, 1 )
64 |
65 | [sub_resource type="StyleBoxFlat" id=11]
66 | content_margin_left = 10.0
67 | content_margin_right = 10.0
68 | content_margin_top = 10.0
69 | content_margin_bottom = 10.0
70 | bg_color = Color( 0.2, 0.23, 0.31, 1 )
71 | border_width_left = 1
72 | border_width_top = 1
73 | border_width_right = 1
74 | border_width_bottom = 1
75 | border_color = Color( 0.8, 0.8, 0.8, 0.109804 )
76 | corner_radius_top_left = 4
77 | corner_radius_top_right = 4
78 | corner_radius_bottom_right = 4
79 | corner_radius_bottom_left = 4
80 |
81 | [sub_resource type="StyleBoxEmpty" id=7]
82 |
83 | [resource]
84 | EventButton/styles/border = SubResource( 6 )
85 | EventButton/styles/normal = SubResource( 4 )
86 | EventIcons/icons/call = ExtResource( 7 )
87 | EventIcons/icons/comment = ExtResource( 10 )
88 | EventIcons/icons/condition = ExtResource( 9 )
89 | EventIcons/icons/custom = ExtResource( 2 )
90 | EventIcons/icons/emit_signal = ExtResource( 6 )
91 | EventIcons/icons/go_to = ExtResource( 4 )
92 | EventIcons/icons/hide = ExtResource( 12 )
93 | EventIcons/icons/set = ExtResource( 5 )
94 | EventIcons/icons/show = ExtResource( 11 )
95 | EventIcons/icons/wait = ExtResource( 3 )
96 | EventNode/colors/default = Color( 0.6, 0.6, 0.6, 1 )
97 | EventNode/colors/event = Color( 0.984314, 0.694118, 0.235294, 1 )
98 | EventNode/colors/hover = Color( 0.156863, 0.572549, 0.843137, 1 )
99 | EventNode/colors/outline = Color( 0.0980392, 0.113725, 0.156863, 1 )
100 | EventNode/constants/indentation = 32
101 | EventNode/constants/margin_left = 6
102 | EventNode/icons/bg = ExtResource( 1 )
103 | EventNode/icons/checked = null
104 | EventNode/icons/unchecked = null
105 | EventNode/styles/hover = SubResource( 9 )
106 | EventNode/styles/outline = SubResource( 1 )
107 | EventNode/styles/pressed = SubResource( 10 )
108 | PopupMenu/styles/panel = SubResource( 11 )
109 | ToolButton/styles/focus = SubResource( 7 )
110 | VBoxContainer/constants/separation = 0
111 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/assets/themes/timeline_editor/timeline_editor_d.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Theme" load_steps=2 format=2]
2 |
3 | [sub_resource type="StyleBoxFlat" id=1]
4 | bg_color = Color( 0.14902, 0.172549, 0.231373, 1 )
5 | border_width_left = 1
6 | border_width_top = 1
7 | border_width_right = 1
8 | border_width_bottom = 1
9 | border_color = Color( 0.0980392, 0.113725, 0.156863, 1 )
10 | anti_aliasing = false
11 |
12 | [resource]
13 | ScrollContainer/styles/bg = SubResource( 1 )
14 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/core/event_inspector.gd:
--------------------------------------------------------------------------------
1 | extends EditorInspectorPlugin
2 |
3 | const InspectorTools = preload("res://addons/event_system_plugin/core/inspector_tools.gd")
4 |
5 | class EventInfo extends VBoxContainer:
6 | func _init():
7 | pass
8 | pass
9 |
10 | var EventClass = load("res://addons/event_system_plugin/resources/event_class/event_class.gd")
11 |
12 | var editor_gui:Control
13 |
14 | func can_handle(object: Object) -> bool:
15 | return object is EventClass
16 |
17 |
18 | func parse_category(object: Object, category: String) -> void:
19 | if category == "Script Variables":
20 | var category_node := InspectorTools.InspectorCategory.new()
21 | category_node.label = "Event [%s]"%str(object.get("event_name"))
22 | category_node.bg_color = object.get("event_color") as Color
23 | category_node.bg_color.a = 0.4
24 | category_node.hint_tooltip = object.get("event_hint")
25 | add_custom_control(category_node)
26 |
27 | var event_info
28 |
29 |
30 | func parse_property(object: Object, type: int, path: String, hint: int, hint_text: String, usage: int) -> bool:
31 | if object == null:
32 | return false
33 | var path_ignore = path+"_ignore"
34 | if (path_ignore in object):
35 | return true
36 |
37 | if path == "next_event":
38 | var node = InspectorTools.InspectorEventSelector.new()
39 | add_property_editor(path, node)
40 | return true
41 |
42 | return false
43 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/core/inspector_tools.gd:
--------------------------------------------------------------------------------
1 | tool
2 |
3 | class InspectorCategory extends Control:
4 | var icon:Texture
5 | var label:String
6 | var bg_color:Color = Color.black
7 |
8 | func _draw() -> void:
9 | draw_rect(Rect2(Vector2(), rect_size), bg_color)
10 |
11 | var font:Font = get_font("font", "Tree")
12 |
13 | var hs:int = get_constant("hseparation", "Tree");
14 | var w:int = font.get_string_size(label).x;
15 | if (icon):
16 | w += hs + icon.get_width();
17 |
18 | var ofs:int = (rect_size.x - w) / 2
19 |
20 | if (icon):
21 | draw_texture(icon, Vector2(ofs, (rect_size.y - icon.get_height()) / 2).floor())
22 | ofs += hs + icon.get_width();
23 |
24 | var color:Color = get_color("font_color", "Tree")
25 | draw_string(font, Vector2(ofs, font.get_ascent() + (rect_size.y - font.get_height()) / 2).floor(), label, color, rect_size.x);
26 |
27 | func _get_minimum_size() -> Vector2:
28 | var font:Font = get_font("font", "Tree")
29 |
30 | var ms:Vector2 = Vector2()
31 | ms.x = 1;
32 | ms.y = font.get_height()
33 | if icon:
34 | ms.y = max(icon.get_height(), ms.y);
35 | ms.y += get_constant("vseparation", "Tree");
36 |
37 | return ms;
38 |
39 | func _ready() -> void:
40 | var parent = get_parent()
41 | if is_instance_valid(parent):
42 | if get_position_in_parent() != 0:
43 | var category := parent.get_child(get_position_in_parent()-1) as Control
44 | category.hide()
45 |
46 | if icon == null:
47 | icon = get_icon("Object", "EditorIcons")
48 | update()
49 |
50 | if bg_color == Color.black:
51 | bg_color = get_color("prop_category", "Editor")
52 | update()
53 |
54 |
55 | class InspectorEventSelector extends EditorProperty:
56 | var event_selector:Button
57 | var popup:ConfirmationDialog
58 | var reset_button:Button
59 | var info_label:Label
60 | var updating:bool = false
61 | func _init() -> void:
62 | event_selector = Button.new()
63 | event_selector.text = "Select event"
64 | event_selector.connect("pressed",self,"_on_button_pressed")
65 | event_selector.size_flags_horizontal = SIZE_EXPAND_FILL
66 |
67 | reset_button = Button.new()
68 | reset_button.connect("pressed", self, "_on_reset_pressed")
69 |
70 | var hb = HBoxContainer.new()
71 | add_child(hb)
72 | hb.add_child(event_selector)
73 | hb.add_child(reset_button)
74 |
75 | popup = load("res://addons/event_system_plugin/nodes/editor/event_selector/event_selector.tscn").instance()
76 | popup.connect("event_selected", self, "_on_event_selected")
77 | add_child(popup)
78 |
79 | info_label = Label.new()
80 | info_label.size_flags_horizontal = SIZE_EXPAND_FILL
81 | info_label.align = Label.ALIGN_RIGHT
82 | add_child(info_label)
83 | set_bottom_editor(info_label)
84 |
85 |
86 | func _ready():
87 | reset_button.icon = get_icon("Remove", "EditorIcons")
88 | update_property()
89 |
90 |
91 | func update_property():
92 | var data:Array = str(get_edited_object()[get_edited_property()]).split(";", false)
93 | if data.empty():
94 | return
95 |
96 | var event_idx = data[0]
97 | var timeline_path = ""
98 | if data.size() >= 2:
99 | timeline_path = data[1]
100 |
101 | var timeline = null
102 | if timeline_path != "":
103 | var node = Engine.get_meta("EventSystem").timeline_editor._edited_node
104 | if is_instance_valid(node):
105 | timeline = node.get_timeline(timeline_path)
106 |
107 | if not timeline:
108 | timeline = Engine.get_meta("EventSystem").timeline_editor._edited_sequence
109 |
110 | if not timeline:
111 | return
112 |
113 | var event = timeline.get_event(int(event_idx))
114 | updating = true
115 |
116 | if event:
117 | event_selector.text = event.get("event_name")
118 | else:
119 | event_selector.text = "Select event"
120 |
121 | info_label.text = "On timeline: '{name}'".format({"name":timeline_path})
122 |
123 | updating = false
124 |
125 |
126 | func _on_button_pressed() -> void:
127 | var timeline = Engine.get_meta("EventSystem").timeline_editor._edited_sequence
128 | if timeline:
129 | popup.build_timeline(timeline)
130 | popup.call_deferred("popup_centered_ratio", 0.45)
131 |
132 |
133 | func _on_event_selected(event_idx, path) -> void:
134 | if updating:
135 | return
136 | var value = "{idx};{path}".format({"idx":event_idx, "path":path})
137 | emit_changed(get_edited_property(), value)
138 |
139 |
140 | func _on_reset_pressed() -> void:
141 | if updating:
142 | return
143 |
144 | emit_changed(get_edited_property(), "-1;")
145 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/core/shortcuts.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 |
3 | static func get_shortcut(property: String) -> ShortCut:
4 | var shortcut:ShortCut = ShortCut.new()
5 | match property:
6 | "duplicate":
7 | shortcut = null
8 | if Engine.editor_hint:
9 | var plugin = ClassDB.instance("EditorPlugin")
10 | var settings:EditorSettings = plugin.get_editor_interface().get_editor_settings()
11 | # shortcut = settings.get("scene_tree/duplicate") as ShortCut
12 | shortcut = null # We can't get shortcuts for now
13 | plugin.free()
14 |
15 | if shortcut == null:
16 | shortcut = ShortCut.new()
17 | var input := InputEventKey.new()
18 | input.scancode = KEY_D
19 | input.control = true
20 | input.pressed = true
21 | shortcut.shortcut = input
22 |
23 | "remove","delete":
24 | shortcut = null
25 |
26 | if Engine.editor_hint:
27 | var plugin = ClassDB.instance("EditorPlugin")
28 | var settings:EditorSettings = plugin.get_editor_interface().get_editor_settings()
29 | # shortcut = settings.get("scene_tree/delete") as ShortCut
30 | shortcut = null # we can't get shortcuts for now
31 | plugin.free()
32 |
33 | if shortcut == null:
34 | shortcut = ShortCut.new()
35 | var input := InputEventKey.new()
36 | input.scancode = KEY_DELETE
37 | input.pressed = true
38 | shortcut.shortcut = input
39 |
40 |
41 | return shortcut
42 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/core/utils.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 |
3 | ## Util function to get a dictionary of object property:value
4 | static func get_property_values_from(object:Object) -> Dictionary:
5 | if object == null:
6 | return {}
7 | var dict = {}
8 | # Hope this doesn't freeze the engine per call
9 | for property in object.get_property_list():
10 | dict[property.name] = object.get(property.name)
11 | return dict
12 |
13 |
14 | # Based on: https://www.askpython.com/python/built-in-methods/python-eval
15 | ## Evaluates an string, excecutes it and returns the result
16 | static func evaluate(input:String, global:Object=null, locals:Dictionary={}, _show_error:bool=true):
17 | var _evaluated_value = null
18 | var _expression = Expression.new()
19 |
20 | var _err = _expression.parse(input, PoolStringArray(locals.keys()))
21 |
22 | if _err != OK:
23 | push_warning(_expression.get_error_text())
24 | else:
25 | _evaluated_value = _expression.execute(locals.values(), global, _show_error)
26 |
27 | if _expression.has_execute_failed():
28 | return input
29 |
30 | return _evaluated_value
31 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/events/call_from.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Event
3 | class_name EventCall
4 |
5 | ## Makes a [code]call()[/code] to a method in a node with any number of arguments.
6 |
7 | export(String) var method:String = "" setget set_method
8 | export(Array) var args:Array = []
9 |
10 | func _init() -> void:
11 | event_color = Color("EB5E55")
12 | event_name = "Call"
13 | event_category = "Node"
14 | event_preview_string = "{event_node_path} {method} ( {args} ) "
15 |
16 | args = []
17 |
18 |
19 | func _execute() -> void:
20 | var node:Node = get_event_node()
21 |
22 | if node.has_method(method):
23 | node.callv(method, args)
24 |
25 | finish()
26 |
27 |
28 | func set_method(value:String) -> void:
29 | method = value
30 | emit_changed()
31 | property_list_changed_notify()
32 |
33 |
34 | func set_args(value:Array) -> void:
35 | args = value.duplicate()
36 | emit_changed()
37 | property_list_changed_notify()
38 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/events/comment.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Event
3 | class_name EventComment
4 |
5 | ## A single comment.
6 | ## It does nothing and can be used as a label point for Go To event.
7 |
8 | export(String, MULTILINE) var text:String = "" setget set_text
9 |
10 | func _init() -> void:
11 | event_name = "Comment"
12 | event_preview_string = "# {text}"
13 | event_hint = "Makes comment in the timeline.\nThis doesn't affects the timeline behaviour."
14 | event_color = Color("#3C3D5E")
15 | continue_at_end = true
16 |
17 |
18 | func _execute(_event_node=null) -> void:
19 | finish()
20 |
21 |
22 | func set_text(value:String) -> void:
23 | text = value
24 | property_list_changed_notify()
25 | emit_changed()
26 |
27 | func _get(property: String):
28 | if property == "continue_at_end_ignore":
29 | return true
30 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/events/condition.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Event
3 | class_name EventCondition
4 |
5 | ## Conditional event that executes true events if the evaluated [code]condition[/code]
6 | ##
7 | ## Works like if-statements. The [code]condition[/code] is evaluated according the
8 | ## assigned [code]event_node[/code]
9 |
10 | const _Utils = preload("res://addons/event_system_plugin/core/utils.gd")
11 |
12 | export(String) var condition:String = ""
13 |
14 | var next_event
15 |
16 | func _execute() -> void:
17 | var variables:Dictionary = _Utils.get_property_values_from(get_event_node())
18 |
19 | var evaluated_condition = _Utils.evaluate(condition, get_event_node(), variables)
20 |
21 | if evaluated_condition and (str(evaluated_condition) != condition):
22 | next_event
23 | else:
24 | next_event
25 |
26 | next_event = "0"
27 |
28 | finish()
29 |
30 |
31 | func _get(property: String):
32 | if property == "custom_event_node":
33 | return load("res://addons/event_system_plugin/nodes/editor/event_node/event_condition_node.gd").new()
34 |
35 |
36 | func _init() -> void:
37 | event_name = "Condition"
38 | event_color = Color("#FBB13C")
39 | event_preview_string = "[ {condition} ]:"
40 | event_hint = "Similar to if-else statement.\nEvaluates a condition and execute events accordingly."
41 | event_category = "Logic"
42 | continue_at_end = true
43 | event_uses_subevents = true
44 |
45 |
46 | func _get_property_list() -> Array:
47 | var p := []
48 |
49 | var usage:int = PROPERTY_USAGE_EDITOR
50 | usage |= PROPERTY_USAGE_STORAGE
51 | p.append({"name":"_events_if", "type":TYPE_OBJECT, "usage":usage})
52 |
53 | p.append({"name":"_events_else","type":TYPE_OBJECT, "usage":usage})
54 | return p
55 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/events/emit_signal.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Event
3 | class_name EventEmitSignal
4 |
5 | ## Makes EventManager emits [signal EventManager.custom_signal] with string value [code]data[/code].
6 |
7 | export(String) var data:String = "" setget _set_data
8 |
9 | func _init() -> void:
10 | event_name = "Emit Signal"
11 | event_color = Color("EB5E55")
12 | event_preview_string = "with [ '{data}' ] value"
13 | event_hint = "Emits EventManager 'custom_signal' with passed value as string"
14 | event_category = "Node"
15 |
16 | func _execute() -> void:
17 | get_event_manager_node().emit_signal("custom_signal", data)
18 | finish()
19 |
20 |
21 | func _set_data(value:String) -> void:
22 | data = value
23 | emit_changed()
24 | property_list_changed_notify()
25 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/events/end_timeline.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Event
3 |
4 | ## Ends the timeline execution.
5 |
6 | func _init() -> void:
7 | event_color = Color("EB5E55")
8 | event_name = "End Timeline"
9 | event_hint = "Terminates the execution of the timeline at this point"
10 |
11 |
12 | func _execute() -> void:
13 | get_event_manager_node().call("_notify_timeline_end")
14 | get_event_manager_node().set("current_timeline", "")
15 | finish()
16 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/events/goto.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Event
3 | class_name EventGoTo
4 |
5 | ## Makes EventManager execute the defined event in [code]next_event[/code] instead
6 | ## of the directly next one.
7 |
8 | # The next event hint of this event. ";"
9 | var next_event:String = "" setget set_next_event
10 |
11 | func _init() -> void:
12 | event_name = "Go to"
13 | event_color = Color("#FBB13C")
14 | event_preview_string = "event [{next_event}]"
15 | continue_at_end = true
16 | event_category = "Logic"
17 | event_hint = "Helper event to define the next event after this event"
18 |
19 | func set_next_event(value:String) -> void:
20 | next_event = value
21 | emit_changed()
22 | property_list_changed_notify()
23 |
24 |
25 | func _get(property):
26 | if property == "event_node_path_ignore":
27 | return true
28 | if property == "continue_at_end_ignore":
29 | return true
30 |
31 |
32 | func _get_property_list():
33 | var p := []
34 | p.append({"name":"next_event", "type":TYPE_STRING})
35 | return p
36 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/events/hide.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends "res://addons/event_system_plugin/events/call_from.gd"
3 | class_name EventHide
4 |
5 | ## Makes the [code]event_node[/code] be hidden if possible.
6 |
7 | func _init() -> void:
8 | event_color = Color("EB5E55")
9 | event_name = "Hide"
10 | event_category = "Node"
11 | method = "set"
12 | args = ["visible", false]
13 | event_preview_string = "{event_node_path}"
14 |
15 |
16 | func _get(property: String):
17 | if property == "method_ignore":
18 | return true
19 | if property == "args_ignore":
20 | return true
21 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/events/set.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends "res://addons/event_system_plugin/events/call_from.gd"
3 | class_name EventSet
4 |
5 | ## Sets [code]variable_name[/code] be [code]variable_value[/code] in [code]event_node[/code].
6 |
7 | export(String) var variable_name:String = "" setget set_var_name
8 | export(String) var variable_value:String = "" setget set_var_value
9 |
10 | func _init() -> void:
11 | event_name = "Set"
12 | event_category = "Node"
13 | event_color = Color("EB5E55")
14 | event_preview_string = "[ {variable_name} ] to be [ {variable_value} ]"
15 | continue_at_end = true
16 | method = "set"
17 | args = ["",""]
18 |
19 |
20 | func set_var_name(value:String) -> void:
21 | variable_name = value
22 | args[0] = variable_name
23 | emit_changed()
24 | property_list_changed_notify()
25 |
26 |
27 | func set_var_value(value:String) -> void:
28 | variable_value = value
29 | args[1] = variable_value
30 | emit_changed()
31 | property_list_changed_notify()
32 |
33 |
34 | func _get(property: String):
35 | if property == "continue_at_end_ignore":
36 | return true
37 | if property == "method_ignore":
38 | return true
39 | if property == "args_ignore":
40 | return true
41 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/events/show.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends "res://addons/event_system_plugin/events/call_from.gd"
3 | class_name EventShow
4 |
5 | ## Makes the [code]event_node[/code] be shown if possible.
6 |
7 | func _init() -> void:
8 | event_color = Color("EB5E55")
9 | event_name = "Show"
10 | event_category = "Node"
11 | method = "set"
12 | args = ["visible", true]
13 | event_preview_string = "{event_node_path}"
14 |
15 |
16 | func _get(property: String):
17 | if property == "method_ignore":
18 | return true
19 | if property == "args_ignore":
20 | return true
21 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/events/wait.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Event
3 | class_name EventWait
4 |
5 | ## Pauses the timeline execution by [code]wait_time[/code] seconds.
6 |
7 | export(float) var wait_time = 0.0 setget set_wait_time
8 |
9 | func _init():
10 | event_name = "Wait"
11 | event_color = Color("#FBB13C")
12 | event_category = "Logic"
13 | event_preview_string = "[{wait_time}] seconds before the next event."
14 |
15 |
16 | func _execute() -> void:
17 | var _timer = get_event_node().get_tree().create_timer(wait_time)
18 | _timer.connect("timeout", self, "finish")
19 |
20 |
21 | func set_wait_time(value:float) -> void:
22 | wait_time = value
23 | emit_changed()
24 | property_list_changed_notify()
25 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/godot_plugin.gd:
--------------------------------------------------------------------------------
1 | # MIT License
2 |
3 | # Copyright (c) 2022 AnidemDex
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 |
23 | # Take a look at the original repo to report issues or update script
24 | # https://github.com/AnidemDex/Godot-PluginTemplate
25 |
26 | tool
27 | extends EditorPlugin
28 |
29 | #####
30 | # Plugin classes
31 | #####
32 |
33 | class WelcomeNode extends WindowDialog:
34 |
35 | ##
36 | ## The node popup that appears when you call show_welcome_node()
37 | ##
38 |
39 | var _main_panel:TabContainer
40 | var _margin:MarginContainer
41 | var _menu:PopupMenu
42 |
43 | var _plugin_data:ConfigFile
44 |
45 | func _ready() -> void:
46 | add_stylebox_override("panel", get_stylebox("panel", "ProjectSettingsEditor"))
47 |
48 | _margin = MarginContainer.new()
49 | _margin.set_anchors_and_margins_preset(Control.PRESET_WIDE, Control.PRESET_MODE_KEEP_SIZE)
50 | _margin.add_constant_override("margin_top", 8)
51 | _margin.add_constant_override("margin_left", 2)
52 | _margin.add_constant_override("margin_right", 2)
53 | _margin.add_constant_override("margin_bottom", 16)
54 | add_child(_margin)
55 |
56 | _main_panel = TabContainer.new()
57 | _margin.add_child(_main_panel)
58 |
59 | _menu = PopupMenu.new()
60 | add_child(_menu)
61 | _main_panel.set_popup(_menu)
62 |
63 | add_tab("Information")
64 | add_tab("Plugin Info")
65 |
66 | var label = Label.new()
67 | label.text = "This plugin uses Plugin Template v%s"%__PLUGIN_VERSION
68 | add_child(label)
69 | label.set_anchors_and_margins_preset(Control.PRESET_BOTTOM_RIGHT)
70 | label.add_color_override("font_color", get_color("disabled_font_color", "Editor"))
71 |
72 | var plugin_information:VBoxContainer = get_tab_by_name("Plugin Info")
73 |
74 | if _plugin_data:
75 | var keys = _plugin_data.get_section_keys(__Constants.PLUGIN)
76 | for key in keys:
77 | var value = _plugin_data.get_value(__Constants.PLUGIN, key, "")
78 | var info_label := Label.new()
79 | info_label.text = "{key}: {value}".format({"key":key.capitalize(), "value":value})
80 | plugin_information.add_child(info_label)
81 |
82 |
83 | ## Adds a tab to welcome popup
84 | func add_tab(tab_name:String) -> void:
85 | var tab = VBoxContainer.new()
86 | tab.name = tab_name
87 | _main_panel.add_child(tab)
88 |
89 |
90 | ## Returns a Control node if find the node by its name
91 | func get_tab_by_name(tab_name) -> Control:
92 | var tab:Control = null
93 | for tab_idx in _main_panel.get_tab_count():
94 | var title = _main_panel.get_tab_title(tab_idx)
95 | if title == tab_name:
96 | tab = get_tab_by_idx(tab_idx)
97 | break
98 | return tab
99 |
100 |
101 | ## Returns a Control node if find the node by its index
102 | func get_tab_by_idx(tab_idx:int) -> Control:
103 | var tab:Control = _main_panel.get_tab_control(tab_idx)
104 | return tab
105 |
106 | ## Returns the TabContainer used by the node. DO NOT free it or you may cause
107 | ## issues with nodes that deppends on this node.
108 | func get_tab_container() -> TabContainer:
109 | return _main_panel
110 |
111 |
112 | ## Sets the data of the plugin using this node. Used internally
113 | func set_plugin_data(plugin_data:ConfigFile) -> void:
114 | _plugin_data = plugin_data
115 |
116 |
117 | #####
118 | # Plugin methods
119 | #####
120 |
121 | ## Returns true if the plugin is editable. Useful for debug.
122 | ## To enable it, add "editable=true" in plugin.cfg file under "plugin" section.
123 | func is_plugin_editable() -> bool:
124 | return __plugin_data.get_value(__Constants.PLUGIN, "editable", false)
125 |
126 |
127 | ## Returns the path of the script file
128 | func get_plugin_path() -> String:
129 | var script:Script = get_script() as Script
130 | var path:String = ""
131 | # No idea why this should return null but anyway...
132 | if script:
133 | path = script.resource_path
134 | return path
135 |
136 |
137 | ## Returns the path of the folder that contains the plugin script.
138 | func get_plugin_folder_path() -> String:
139 | var path:String = get_plugin_path()
140 | return path.get_base_dir()
141 |
142 |
143 | ## Returns the plugin's author.
144 | func get_plugin_author() -> String:
145 | return __plugin_data.get_value(__Constants.PLUGIN, __Constants.AUTHOR, "")
146 |
147 |
148 | ## Returns the plugin's version
149 | func get_plugin_version() -> String:
150 | return str(__plugin_data.get_value(__Constants.PLUGIN, __Constants.VERSION, ""))
151 |
152 |
153 | ## Returns the name of the plugin defined in plugin.cfg.
154 | func get_plugin_real_name() -> String:
155 | return __plugin_data.get_value(__Constants.PLUGIN, __Constants.NAME, "")
156 |
157 |
158 | ## Returns the plugin's description.
159 | func get_plugin_description() -> String:
160 | return __plugin_data.get_value(__Constants.PLUGIN, __Constants.DESCRIPTION, "")
161 |
162 |
163 | ## Returns the plugin's docs url. Defined in plugin.cfg as "docs" under plugin section.
164 | func get_plugin_docs_url() -> String:
165 | return __plugin_data.get_value(__Constants.PLUGIN, __Constants.DOCS, "")
166 |
167 |
168 | ## Returns the plugin's repository url. Defined in plugin.cfg as "repository" under plugin section.
169 | func get_plugin_repository() -> String:
170 | return __plugin_data.get_value(__Constants.PLUGIN, __Constants.REPOSITORY, "")
171 |
172 |
173 | ## Returns the plugin's license. This can be whatever the dev needs, from a URL to a simple string.
174 | ## Defined in plugin.cfg as "license" under plugin section.
175 | func get_plugin_license() -> String:
176 | return __plugin_data.get_value(__Constants.PLUGIN, __Constants.LICENSE, "")
177 |
178 |
179 | ## Returns the plugin configuration file. This is the equivalent data file readed from plugin.cfg.
180 | ## All the plugin data will be saved to plugin.cfg.
181 | func get_plugin_data() -> ConfigFile:
182 | return __plugin_data
183 |
184 |
185 | ## Returns the WelcomeNode popup used by the plugin.
186 | ## See WelcomeNode.
187 | func get_plugin_welcome_node() -> WelcomeNode:
188 | return __welcome_node
189 |
190 |
191 | ## Registers a node as a node that belongs to this plugin.
192 | ## The node will be automatically freed when the plugin gets removed.
193 | func register_plugin_node(node:Node) -> void:
194 | assert(node != null)
195 |
196 | assert(not node in __registered_nodes, "The node %s is already registered"%node)
197 | __registered_nodes.append(node)
198 |
199 |
200 | ## Alternative to add_control_to_dock().
201 | ## It registers a node as a node that belongs to this plugin and save its dock position
202 | ## even if the plugin is disabled.
203 | ## In order to save the node position in docks, you need to give it a name before register the node.
204 | func register_control_to_dock(control:Control, dock_slot:int = -1) -> void:
205 | assert(control != null)
206 |
207 | # Restore previously saved slot if exists
208 | var plugin_data:ConfigFile = get_plugin_data()
209 | if control.name != "":
210 | control.name = control.name.capitalize().replace(" ", "")
211 | if dock_slot < 0:
212 | var dock_slot_name:String = plugin_data.get_value(__Constants.DOCK, control.name, "DOCK_SLOT_LEFT_UL")
213 | dock_slot = ClassDB.class_get_integer_constant("EditorPlugin", dock_slot_name)
214 |
215 | register_plugin_node(control)
216 | add_control_to_dock(dock_slot, control)
217 |
218 | assert(not control in __nodes_in_dock, "The node %s is already in dock"%control)
219 | __nodes_in_dock.append(control)
220 |
221 |
222 | func register_editor_plugin(plugin:EditorInspectorPlugin) -> void:
223 | assert(not plugin in __registered_editor_plugins, "The plugin %s is already registered"%plugin)
224 | __registered_editor_plugins.append(plugin)
225 | add_inspector_plugin(plugin)
226 |
227 |
228 | ## Adds a node to the editor base control node.
229 | ## This is similar to do get_editor_interface().get_base_control().add_child()
230 | ## but it registers the node as a node that belongs to this plugin.
231 | func add_editor_node(node:Node) -> void:
232 | if not node in __registered_nodes:
233 | register_plugin_node(node)
234 |
235 | if not node.is_inside_tree():
236 | get_editor_interface().get_base_control().add_child(node)
237 |
238 |
239 | ## Shows the welcome node.
240 | func show_welcome_node() -> void:
241 | var welcome_node:Control = get_plugin_welcome_node()
242 | # For some reason, hot reload makes all childs be out of the tree
243 | if not welcome_node.is_inside_tree():
244 | add_editor_node(welcome_node)
245 | get_plugin_welcome_node().popup_centered_ratio(0.45)
246 |
247 |
248 | ## Shows the plugin version button.
249 | ## VersionButton will appear next to Editor's version button.
250 | func show_plugin_version_button() -> void:
251 | __version_button.show()
252 |
253 |
254 | ## Request, from another plugin, any method with variable number of arguments.
255 | ## `from_plugin` is plugin's name (defined with [get_plugin_name()] wich is the plugin real name
256 | ## by default.
257 | ## `method` is the method to call in the other plugin.
258 | ## `args` is an array that contains the arguments of the method call.
259 | ## This function only works with other plugins that uses PluginTemplate
260 | func request(from_plugin:String, method:String, args:=[]):
261 | var plugin:EditorPlugin = get_plugin_or_null(from_plugin)
262 | if plugin == null:
263 | return
264 |
265 | assert(plugin.has_method(method))
266 | if plugin.has_method(method):
267 | return plugin.callv(method, args)
268 |
269 |
270 | ## Gets another plugin with `plugin_name`.
271 | ## `plugin_name` is plugin's name (defined with [get_plugin_name()] wich is the plugin real name
272 | ## by default.
273 | ## This function only works with other plugins that uses PluginTemplate. Returns null if was unable
274 | ## to find the plugin.
275 | func get_plugin_or_null(plugin_name:String) -> EditorPlugin:
276 | if Engine.has_meta(plugin_name):
277 | return Engine.get_meta(plugin_name) as EditorPlugin
278 | return null
279 |
280 | ## Reloads plugin data from plugin.cfg
281 | func reload_plugin_data() -> void:
282 | var _err = __plugin_data.load(get_plugin_folder_path()+"/plugin.cfg")
283 | assert(_err == OK, "There was an error while loading plugin data: %s"%_err)
284 |
285 | ####
286 | # "Virtual" methods
287 | ####
288 |
289 | func _get_plugin_name() -> String:
290 | return get_plugin_real_name()
291 |
292 | func _get_state() -> Dictionary:
293 | var plugin_data:ConfigFile = get_plugin_data()
294 | var state = plugin_data.get_value("state", "plugin_state", {})
295 | return state
296 |
297 | #####
298 | # Virtual functions replaced with custom ones
299 | # Why? Because the template needs those **and** virtual methods
300 | # are usually marked with a _ prefix in Godot.
301 | # Ok but why all? Just in case I need to add different behaviours to those.
302 | #####
303 |
304 | func apply_changes() -> void:
305 | if has_method("_apply_changes"):
306 | call("_apply_changes")
307 |
308 |
309 | func build() -> bool:
310 | if has_method("_build"):
311 | return call("_build")
312 | return true
313 |
314 |
315 | func clear() -> void:
316 | if has_method("_clear"):
317 | call("_clear")
318 |
319 |
320 | func disable_plugin() -> void:
321 | if has_method("_disable_plugin"):
322 | call("_disable_plugin")
323 |
324 |
325 | func edit(object:Object) -> void:
326 | if has_method("_edit"):
327 | call("_edit", object)
328 |
329 |
330 | func enable_plugin() -> void:
331 | if has_method("_enable_plugin"):
332 | call("_enable_plugin")
333 |
334 |
335 | func forward_canvas_draw_over_viewport(overlay: Control) -> void:
336 | if has_method("_forward_canvas_draw_over_viewport"):
337 | call("_forward_canvas_draw_over_viewport", overlay)
338 |
339 |
340 | func forward_canvas_force_draw_over_viewport(overlay: Control) -> void:
341 | if has_method("_forward_canvas_force_draw_over_viewport"):
342 | call("_forward_canvas_force_draw_over_viewport", overlay)
343 |
344 |
345 | func forward_canvas_gui_input(event: InputEvent) -> bool:
346 | if has_method("_forward_canvas_gui_input"):
347 | return call("_forward_canvas_gui_input", event)
348 | return false
349 |
350 |
351 | func forward_spatial_draw_over_viewport(overlay: Control) -> void:
352 | if has_method("_forward_spatial_draw_over_viewport"):
353 | call("_forward_spatial_draw_over_viewport", overlay)
354 |
355 |
356 | func forward_spatial_force_draw_over_viewport(overlay: Control) -> void:
357 | if has_method("_forward_spatial_force_draw_over_viewport"):
358 | call("_forward_spatial_force_draw_over_viewport", overlay)
359 |
360 |
361 | func forward_spatial_gui_input(camera: Camera, event: InputEvent) -> bool:
362 | if has_method("_forward_spatial_gui_input"):
363 | return call("_forward_spatial_gui_input", camera, event)
364 | return false
365 |
366 |
367 | func get_breakpoints() -> PoolStringArray:
368 | if has_method("_get_breakpoints"):
369 | return call("_get_breakpoints")
370 | return PoolStringArray()
371 |
372 |
373 | func get_plugin_icon() -> Texture:
374 | if has_method("_get_plugin_icon"):
375 | return call("_get_plugin_icon")
376 | return get_editor_interface().get_base_control().get_icon("Node","EditorIcons")
377 |
378 |
379 | func get_plugin_name() -> String:
380 | return _get_plugin_name()
381 |
382 |
383 | func get_state() -> Dictionary:
384 | return _get_state()
385 |
386 |
387 | func get_window_layout(layout: ConfigFile) -> void:
388 | # This is called when you call queue_save_layout()
389 | # [docks]
390 | # dock_?_x where ? can be filesystem_* split or hsplit and x is an integer
391 | # [EditorNode]
392 | # open_scenes []
393 | # [ScriptEditor]
394 | # open_scripts [] Array of dicts
395 | # open_help [] PoolStringArray
396 | # split_offset
397 | var plugin_data:ConfigFile = get_plugin_data()
398 |
399 | if plugin_data.has_section(__Constants.DOCK):
400 | plugin_data.erase_section(__Constants.DOCK)
401 |
402 | var dock_nodes_names = []
403 | for node in __nodes_in_dock:
404 | dock_nodes_names.append(node.name)
405 |
406 | for key in layout.get_section_keys(__Constants.DOCK):
407 | key = str(key)
408 |
409 | # Avoid other docks properties
410 | if key.length()>6:
411 | continue
412 |
413 | var dock_slot:int = int(key[5])-1
414 | var c_enum = ClassDB.class_get_enum_constants("EditorPlugin", "DockSlot")
415 | var names:String = layout.get_value(__Constants.DOCK, key, "")
416 | var node_names := names.split(",")
417 | for node_name in node_names:
418 | if node_name in dock_nodes_names:
419 | plugin_data.set_value(__Constants.DOCK, node_name, c_enum[dock_slot])
420 |
421 | if has_method("_get_window_layout"):
422 | call("_get_window_layout", layout)
423 |
424 |
425 | func handles(object: Object) -> bool:
426 | if has_method("_handles"):
427 | return call("_handles", object)
428 | return false
429 |
430 |
431 | func has_main_screen() -> bool:
432 | if has_method("_has_main_screen"):
433 | return call("_has_main_screen")
434 | return false
435 |
436 |
437 | func make_visible(visible: bool) -> void:
438 | if has_method("_make_visible"):
439 | call("_make_visible", visible)
440 |
441 |
442 | func save_external_data() -> void:
443 | var plugin_data:ConfigFile = get_plugin_data()
444 |
445 | if __plugin_sensible_data_modified:
446 | var message = "'{plugin}' sensible data was modified. The plugin will be reloaded."
447 | var plugin_good_name = get_plugin_folder_path().split("/")[-1]
448 | message = message.format({"plugin":get_plugin_name()})
449 | OS.call_deferred("alert", message)
450 | get_editor_interface().call_deferred("set_plugin_enabled", plugin_good_name, false)
451 | get_editor_interface().call_deferred("set_plugin_enabled", plugin_good_name, true)
452 | var _err = plugin_data.save(get_plugin_folder_path()+"/plugin.cfg")
453 |
454 | if has_method("_save_external_data"):
455 | call("_save_external_data")
456 |
457 | assert(_err == OK, "There was a problem while saving plugin data: %s"%_err)
458 |
459 |
460 | func set_state(state: Dictionary) -> void:
461 | var plugin_data:ConfigFile = get_plugin_data()
462 | var key := __Constants.PLUGIN+"_"+__Constants.STATE
463 | plugin_data.set_value(__Constants.STATE, key, state)
464 | if has_method("_set_state"):
465 | call("_set_state", state)
466 |
467 |
468 | func set_window_layout(layout: ConfigFile) -> void:
469 | # This is called when the plugin was enabled while the editor is restoring its layout
470 | # see get_window_layout
471 | if has_method("_set_window_layout"):
472 | call("_set_window_layout", layout)
473 |
474 | #####
475 | # Godot methods
476 | #####
477 |
478 | func _enter_tree() -> void:
479 | add_editor_node(__welcome_node)
480 | __add_plugin_version_button()
481 |
482 |
483 | func _ready() -> void:
484 | __register_itself_on_editor()
485 | __register_plugin_template()
486 |
487 |
488 | func _exit_tree() -> void:
489 | __cleanup()
490 |
491 |
492 | func _set(property: String, value) -> bool:
493 | var plugin_data := get_plugin_data()
494 | var has_property := false
495 |
496 | for section in plugin_data.get_sections():
497 | if property.begins_with("plugin_"):
498 | property = property.replace("plugin_", "")
499 | __plugin_sensible_data_modified = true
500 | has_property = plugin_data.has_section_key(section, property)
501 | if has_property:
502 | plugin_data.set_value(section, property, value)
503 | if __plugin_sensible_data_modified:
504 | property_list_changed_notify()
505 | has_property = false # let default values go up
506 |
507 | return has_property
508 |
509 |
510 | func _get(property: String):
511 | var plugin_data := get_plugin_data()
512 | for section in plugin_data.get_sections():
513 | if property.begins_with("plugin_"):
514 | property = property.replace("plugin_", "")
515 | if plugin_data.has_section_key(section, property):
516 | return plugin_data.get_value(section, property, null)
517 |
518 |
519 | func _get_property_list() -> Array:
520 | var p := []
521 |
522 | for section in __plugin_data.get_sections():
523 | var pre := ""
524 | var _section:String = str(section)
525 |
526 | if _section == __Constants.PLUGIN:
527 | pre = _section+"_"
528 |
529 | p.append({"name":_section.capitalize(), "type":TYPE_NIL, "usage":PROPERTY_USAGE_CATEGORY})
530 |
531 | for key in __plugin_data.get_section_keys(section):
532 | var _key:String = str(key)
533 | var _value = __plugin_data.get_value(_section, _key)
534 | var _type:int = typeof(_value)
535 | var usage_hint := PROPERTY_USAGE_EDITOR
536 |
537 | if _section == __Constants.PLUGIN:
538 | usage_hint |= PROPERTY_USAGE_RESTART_IF_CHANGED
539 | if not is_plugin_editable():
540 | usage_hint = 0
541 |
542 | p.append({"name":pre+key, "type":_type, "usage":usage_hint})
543 | return p
544 |
545 |
546 | func _init() -> void:
547 | __registered_nodes = []
548 | __nodes_in_dock = []
549 |
550 | __plugin_data = ConfigFile.new()
551 | reload_plugin_data()
552 |
553 | name = get_plugin_name()
554 |
555 | __welcome_node = WelcomeNode.new()
556 | __welcome_node.set_plugin_data(__plugin_data)
557 | __welcome_node.window_title = get_plugin_name().capitalize()
558 | register_plugin_node(__welcome_node)
559 |
560 | __version_button = ToolButton.new()
561 | register_plugin_node(__version_button)
562 |
563 |
564 | #####
565 | # Private
566 | #####
567 |
568 | # what is an struct?
569 | class __Constants:
570 | const PLUGIN = "plugin"
571 | const VERSION = "version"
572 | const NAME = "name"
573 | const AUTHOR = "author"
574 | const SCRIPT = "script"
575 | const DESCRIPTION = "description"
576 | const DOCS = "docs"
577 | const REPOSITORY = "repository"
578 | const LICENSE = "license"
579 | const PLUGIN_TEMPLATE = "PluginTemplateHandler"
580 | const STATE = "state"
581 | const DOCK = "docks"
582 |
583 |
584 | class __Logger:
585 | # Future idea: make a logger using CassianoBelniak/katuiche-colorful-console
586 | # it has to be an static class available in the whole editor
587 | enum LogType {DEBUG, INFO, WARNING, ERROR}
588 |
589 |
590 | class __PluginTemplate extends EditorPlugin:
591 | class __NodeHandler extends EditorInspectorPlugin:
592 |
593 | var ignore_category = false
594 |
595 | func can_handle(object: Object) -> bool:
596 | return object is EditorPlugin
597 |
598 |
599 | func parse_begin(_object: Object) -> void:
600 | pass
601 |
602 |
603 | func parse_category(_object: Object, category: String) -> void:
604 | ignore_category = "Node" == category
605 |
606 |
607 | func parse_property(_object: Object, _type: int, _path: String, _hint: int, _hint_text: String, _usage: int) -> bool:
608 | if ignore_category:
609 | return true
610 | return false
611 |
612 |
613 | var node_handler := __NodeHandler.new()
614 |
615 | func _enter_tree() -> void:
616 | add_inspector_plugin(node_handler)
617 |
618 |
619 | func _ready() -> void:
620 | __register_itself_on_editor()
621 |
622 |
623 | func _exit_tree() -> void:
624 | remove_inspector_plugin(node_handler)
625 |
626 | # Copied from godot_plugin since we can't extend itself
627 | func __register_itself_on_editor() -> void:
628 | Engine.set_meta(__Constants.PLUGIN_TEMPLATE, self)
629 |
630 |
631 | const __PLUGIN_VERSION = 0.1
632 |
633 | var __plugin_data:ConfigFile
634 | var __welcome_node:WelcomeNode
635 | var __version_button:BaseButton
636 |
637 | var __registered_nodes:Array = []
638 | var __registered_editor_plugins:Array = []
639 | var __nodes_in_dock:Array = []
640 |
641 | var __plugin_sensible_data_modified:bool = false
642 |
643 | func __add_plugin_version_button() -> void:
644 | if __version_button.is_inside_tree():
645 | return
646 |
647 | var _v = {"version":get_plugin_version(), "plugin_name":get_plugin_name()}
648 |
649 | __version_button.set("text", "[{version}]".format(_v))
650 | __version_button.hint_tooltip = "{plugin_name} version {version}".format(_v)
651 | var _e = __version_button.connect("pressed", self, "__WelcomeButton_pressed")
652 |
653 | var _new_color = __version_button.get_color("font_color")
654 | _new_color.a = 0.6
655 | __version_button.add_color_override("font_color", _new_color)
656 | __version_button.size_flags_vertical = Control.SIZE_EXPAND_FILL
657 |
658 | var _dummy := Control.new()
659 | var _dock_button := add_control_to_bottom_panel(_dummy, "dummy")
660 | _dock_button.get_parent().get_parent().add_child(__version_button)
661 | _dock_button.get_parent().get_parent().move_child(__version_button, 1)
662 | remove_control_from_bottom_panel(_dummy)
663 | _dummy.free()
664 |
665 | __version_button.hide()
666 |
667 |
668 | func __request_configuration() -> void:
669 | if not is_instance_valid(get_editor_interface().get_edited_scene_root()):
670 | return
671 | get_editor_interface().inspect_object(self)
672 |
673 |
674 | func __register_itself_on_editor() -> void:
675 | # Technically we can use get_tree(), but I don't rely on tree order
676 | Engine.set_meta(get_plugin_name(), self)
677 | add_tool_menu_item(get_plugin_name(), self, "__ToolMenu_item_pressed")
678 | var _e = connect("tree_exiting", self, "remove_tool_menu_item", [get_plugin_name()])
679 |
680 |
681 | func __register_plugin_template() -> void:
682 | var plugin:EditorPlugin = get_plugin_or_null(__Constants.PLUGIN_TEMPLATE) as EditorPlugin
683 | if plugin != null:
684 | return
685 | plugin = __PluginTemplate.new()
686 | plugin.name = __Constants.PLUGIN_TEMPLATE
687 | get_parent().add_child(plugin)
688 |
689 |
690 | func __WelcomeButton_pressed() -> void:
691 | __request_configuration()
692 | show_welcome_node()
693 |
694 |
695 | func __ToolMenu_item_pressed(_d):
696 | __request_configuration()
697 | show_welcome_node()
698 |
699 |
700 | func __cleanup() -> void:
701 | queue_save_layout()
702 | for node in __registered_nodes:
703 | if not is_instance_valid(node):
704 | # For some reason is null???
705 | continue
706 |
707 | if node in __nodes_in_dock:
708 | remove_control_from_docks(node)
709 |
710 | node.free()
711 |
712 | for plugin in __registered_editor_plugins:
713 | plugin = plugin as EditorPlugin
714 | if not plugin:
715 | # why is this not a valid plugin???
716 | continue
717 | remove_inspector_plugin(plugin)
718 |
719 | __registered_nodes.clear()
720 | __nodes_in_dock.clear()
721 |
722 | save_external_data()
723 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/icon.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:1a444322a7d5f8a4e7e2e109299e3f2d68ab225030bfeeaa407d9f439993dff9
3 | size 5329
4 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/icon.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/icon.png-2cbbc86fe8426a381ba771f472ef31e5.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/event_system_plugin/icon.png"
13 | dest_files=[ "res://.import/icon.png-2cbbc86fe8426a381ba771f472ef31e5.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/nodes/editor/category_manager.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends PanelContainer
3 |
4 | const EventButtonNode = preload("res://addons/event_system_plugin/nodes/editor/event_node/event_node.gd")
5 | const EventClass = preload("res://addons/event_system_plugin/resources/event_class/event_class.gd")
6 | const TimelineClass = preload("res://addons/event_system_plugin/resources/timeline_class/timeline_class.gd")
7 |
8 | class EventButton extends PanelContainer:
9 | var event_script:Script
10 | var icon
11 | var text
12 |
13 | var button:ToolButton
14 | var border:PanelContainer
15 | var icon_node:TextureRect
16 | var spacer:Control
17 | var text_node:Label
18 |
19 | func get_drag_data(position):
20 | var node = EventButtonNode.new()
21 | node.event = event_script.new()
22 | node.call_deferred("update_values")
23 | set_drag_preview(node)
24 | return {"event":event_script.new()}
25 |
26 | func _ready():
27 | var dummy = event_script.new()
28 |
29 | if not text:
30 | text = dummy.get("event_name")
31 |
32 | if not icon:
33 | icon = dummy.get("event_icon")
34 |
35 | text_node.text = text
36 | icon_node.texture = icon
37 | hint_tooltip = "%s" % dummy.get("event_hint")
38 |
39 | var style := get_stylebox("border", "EventButton").duplicate()
40 | style.set("bg_color", dummy.get("event_color"))
41 |
42 | border.add_stylebox_override("panel", style)
43 | add_stylebox_override("panel", get_stylebox("normal", "EventButton"))
44 |
45 |
46 | func _init():
47 | rect_clip_content = true
48 | size_flags_vertical = SIZE_EXPAND_FILL
49 |
50 | button = ToolButton.new()
51 | button.show_behind_parent = true
52 | button.mouse_filter = Control.MOUSE_FILTER_PASS
53 | add_child(button)
54 |
55 | icon_node = TextureRect.new()
56 | icon_node.expand = true
57 | icon_node.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
58 | icon_node.focus_mode = Control.FOCUS_NONE
59 | icon_node.mouse_filter = Control.MOUSE_FILTER_IGNORE
60 | var scale:float = 1
61 | if Engine.editor_hint:
62 | var plugin:EditorPlugin = EditorPlugin.new()
63 | scale = plugin.get_editor_interface().get_editor_scale()
64 | plugin.free()
65 | icon_node.rect_min_size = Vector2(24,24) * scale
66 |
67 | text_node = Label.new()
68 | text_node.focus_mode = Control.FOCUS_NONE
69 | text_node.mouse_filter = Control.MOUSE_FILTER_IGNORE
70 |
71 | border = PanelContainer.new()
72 | border.focus_mode = Control.FOCUS_NONE
73 | border.mouse_filter = Control.MOUSE_FILTER_IGNORE
74 | border.rect_min_size.x = 4
75 |
76 | spacer = Control.new()
77 | spacer.focus_mode = Control.FOCUS_NONE
78 | spacer.mouse_filter = Control.MOUSE_FILTER_IGNORE
79 | spacer.rect_min_size = Vector2(2, 0)
80 |
81 | var hb := HBoxContainer.new()
82 | hb.size_flags_horizontal = SIZE_EXPAND_FILL
83 | hb.focus_mode = Control.FOCUS_NONE
84 | hb.mouse_filter = Control.MOUSE_FILTER_IGNORE
85 | hb.add_constant_override("separation", 0)
86 | hb.add_child(border)
87 | hb.add_child(icon_node)
88 | hb.add_child(spacer)
89 | hb.add_child(text_node)
90 |
91 | add_child(hb)
92 |
93 |
94 | class Category extends VBoxContainer:
95 | const FlowContainer = preload("res://addons/event_system_plugin/nodes/editor/flow_container.gd")
96 |
97 | signal event_button_added(button)
98 |
99 | var name_label:Label
100 | var event_scripts:Array = []
101 | var button_container:FlowContainer
102 |
103 | func add_event(event) -> void:
104 | var event_script:Script = event.get_script()
105 | if event_script in event_scripts:
106 | return
107 |
108 | event_scripts.append(event_script)
109 |
110 | var btn := EventButton.new()
111 | btn.event_script = event_script
112 | # btn.icon_node.texture = event.event_icon
113 | # btn.text_node.text = event.get("event_name")
114 | # var event_hint := "{event_name}\n-----\n{event_hint}"
115 | # btn.hint_tooltip = event_hint.format({"event_name":event.get("event_name"), "event_hint":event.get("event_hint")})
116 | button_container.add_child(btn)
117 | btn.add_color_override("font_color", get_color("font_color", "Editor"))
118 | btn.add_color_override("font_color_hover", get_color("accent_color", "Editor"))
119 | emit_signal("event_button_added", btn)
120 |
121 |
122 | func _set(property, value) -> bool:
123 | if property == "name":
124 | name = value
125 | name_label.text = value
126 | return true
127 | return false
128 |
129 |
130 | func _init():
131 | event_scripts = []
132 | name_label = Label.new()
133 | name_label.align = Label.ALIGN_CENTER
134 | var separator = HSeparator.new()
135 | separator.size_flags_horizontal = SIZE_EXPAND_FILL
136 | var hb = HBoxContainer.new()
137 | hb.size_flags_horizontal = SIZE_EXPAND_FILL
138 | hb.add_child(name_label)
139 | hb.add_child(separator)
140 | add_child(hb)
141 |
142 | button_container = FlowContainer.new()
143 | button_container.hseparation = 2
144 | button_container.vseparation = 1
145 | add_child(button_container)
146 |
147 |
148 | signal toolbar_button_pressed(button, event_script)
149 |
150 | var know_events:TimelineClass
151 | var categories:Dictionary = {}
152 |
153 | var _category_container:VBoxContainer
154 |
155 | func reload() -> void:
156 | categories.clear()
157 |
158 | for child in _category_container.get_children():
159 | child.queue_free()
160 |
161 | create_categories()
162 |
163 |
164 | func create_categories() -> void:
165 | for event in know_events.get_events():
166 | event = event as EventClass
167 | if not event:
168 | continue
169 |
170 | var category:String = event.event_category
171 | add_category(category)
172 |
173 | var category_node:Category = categories.get(category, null)
174 | category_node.add_event(event)
175 |
176 |
177 | func add_category(category_name:String) -> void:
178 | if category_name in categories:
179 | return
180 |
181 | var category:Category = Category.new()
182 | categories[category_name] = category
183 |
184 | category.connect("event_button_added", self, "_on_Category_event_button_added")
185 | category.name = category_name
186 | _category_container.add_child(category)
187 |
188 |
189 | func _enter_tree():
190 | know_events = load("res://addons/event_system_plugin/resources/registered_events/registered_events.tres")
191 |
192 | if not know_events.is_connected("changed",self,"reload"):
193 | know_events.connect("changed",self,"reload")
194 |
195 |
196 | func _on_Category_event_button_added(event_button:EventButton) -> void:
197 | event_button.button.connect("pressed", self, "_on_Category_event_button_pressed", [event_button])
198 |
199 |
200 | func _on_Category_event_button_pressed(event_button:EventButton) -> void:
201 | emit_signal("toolbar_button_pressed", event_button, event_button.event_script)
202 |
203 |
204 | func _notification(what: int) -> void:
205 | if what == NOTIFICATION_POST_ENTER_TREE:
206 | know_events.emit_changed()
207 |
208 |
209 | func _init():
210 | categories = {}
211 | name = "CategoryManager"
212 | size_flags_vertical = SIZE_EXPAND_FILL
213 | rect_min_size = Vector2(128, 64)
214 |
215 | var _sc = ScrollContainer.new()
216 | _sc.size_flags_horizontal = SIZE_EXPAND_FILL
217 | _sc.size_flags_vertical = SIZE_EXPAND_FILL
218 | add_child(_sc)
219 |
220 | _category_container = VBoxContainer.new()
221 | _category_container.size_flags_horizontal = SIZE_EXPAND_FILL
222 | _category_container.size_flags_vertical = SIZE_EXPAND_FILL
223 | _sc.add_child(_category_container)
224 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/nodes/editor/event_node/event_condition_node.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends "res://addons/event_system_plugin/nodes/editor/event_node/event_node.gd"
3 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/nodes/editor/event_node/event_node.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends HBoxContainer
3 |
4 | const EventClass = preload("res://addons/event_system_plugin/resources/event_class/event_class.gd")
5 | const TimelineClass = preload("res://addons/event_system_plugin/resources/timeline_class/timeline_class.gd")
6 | const Utils = preload("res://addons/event_system_plugin/core/utils.gd")
7 |
8 | var event_button:Button
9 |
10 | ## Event related to this node
11 | var event:EventClass setget set_event
12 |
13 | ## Timeline that contains this event. Used as editor hint
14 | var timeline:TimelineClass
15 | var idx:int setget set_idx
16 |
17 | # Background
18 | var __bg:PanelContainer
19 | var __indent_node:Control
20 | var __header:HBoxContainer
21 | var __body:MarginContainer
22 | var __icon_container:PanelContainer
23 | var __icon_node:TextureRect
24 | var __event_label:Label
25 | var __event_preview_label:Label
26 | var __expand_button:CheckButton
27 |
28 | func update_values() -> void:
29 | __update_event_icon()
30 | __update_event_name()
31 | __update_preview_hint()
32 | __update_identation()
33 |
34 | if has_method("_update_values"):
35 | call("_update_values")
36 |
37 |
38 | func add_node_at_header(node:Control) -> void:
39 | __header.get_child(1).add_child(node)
40 |
41 |
42 | func add_node_at_body(node:Control) -> void:
43 | __expand_button.visible = true
44 | __body.get_child(0).add_child(node)
45 |
46 |
47 | func set_event(_event) -> void:
48 | if event and event.is_connected("changed",self,"update_values"):
49 | event.disconnect("changed",self,"update_values")
50 |
51 | event = _event
52 |
53 | if event != null:
54 | if not event.is_connected("changed",self,"update_values"):
55 | event.connect("changed",self,"update_values")
56 | name = event.event_name
57 |
58 |
59 | func set_idx(value:int) -> void:
60 | idx = value
61 |
62 |
63 | func set_indentation_level(level:int) -> void:
64 | if !is_instance_valid(__indent_node):
65 | return
66 | level = max(level, 0)
67 | __indent_node.rect_min_size.x = get_constant("indentation", "EventNode") * level
68 |
69 |
70 | func set_button_group(button_group:ButtonGroup) -> void:
71 | event_button.set_button_group(button_group)
72 |
73 |
74 | func _on_event_button_toggled(toggled:bool) -> void:
75 | var color:Color = Color.white
76 | var icon_color:Color = color
77 | if toggled:
78 | color = Color.cyan if not Engine.editor_hint else get_color("accent_color", "Editor")
79 | if event:
80 | icon_color = event.event_color
81 |
82 | event_button.self_modulate = color
83 | __icon_container.self_modulate = icon_color
84 |
85 |
86 |
87 | func _on_expand_toggled(toggled:bool) -> void:
88 | __body.visible = toggled
89 |
90 |
91 | func __update_event_name() -> void:
92 | var text := "{Event Name}"
93 | if event:
94 | text = event.event_name
95 | __event_label.text = text
96 |
97 |
98 | func __update_event_icon() -> void:
99 | var icon:Texture = get_icon("warning", "EditorIcons")
100 | var color:Color = get_color("")
101 | if event:
102 | icon = event.event_icon
103 |
104 | __icon_node.texture = icon
105 |
106 |
107 | func __update_preview_hint() -> void:
108 | var text:String = ""
109 |
110 | if event:
111 | text = event.event_preview_string
112 |
113 | if "next_event" in text:
114 | text = text.replace("next_event", "__next_event__")
115 |
116 | text = text.format(Utils.get_property_values_from(event))
117 | if "next_event" in event:
118 | var data = str(event.get("next_event")).split(";", false, 1)
119 | var next_idx = -1
120 | var event_name = "???"
121 | var timeline_name = ""
122 | var hint_string = "{event_name}"
123 | var used_timeline = timeline
124 |
125 | if data.size() >= 1:
126 | next_idx = int(data[0])
127 | if data.size() >= 2:
128 | timeline_name = str(data[1])
129 | hint_string += " from {timeline_name}"
130 | if is_instance_valid(Engine.get_meta("EventSystem").timeline_editor._edited_node):
131 | used_timeline = Engine.get_meta("EventSystem").timeline_editor._edited_node.get_timeline(timeline_name)
132 |
133 | if used_timeline.get_event(next_idx):
134 | event_name = used_timeline.get("event/"+str(next_idx)).resource_name
135 |
136 | hint_string = hint_string.format({"event_name":event_name, "timeline_name":timeline_name})
137 | text = text.format({"__next_event__":hint_string})
138 |
139 |
140 | __event_preview_label.text = text
141 |
142 |
143 | func __update_identation() -> void:
144 | var indentation_level:int = 0
145 | if event:
146 | indentation_level = event.event_indent_level
147 | set_indentation_level(indentation_level)
148 |
149 |
150 | func _notification(what):
151 | match what:
152 | NOTIFICATION_THEME_CHANGED, NOTIFICATION_ENTER_TREE:
153 | var none := StyleBoxEmpty.new()
154 | event_button.add_stylebox_override("normal", none)
155 | event_button.add_stylebox_override("hover", get_stylebox("hover", "EventNode"))
156 | event_button.add_stylebox_override("pressed", get_stylebox("pressed", "EventNode"))
157 | event_button.add_stylebox_override("focus", get_stylebox("hover", "EventNode"))
158 |
159 | __header.get_child(0).set_deferred("rect_min_size", Vector2(get_constant("margin_left", "EventNode"),0))
160 |
161 | var icon_bg = StyleBoxTexture.new()
162 | icon_bg.texture = get_icon("bg", "EventNode")
163 | __icon_container.add_stylebox_override("panel", icon_bg)
164 |
165 | __expand_button.add_icon_override("off", get_icon("unchecked", "EventNode"))
166 | __expand_button.add_icon_override("on", get_icon("checked", "EventNode"))
167 |
168 | __body.add_constant_override("margin_left", 50)
169 |
170 | var style = StyleBoxEmpty.new()
171 | style.content_margin_bottom = 3
172 | __bg.add_stylebox_override("panel", style)
173 |
174 |
175 | func _init():
176 | name = "EventNode"
177 | size_flags_horizontal = SIZE_EXPAND_FILL
178 | rect_clip_content = true
179 |
180 | __indent_node = Control.new()
181 |
182 | __bg = PanelContainer.new()
183 | __bg.focus_mode = Control.FOCUS_NONE
184 | __bg.mouse_filter = Control.MOUSE_FILTER_IGNORE
185 | __bg.size_flags_horizontal = SIZE_EXPAND_FILL
186 |
187 | event_button = Button.new()
188 | event_button.toggle_mode = true
189 | event_button.focus_mode = Control.FOCUS_ALL
190 | event_button.mouse_filter = Control.MOUSE_FILTER_PASS
191 | event_button.name = "UIBehaviour"
192 | event_button.set_meta("event_node", self)
193 | event_button.connect("toggled", self, "_on_event_button_toggled")
194 |
195 | var vb = VBoxContainer.new()
196 | vb.focus_mode = Control.FOCUS_NONE
197 | vb.mouse_filter = Control.MOUSE_FILTER_IGNORE
198 |
199 | __header = HBoxContainer.new()
200 | __header.name = "Header"
201 | __header.focus_mode = Control.FOCUS_NONE
202 | __header.mouse_filter = Control.MOUSE_FILTER_IGNORE
203 |
204 | __body = MarginContainer.new()
205 | __body.name = "Body"
206 | __body.focus_mode = Control.FOCUS_NONE
207 | __body.mouse_filter = Control.MOUSE_FILTER_IGNORE
208 |
209 | __expand_button = CheckButton.new()
210 | __expand_button.visible = false
211 | __expand_button.connect("toggled", self, "_on_expand_toggled")
212 | __expand_button.set_pressed_no_signal(true)
213 |
214 | __icon_container = PanelContainer.new()
215 | __icon_node = TextureRect.new()
216 | __icon_node.name = "Icon"
217 | __icon_node.expand = true
218 | __icon_node.rect_min_size = Vector2(32,32)
219 | __icon_node.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
220 | __icon_container.add_child(__icon_node)
221 |
222 | __event_label = Label.new()
223 | __event_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
224 | __event_label.focus_mode = Control.FOCUS_NONE
225 |
226 | __event_preview_label = Label.new()
227 | __event_preview_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
228 | __event_preview_label.focus_mode = Control.FOCUS_NONE
229 |
230 | var c := Control.new()
231 | c.focus_mode = Control.FOCUS_NONE
232 | c.mouse_filter = Control.MOUSE_FILTER_IGNORE
233 | __header.add_child(c)
234 |
235 | var hb := HBoxContainer.new()
236 | hb.focus_mode = Control.FOCUS_NONE
237 | hb.mouse_filter = Control.MOUSE_FILTER_IGNORE
238 | __header.add_child(hb)
239 | __header.add_child(__expand_button)
240 |
241 | __body.add_child(VBoxContainer.new())
242 |
243 | vb.add_child(__header)
244 | vb.add_child(__body)
245 |
246 | __bg.add_child(event_button)
247 | __bg.add_child(vb)
248 |
249 | add_child(__indent_node)
250 | add_child(__bg)
251 |
252 | add_node_at_header(__icon_container)
253 | add_node_at_header(__event_label)
254 | # add_node_at_header(VSeparator.new())
255 | add_node_at_header(__event_preview_label)
256 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/nodes/editor/event_node/event_popup_menu.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends PopupMenu
3 |
4 | ## This serves as a builder for the popup menu
5 | ## Its behaviour is inside the timeline editor, since
6 | ## this node doesn't need its context at all.
7 |
8 | # ItemType and item generation have a 1:1 relationship
9 | # Use get_item_index(ItemType) to get the idx of that item
10 | enum ItemType {
11 | TITLE,
12 | EDIT,
13 | DUPLICATE,
14 | REMOVE,
15 | HELP,
16 | MOVE_UP,
17 | MOVE_DOWN,
18 | }
19 |
20 | var used_event:Resource setget set_event
21 | var shortcuts = load("res://addons/event_system_plugin/core/shortcuts.gd")
22 |
23 | func _enter_tree() -> void:
24 | var remove_shortcut = shortcuts.get_shortcut("remove")
25 | var duplicate_shortcut = shortcuts.get_shortcut("duplicate")
26 |
27 | add_separator("{EventName}", ItemType.TITLE)
28 | add_icon_item(get_icon("Edit", "EditorIcons"), "Edit in Inspector", ItemType.EDIT)
29 |
30 | add_shortcut(duplicate_shortcut, ItemType.DUPLICATE)
31 | set_item_icon(get_item_index(ItemType.DUPLICATE), get_icon("ActionCopy", "EditorIcons"))
32 | set_item_text(get_item_index(ItemType.DUPLICATE), "Duplicate")
33 |
34 | add_shortcut(remove_shortcut, ItemType.REMOVE)
35 | set_item_icon(get_item_index(ItemType.REMOVE), get_icon("Remove", "EditorIcons"))
36 | set_item_text(get_item_index(ItemType.REMOVE), "Remove")
37 |
38 |
39 | add_icon_item(get_icon("Help", "EditorIcons"), "Documentation", ItemType.HELP)
40 | add_separator()
41 | add_icon_item(get_icon("ArrowUp", "EditorIcons"), "Move up", ItemType.MOVE_UP)
42 | add_icon_item(get_icon("ArrowDown", "EditorIcons"), "Move down", ItemType.MOVE_DOWN)
43 |
44 | get_stylebox("panel").set("bg_color", get_color("base_color", "Editor"))
45 | add_color_override('font_color_hover', get_color("accent_color", "Editor"))
46 | add_stylebox_override('hover', StyleBoxEmpty.new())
47 |
48 |
49 | func set_title(title:String) -> void:
50 | set_item_text(get_item_index(ItemType.TITLE), title)
51 |
52 |
53 | func set_event(event:Resource) -> void:
54 | used_event = event
55 | var event_name:String = "{EventName}"
56 | if used_event:
57 | event_name = str(used_event.get("event_name"))
58 | set_title(event_name)
59 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/nodes/editor/event_selector/event_selector.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends ConfirmationDialog
3 |
4 | signal event_selected(event, timeline_path)
5 |
6 | const TimelineDisplayer = preload("res://addons/event_system_plugin/nodes/editor/timeline_displayer.gd")
7 | const TimelineList = preload("res://addons/event_system_plugin/nodes/editor/timeline_list.gd")
8 | const TimelineClass = preload("res://addons/event_system_plugin/resources/timeline_class/timeline_class.gd")
9 | const EvManager = preload("res://addons/event_system_plugin/nodes/event_manager/event_manager.gd")
10 |
11 | export(NodePath) var displayer_path:NodePath
12 | export(NodePath) var list_path:NodePath
13 | onready var timeline_displayer:TimelineDisplayer = get_node(displayer_path) as TimelineDisplayer
14 | onready var timeline_list:TimelineList = get_node(list_path) as TimelineList
15 |
16 | var last_selected_item:Node = null
17 | var timeline_name:String = ""
18 | var button_group = ButtonGroup.new()
19 | var edited_node:EvManager
20 | var edited_timeline:TimelineClass
21 | var event_summoner:Resource = null
22 |
23 | func _notification(what):
24 | match what:
25 | NOTIFICATION_POPUP_HIDE:
26 | if not visible:
27 | set_deferred("timeline_name", "")
28 | set_deferred("used_timeline", null)
29 |
30 | NOTIFICATION_POST_POPUP:
31 | if Engine.editor_hint:
32 | edited_node = Engine.get_meta("EventSystem").timeline_editor._edited_node
33 | edited_timeline = Engine.get_meta("EventSystem").timeline_editor._edited_sequence
34 |
35 | timeline_list.node = edited_node
36 | timeline_list.list_timelines()
37 | build_timeline(edited_timeline)
38 |
39 | NOTIFICATION_POST_ENTER_TREE:
40 | theme = load("res://addons/event_system_plugin/assets/themes/timeline_editor.tres")
41 |
42 |
43 | func _ready() -> void:
44 | timeline_displayer.connect("event_node_added", self, "_on_event_node_added")
45 | button_group.connect("pressed", self, "_on_event_node_pressed")
46 | timeline_list.connect("item_selected", self, "_timeline_selected")
47 |
48 |
49 | func build_timeline(timeline) -> void:
50 | edited_timeline = timeline
51 | timeline_displayer.load_timeline(timeline)
52 |
53 |
54 | func get_selected_event() -> Resource:
55 | var selected_event:Resource
56 |
57 | if is_instance_valid(last_selected_item):
58 | selected_event = last_selected_item.get("event")
59 |
60 | return selected_event
61 |
62 |
63 | func _get_current() -> String:
64 | var current:String = ""
65 | var selected_id:int = timeline_list.get_selected_id()
66 |
67 | if selected_id >= 0 && selected_id < timeline_list.get_item_count():
68 | current = timeline_list.get_item_text(selected_id)
69 |
70 | return current
71 |
72 |
73 | func _timeline_selected(_index:int) -> void:
74 | var current := _get_current()
75 |
76 | if current != "":
77 | var timeline = edited_node.get_timeline(current)
78 | build_timeline(timeline)
79 |
80 |
81 | func _on_event_node_added(event_node) -> void:
82 | event_node.set_button_group(button_group)
83 |
84 |
85 | func _on_event_node_pressed(button:Button) -> void:
86 | last_selected_item = button.get_meta("event_node")
87 |
88 |
89 | func _on_ConfirmationDialog_confirmed():
90 | var event = get_selected_event()
91 | var event_idx = edited_timeline.get_event_idx(event)
92 | var current_timeline = _get_current()
93 |
94 | emit_signal("event_selected", event_idx, current_timeline)
95 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/nodes/editor/event_selector/event_selector.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=5 format=2]
2 |
3 | [ext_resource path="res://addons/event_system_plugin/nodes/editor/event_selector/event_selector.gd" type="Script" id=1]
4 | [ext_resource path="res://addons/event_system_plugin/nodes/editor/timeline_list.gd" type="Script" id=2]
5 | [ext_resource path="res://addons/event_system_plugin/nodes/editor/timeline_displayer.gd" type="Script" id=3]
6 | [ext_resource path="res://addons/event_system_plugin/assets/themes/timeline_editor.tres" type="Theme" id=4]
7 |
8 | [node name="ConfirmationDialog" type="ConfirmationDialog"]
9 | anchor_right = 1.0
10 | anchor_bottom = 1.0
11 | rect_min_size = Vector2( 150, 52.5 )
12 | theme = ExtResource( 4 )
13 | window_title = "Event Selector"
14 | script = ExtResource( 1 )
15 | __meta__ = {
16 | "_edit_use_anchors_": false
17 | }
18 | displayer_path = NodePath("VBoxContainer/ScrollContainer/TimelineDisplayer")
19 | list_path = NodePath("VBoxContainer/HBoxContainer/OptionButton")
20 |
21 | [node name="VBoxContainer" type="VBoxContainer" parent="."]
22 | anchor_right = 1.0
23 | anchor_bottom = 1.0
24 | margin_left = 8.0
25 | margin_top = 8.0
26 | margin_right = -8.0
27 | margin_bottom = -36.0
28 | __meta__ = {
29 | "_edit_use_anchors_": false
30 | }
31 |
32 | [node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"]
33 | margin_right = 1008.0
34 | margin_bottom = 20.0
35 |
36 | [node name="Label" type="Label" parent="VBoxContainer/HBoxContainer"]
37 | margin_top = 3.0
38 | margin_right = 152.0
39 | margin_bottom = 17.0
40 | text = "Please, select an event:"
41 |
42 | [node name="OptionButton" type="OptionButton" parent="VBoxContainer/HBoxContainer"]
43 | margin_left = 156.0
44 | margin_right = 1008.0
45 | margin_bottom = 20.0
46 | size_flags_horizontal = 3
47 | script = ExtResource( 2 )
48 | __meta__ = {
49 | "_edit_use_anchors_": false
50 | }
51 |
52 | [node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer"]
53 | margin_top = 24.0
54 | margin_right = 1008.0
55 | margin_bottom = 556.0
56 | size_flags_vertical = 3
57 |
58 | [node name="TimelineDisplayer" type="VBoxContainer" parent="VBoxContainer/ScrollContainer"]
59 | margin_right = 1008.0
60 | margin_bottom = 532.0
61 | rect_min_size = Vector2( 128, 32 )
62 | size_flags_horizontal = 3
63 | size_flags_vertical = 3
64 | script = ExtResource( 3 )
65 |
66 | [connection signal="confirmed" from="." to="." method="_on_ConfirmationDialog_confirmed"]
67 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/nodes/editor/flow_container.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Container
3 |
4 | class _LineData:
5 | var child_count:int = 0
6 | var min_line_height:int = 0
7 | var min_line_length:int = 0
8 | var stretch_avail:int = 0
9 | var stretch_ratio_total:float = 0
10 |
11 | export(int) var hseparation = 1 setget set_h_separation
12 | export(int) var vseparation = 1 setget set_v_separation
13 | export(bool) var vertical:bool = false
14 |
15 | var cached_size:int = 0
16 | var cached_line_count:int = 0
17 |
18 |
19 | func set_h_separation(value:int) -> void:
20 | hseparation = value
21 | add_constant_override("hseparation", value)
22 | property_list_changed_notify()
23 | queue_sort()
24 |
25 |
26 | func set_v_separation(value:int) -> void:
27 | vseparation = value
28 | add_constant_override("vseparation", value)
29 | property_list_changed_notify()
30 | queue_sort()
31 |
32 |
33 | func _resort() -> void:
34 | var separation_horizontal:int = get_constant("hseparation")
35 | var separation_vertical:int = get_constant("vseparation")
36 |
37 | # Not implemented in 3.4
38 | # var rtl = is_layout_rtl()
39 | var rtl = false
40 |
41 | var children_minsize_cache = {}
42 |
43 | var lines_data = []
44 |
45 | var ofs:Vector2;
46 | var line_height:int = 0;
47 | var line_length:int = 0;
48 | var line_stretch_ratio_total:float = 0;
49 | var current_container_size:int = get_rect().size.y if vertical else get_rect().size.x
50 | var children_in_current_line:int = 0
51 |
52 | # First pass for line wrapping and minimum size calculation.
53 | for i in get_child_count():
54 | var child:Control = get_child(i) as Control
55 | if (!child or !child.is_visible_in_tree()):
56 | continue
57 |
58 | if (child.is_set_as_toplevel()):
59 | continue
60 |
61 | var child_msc:Vector2 = child.get_combined_minimum_size()
62 |
63 | if (vertical): # /* Vertical */
64 | if (children_in_current_line > 0):
65 | ofs.y += separation_vertical;
66 |
67 | if (ofs.y + child_msc.y > current_container_size):
68 | line_length = ofs.y - separation_vertical;
69 | var line_data = _LineData.new()
70 | line_data.child_count = children_in_current_line
71 | line_data.min_line_height = line_height
72 | line_data.min_line_length = line_length
73 | line_data.stretch_avail = current_container_size - line_length
74 | line_data.stretch_ratio_total = line_stretch_ratio_total
75 | lines_data.push_back(line_data)
76 |
77 | # Move in new column (vertical line).
78 | ofs.x += line_height + separation_horizontal;
79 | ofs.y = 0;
80 | line_height = 0;
81 | line_stretch_ratio_total = 0;
82 | children_in_current_line = 0;
83 |
84 | line_height = max(line_height, child_msc.x);
85 | if (child.get_v_size_flags() & SIZE_EXPAND):
86 | line_stretch_ratio_total += child.get_stretch_ratio()
87 |
88 | ofs.y += child_msc.y;
89 |
90 | else: # /* HORIZONTAL */
91 | if (children_in_current_line > 0):
92 | ofs.x += separation_horizontal
93 |
94 | if (ofs.x + child_msc.x > current_container_size):
95 | line_length = ofs.x - separation_horizontal;
96 | var line_data = _LineData.new()
97 | line_data.child_count = children_in_current_line
98 | line_data.min_line_height = line_height
99 | line_data.min_line_length = line_length
100 | line_data.stretch_avail = current_container_size - line_length
101 | line_data.stretch_ratio_total = line_stretch_ratio_total
102 | lines_data.push_back(line_data)
103 |
104 | # Move in new line.
105 | ofs.y += line_height + separation_vertical;
106 | ofs.x = 0;
107 | line_height = 0;
108 | line_stretch_ratio_total = 0;
109 | children_in_current_line = 0;
110 |
111 |
112 | line_height = max(line_height, child_msc.y);
113 | if (child.get_h_size_flags() & SIZE_EXPAND):
114 | line_stretch_ratio_total += child.get_stretch_ratio()
115 |
116 | ofs.x += child_msc.x
117 |
118 | children_minsize_cache[child] = child_msc;
119 | children_in_current_line += 1
120 |
121 | line_length = (ofs.y) if vertical else (ofs.x)
122 |
123 | var ld:_LineData = _LineData.new()
124 | ld.child_count = children_in_current_line
125 | ld.min_line_length = line_height
126 | ld.min_line_length = line_length
127 | ld.stretch_avail = current_container_size - line_length
128 | ld.stretch_ratio_total = line_stretch_ratio_total
129 | lines_data.push_back(ld)
130 |
131 | # Second pass for in-line expansion and alignment.
132 |
133 | var current_line_idx = 0
134 | var child_idx_in_line = 0
135 |
136 | ofs.x = 0
137 | ofs.y = 0
138 |
139 | for i in get_child_count():
140 | var child:Control = get_child(i) as Control
141 | if (!child or !child.is_visible_in_tree()):
142 | continue
143 |
144 | if (child.is_set_as_toplevel()):
145 | continue
146 |
147 | var child_size:Vector2 = children_minsize_cache[child];
148 |
149 | var line_data:_LineData = lines_data[current_line_idx]
150 | if (child_idx_in_line >= lines_data[current_line_idx].child_count):
151 | current_line_idx += 1;
152 | child_idx_in_line = 0;
153 | if (vertical):
154 | ofs.x += line_data.min_line_height + separation_horizontal
155 | ofs.y = 0
156 | else:
157 | ofs.x = 0
158 | ofs.y += line_data.min_line_height + separation_vertical
159 |
160 | line_data = lines_data[current_line_idx]
161 |
162 | if (vertical): # /* VERTICAL */
163 | if (child.get_h_size_flags() & (SIZE_FILL | SIZE_SHRINK_CENTER | SIZE_SHRINK_END)):
164 | child_size.x = line_data.min_line_height;
165 |
166 | if (child.get_v_size_flags() & SIZE_EXPAND):
167 | var stretch:int = line_data.stretch_avail * child.get_stretch_ratio() / line_data.stretch_ratio_total
168 | child_size.y += stretch;
169 |
170 |
171 | else: # /* HORIZONTAL */
172 | if (child.get_v_size_flags() & (SIZE_FILL | SIZE_SHRINK_CENTER | SIZE_SHRINK_END)):
173 | child_size.y = line_data.min_line_height;
174 |
175 | if (child.get_h_size_flags() & SIZE_EXPAND):
176 | var stretch:int = line_data.stretch_avail * child.get_stretch_ratio() / line_data.stretch_ratio_total;
177 | child_size.x += stretch
178 |
179 |
180 | var child_rect:Rect2 = Rect2(ofs, child_size)
181 | if (rtl):
182 | child_rect.position.x = get_rect().size.x - child_rect.position.x - child_rect.size.x
183 |
184 | fit_child_in_rect(child, child_rect);
185 |
186 | if (vertical): # /* VERTICAL */
187 | ofs.y += child_size.y + separation_vertical;
188 | else: # /* HORIZONTAL */
189 | ofs.x += child_size.x + separation_horizontal;
190 |
191 | child_idx_in_line += 1
192 |
193 | cached_size = (ofs.x if vertical else ofs.y) + line_height;
194 | cached_line_count = lines_data.size();
195 |
196 |
197 | func _get_minimum_size() -> Vector2:
198 | var minimum:Vector2 = Vector2()
199 |
200 | for i in get_child_count():
201 | var child:Control = get_child(i) as Control
202 |
203 | if (!child or !child.is_visible_in_tree()):
204 | continue
205 |
206 | if (child.is_set_as_toplevel()):
207 | continue
208 |
209 | var size:Vector2 = child.get_combined_minimum_size()
210 |
211 | if (vertical): # /* VERTICAL */
212 | minimum.y = max(minimum.y, size.y);
213 | minimum.x = cached_size;
214 |
215 | else: # /* HORIZONTAL */
216 | minimum.x = max(minimum.x, size.x);
217 | minimum.y = cached_size;
218 |
219 | return minimum;
220 |
221 |
222 | func _notification(p_what:int) -> void:
223 | match (p_what):
224 | NOTIFICATION_SORT_CHILDREN:
225 | _resort();
226 | minimum_size_changed()
227 |
228 | NOTIFICATION_THEME_CHANGED:
229 | minimum_size_changed()
230 |
231 | NOTIFICATION_TRANSLATION_CHANGED:
232 | queue_sort()
233 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/nodes/editor/playground/event_manager_demo.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=30 format=2]
2 |
3 | [ext_resource path="res://addons/event_system_plugin/nodes/event_manager/event_manager.gd" type="Script" id=1]
4 | [ext_resource path="res://addons/event_system_plugin/resources/timeline_class/timeline_class.gd" type="Script" id=2]
5 | [ext_resource path="res://addons/event_system_plugin/events/call_from.gd" type="Script" id=3]
6 | [ext_resource path="res://addons/event_system_plugin/events/end_timeline.gd" type="Script" id=4]
7 | [ext_resource path="res://addons/event_system_plugin/events/set.gd" type="Script" id=5]
8 | [ext_resource path="res://addons/event_system_plugin/events/hide.gd" type="Script" id=6]
9 | [ext_resource path="res://addons/event_system_plugin/events/wait.gd" type="Script" id=7]
10 | [ext_resource path="res://addons/event_system_plugin/events/goto.gd" type="Script" id=8]
11 | [ext_resource path="res://addons/event_system_plugin/events/condition.gd" type="Script" id=9]
12 | [ext_resource path="res://addons/event_system_plugin/events/emit_signal.gd" type="Script" id=10]
13 | [ext_resource path="res://addons/event_system_plugin/events/show.gd" type="Script" id=11]
14 | [ext_resource path="res://addons/event_system_plugin/events/comment.gd" type="Script" id=12]
15 |
16 | [sub_resource type="GDScript" id=3]
17 | script/source = "extends Node
18 |
19 | var test = true
20 |
21 | func d_print(arg):
22 | print(arg)
23 |
24 |
25 | func _on_EventManager_event_started(event):
26 | prints(\"start\",event)
27 |
28 |
29 | func _on_EventManager_event_finished(event):
30 | print(\"finish\", event)
31 |
32 |
33 | func _on_EventManager_timeline_started(timeline_resource):
34 | prints(\"tmln start\",timeline_resource)
35 |
36 |
37 | func _on_EventManager_timeline_finished(timeline_resource):
38 | prints(\"tmln end\",timeline_resource)
39 | "
40 |
41 | [sub_resource type="Resource" id=7]
42 | resource_name = "Call"
43 | script = ExtResource( 3 )
44 | continue_at_end = true
45 | method = "d_print"
46 | args = [ "working" ]
47 | event_node_path = NodePath("")
48 | event_subevents_quantity = 0
49 |
50 | [sub_resource type="Resource" id=8]
51 | resource_name = "Emit Signal"
52 | script = ExtResource( 10 )
53 | continue_at_end = true
54 | data = ""
55 | event_node_path = NodePath("")
56 | event_subevents_quantity = 0
57 |
58 | [sub_resource type="Resource" id=9]
59 | resource_name = "Hide"
60 | script = ExtResource( 6 )
61 | continue_at_end = true
62 | method = "set"
63 | args = [ "visible", false ]
64 | event_node_path = NodePath("")
65 | event_subevents_quantity = 0
66 |
67 | [sub_resource type="Resource" id=10]
68 | resource_name = "Set"
69 | script = ExtResource( 5 )
70 | continue_at_end = true
71 | method = "set"
72 | args = [ "", "" ]
73 | variable_name = ""
74 | variable_value = ""
75 | event_node_path = NodePath("")
76 | event_subevents_quantity = 0
77 |
78 | [sub_resource type="Resource" id=11]
79 | resource_name = "Show"
80 | script = ExtResource( 11 )
81 | continue_at_end = true
82 | method = "set"
83 | args = [ "visible", true ]
84 | event_node_path = NodePath("")
85 | event_subevents_quantity = 0
86 |
87 | [sub_resource type="Resource" id=12]
88 | resource_name = "Comment"
89 | script = ExtResource( 12 )
90 | continue_at_end = true
91 | text = ""
92 | event_node_path = NodePath("")
93 | event_subevents_quantity = 0
94 |
95 | [sub_resource type="Resource" id=13]
96 | resource_name = "End Timeline"
97 | script = ExtResource( 4 )
98 | continue_at_end = true
99 | event_node_path = NodePath("")
100 | event_subevents_quantity = 0
101 |
102 | [sub_resource type="Resource" id=14]
103 | resource_name = "Condition"
104 | script = ExtResource( 9 )
105 | continue_at_end = true
106 | condition = ""
107 | event_node_path = NodePath("")
108 | event_subevents_quantity = 0
109 |
110 | [sub_resource type="Resource" id=15]
111 | resource_name = "Wait"
112 | script = ExtResource( 7 )
113 | continue_at_end = true
114 | wait_time = 0.0
115 | event_node_path = NodePath("")
116 | event_subevents_quantity = 0
117 |
118 | [sub_resource type="Resource" id=16]
119 | resource_name = "Go to"
120 | script = ExtResource( 8 )
121 | continue_at_end = true
122 | next_event = "3;Test timeline"
123 | event_node_path = NodePath("")
124 | event_subevents_quantity = 0
125 |
126 | [sub_resource type="Resource" id=5]
127 | resource_name = "Timeline"
128 | script = ExtResource( 2 )
129 | event/0 = SubResource( 7 )
130 | event/1 = SubResource( 8 )
131 | event/2 = SubResource( 9 )
132 | event/3 = SubResource( 10 )
133 | event/4 = SubResource( 11 )
134 | event/5 = SubResource( 12 )
135 | event/6 = SubResource( 13 )
136 | event/7 = SubResource( 14 )
137 | event/8 = SubResource( 15 )
138 | event/9 = SubResource( 16 )
139 |
140 | [sub_resource type="Resource" id=17]
141 | resource_name = "Call"
142 | script = ExtResource( 3 )
143 | continue_at_end = true
144 | method = "d_print"
145 | args = [ "hello" ]
146 | event_node_path = NodePath("")
147 | event_subevents_quantity = 0
148 |
149 | [sub_resource type="Resource" id=18]
150 | resource_name = "Go to"
151 | script = ExtResource( 8 )
152 | continue_at_end = true
153 | next_event = ""
154 | event_node_path = NodePath("")
155 | event_subevents_quantity = 0
156 |
157 | [sub_resource type="Resource" id=6]
158 | resource_name = "Timeline"
159 | script = ExtResource( 2 )
160 | event/0 = SubResource( 17 )
161 | event/1 = SubResource( 18 )
162 |
163 | [sub_resource type="Resource" id=19]
164 | resource_name = "Call"
165 | script = ExtResource( 3 )
166 | continue_at_end = true
167 | method = "d_print"
168 | args = [ "it works" ]
169 | event_node_path = NodePath("")
170 | event_subevents_quantity = 0
171 |
172 | [sub_resource type="Resource" id=20]
173 | resource_name = "Timeline"
174 | script = ExtResource( 2 )
175 | event/0 = SubResource( 19 )
176 |
177 | [node name="Node" type="Node"]
178 | script = SubResource( 3 )
179 |
180 | [node name="EventManager" type="Node" parent="."]
181 | script = ExtResource( 1 )
182 | event_node_fallback_path = NodePath("..")
183 | start_on_ready = true
184 | current_timeline = "debug"
185 | "timeline/Test timeline" = SubResource( 5 )
186 | timeline/debug = SubResource( 6 )
187 | timeline/test = SubResource( 20 )
188 |
189 | [connection signal="event_finished" from="EventManager" to="." method="_on_EventManager_event_finished"]
190 | [connection signal="event_started" from="EventManager" to="." method="_on_EventManager_event_started"]
191 | [connection signal="timeline_finished" from="EventManager" to="." method="_on_EventManager_timeline_finished"]
192 | [connection signal="timeline_started" from="EventManager" to="." method="_on_EventManager_timeline_started"]
193 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/nodes/editor/playground/in_game_editor.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=2]
2 |
3 | [sub_resource type="GDScript" id=1]
4 | script/source = "extends Node
5 |
6 | var tml
7 | var editor:Control = load(\"res://addons/event_system_plugin/nodes/editor/timeline_editor.gd\").new()
8 |
9 | func _ready() -> void:
10 | add_child(editor)
11 | editor.set_margins_preset(Control.PRESET_WIDE)
12 |
13 | # if ResourceLoader.exists(\"test.tres\"):
14 | # tml = load(\"test.tres\") as Timeline
15 |
16 | if !tml:
17 | tml = Timeline.new()
18 | var cond = EventCondition.new()
19 | # cond.event_subevents_quantity = 1
20 | tml.add_event(cond)
21 | tml.add_event(Event.new())
22 | tml.add_event(EventComment.new())
23 |
24 | editor.timeline_displayer.connect(\"load_ended\", self, \"timeline_changed\")
25 |
26 | var node := EventManager.new()
27 | add_child(node)
28 | node.add_timeline(\"new timeline\", tml)
29 | # node.add_timeline(\"timeline 2\", tml2)
30 | editor.edit_node(node)
31 | $Label.raise()
32 | $Control.raise()
33 | tml.emit_changed()
34 |
35 |
36 | func timeline_changed():
37 | $Label.text = get_string_tree()
38 | $Control.update()
39 |
40 |
41 | func _exit_tree() -> void:
42 | print(get_string_tree())
43 | # assert(ResourceSaver.save(\"test.tres\", tml) == OK)
44 |
45 |
46 | func get_string_tree() -> String:
47 | var tree = \"\"
48 | for event in tml.get_events():
49 | for i in event.event_indent_level:
50 | tree += \"- \"
51 | tree += event.event_name
52 | tree += \" | [{sub}] idx:{idx} \\n\".format({\"idx\":tml.get_event_idx(event), \"sub\":event.event_subevents_quantity})
53 |
54 | return tree
55 |
56 | func _on_Button_pressed() -> void:
57 | editor.reload()
58 |
59 |
60 | func _on_Control_draw() -> void:
61 | var rect:Rect2 = editor.timeline_displayer.get_rect()
62 | rect.position = editor.timeline_displayer.rect_global_position
63 | $Control.draw_rect(rect, Color.red, false)
64 |
65 |
66 | func _on_Undo_pressed() -> void:
67 | var ur:UndoRedo = editor._get_undo_redo()
68 | if ur.has_undo():
69 | ur.undo()
70 |
71 |
72 | func _on_Redo_pressed() -> void:
73 | var ur:UndoRedo = editor._get_undo_redo()
74 | if ur.has_redo():
75 | ur.redo()
76 | "
77 |
78 | [sub_resource type="Animation" id=2]
79 | resource_name = "Nueva Animación"
80 | tracks/0/type = "value"
81 | tracks/0/path = NodePath(".:editor_description")
82 | tracks/0/interp = 1
83 | tracks/0/loop_wrap = true
84 | tracks/0/imported = false
85 | tracks/0/enabled = true
86 | tracks/0/keys = {
87 | "times": PoolRealArray( 0.1, 0.6 ),
88 | "transitions": PoolRealArray( 1, 1 ),
89 | "update": 1,
90 | "values": [ "", "asdfasdasda" ]
91 | }
92 |
93 | [sub_resource type="Animation" id=3]
94 | resource_name = "Nueva Animación (2)"
95 |
96 | [node name="Playground" type="Node"]
97 | script = SubResource( 1 )
98 | __meta__ = {
99 | "_editor_description_": "asdfasdasda"
100 | }
101 |
102 | [node name="AnimationPlayer" type="AnimationPlayer" parent="."]
103 | "anims/Nueva Animación" = SubResource( 2 )
104 | "anims/Nueva Animación (2)" = SubResource( 3 )
105 |
106 | [node name="Label" type="Label" parent="."]
107 | margin_left = 743.0
108 | margin_top = 3.0
109 | margin_right = 1020.0
110 | margin_bottom = 231.0
111 | grow_horizontal = 0
112 | autowrap = true
113 | __meta__ = {
114 | "_edit_use_anchors_": false
115 | }
116 |
117 | [node name="Control" type="Control" parent="."]
118 | anchor_right = 1.0
119 | anchor_bottom = 1.0
120 | mouse_filter = 2
121 | __meta__ = {
122 | "_edit_use_anchors_": false
123 | }
124 |
125 | [node name="Button" type="Button" parent="Control"]
126 | margin_left = 778.0
127 | margin_top = 557.0
128 | margin_right = 942.0
129 | margin_bottom = 587.0
130 | text = "reset"
131 | __meta__ = {
132 | "_edit_use_anchors_": false
133 | }
134 |
135 | [node name="Undo" type="Button" parent="Control"]
136 | margin_left = 651.0
137 | margin_top = 562.0
138 | margin_right = 697.0
139 | margin_bottom = 582.0
140 | text = "Undo"
141 | __meta__ = {
142 | "_edit_use_anchors_": false
143 | }
144 |
145 | [node name="Redo" type="Button" parent="Control"]
146 | margin_left = 712.0
147 | margin_top = 562.0
148 | margin_right = 758.0
149 | margin_bottom = 582.0
150 | text = "Redo"
151 | __meta__ = {
152 | "_edit_use_anchors_": false
153 | }
154 |
155 | [connection signal="draw" from="Control" to="." method="_on_Control_draw"]
156 | [connection signal="pressed" from="Control/Button" to="." method="_on_Button_pressed"]
157 | [connection signal="pressed" from="Control/Undo" to="." method="_on_Undo_pressed"]
158 | [connection signal="pressed" from="Control/Redo" to="." method="_on_Redo_pressed"]
159 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/nodes/editor/subtimeline.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends PanelContainer
3 |
4 | class TitleBar extends PanelContainer:
5 | signal toggled(pressed)
6 |
7 | var bar:HBoxContainer
8 | var collapse_button:CheckBox
9 |
10 | func _gui_input(event: InputEvent) -> void:
11 | if event is InputEventMouseButton and event.is_pressed():
12 | collapse_button.grab_focus()
13 | collapse_button.grab_click_focus()
14 |
15 |
16 | func _toggle(button_pressed:bool) -> void:
17 | emit_signal("toggled", button_pressed)
18 |
19 |
20 | func _enter_tree() -> void:
21 | collapse_button.add_icon_override("unchecked", get_icon("Forward", "EditorIcons"))
22 | collapse_button.add_icon_override("checked", get_icon("Collapse", "EditorIcons"))
23 | add_stylebox_override("panel", get_stylebox("panel_odd", "TabContainer"))
24 |
25 |
26 | func _init() -> void:
27 | bar = HBoxContainer.new()
28 | bar.mouse_filter = Control.MOUSE_FILTER_IGNORE
29 | bar.focus_mode = Control.FOCUS_NONE
30 | bar.size_flags_horizontal = SIZE_EXPAND_FILL
31 | bar.size_flags_vertical = SIZE_EXPAND_FILL
32 | bar.rect_clip_content = true
33 |
34 | collapse_button = CheckBox.new()
35 | collapse_button.set_pressed_no_signal(true)
36 | bar.add_child(collapse_button)
37 | add_child(bar)
38 |
39 | collapse_button.connect("toggled", self, "_toggle")
40 |
41 |
42 | func generate_previews(for_these_events:Array) -> void:
43 | for child in bar.get_children():
44 | if child == collapse_button:
45 | continue
46 | child.queue_free()
47 |
48 | var holder = HBoxContainer.new()
49 | holder.focus_mode = Control.FOCUS_NONE
50 | holder.mouse_filter = Control.MOUSE_FILTER_IGNORE
51 | bar.add_child(holder)
52 | for event in for_these_events:
53 | var t_node := TextureRect.new()
54 | t_node.focus_mode = Control.FOCUS_NONE
55 | t_node.mouse_filter = Control.MOUSE_FILTER_IGNORE
56 | t_node.rect_min_size = Vector2(16,16)
57 | t_node.expand = true
58 | t_node.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
59 | t_node.texture = event.get("event_icon") as Texture
60 | holder.add_child(t_node)
61 |
62 |
63 | var unfolded_container:TabContainer
64 | var body:VBoxContainer
65 | var title_bar:TitleBar
66 | var preview:Resource
67 |
68 | func add_timeline_and_get_node(timeline:Resource) -> Control:
69 | var TimelineDisplayer = load("res://addons/event_system_plugin/nodes/editor/timeline_displayer.gd")
70 | var timeline_displayer:Control = TimelineDisplayer.new()
71 | unfolded_container.add_child(timeline_displayer)
72 |
73 | if not preview:
74 | preview = timeline
75 |
76 | if unfolded_container.get_child_count() > 1:
77 | unfolded_container.tabs_visible = true
78 |
79 | timeline_displayer.set("last_used_timeline", timeline)
80 | timeline_displayer.call_deferred("load_timeline", timeline)
81 | timeline.connect("changed", timeline_displayer, "reload")
82 | return timeline_displayer
83 |
84 |
85 | func _set_subtimeline_visible(_visible:bool) -> void:
86 | unfolded_container.visible = _visible
87 |
88 | var events := []
89 | if not _visible:
90 | events = preview.get_events()
91 | title_bar.generate_previews(events)
92 |
93 |
94 | func _enter_tree() -> void:
95 | body.add_constant_override("separation", 0)
96 |
97 |
98 | func _init() -> void:
99 | name = "SubtimelineContainer"
100 | mouse_filter = Control.MOUSE_FILTER_IGNORE
101 | focus_mode = Control.FOCUS_NONE
102 |
103 | unfolded_container = TabContainer.new()
104 | title_bar = TitleBar.new()
105 | body = VBoxContainer.new()
106 | body.mouse_filter = Control.MOUSE_FILTER_IGNORE
107 | body.add_child(title_bar)
108 | body.add_child(unfolded_container)
109 | add_child(body)
110 |
111 | unfolded_container.tabs_visible = false
112 |
113 | title_bar.connect("toggled", self, "_set_subtimeline_visible")
114 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/nodes/editor/timeline_displayer.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends VBoxContainer
3 |
4 | const EventClass = preload("res://addons/event_system_plugin/resources/event_class/event_class.gd")
5 | const TimelineClass = preload("res://addons/event_system_plugin/resources/timeline_class/timeline_class.gd")
6 |
7 | signal event_node_added(event_node)
8 | signal load_started
9 | signal load_ended
10 |
11 | const EventNode = preload("res://addons/event_system_plugin/nodes/editor/event_node/event_node.gd")
12 | const DEFAULT_MIN_SIZE = Vector2(128, 32)
13 |
14 | var data := []
15 | var loading := false
16 |
17 | # Hint for editor
18 | var last_used_timeline:Resource = null
19 |
20 |
21 | func load_timeline(timeline) -> void:
22 | remove_all_displayed_events()
23 | data = timeline.get_events()
24 | last_used_timeline = timeline
25 | update_view()
26 |
27 |
28 | func is_loading() -> bool:
29 | return loading
30 |
31 |
32 | func update_view() -> void:
33 | _notify_load_started()
34 |
35 | for event_idx in data.size():
36 | var event = data[event_idx]
37 | var event_node = _get_event_node(event)
38 | event_node.set("timeline",last_used_timeline)
39 | event_node.set("idx", event_idx)
40 | emit_signal("event_node_added", event_node)
41 | add_child(event_node)
42 | event_node.call_deferred("update_values")
43 |
44 | update_indentation()
45 | _notify_load_ended()
46 |
47 | func update_indentation() -> void:
48 | last_used_timeline.update_structure()
49 |
50 |
51 | func remove_all_displayed_events() -> void:
52 | for child in get_children():
53 | child.queue_free()
54 |
55 |
56 | func reload() -> void:
57 | remove_all_displayed_events()
58 | load_timeline(last_used_timeline)
59 |
60 |
61 | func _get_event_node(event:EventClass) -> EventNode:
62 | if not event:
63 | return null
64 |
65 | var event_node:EventNode
66 | event_node = event.get("custom_event_node") as EventNode
67 | if event_node == null:
68 | event_node = EventNode.new()
69 |
70 | event_node.event = event
71 | return event_node
72 |
73 |
74 | func _notify_load_started() -> void:
75 | loading = true
76 | emit_signal("load_started")
77 |
78 |
79 | func _notify_load_ended() -> void:
80 | loading = false
81 | emit_signal("load_ended")
82 | queue_sort()
83 |
84 |
85 | func _init() -> void:
86 | mouse_filter = Control.MOUSE_FILTER_PASS
87 | size_flags_horizontal = SIZE_EXPAND_FILL
88 | size_flags_vertical = SIZE_EXPAND_FILL
89 | rect_min_size = DEFAULT_MIN_SIZE
90 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/nodes/editor/timeline_drawer.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Control
3 |
4 | const TimelineDisplayer = preload("res://addons/event_system_plugin/nodes/editor/timeline_displayer.gd")
5 | const EventNode = preload("res://addons/event_system_plugin/nodes/editor/event_node/event_node.gd")
6 |
7 | var timeline_displayer:TimelineDisplayer setget set_timeline_displayer
8 |
9 | func set_timeline_displayer(displayer:TimelineDisplayer) -> void:
10 | if is_instance_valid(timeline_displayer):
11 | if timeline_displayer.is_connected("load_ended", self, "_load_ended"):
12 | timeline_displayer.disconnect("load_ended",self,"_load_ended")
13 |
14 | timeline_displayer = displayer
15 |
16 | if is_instance_valid(timeline_displayer):
17 | timeline_displayer.connect("load_ended", self, "_load_ended")
18 |
19 |
20 | func _displayer_draw() -> void:
21 | var child_size:int = timeline_displayer.get_children().size()
22 | var td = timeline_displayer # timeline_displayer is too long, and i'm too lazy
23 | for node in timeline_displayer.get_children():
24 | node = node as Control
25 | if not node:
26 | continue
27 | # td.draw_line(node.rect_position, Vector2(0, node.rect_size.y), Color.red, 2)
28 | draw_rect(node.get_rect(), Color.red, false, 4)
29 |
30 |
31 | func _load_ended() -> void:
32 | update()
33 |
34 | func _init():
35 | mouse_filter = Control.MOUSE_FILTER_IGNORE
36 | focus_mode = Control.FOCUS_NONE
37 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/nodes/editor/timeline_editor.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends VBoxContainer
3 |
4 | const TimelineDisplayer = preload("res://addons/event_system_plugin/nodes/editor/timeline_displayer.gd")
5 | const EventNode = preload("res://addons/event_system_plugin/nodes/editor/event_node/event_node.gd")
6 | const CategoryManager = preload("res://addons/event_system_plugin/nodes/editor/category_manager.gd")
7 | const EventClass = preload("res://addons/event_system_plugin/resources/event_class/event_class.gd")
8 | const TimelineClass = preload("res://addons/event_system_plugin/resources/timeline_class/timeline_class.gd")
9 | const EventMenu = preload("res://addons/event_system_plugin/nodes/editor/event_node/event_popup_menu.gd")
10 | const TimelineList = preload("res://addons/event_system_plugin/nodes/editor/timeline_list.gd")
11 | const EventManagerClass = preload("res://addons/event_system_plugin/nodes/event_manager/event_manager.gd")
12 |
13 | enum {
14 | TOOL_NEW_TIMELINE,
15 | TOOL_DUPLICATE_TIMELINE,
16 | TOOL_RENAME_TIMELINE,
17 | TOOL_REMOVE_TIMELINE,
18 | TOOL_EDIT_RESOURCE
19 | }
20 |
21 | signal inspection_requested(resource)
22 |
23 | var shortcuts = load("res://addons/event_system_plugin/core/shortcuts.gd")
24 |
25 | var timeline_displayer:TimelineDisplayer
26 | var last_selected_event_node:EventNode
27 | var is_moving_event:bool = false
28 |
29 | var _sc:ScrollContainer
30 | var _event_menu:EventMenu
31 | var _edited_sequence:TimelineClass
32 | var _category_manager:CategoryManager
33 | var _timeline_list:TimelineList
34 | var _timeline_tools:MenuButton
35 | var _error_dialog:AcceptDialog
36 | var _error_label:Label
37 | var _name_dialog:ConfirmationDialog
38 | var _new_name_label:Label
39 | var _new_name_edit:LineEdit
40 | var _remove_dialog:ConfirmationDialog
41 | var _remove_label:Label
42 | var _info_label:Label
43 |
44 | var _renaming := false
45 |
46 | var _edited_node:EventManagerClass
47 |
48 | var __undo_redo:UndoRedo # Do not use thid directly, get its reference with _get_undo_redo
49 | var __group:ButtonGroup
50 |
51 | func set_undo_redo(value:UndoRedo) -> void:
52 | # Sets UndoRedo, but this object can leave leaked isntances so make sure to set it
53 | # with an external reference (aka Editor's UndoRedo).
54 | # To internal use of UndoRedo use _get_undo_redo instead.
55 | __undo_redo = value
56 |
57 | func edit(object:Object) -> void:
58 | if object is TimelineClass:
59 | _info_label.show()
60 | _info_label.text = "You're editing a single timeline. Some editor tools may not be enabled."
61 |
62 | _edited_node = null
63 |
64 | _timeline_list.node = null
65 | _timeline_list.list_timelines()
66 | _timeline_list.add_item(object.resource_name)
67 | _timeline_list.disabled = true
68 |
69 | _timeline_tools.disabled = true
70 |
71 | edit_timeline(object)
72 |
73 | if object is EventManagerClass:
74 | _info_label.hide()
75 | _timeline_list.disabled = false
76 | _timeline_tools.disabled = false
77 | edit_node(object)
78 |
79 |
80 | func edit_node(node:EventManagerClass) -> void:
81 | _edited_node = node
82 | _timeline_list.node = _edited_node
83 | _timeline_list.list_timelines()
84 | if _edited_node:
85 | if _get_current() == "":
86 | edit_timeline(null)
87 | return
88 |
89 | edit_timeline(_edited_node.get_timeline(_get_current()))
90 |
91 |
92 | func edit_timeline(sequence) -> void:
93 | _disconnect_edited_sequence_signals()
94 |
95 | _edited_sequence = sequence
96 | timeline_displayer.remove_all_displayed_events()
97 | if sequence:
98 | timeline_displayer.load_timeline(sequence)
99 |
100 | _connect_edited_sequence_signals()
101 |
102 |
103 | func edit_timeline_by_name(timeline_name:String) -> void:
104 | for idx in _timeline_list.get_item_count():
105 | var item_name = _timeline_list.get_item_text(idx)
106 | if item_name == timeline_name:
107 | _timeline_list.select(idx)
108 |
109 | edit_timeline(_edited_node.get_timeline(_get_current()))
110 |
111 |
112 | func reload() -> void:
113 | timeline_displayer.call_deferred("load_timeline", _edited_sequence)
114 |
115 |
116 | func remove_event(event:EventClass, from_resource:TimelineClass) -> void:
117 | if event == null or from_resource == null:
118 | return
119 |
120 | var _UndoRedo:UndoRedo = _get_undo_redo()
121 |
122 | var parent_event_ref:WeakRef = event.event_subevent_from
123 | var parent_event:EventClass
124 | var old_value:int = 0
125 | var new_value:int = 0
126 | if parent_event_ref:
127 | parent_event = parent_event_ref.get_ref() as EventClass
128 | if parent_event:
129 | old_value = parent_event.event_subevents_quantity
130 | new_value = max(0, old_value-1)
131 |
132 | var event_idx:int = from_resource.get_event_idx(event)
133 | _UndoRedo.create_action("Remove event from timeline")
134 | _UndoRedo.add_do_method(from_resource, "erase_event", event)
135 | _UndoRedo.add_undo_method(from_resource, "insert_event", event, event_idx)
136 |
137 | if parent_event:
138 | _UndoRedo.add_do_property(parent_event, "event_subevents_quantity", new_value)
139 | _UndoRedo.add_undo_property(parent_event, "event_subevents_quantity", old_value)
140 |
141 | _UndoRedo.commit_action()
142 |
143 |
144 | func add_event(event:EventClass, at_position:int=-1, from_resource:Resource=_edited_sequence, as_subevent_of:EventClass=null) -> void:
145 | if not from_resource:
146 | return
147 |
148 | var _UndoRedo:UndoRedo = _get_undo_redo()
149 |
150 | var parent_event:EventClass = as_subevent_of
151 | var old_value:int = 0
152 | var new_value:int = 0
153 | if parent_event:
154 | old_value = parent_event.event_subevents_quantity
155 | new_value = old_value+1
156 |
157 | _UndoRedo.create_action("Add event %s"%event.event_name)
158 | if at_position < 0:
159 | _UndoRedo.add_do_method(from_resource, "add_event", event)
160 | else:
161 | _UndoRedo.add_do_method(from_resource, "insert_event", event, at_position)
162 |
163 | _UndoRedo.add_undo_method(from_resource, "erase_event", event)
164 |
165 | if parent_event:
166 | _UndoRedo.add_do_property(parent_event, "event_subevents_quantity", new_value)
167 | _UndoRedo.add_undo_property(parent_event, "event_subevents_quantity", old_value)
168 |
169 | _UndoRedo.commit_action()
170 |
171 |
172 | func move_event(event:EventClass, to:int, from_resource:TimelineClass=_edited_sequence, as_subevent_of:EventClass=null) -> void:
173 | if not from_resource:
174 | return
175 |
176 | var old_position:int = from_resource.get_event_idx(event)
177 |
178 | var _UndoRedo:UndoRedo = _get_undo_redo()
179 |
180 | _UndoRedo.create_action("Move event %s"%event.event_name)
181 |
182 | var old_parent:EventClass
183 | var new_parent:EventClass = as_subevent_of
184 |
185 | if event.event_subevent_from:
186 | old_parent = event.event_subevent_from.get_ref() as EventClass
187 |
188 | var old_value:int = 0
189 | var new_value:int = 0
190 |
191 | if !from_resource.event_is_subevent_of(event, new_parent):
192 | if old_parent:
193 | old_value = old_parent.event_subevents_quantity
194 | new_value = max(0, old_value-1)
195 | _UndoRedo.add_do_property(old_parent, "event_subevents_quantity", new_value)
196 | _UndoRedo.add_undo_property(old_parent, "event_subevents_quantity", old_value)
197 |
198 | if new_parent:
199 | old_value = new_parent.event_subevents_quantity
200 | new_value = old_value+1
201 | _UndoRedo.add_do_property(new_parent, "event_subevents_quantity", new_value)
202 | _UndoRedo.add_undo_property(new_parent, "event_subevents_quantity", old_value)
203 |
204 | if to < 0:
205 | if old_parent:
206 | old_value = old_parent.event_subevents_quantity
207 | new_value = max(0, old_value-1)
208 | _UndoRedo.add_do_property(old_parent, "event_subevents_quantity", new_value)
209 | _UndoRedo.add_undo_property(old_parent, "event_subevents_quantity", old_value)
210 |
211 | event.event_indent_level = 0
212 |
213 | _UndoRedo.add_do_method(from_resource, "move_event", event, to)
214 | _UndoRedo.add_undo_method(from_resource, "move_event", event, old_position)
215 |
216 | _UndoRedo.commit_action()
217 |
218 |
219 | func get_drag_data_fw(position, node):
220 | if node is EventNode:
221 | var event:EventClass = node.get("event")
222 | var timeline:TimelineClass = node.get("timeline")
223 | is_moving_event = true
224 |
225 | if not event:
226 | return null
227 |
228 | var _node = node.duplicate(0)
229 |
230 | _node.rect_size = Vector2.ZERO
231 | set_drag_preview(_node)
232 | var data = {}
233 | data["event"] = event
234 |
235 | return data
236 |
237 |
238 | var _separator_node:EventNode
239 | var _idx_hint:int = -1
240 | var _last_node:Node
241 | func can_drop_data_fw(position: Vector2, data, node:Control) -> bool:
242 | var event_data:EventClass
243 |
244 | if typeof(data) in [TYPE_OBJECT, TYPE_DICTIONARY]:
245 | event_data = data.get("event")
246 | if event_data == null:
247 | return false
248 | else:
249 | return false
250 |
251 | # if !is_instance_valid(_separator_node):
252 | # _generate_separator_node()
253 | # _separator_node.event = node.get("event") as EventClass
254 | # _separator_node.update_values()
255 | #
256 | # if node is EventNode:
257 | # var node_rect:Rect2 = node.get_rect()
258 | # var node_event = node.get("event")
259 | #
260 | # var pos = node.get_index()
261 | # if position.y > node_rect.size.y/2:
262 | # pos = node.get_index()+1
263 | # timeline_displayer.move_child(_separator_node, pos)
264 |
265 | _last_node = node
266 | # return node is TimelineDisplayer and event_data is EventClass
267 | return event_data is EventClass
268 |
269 |
270 | func drop_data_fw(position: Vector2, data, node) -> void:
271 | var event_data:EventClass = data.get("event")
272 | var subevent_of = null
273 |
274 | if node is EventNode:
275 | if event_data == node.event:
276 | return
277 |
278 | if node != _separator_node:
279 | var node_rect:Rect2 = node.get_rect()
280 | var node_event = node.get("event")
281 |
282 | _idx_hint = _edited_sequence.get_event_idx(node.event)
283 | if position.y > node_rect.size.y/2:
284 | _idx_hint = _edited_sequence.get_event_idx(node.event)+1
285 |
286 | if node.event.event_uses_subevents:
287 | subevent_of = node.event
288 |
289 | elif node.event.event_subevent_from:
290 | subevent_of = node.event.event_subevent_from.get_ref()
291 |
292 | if event_data.event_subevent_from:
293 | pass
294 |
295 | event_data.event_indent_level = node.event.event_indent_level
296 |
297 | if node is TimelineDisplayer:
298 | _idx_hint = -1
299 | event_data.event_indent_level = 0
300 | event_data.event_subevent_from = null
301 |
302 | if !is_moving_event:
303 | add_event(event_data, _idx_hint, _edited_sequence, subevent_of)
304 | else:
305 | move_event(event_data, _idx_hint, _edited_sequence, subevent_of)
306 |
307 | _idx_hint = -1
308 |
309 |
310 | func _generate_separator_node() -> void:
311 | _separator_node = EventNode.new()
312 | _separator_node.propagate_call("set", ["focus_mode", Control.FOCUS_NONE])
313 | _separator_node.propagate_call("set", ["mouse_filter", Control.MOUSE_FILTER_PASS])
314 | _separator_node.modulate.a = 0.5
315 | _separator_node.modulate = _separator_node.modulate.darkened(0.2)
316 | connect("tree_exited", _separator_node, "free")
317 | # _separator_node.set_drag_forwarding(self)
318 | timeline_displayer.add_child(_separator_node)
319 |
320 |
321 | func _get_undo_redo() -> UndoRedo:
322 | if not is_instance_valid(__undo_redo):
323 | __undo_redo = UndoRedo.new()
324 | connect("tree_exiting", __undo_redo, "free")
325 | return __undo_redo
326 |
327 |
328 | func _disconnect_edited_sequence_signals() -> void:
329 | if _edited_sequence:
330 | if _edited_sequence.is_connected("changed", self, "reload"):
331 | _edited_sequence.disconnect("changed",self,"reload")
332 |
333 |
334 | func _connect_edited_sequence_signals() -> void:
335 | if _edited_sequence:
336 | if not _edited_sequence.is_connected("changed",self,"reload"):
337 | _edited_sequence.connect("changed",self,"reload", [], CONNECT_DEFERRED)
338 |
339 |
340 | func _timeline_selected(_index:int) -> void:
341 | var current := _get_current()
342 |
343 | if current != "":
344 | var timeline = _edited_node.get_timeline(current)
345 | edit_timeline(timeline)
346 |
347 |
348 | func _timeline_tools_menu(option:int):
349 | match option:
350 | TOOL_NEW_TIMELINE:
351 | _timeline_new()
352 |
353 | TOOL_DUPLICATE_TIMELINE:
354 | _timeline_duplicate()
355 |
356 | TOOL_RENAME_TIMELINE:
357 | _timeline_rename()
358 |
359 | TOOL_REMOVE_TIMELINE:
360 | _timeline_remove()
361 |
362 | TOOL_EDIT_RESOURCE:
363 | _timeline_edit_resource()
364 |
365 |
366 | func _timeline_new() -> void:
367 | _renaming = false
368 | _name_dialog.window_title = "New Timeline"
369 | _new_name_edit.placeholder_text = ""
370 | _new_name_edit.text = ""
371 | _name_dialog.popup_centered()
372 |
373 |
374 | func _timeline_duplicate() -> void:
375 | var _timeline:TimelineClass = _edited_node.get_timeline(_get_current())
376 | if _timeline == null:
377 | return
378 |
379 | # For some reason, duplicate(true) removes the script
380 | var new_timeline = _timeline.duplicate()
381 |
382 | var events = new_timeline.get_events()
383 | var new_events = []
384 | for event in events:
385 | new_events.append(event.duplicate())
386 | new_timeline.set_events(new_events)
387 |
388 | var new_name := _get_current() + " ({idx})"
389 | var idx = 2
390 | while _edited_node.has_timeline(new_name.format({"idx":idx})):
391 | idx += 1
392 |
393 | _edited_node.add_timeline(new_name.format({"idx":idx}), new_timeline)
394 | edit_node(_edited_node)
395 |
396 | func _timeline_rename() -> void:
397 | _renaming = true
398 | _name_dialog.window_title = "Rename Timeline"
399 | _new_name_edit.placeholder_text = _get_current()
400 | _new_name_edit.text = _get_current()
401 | _name_dialog.popup_centered()
402 |
403 |
404 | func _timeline_remove() -> void:
405 | _remove_label.text = "Removing '%s' timeline. Are you sure?"%_get_current()
406 | _remove_dialog.popup_centered()
407 |
408 |
409 | func _timeline_edit_resource() -> void:
410 | if !Engine.editor_hint:
411 | print("Tried to edit the resource, but you're not in the editor!")
412 | return
413 | emit_signal("inspection_requested", _edited_node.get_timeline(_get_current()))
414 |
415 |
416 | func _get_current() -> String:
417 | var current:String = ""
418 | var selected_id:int = _timeline_list.get_selected_id()
419 |
420 | if selected_id >= 0 && selected_id < _timeline_list.get_item_count():
421 | current = _timeline_list.get_item_text(selected_id)
422 |
423 | return current
424 |
425 |
426 | func _input(event: InputEvent) -> void:
427 | var event_node = last_selected_event_node
428 | var focus_owner = get_focus_owner()
429 |
430 | if not is_instance_valid(event_node):
431 | return
432 |
433 | if is_instance_valid(focus_owner):
434 | if not event_node.is_a_parent_of(focus_owner):
435 | return
436 |
437 | var _event = last_selected_event_node.get("event")
438 |
439 | var duplicate_shortcut = shortcuts.get_shortcut("duplicate")
440 | if event.shortcut_match(duplicate_shortcut.shortcut):
441 | if _event and event.is_pressed():
442 | timeline_displayer.remove_all_displayed_events()
443 | var position:int = _edited_sequence.get_events().find(_event)
444 | add_event(_event.duplicate(), position+1, event_node.timeline)
445 | event_node.accept_event()
446 |
447 | var delete_shortcut = shortcuts.get_shortcut("delete")
448 | if event.shortcut_match(delete_shortcut.shortcut):
449 | if _event:
450 | timeline_displayer.remove_all_displayed_events()
451 | remove_event(_event, event_node.timeline)
452 | event_node.accept_event()
453 |
454 |
455 | func _on_EventButton_selected(button) -> void:
456 | last_selected_event_node = button.get_meta("event_node")
457 | emit_signal("inspection_requested", last_selected_event_node.event)
458 |
459 |
460 | func _on_EventNode_gui_input(event: InputEvent, event_node:EventNode) -> void:
461 | var _event:EventClass = event_node.event
462 |
463 | if event is InputEventMouseButton:
464 | if event.button_index == BUTTON_RIGHT and event.pressed:
465 | if _event:
466 | _event_menu.used_event = _event
467 | _event_menu.popup(Rect2(get_global_mouse_position()+Vector2(1,1), _event_menu.rect_size))
468 | event_node.event_button.pressed = true
469 | event_node.accept_event()
470 |
471 |
472 | func _on_TimelineDisplayer_event_node_added(event_node:Control) -> void:
473 | if not event_node.is_connected("gui_input", self, "_on_EventNode_gui_input"):
474 | event_node.connect("gui_input", self, "_on_EventNode_gui_input", [event_node])
475 |
476 | event_node.set_drag_forwarding(self)
477 | event_node.set_button_group(__group)
478 |
479 |
480 | func _on_EventMenu_index_pressed(idx:int) -> void:
481 | var _used_event:EventClass = _event_menu.used_event as EventClass
482 |
483 | if _used_event == null:
484 | return
485 |
486 | # I'm not gonna lost my time recycling nodes tbh
487 | # timeline_displayer.remove_all_displayed_events()
488 |
489 | match idx:
490 | EventMenu.ItemType.EDIT:
491 | emit_signal("inspection_requested", _used_event)
492 |
493 | EventMenu.ItemType.DUPLICATE:
494 | var position:int = _edited_sequence.get_events().find(_used_event)
495 | add_event(_used_event.duplicate(), position+1)
496 |
497 | EventMenu.ItemType.REMOVE:
498 | remove_event(_used_event, _edited_sequence)
499 |
500 |
501 | func _on_CategoryManager_button_pressed(button:Button, event_script:Script) -> void:
502 | var idx := -1
503 | var timeline := _edited_sequence
504 | if is_instance_valid(last_selected_event_node):
505 | idx = last_selected_event_node.idx+1
506 | timeline = last_selected_event_node.timeline
507 | if not timeline:
508 | timeline = _edited_sequence
509 | idx = -1
510 | add_event(event_script.new(), idx, timeline)
511 |
512 |
513 | func _on_name_dialog_confirmed() -> void:
514 | if !is_instance_valid(_edited_node):
515 | return
516 |
517 | var new_name:String = _new_name_edit.text
518 |
519 | if new_name == "":
520 | _error_label.text = "Timeline label can't be empty"
521 | _error_dialog.popup_centered()
522 | return
523 |
524 | if new_name == "[None]":
525 | _error_label.text = "Invalid name!"
526 | _error_dialog.popup_centered()
527 | return
528 |
529 | if _renaming:
530 | _renaming = false
531 |
532 | if new_name == _get_current():
533 | _name_dialog.hide()
534 | return
535 |
536 | _edited_node.rename_timeline(_get_current(), new_name)
537 |
538 | else:
539 | if _edited_node.has_timeline(new_name):
540 | _error_label.text = "Timeline '%s' already exist"%new_name
541 | _error_dialog.popup_centered()
542 | return
543 |
544 | var res:TimelineClass = TimelineClass.new()
545 | res.resource_name = new_name
546 | _edited_node.add_timeline(new_name, res)
547 |
548 | edit_node(_edited_node)
549 | edit_timeline_by_name(new_name)
550 |
551 | if _get_undo_redo() != null:
552 | _get_undo_redo().clear_history()
553 |
554 | _name_dialog.hide()
555 |
556 |
557 | func _on_remove_dialog_confirmed() -> void:
558 | if !is_instance_valid(_edited_node):
559 | return
560 |
561 | _edited_node.remove_timeline(_get_current())
562 | edit_node(_edited_node)
563 |
564 | func _init() -> void:
565 | __group = ButtonGroup.new()
566 | __group.connect("pressed", self, "_on_EventButton_selected")
567 | add_constant_override("separation", 2)
568 | theme = load("res://addons/event_system_plugin/assets/themes/timeline_editor.tres") as Theme
569 | mouse_filter = Control.MOUSE_FILTER_STOP
570 |
571 | _sc = ScrollContainer.new()
572 | _sc.follow_focus = true
573 | _sc.size_flags_horizontal = SIZE_EXPAND_FILL
574 | _sc.size_flags_vertical = SIZE_EXPAND_FILL
575 | _sc.mouse_filter = Control.MOUSE_FILTER_PASS
576 | var scale := 1.0
577 |
578 | if Engine.editor_hint:
579 | var plugin:EditorPlugin = EditorPlugin.new()
580 | scale = float(plugin.get_editor_interface().get_editor_scale())
581 | plugin.free()
582 |
583 | _sc.rect_min_size = Vector2(0, 180) * scale
584 |
585 | var _dummy_panel := PanelContainer.new()
586 | _dummy_panel.size_flags_horizontal = SIZE_EXPAND_FILL
587 | _dummy_panel.size_flags_vertical = SIZE_EXPAND_FILL
588 | _dummy_panel.mouse_filter = Control.MOUSE_FILTER_STOP
589 | _dummy_panel.focus_mode = Control.FOCUS_CLICK
590 | _sc.add_child(_dummy_panel)
591 |
592 | var timeline_drawer = load("res://addons/event_system_plugin/nodes/editor/timeline_drawer.gd").new()
593 | timeline_drawer.focus_mode = Control.FOCUS_NONE
594 | timeline_drawer.mouse_filter = Control.MOUSE_FILTER_IGNORE
595 | _dummy_panel.add_child(timeline_drawer)
596 |
597 | timeline_displayer = TimelineDisplayer.new()
598 | timeline_displayer.connect("event_node_added", self, "_on_TimelineDisplayer_event_node_added")
599 | _dummy_panel.add_child(timeline_displayer)
600 | timeline_drawer.timeline_displayer = timeline_displayer
601 | timeline_displayer.set_drag_forwarding(self)
602 |
603 | _category_manager = CategoryManager.new()
604 | _category_manager.connect("toolbar_button_pressed", self, "_on_CategoryManager_button_pressed")
605 |
606 | _event_menu = EventMenu.new()
607 | _event_menu.connect("index_pressed", self, "_on_EventMenu_index_pressed")
608 | _event_menu.connect("hide", _event_menu, "set", ["used_event", null])
609 |
610 | var _hs := HSplitContainer.new()
611 | _hs.size_flags_horizontal = SIZE_EXPAND_FILL
612 | _hs.size_flags_vertical = SIZE_EXPAND_FILL
613 |
614 | _hs.add_child(_category_manager)
615 |
616 | var _vb = VBoxContainer.new()
617 | _vb.add_constant_override("separation", 4)
618 |
619 | var _toolbar := HBoxContainer.new()
620 | _timeline_tools = MenuButton.new()
621 | _timeline_tools.text = "Timeline"
622 | _timeline_tools.flat = false
623 |
624 | _timeline_tools.get_popup().add_item("New", TOOL_NEW_TIMELINE)
625 | _timeline_tools.get_popup().add_separator()
626 | _timeline_tools.get_popup().add_item("Duplicate", TOOL_DUPLICATE_TIMELINE)
627 | _timeline_tools.get_popup().add_separator()
628 | _timeline_tools.get_popup().add_item("Rename...", TOOL_RENAME_TIMELINE)
629 | _timeline_tools.get_popup().add_item("Open in Inspector", TOOL_EDIT_RESOURCE)
630 | _timeline_tools.get_popup().add_separator()
631 | _timeline_tools.get_popup().add_item("Remove", TOOL_REMOVE_TIMELINE)
632 |
633 | _timeline_list = TimelineList.new()
634 | _timeline_list.size_flags_horizontal = SIZE_EXPAND_FILL
635 |
636 | _name_dialog = ConfirmationDialog.new()
637 | _name_dialog.window_title = "Create New Timeline"
638 | _name_dialog.dialog_hide_on_ok = false
639 | add_child(_name_dialog)
640 |
641 | var vb = VBoxContainer.new()
642 | _name_dialog.add_child(vb)
643 |
644 | _new_name_label = Label.new()
645 | _new_name_label.text = "Timeline name:"
646 | vb.add_child(_new_name_label)
647 |
648 | _new_name_edit = LineEdit.new()
649 | _new_name_edit.size_flags_horizontal = SIZE_EXPAND_FILL
650 | vb.add_child(_new_name_edit)
651 | _name_dialog.register_text_enter(_new_name_edit)
652 |
653 | _error_dialog = AcceptDialog.new()
654 | _error_dialog.window_title = "Error!"
655 | add_child(_error_dialog)
656 |
657 | _error_label = Label.new()
658 | _error_dialog.add_child(_error_label)
659 |
660 | _remove_dialog = ConfirmationDialog.new()
661 | add_child(_remove_dialog)
662 |
663 | _remove_label = Label.new()
664 | _remove_label.text = "Are you sure?"
665 | _remove_dialog.add_child(_remove_label)
666 |
667 | _info_label = Label.new()
668 | _info_label.align = Label.ALIGN_CENTER
669 | _info_label.visible = false
670 |
671 | _toolbar.add_child(_timeline_tools)
672 | _toolbar.add_child(_timeline_list)
673 | _vb.add_child(_info_label)
674 | _vb.add_child(_toolbar)
675 | _vb.add_child(_sc)
676 |
677 | _hs.add_child(_vb)
678 |
679 | add_child(_hs)
680 | add_child(_event_menu)
681 |
682 |
683 | func _notification(what: int) -> void:
684 | match what:
685 | NOTIFICATION_ENTER_TREE:
686 | _timeline_list.connect("item_selected", self, "_timeline_selected")
687 | _timeline_tools.get_popup().connect("id_pressed", self, "_timeline_tools_menu")
688 | _name_dialog.connect("confirmed", self, "_on_name_dialog_confirmed")
689 | _remove_dialog.connect("confirmed", self, "_on_remove_dialog_confirmed")
690 |
691 | NOTIFICATION_DRAG_END:
692 | if is_instance_valid(_separator_node):
693 | _separator_node.queue_free()
694 |
695 | if is_moving_event:
696 | is_moving_event = false
697 |
698 | NOTIFICATION_THEME_CHANGED:
699 | # For some reason this is called _before_ init (what?!)
700 | if !is_inside_tree():
701 | return
702 | _sc.add_stylebox_override("bg",get_stylebox("bg", "Tree"))
703 | _timeline_tools.add_stylebox_override("normal", get_stylebox("normal", "Button"))
704 |
705 | var menu:PopupMenu = _timeline_tools.get_popup()
706 | menu.set_item_icon(menu.get_item_index(TOOL_NEW_TIMELINE), get_icon("New", "EditorIcons"))
707 | menu.set_item_icon(menu.get_item_index(TOOL_DUPLICATE_TIMELINE), get_icon("Duplicate", "EditorIcons"))
708 | menu.set_item_icon(menu.get_item_index(TOOL_EDIT_RESOURCE), get_icon("Edit", "EditorIcons"))
709 | menu.set_item_icon(menu.get_item_index(TOOL_REMOVE_TIMELINE), get_icon("Remove", "EditorIcons"))
710 | menu.set_item_icon(menu.get_item_index(TOOL_RENAME_TIMELINE), get_icon("Rename", "EditorIcons"))
711 |
712 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/nodes/editor/timeline_list.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends OptionButton
3 |
4 | const EvManager = preload("res://addons/event_system_plugin/nodes/event_manager/event_manager.gd")
5 |
6 | var plugin:EditorPlugin
7 | var node:EvManager
8 |
9 | func list_timelines() -> void:
10 | clear()
11 | if !is_instance_valid(node):
12 | disabled = true
13 | return
14 |
15 | disabled = false
16 | for timeline_name in node.get_timeline_list():
17 | add_item(timeline_name)
18 |
19 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/nodes/editor/welcome/main_panel.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Control
3 |
4 | export(NodePath) var VersionNodePath:NodePath
5 |
6 | var repository:String = ""
7 | var docs:String = ""
8 | var version:String = "0"
9 |
10 | onready var version_node:Label = get_node(VersionNodePath) as Label
11 |
12 | func _ready() -> void:
13 | version_node.text = version
14 |
15 |
16 | func _on_Docs_pressed() -> void:
17 | OS.shell_open(docs)
18 |
19 |
20 | func _on_Repository_pressed() -> void:
21 | OS.shell_open(repository)
22 |
23 |
24 | func _on_License_pressed() -> void:
25 | var license_path = ProjectSettings.globalize_path("res://addons/event_system_plugin/LICENSE")
26 | OS.shell_open(license_path)
27 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/nodes/editor/welcome/main_panel.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=2]
2 |
3 | [ext_resource path="res://icon.png" type="Texture" id=1]
4 | [ext_resource path="res://addons/event_system_plugin/nodes/editor/welcome/main_panel.gd" type="Script" id=2]
5 |
6 | [node name="PanelContainer" type="PanelContainer"]
7 | anchor_right = 1.0
8 | anchor_bottom = 1.0
9 | size_flags_horizontal = 3
10 | size_flags_vertical = 3
11 | script = ExtResource( 2 )
12 | __meta__ = {
13 | "_edit_use_anchors_": false
14 | }
15 | VersionNodePath = NodePath("VBoxContainer/HBoxContainer/VBoxContainer/Version")
16 |
17 | [node name="VBoxContainer" type="VBoxContainer" parent="."]
18 | margin_left = 32.0
19 | margin_top = 7.0
20 | margin_right = 1017.0
21 | margin_bottom = 593.0
22 |
23 | [node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"]
24 | margin_right = 985.0
25 | margin_bottom = 562.0
26 | size_flags_vertical = 3
27 | custom_constants/separation = 16
28 |
29 | [node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"]
30 | margin_right = 128.0
31 | margin_bottom = 562.0
32 | alignment = 1
33 |
34 | [node name="Button" type="Button" parent="VBoxContainer/HBoxContainer/VBoxContainer"]
35 | margin_top = 208.0
36 | margin_right = 128.0
37 | margin_bottom = 336.0
38 | rect_min_size = Vector2( 128, 128 )
39 | icon = ExtResource( 1 )
40 | clip_text = true
41 | expand_icon = true
42 |
43 | [node name="Version" type="Label" parent="VBoxContainer/HBoxContainer/VBoxContainer"]
44 | margin_top = 340.0
45 | margin_right = 128.0
46 | margin_bottom = 354.0
47 | text = "{VERSION_NUMBER}"
48 | align = 1
49 |
50 | [node name="VBoxContainer2" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"]
51 | margin_left = 144.0
52 | margin_right = 985.0
53 | margin_bottom = 562.0
54 | size_flags_horizontal = 3
55 | alignment = 1
56 |
57 | [node name="Label3" type="Label" parent="VBoxContainer/HBoxContainer/VBoxContainer2"]
58 | margin_top = 207.0
59 | margin_right = 841.0
60 | margin_bottom = 255.0
61 | text = "Many thanks for using EventSystem!
62 |
63 | This plugin was made for the comunnity."
64 | autowrap = true
65 |
66 | [node name="HSeparator2" type="HSeparator" parent="VBoxContainer/HBoxContainer/VBoxContainer2"]
67 | margin_top = 259.0
68 | margin_right = 841.0
69 | margin_bottom = 263.0
70 | __meta__ = {
71 | "_edit_use_anchors_": false
72 | }
73 |
74 | [node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/VBoxContainer2"]
75 | margin_top = 267.0
76 | margin_right = 841.0
77 | margin_bottom = 281.0
78 | text = "Take a look in the documentation page:"
79 |
80 | [node name="Docs" type="Button" parent="VBoxContainer/HBoxContainer/VBoxContainer2"]
81 | margin_top = 285.0
82 | margin_right = 841.0
83 | margin_bottom = 305.0
84 | text = "Documentation Page"
85 |
86 | [node name="HSeparator" type="HSeparator" parent="VBoxContainer/HBoxContainer/VBoxContainer2"]
87 | margin_top = 309.0
88 | margin_right = 841.0
89 | margin_bottom = 313.0
90 |
91 | [node name="Label2" type="Label" parent="VBoxContainer/HBoxContainer/VBoxContainer2"]
92 | margin_top = 317.0
93 | margin_right = 841.0
94 | margin_bottom = 331.0
95 | text = "Github Repository:"
96 |
97 | [node name="Repository" type="Button" parent="VBoxContainer/HBoxContainer/VBoxContainer2"]
98 | margin_top = 335.0
99 | margin_right = 841.0
100 | margin_bottom = 355.0
101 | hint_tooltip = "You can report bugs, request features or help with the plugin here"
102 | text = "AnidemDex/Godot-EventSystem"
103 |
104 | [node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer"]
105 | margin_top = 566.0
106 | margin_right = 985.0
107 | margin_bottom = 586.0
108 |
109 | [node name="License" type="Button" parent="VBoxContainer/HBoxContainer2"]
110 | margin_right = 91.0
111 | margin_bottom = 20.0
112 | text = "MIT LICENSE"
113 |
114 | [connection signal="pressed" from="VBoxContainer/HBoxContainer/VBoxContainer2/Docs" to="." method="_on_Docs_pressed"]
115 | [connection signal="pressed" from="VBoxContainer/HBoxContainer/VBoxContainer2/Repository" to="." method="_on_Repository_pressed"]
116 | [connection signal="pressed" from="VBoxContainer/HBoxContainer2/License" to="." method="_on_License_pressed"]
117 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/nodes/event_manager/event_manager.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Node
3 | class_name EventManager
4 |
5 | ##
6 | ## Base class for all event manager nodes.
7 | ##
8 | ## EventManager executes the event behaviour, and manages the event order execution.
9 | ##
10 |
11 | signal custom_signal(data)
12 |
13 | ## Emmited when an Event is executed. Event resource is passed in the signal
14 | signal event_started(event)
15 | ## Emmited when an Event finished. Event resource is passed in the signal.
16 | signal event_finished(event)
17 |
18 | ## Emmited when a timeline starts. Timeline resource is passed in the signal
19 | signal timeline_started(timeline_resource)
20 | ## Emmited when a timeline finish. Timeline resource is passed in the signal
21 | signal timeline_finished(timeline_resource)
22 |
23 | ## This is the node were events will be applied to.
24 | ## This node is used if the event doesn't define an [member Event.event_node_path]
25 | ## and is relative to the current scene node owner.
26 | export(NodePath) var event_node_fallback_path:NodePath = "."
27 | ## If is [code]true[/code], the node will call [method start_timeline] when owner is ready.
28 | export(bool) var start_on_ready:bool = false
29 |
30 | ## Current timeline name. You can get the current timeline resource with [method get_timeline]
31 | var current_timeline:String=""
32 | ## Current executed event.
33 | var current_event
34 | ## The current event position accordint to [member current_timeline] resource.
35 | var current_idx:int = -1
36 |
37 | var __data := {}
38 |
39 | func _ready() -> void:
40 | if Engine.editor_hint:
41 | return
42 |
43 | if start_on_ready:
44 | call_deferred("start_timeline", current_timeline)
45 |
46 | ## Starts timeline. This method must be called to start EventManager process.
47 | ## [code]timeline_name[/code] is the name of any timeline saved in the node.
48 | ## You can optionally pass [code]from_event_index[/code] to define from
49 | ## where the timeline should start.
50 | func start_timeline(timeline_name:String, from_event_index:int=0) -> void:
51 | if timeline_name == "[None]":
52 | return
53 |
54 | if !has_timeline(timeline_name):
55 | push_error("start_timeline: Can't find %p timeline"%timeline_name)
56 | return
57 |
58 | current_timeline = timeline_name
59 | _notify_timeline_start()
60 | go_to_next_event()
61 |
62 | ## Advances to the next event in the current timeline.
63 | func go_to_next_event() -> void:
64 | var event
65 |
66 | if current_timeline == "" or !has_timeline(current_timeline):
67 | # For some reason, the current timeline doesn't exist
68 |
69 | return
70 |
71 |
72 | if current_event:
73 | if "next_event" in current_event and current_event["next_event"] != "":
74 | var data = current_event.get("next_event").split(";")
75 | current_idx = int(data[0])
76 | var new_timeline = ""
77 | if data.size() > 1:
78 | new_timeline = data[1]
79 |
80 | if new_timeline != "":
81 | current_timeline = new_timeline
82 | else:
83 | current_idx += 1
84 |
85 | if current_idx < 0:
86 | current_idx = 0
87 |
88 | var timeline = get_timeline(current_timeline)
89 |
90 | event = timeline.get("event/{idx}".format({"idx":current_idx}))
91 | current_event = event
92 |
93 | if current_event == null:
94 | _notify_timeline_end()
95 | return
96 |
97 | _execute_event(event)
98 |
99 | ## Adds a [code]timeline[/code] to this node named [code]timeline_name[/code].
100 | func add_timeline(timeline_name:String, timeline) -> void:
101 | if timeline_name == "":
102 | push_error("add_timeline: Tried to add a timeline with an empty name!")
103 | return
104 |
105 | if timeline == null:
106 | push_error("add_timeline: Tried to add '%s' with a null value"%timeline_name)
107 | return
108 |
109 | if has_timeline(timeline_name):
110 | push_error("add_timeline: Timeline '%s' already exist"%timeline_name)
111 | return
112 |
113 | __data[timeline_name] = timeline
114 | property_list_changed_notify()
115 |
116 | ## Returns the [code]timeline[/code] associated to [code]timeline_name[/code]
117 | func get_timeline(timeline_name:String) -> Timeline:
118 | var res = null
119 |
120 | if !has_timeline(timeline_name):
121 | push_error("get_timeline: Can't find {n} timeline".format({"n":timeline_name}))
122 |
123 | res = __data.get(timeline_name, null)
124 | return res
125 |
126 | ## Returns true if the node has a [code]timeline_name[/code]
127 | func has_timeline(timeline_name:String) -> bool:
128 | return __data.has(timeline_name)
129 |
130 | ## Removes the timeline associated to [code]timeline_name[/code]
131 | func remove_timeline(timeline_name:String) -> void:
132 | if !has_timeline(timeline_name):
133 | push_warning("remove_timeline: Tried to remove '%s' timeline but the timeline doesn't exist."%timeline_name)
134 | return
135 | __data.erase(timeline_name)
136 | property_list_changed_notify()
137 |
138 | ## Renames [code]timeline_name[/code] to [code]new_name[/code]
139 | func rename_timeline(timeline_name:String, new_name:String) -> void:
140 | var timeline:Timeline = get_timeline(timeline_name)
141 |
142 | if !has_timeline(timeline_name):
143 | push_warning("rename_timeline: Tried to rename '%s' timeline but the timeline doesn't exist."%timeline_name)
144 | return
145 |
146 | if has_timeline(new_name):
147 | push_warning("rename_timeline: Tried to rename '{name}' timeline to '{new_name}' but '{new_name}' already exist.".format({"name":timeline_name, "new_name":new_name}))
148 | return
149 |
150 | remove_timeline(timeline_name)
151 | add_timeline(new_name, timeline)
152 |
153 | ## Returns a [class PoolStringArray] containing timeline names saved on this node.
154 | func get_timeline_list() -> PoolStringArray:
155 | return PoolStringArray(__data.keys())
156 |
157 |
158 | func _execute_event(event:Event) -> void:
159 | if event == null:
160 | assert(false)
161 | return
162 |
163 | var node:Node = self if event_node_fallback_path == @"." else get_node(event_node_fallback_path)
164 | # This is a crime, needs to be modified in future versions
165 | event.set("_event_manager", self)
166 | event.set("_event_node_fallback", node)
167 |
168 | _connect_event_signals(event)
169 |
170 | event.execute()
171 |
172 |
173 | func _connect_event_signals(event:Event) -> void:
174 | if not event.is_connected("event_started", self, "_on_Event_started"):
175 | event.connect("event_started", self, "_on_Event_started", [], CONNECT_ONESHOT)
176 | if not event.is_connected("event_finished", self, "_on_Event_finished"):
177 | event.connect("event_finished", self, "_on_Event_finished", [], CONNECT_ONESHOT)
178 |
179 |
180 | func _on_Event_started(event:Event) -> void:
181 | emit_signal("event_started", event)
182 |
183 |
184 | func _on_Event_finished(event:Event) -> void:
185 | emit_signal("event_finished", event)
186 | if event.continue_at_end:
187 | go_to_next_event()
188 |
189 |
190 | func _notify_timeline_start() -> void:
191 | emit_signal("timeline_started", get_timeline(current_timeline))
192 |
193 |
194 | func _notify_timeline_end() -> void:
195 | emit_signal("timeline_finished", get_timeline(current_timeline))
196 |
197 |
198 | func _hide_script_from_inspector():
199 | return true
200 |
201 |
202 | func _set(property:String, value) -> bool:
203 | if property == "timeline":
204 | property = "timeline/legacy_timeline"
205 |
206 | if property.begins_with("timeline/"):
207 | var p := property.replace("timeline/", "")
208 | if p == "":
209 | return false
210 |
211 | add_timeline(p, value)
212 | property_list_changed_notify()
213 |
214 | return true
215 |
216 | return false
217 |
218 |
219 | func _get(property: String):
220 | if property.begins_with("timeline/"):
221 | var p := property.replace("timeline/", "")
222 | if p == "":
223 | return
224 |
225 | return get_timeline(p)
226 |
227 |
228 | func property_can_revert(property:String) -> bool:
229 | if property == "current_timeline":
230 | return true
231 | return false
232 |
233 |
234 | func property_get_revert(property:String):
235 | if property == "current_timeline":
236 | return "[None]"
237 |
238 |
239 | func _get_property_list() -> Array:
240 | var p := []
241 | var hint_string = "[None]"
242 | for timeline_name in get_timeline_list():
243 | hint_string += ",%s"%timeline_name
244 | p.append({"type":TYPE_STRING, "name":"current_timeline", "hint":PROPERTY_HINT_ENUM, "hint_string":hint_string, "usage":PROPERTY_USAGE_SCRIPT_VARIABLE|PROPERTY_USAGE_DEFAULT})
245 |
246 | var usage := PROPERTY_USAGE_SCRIPT_VARIABLE | PROPERTY_USAGE_NOEDITOR
247 | for timeline_name in __data.keys():
248 | p.append({"type":TYPE_OBJECT, "name":"timeline/"+timeline_name, "usage":usage})
249 | return p
250 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/plugin.cfg:
--------------------------------------------------------------------------------
1 | [plugin]
2 |
3 | name="EventSystem"
4 | description="An easy but powerful event system implementation for Godot Engine"
5 | author="AnidemDex"
6 | version="2.0"
7 | script="plugin_script.gd"
8 | repository="https://github.com/AnidemDex/Godot-EventSystem"
9 | license="https://github.com/AnidemDex/Godot-EventSystem/blob/main/LICENSE"
10 | docs="https://godotplugins.gitbook.io/eventsystem/"
11 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/plugin_script.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends "godot_plugin.gd"
3 |
4 | const TimelineEditor = preload("nodes/editor/timeline_editor.gd")
5 | const EventManagerClass = preload("nodes/event_manager/event_manager.gd")
6 | const EventClass = preload("resources/event_class/event_class.gd")
7 | const TimelineClass = preload("resources/timeline_class/timeline_class.gd")
8 |
9 | var timeline_editor:TimelineEditor
10 | var timeline_dock_button:ToolButton
11 |
12 | func _enter_tree():
13 | var inspector:EditorInspectorPlugin = load("res://addons/event_system_plugin/core/event_inspector.gd").new()
14 | register_editor_plugin(inspector)
15 |
16 | show_plugin_version_button()
17 |
18 | timeline_editor.connect("inspection_requested", self, "_on_TimelineEditor_inspect")
19 | timeline_dock_button = add_control_to_bottom_panel(timeline_editor, "TimelineEditor")
20 | timeline_dock_button.call_deferred("hide")
21 |
22 | var main_panel:PanelContainer = load("res://addons/event_system_plugin/nodes/editor/welcome/main_panel.tscn").instance()
23 | main_panel.set("repository", get_plugin_repository())
24 | main_panel.set("docs", get_plugin_docs_url())
25 | main_panel.set("version", get_plugin_version())
26 | get_plugin_welcome_node().get_tab_by_idx(0).add_child(main_panel)
27 |
28 |
29 | func _enable_plugin():
30 | show_welcome_node()
31 |
32 |
33 | func _handles(object: Object) -> bool:
34 | if object is Script:
35 | return false
36 |
37 | if object.get_class() == "ScriptEditorDebuggerInspectedObject":
38 | return false
39 |
40 |
41 | if object as EventManagerClass != null:
42 | return true
43 |
44 | if object as TimelineClass != null:
45 | return true
46 |
47 | return false
48 |
49 |
50 | func _edit(object: Object) -> void:
51 | timeline_editor.set_undo_redo(get_undo_redo())
52 | timeline_editor.edit(object)
53 |
54 |
55 | func _make_visible(visible: bool) -> void:
56 | if visible:
57 | timeline_dock_button.show()
58 | make_bottom_panel_item_visible(timeline_editor)
59 | timeline_editor.set_process_input(true)
60 | else:
61 | if timeline_dock_button.is_visible_in_tree():
62 | hide_bottom_panel()
63 | timeline_dock_button.hide()
64 | timeline_editor.set_process_input(false)
65 |
66 |
67 | func _scene_change(scene_root:Node) -> void:
68 | pass
69 |
70 |
71 | func _on_TimelineEditor_inspect(resource:Resource) -> void:
72 | get_editor_interface().inspect_object(resource, "", true)
73 |
74 |
75 | func _init() -> void:
76 | timeline_editor = TimelineEditor.new()
77 | register_plugin_node(timeline_editor)
78 |
79 | connect("scene_changed", self, "_scene_change")
80 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/resources/event_class/event_class.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Resource
3 | class_name Event, "res://addons/event_system_plugin/assets/icons/timeline_icon.png"
4 |
5 | ##
6 | ## Base class for all events.
7 | ##
8 | ## Every event relies on this class.
9 | ## If you want to do your own event, you should [code]extend[/code] this class.
10 | ##
11 |
12 | ## Emmited when the event starts.
13 | ## The signal is emmited with the event resource [code]event_resource[/code]
14 | signal event_started(event_resource)
15 |
16 | ## Emmited when the event finish.
17 | ## The signal is emmited with the event resource [code]event_resource[/code]
18 | signal event_finished(event_resource)
19 |
20 | ##########
21 | # Default Event Properties
22 | ##########
23 |
24 | ## Determines if the event will go to next event inmediatly or not.
25 | ## If value is true, the next event will be executed when event ends.
26 | export(bool) var continue_at_end:bool = true setget _set_continue
27 |
28 | var event_node_path:NodePath setget _set_event_node_path
29 |
30 | ##########
31 | # Event Editor Properties
32 | ##########
33 |
34 | ## The event icon that'll be displayed in the editor
35 | var event_icon:Texture setget ,get_event_icon
36 |
37 | ## The event color that event node will take in the editor
38 | var event_color:Color = Color("FBB13C")
39 |
40 | ## The event name that'll be displayed in the editor.
41 | ## If the resource name is different from the event name, resource_name is returned instead.
42 | var event_name:String = "Event" setget ,get_event_name
43 |
44 | ## The event preview string that will be displayed next to the event name in the editor.
45 | ## You can use String formats to parse variables from the script:
46 | ## [codeblock] event_preview_string = "{resource_name}" [/codeblock]
47 | ## Will display the resource's name instead of [code]{resource_name}[/code].
48 | var event_preview_string:String = ""
49 |
50 | ## The event hint that'll be displayed when you hover the event button in the editor.
51 | var event_hint:String = ""
52 |
53 | ## The event category it belongs to. Used by the editor.
54 | var event_category:String = "Custom"
55 |
56 | ## The event indentation level. Used by the editor.
57 | var event_indent_level:int = 0
58 |
59 | ## Determines if this event uses subevents.
60 | var event_uses_subevents:bool = false
61 |
62 | ## The quantity of subevents this event has.
63 | var event_subevents_quantity:int = 0
64 |
65 | ## Assigned by the editor.
66 | var event_subevent_from:WeakRef = null
67 |
68 | var _event_manager:Node
69 | var _event_node_fallback:Node
70 |
71 | ## Executes the event behaviour.
72 | func execute() -> void:
73 | emit_signal("event_started", self)
74 |
75 | call_deferred("_execute")
76 |
77 |
78 | ## Ends the event behaviour.
79 | func finish() -> void:
80 | emit_signal("event_finished", self)
81 |
82 |
83 | func _execute() -> void:
84 | finish()
85 |
86 |
87 | func get_event_name() -> String:
88 | if event_name != resource_name and resource_name != "":
89 | return resource_name
90 | return event_name
91 |
92 |
93 | func get_event_manager_node() -> Node:
94 | return _event_manager
95 |
96 |
97 | func get_event_node() -> Node:
98 | var event_node:Node
99 | if event_node_path != NodePath():
100 | event_node = get_event_manager_node().get_tree().current_scene.get_node(event_node_path)
101 |
102 | if not is_instance_valid(event_node):
103 | event_node = _event_node_fallback
104 |
105 | return event_node
106 |
107 |
108 | func get_event_icon() -> Texture:
109 | if event_icon:
110 | return event_icon
111 |
112 | var theme:Theme = load("res://addons/event_system_plugin/assets/themes/timeline_editor.tres")
113 | var good_name = event_name.replace(" ","_").to_lower()
114 | if theme.has_icon(good_name, "EventIcons"):
115 | return theme.get_icon(good_name, "EventIcons") as Texture
116 |
117 | return theme.get_icon("custom", "EventIcons") as Texture
118 |
119 |
120 | func _set_continue(value:bool) -> void:
121 | continue_at_end = value
122 | property_list_changed_notify()
123 | emit_changed()
124 |
125 |
126 | func _set_event_node_path(value:NodePath) -> void:
127 | event_node_path = value
128 | property_list_changed_notify()
129 | emit_changed()
130 |
131 |
132 | func _set(property: String, value) -> bool:
133 |
134 | if property == "event_manager":
135 | _event_manager = value
136 | return true
137 |
138 | if property == "resource_name":
139 | event_name = property
140 | emit_changed()
141 | property_list_changed_notify()
142 | return true
143 |
144 | return false
145 |
146 | func _get(property: String):
147 | if property == "resource_name":
148 | return event_name
149 |
150 |
151 | func _get_property_list() -> Array:
152 | var p:Array = []
153 | p.append({"name":"event_node_path", "type":TYPE_NODE_PATH})
154 | p.append({"name":"event_subevents_quantity", "type":TYPE_INT, "usage":PROPERTY_USAGE_SCRIPT_VARIABLE|PROPERTY_USAGE_NOEDITOR})
155 |
156 | return p
157 |
158 |
159 | func property_can_revert(property:String) -> bool:
160 | if property == "event_node_path":
161 | return true
162 | return false
163 |
164 |
165 | func property_get_revert(property:String):
166 | if property == "event_node_path":
167 | return NodePath()
168 |
169 |
170 | func _to_string() -> String:
171 | return "[{event_name}:{id}]".format({"event_name":event_name, "id":get_instance_id()})
172 |
173 |
174 | func _hide_script_from_inspector():
175 | return true
176 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/resources/registered_events/_.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends "res://addons/event_system_plugin/resources/timeline_class/timeline_class.gd"
3 |
4 | ## This file stores events displayed in the editor toolbar.
5 |
6 | func _init():
7 | var events = [
8 | load("res://addons/event_system_plugin/events/call_from.gd").new(),
9 | load("res://addons/event_system_plugin/events/comment.gd").new(),
10 | load("res://addons/event_system_plugin/events/emit_signal.gd").new(),
11 | load("res://addons/event_system_plugin/events/end_timeline.gd").new(),
12 | load("res://addons/event_system_plugin/events/hide.gd").new(),
13 | load("res://addons/event_system_plugin/events/condition.gd").new(),
14 | load("res://addons/event_system_plugin/events/set.gd").new(),
15 | load("res://addons/event_system_plugin/events/show.gd").new(),
16 | load("res://addons/event_system_plugin/events/wait.gd").new(),
17 | load("res://addons/event_system_plugin/events/goto.gd").new()
18 | ]
19 |
20 | for ev in events:
21 | register_event(ev)
22 |
23 |
24 | func register_event(event) -> void:
25 | if event == null:
26 | return
27 |
28 | var _scripts := []
29 | for _event in _events:
30 | _scripts.append((event as Resource).get_script())
31 |
32 | if event.get_script() in _scripts:
33 | return
34 |
35 | add_event(event)
36 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/resources/registered_events/registered_events.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" load_steps=22 format=2]
2 |
3 | [ext_resource path="res://addons/event_system_plugin/resources/registered_events/_.gd" type="Script" id=1]
4 | [ext_resource path="res://addons/event_system_plugin/events/comment.gd" type="Script" id=2]
5 | [ext_resource path="res://addons/event_system_plugin/events/set.gd" type="Script" id=3]
6 | [ext_resource path="res://addons/event_system_plugin/events/goto.gd" type="Script" id=4]
7 | [ext_resource path="res://addons/event_system_plugin/events/wait.gd" type="Script" id=5]
8 | [ext_resource path="res://addons/event_system_plugin/events/condition.gd" type="Script" id=6]
9 | [ext_resource path="res://addons/event_system_plugin/events/emit_signal.gd" type="Script" id=7]
10 | [ext_resource path="res://addons/event_system_plugin/events/show.gd" type="Script" id=9]
11 | [ext_resource path="res://addons/event_system_plugin/events/hide.gd" type="Script" id=10]
12 | [ext_resource path="res://addons/event_system_plugin/events/end_timeline.gd" type="Script" id=11]
13 | [ext_resource path="res://addons/event_system_plugin/events/call_from.gd" type="Script" id=12]
14 |
15 | [sub_resource type="Resource" id=1]
16 | resource_name = "Call"
17 | script = ExtResource( 12 )
18 | continue_at_end = true
19 | method = ""
20 | args = [ ]
21 | event_node_path = NodePath("")
22 | event_subevents_quantity = 0
23 |
24 | [sub_resource type="Resource" id=2]
25 | resource_name = "Comment"
26 | script = ExtResource( 2 )
27 | continue_at_end = true
28 | text = ""
29 | event_node_path = NodePath("")
30 | event_subevents_quantity = 0
31 |
32 | [sub_resource type="Resource" id=3]
33 | resource_name = "Emit Signal"
34 | script = ExtResource( 7 )
35 | continue_at_end = true
36 | data = ""
37 | event_node_path = NodePath("")
38 | event_subevents_quantity = 0
39 |
40 | [sub_resource type="Resource" id=4]
41 | resource_name = "End Timeline"
42 | script = ExtResource( 11 )
43 | continue_at_end = true
44 | event_node_path = NodePath("")
45 | event_subevents_quantity = 0
46 |
47 | [sub_resource type="Resource" id=5]
48 | resource_name = "Hide"
49 | script = ExtResource( 10 )
50 | continue_at_end = true
51 | method = "set"
52 | args = [ "visible", false ]
53 | event_node_path = NodePath("")
54 | event_subevents_quantity = 0
55 |
56 | [sub_resource type="Resource" id=6]
57 | resource_name = "Condition"
58 | script = ExtResource( 6 )
59 | continue_at_end = true
60 | condition = ""
61 | event_node_path = NodePath("")
62 | event_subevents_quantity = 0
63 |
64 | [sub_resource type="Resource" id=7]
65 | resource_name = "Set"
66 | script = ExtResource( 3 )
67 | continue_at_end = true
68 | method = "set"
69 | args = [ "", "" ]
70 | variable_name = ""
71 | variable_value = ""
72 | event_node_path = NodePath("")
73 | event_subevents_quantity = 0
74 |
75 | [sub_resource type="Resource" id=8]
76 | resource_name = "Show"
77 | script = ExtResource( 9 )
78 | continue_at_end = true
79 | method = "set"
80 | args = [ "visible", true ]
81 | event_node_path = NodePath("")
82 | event_subevents_quantity = 0
83 |
84 | [sub_resource type="Resource" id=9]
85 | resource_name = "Wait"
86 | script = ExtResource( 5 )
87 | continue_at_end = true
88 | wait_time = 0.0
89 | event_node_path = NodePath("")
90 | event_subevents_quantity = 0
91 |
92 | [sub_resource type="Resource" id=10]
93 | resource_name = "Go to"
94 | script = ExtResource( 4 )
95 | continue_at_end = true
96 | next_event = ""
97 | event_node_path = NodePath("")
98 | event_subevents_quantity = 0
99 |
100 | [resource]
101 | resource_name = "Timeline"
102 | script = ExtResource( 1 )
103 | event/0 = SubResource( 1 )
104 | event/1 = SubResource( 2 )
105 | event/2 = SubResource( 3 )
106 | event/3 = SubResource( 4 )
107 | event/4 = SubResource( 5 )
108 | event/5 = SubResource( 6 )
109 | event/6 = SubResource( 7 )
110 | event/7 = SubResource( 8 )
111 | event/8 = SubResource( 9 )
112 | event/9 = SubResource( 10 )
113 |
--------------------------------------------------------------------------------
/addons/event_system_plugin/resources/timeline_class/timeline_class.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Resource
3 | class_name Timeline, "res://addons/event_system_plugin/assets/icons/timeline_icon.png"
4 |
5 | ##
6 | ## Base class for all Timelines
7 | ##
8 | ## This resource only keeps an ordered reference of all events registered on it.
9 |
10 | # Can't reference:
11 | # - EventManager node
12 | # - Event
13 | # Note for future devs: Keep this resource as an event container. No magic tricks
14 | var _events:Array = [] setget set_events
15 | var _structure:Dictionary = {}
16 |
17 | ## Sets the event collection of this timeline. This replaces the current collection.
18 | func set_events(events:Array) -> void:
19 | _events = events
20 | emit_changed()
21 | property_list_changed_notify()
22 |
23 | ## Adds an event to the timeline.
24 | func add_event(event) -> void:
25 | if has(event):
26 | push_error("add_event: Trying to add an event to the timeline, but the event is already added")
27 | return
28 |
29 | _events.append(event)
30 |
31 | update_structure()
32 | emit_changed()
33 | property_list_changed_notify()
34 |
35 | ## Insert an [code]event[/code] at position.
36 | func insert_event(event, at_position:int) -> void:
37 | if has(event):
38 | push_error("insert_event: Trying to add an event to the timeline, but the event already exist")
39 | return
40 |
41 | var idx = at_position if at_position > -1 else _events.size()
42 | _events.insert(idx, event)
43 |
44 | update_structure()
45 | emit_changed()
46 | property_list_changed_notify()
47 |
48 | ## Moves an [code]event[/code] to position.
49 | func move_event(event, to_position:int) -> void:
50 | if !has(event):
51 | push_error("move_event: Trying to move an event in the timeline, but the event is not added.")
52 | return
53 |
54 | var old_position:int = get_event_idx(event)
55 | if old_position < 0:
56 | return
57 |
58 | to_position = to_position if to_position > -1 else _events.size()
59 | if to_position == old_position:
60 | emit_changed()
61 | return
62 |
63 | _events.remove(old_position)
64 |
65 | if to_position < 0 or to_position > _events.size():
66 | to_position = _events.size()
67 |
68 | _events.insert(to_position, event)
69 |
70 | update_structure()
71 | emit_changed()
72 | property_list_changed_notify()
73 |
74 |
75 | ## Removes an event from the timeline.
76 | func erase_event(event) -> void:
77 | _events.erase(event)
78 | update_structure()
79 | emit_changed()
80 | property_list_changed_notify()
81 |
82 | ## Removes an event at [code]position[/code] from the timelin
83 | func remove_event(position:int) -> void:
84 | _events.remove(position)
85 | update_structure()
86 | emit_changed()
87 | property_list_changed_notify()
88 |
89 | ## Get the event at [code]position[/code]
90 | func get_event(position:int) -> Resource:
91 | if position == -1:
92 | return null
93 |
94 | if position < _events.size():
95 | return _events[position]
96 |
97 | push_error("get_event: Tried to get an event on a non-existing position.")
98 | return null
99 |
100 | ## Returns [code]true[/code] if the [code]event[/code] is sub-event of [code]of_event[/code]
101 | func event_is_subevent_of(event, of_event) -> bool:
102 | if of_event in _structure:
103 | return event in _structure.get(of_event, [])
104 | return false
105 |
106 | ## Returns an array that contains the sub-events of [code]event[/code]
107 | func get_event_subevents(event) -> Array:
108 | var subevents:Array = []
109 | if event in _structure:
110 | subevents = _structure.get(event, [])
111 | return subevents
112 |
113 | ## Updates the internal event structure.
114 | func update_structure() -> void:
115 | var subevent_holders := []
116 |
117 | for event in _events:
118 | _structure[event] = []
119 | event.set("event_subevent_from", null)
120 | event.set("event_indent_level", 0)
121 | if event.get("event_uses_subevents"):
122 | subevent_holders.append(event)
123 |
124 | _structure["subevent_holders"] = subevent_holders
125 |
126 | for event in subevent_holders:
127 | var from_here := false
128 | var sub_ev_counter := 0
129 |
130 | for sub_ev in _events:
131 | if from_here:
132 | sub_ev_counter += 1
133 | if sub_ev_counter > event.get("event_subevents_quantity"):
134 | break
135 | _structure[event].append(sub_ev)
136 | sub_ev.set("event_subevent_from", weakref(event))
137 | sub_ev.set("event_indent_level", event.get("event_indent_level")+1)
138 |
139 | elif sub_ev != event:
140 | continue
141 |
142 | from_here = true
143 |
144 | if sub_ev_counter < 1:
145 | event.set("event_subevents_quantity", 0)
146 |
147 | ## Returns [code]true[/code] if the timeline contains that event.
148 | func has(event:Resource) -> bool:
149 | return _events.has(event)
150 |
151 | ## Returns the event position in the timeline.
152 | func get_event_idx(event) -> int:
153 | return _events.find(event)
154 |
155 | ## Returns an array containing the events of the timeline.
156 | func get_events() -> Array:
157 | return _events.duplicate()
158 |
159 |
160 | func _set(property:String, value) -> bool:
161 | var has_property := false
162 |
163 | if property.begins_with("event/"):
164 | var event_idx:int = int(property.split("/", true, 2)[1])
165 | if event_idx < _events.size():
166 | _events[event_idx] = value
167 | else:
168 | _events.insert(event_idx, value)
169 |
170 | has_property = true
171 | emit_changed()
172 |
173 | return has_property
174 |
175 |
176 | func _get(property:String):
177 | if property.begins_with("event/"):
178 | var event_idx:int = int(property.split("/", true, 2)[1])
179 | if event_idx == -1:
180 | return null
181 | return get_event(event_idx)
182 |
183 |
184 | func _init() -> void:
185 | _events = []
186 | _structure = {}
187 | resource_name = get_class()
188 |
189 |
190 | func _to_string() -> String:
191 | return "[{class}:{id}]".format({"class":get_class(), "id":get_instance_id()})
192 |
193 |
194 | func get_class() -> String: return "Timeline"
195 |
196 |
197 | func _get_property_list() -> Array:
198 | var p = []
199 | for event_idx in _events.size():
200 | p.append(
201 | {
202 | "name":"event/{idx}".format({"idx":event_idx}),
203 | "type":TYPE_OBJECT,
204 | "usage":PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_SCRIPT_VARIABLE
205 | }
206 | )
207 | return p
208 |
--------------------------------------------------------------------------------