└── addons
└── ui_design_tool
├── assets
└── icons
│ ├── folder_open-white-18dp.svg
│ ├── folder_open-white-18dp.svg.import
│ ├── format-color-text.png
│ ├── format-color-text.png.import
│ ├── format_align_center-white-18dp.svg
│ ├── format_align_center-white-18dp.svg.import
│ ├── format_align_left-white-18dp.svg
│ ├── format_align_left-white-18dp.svg.import
│ ├── format_align_right-white-18dp.svg
│ ├── format_align_right-white-18dp.svg.import
│ ├── format_bold-white-18dp.svg
│ ├── format_bold-white-18dp.svg.import
│ ├── format_clear-white-18dp.svg
│ ├── format_clear-white-18dp.svg.import
│ ├── format_color_reset-white-18dp.svg
│ ├── format_color_reset-white-18dp.svg.import
│ ├── format_italic-white-18dp.svg
│ ├── format_italic-white-18dp.svg.import
│ ├── format_underlined-white-18dp.svg
│ ├── format_underlined-white-18dp.svg.import
│ ├── marker.png
│ ├── marker.png.import
│ ├── more_horiz-white-18dp.svg
│ ├── more_horiz-white-18dp.svg.import
│ ├── more_vert-white-18dp.svg
│ ├── more_vert-white-18dp.svg.import
│ ├── photo_size_select_small-white-18dp.svg
│ ├── photo_size_select_small-white-18dp.svg.import
│ ├── refresh-white-18dp.svg
│ ├── refresh-white-18dp.svg.import
│ ├── vertical_align_bottom-white-18dp.svg
│ ├── vertical_align_bottom-white-18dp.svg.import
│ ├── vertical_align_center-white-18dp.svg
│ ├── vertical_align_center-white-18dp.svg.import
│ ├── vertical_align_top-white-18dp.svg
│ └── vertical_align_top-white-18dp.svg.import
├── plugin.cfg
├── plugin.gd
├── scenes
├── OverlayTextEdit.gd
├── OverlayTextEdit.tscn
├── Toolbar.gd
└── Toolbar.tscn
└── scripts
├── FontManager.gd
└── Utils.gd
/addons/ui_design_tool/assets/icons/folder_open-white-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/folder_open-white-18dp.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://d1uver224k3px"
6 | path="res://.godot/imported/folder_open-white-18dp.svg-b9b09b2c311e4324f6ceb8d836d92307.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/ui_design_tool/assets/icons/folder_open-white-18dp.svg"
14 | dest_files=["res://.godot/imported/folder_open-white-18dp.svg-b9b09b2c311e4324f6ceb8d836d92307.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/format-color-text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imjp94/UIDesignTool/0e3bdbbfe966a4ff27ab9b711eff55a049968fd9/addons/ui_design_tool/assets/icons/format-color-text.png
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/format-color-text.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://b3tqua2bt1ix2"
6 | path="res://.godot/imported/format-color-text.png-cb1d0e154a77178073ac1079d1806720.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/ui_design_tool/assets/icons/format-color-text.png"
14 | dest_files=["res://.godot/imported/format-color-text.png-cb1d0e154a77178073ac1079d1806720.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/format_align_center-white-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/format_align_center-white-18dp.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://i11r3de57bc3"
6 | path="res://.godot/imported/format_align_center-white-18dp.svg-223e2eb74ca8e39f9d4bf989291c7829.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/ui_design_tool/assets/icons/format_align_center-white-18dp.svg"
14 | dest_files=["res://.godot/imported/format_align_center-white-18dp.svg-223e2eb74ca8e39f9d4bf989291c7829.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/format_align_left-white-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/format_align_left-white-18dp.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dtsld0omp3fy0"
6 | path="res://.godot/imported/format_align_left-white-18dp.svg-f4e62d6e31b71bc8605b920932857161.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/ui_design_tool/assets/icons/format_align_left-white-18dp.svg"
14 | dest_files=["res://.godot/imported/format_align_left-white-18dp.svg-f4e62d6e31b71bc8605b920932857161.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/format_align_right-white-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/format_align_right-white-18dp.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://d0t8qupuaoigg"
6 | path="res://.godot/imported/format_align_right-white-18dp.svg-639ae8d469d29b7a7afdff99480dfa70.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/ui_design_tool/assets/icons/format_align_right-white-18dp.svg"
14 | dest_files=["res://.godot/imported/format_align_right-white-18dp.svg-639ae8d469d29b7a7afdff99480dfa70.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/format_bold-white-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/format_bold-white-18dp.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://d3xaf7s36xuqc"
6 | path="res://.godot/imported/format_bold-white-18dp.svg-dd70eba3f014196757627e0aea4304f1.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/ui_design_tool/assets/icons/format_bold-white-18dp.svg"
14 | dest_files=["res://.godot/imported/format_bold-white-18dp.svg-dd70eba3f014196757627e0aea4304f1.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/format_clear-white-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/format_clear-white-18dp.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://xnn5xt6piaat"
6 | path="res://.godot/imported/format_clear-white-18dp.svg-47d87e370b9f3dc70b33de4a26f02608.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/ui_design_tool/assets/icons/format_clear-white-18dp.svg"
14 | dest_files=["res://.godot/imported/format_clear-white-18dp.svg-47d87e370b9f3dc70b33de4a26f02608.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/format_color_reset-white-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/format_color_reset-white-18dp.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://8qawl7hrofkj"
6 | path="res://.godot/imported/format_color_reset-white-18dp.svg-e433d2e99c38830ed08d7fa1f97f9a11.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/ui_design_tool/assets/icons/format_color_reset-white-18dp.svg"
14 | dest_files=["res://.godot/imported/format_color_reset-white-18dp.svg-e433d2e99c38830ed08d7fa1f97f9a11.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/format_italic-white-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/format_italic-white-18dp.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://ck4h5hqubttt7"
6 | path="res://.godot/imported/format_italic-white-18dp.svg-7e46946409e5ba47a73f9c86ddf1ce61.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/ui_design_tool/assets/icons/format_italic-white-18dp.svg"
14 | dest_files=["res://.godot/imported/format_italic-white-18dp.svg-7e46946409e5ba47a73f9c86ddf1ce61.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/format_underlined-white-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/format_underlined-white-18dp.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://b44il4qj7cem1"
6 | path="res://.godot/imported/format_underlined-white-18dp.svg-b2765a4e60c3b18727158aebc6b78640.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/ui_design_tool/assets/icons/format_underlined-white-18dp.svg"
14 | dest_files=["res://.godot/imported/format_underlined-white-18dp.svg-b2765a4e60c3b18727158aebc6b78640.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/marker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imjp94/UIDesignTool/0e3bdbbfe966a4ff27ab9b711eff55a049968fd9/addons/ui_design_tool/assets/icons/marker.png
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/marker.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://d1rj7h72swjhn"
6 | path="res://.godot/imported/marker.png-3deee63f805205d2092032fd6772df3e.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/ui_design_tool/assets/icons/marker.png"
14 | dest_files=["res://.godot/imported/marker.png-3deee63f805205d2092032fd6772df3e.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/more_horiz-white-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/more_horiz-white-18dp.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cm5d77b25dgjc"
6 | path="res://.godot/imported/more_horiz-white-18dp.svg-2292c39c5fef87774f0dcabbf9749663.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/ui_design_tool/assets/icons/more_horiz-white-18dp.svg"
14 | dest_files=["res://.godot/imported/more_horiz-white-18dp.svg-2292c39c5fef87774f0dcabbf9749663.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/more_vert-white-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/more_vert-white-18dp.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://crte1qj0ftynh"
6 | path="res://.godot/imported/more_vert-white-18dp.svg-f9ce1c1392fbe43035b0f9c38f40fd8c.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/ui_design_tool/assets/icons/more_vert-white-18dp.svg"
14 | dest_files=["res://.godot/imported/more_vert-white-18dp.svg-f9ce1c1392fbe43035b0f9c38f40fd8c.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/photo_size_select_small-white-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/photo_size_select_small-white-18dp.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cqv3uc8bew0am"
6 | path="res://.godot/imported/photo_size_select_small-white-18dp.svg-a132cc84485fb38b8289f82a1cfb4be4.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/ui_design_tool/assets/icons/photo_size_select_small-white-18dp.svg"
14 | dest_files=["res://.godot/imported/photo_size_select_small-white-18dp.svg-a132cc84485fb38b8289f82a1cfb4be4.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/refresh-white-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/refresh-white-18dp.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dn7q7grbfr7kh"
6 | path="res://.godot/imported/refresh-white-18dp.svg-8592ca638cd7e6c945a15796e8610b7c.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/ui_design_tool/assets/icons/refresh-white-18dp.svg"
14 | dest_files=["res://.godot/imported/refresh-white-18dp.svg-8592ca638cd7e6c945a15796e8610b7c.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/vertical_align_bottom-white-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/vertical_align_bottom-white-18dp.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://rpjhdv5qake3"
6 | path="res://.godot/imported/vertical_align_bottom-white-18dp.svg-d38142e787fc53732b40c7e09204caed.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/ui_design_tool/assets/icons/vertical_align_bottom-white-18dp.svg"
14 | dest_files=["res://.godot/imported/vertical_align_bottom-white-18dp.svg-d38142e787fc53732b40c7e09204caed.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/vertical_align_center-white-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/vertical_align_center-white-18dp.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://ckriw8d4yelu"
6 | path="res://.godot/imported/vertical_align_center-white-18dp.svg-ff9e4504ee166be50beb982105c87414.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/ui_design_tool/assets/icons/vertical_align_center-white-18dp.svg"
14 | dest_files=["res://.godot/imported/vertical_align_center-white-18dp.svg-ff9e4504ee166be50beb982105c87414.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/vertical_align_top-white-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/assets/icons/vertical_align_top-white-18dp.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cjan2dq5nvdvk"
6 | path="res://.godot/imported/vertical_align_top-white-18dp.svg-baa4704503a2c09de95348bc71c911d2.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/ui_design_tool/assets/icons/vertical_align_top-white-18dp.svg"
14 | dest_files=["res://.godot/imported/vertical_align_top-white-18dp.svg-baa4704503a2c09de95348bc71c911d2.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/plugin.cfg:
--------------------------------------------------------------------------------
1 | [plugin]
2 |
3 | name="UI Design Tool"
4 | description=""
5 | author="imjp94"
6 | version="0.2.2"
7 | script="plugin.gd"
8 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/plugin.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends EditorPlugin
3 | const Toolbar = preload("scenes/Toolbar.tscn")
4 | const OverlayTextEdit = preload("scenes/OverlayTextEdit.tscn")
5 |
6 | var toolbar
7 | var overlay_text_edit
8 |
9 | var editor_inspector = get_editor_interface().get_inspector()
10 | var editor_selection = get_editor_interface().get_selection()
11 |
12 |
13 | func _enter_tree():
14 | toolbar = Toolbar.instantiate()
15 | toolbar.undo_redo = get_undo_redo()
16 | toolbar.connect("property_edited", _on_Toolbar_property_edited)
17 | overlay_text_edit = OverlayTextEdit.instantiate()
18 | overlay_text_edit.undo_redo = get_undo_redo()
19 | overlay_text_edit.connect("property_edited", _on_OverlayTextEdit_property_edited)
20 |
21 | editor_inspector.connect("property_selected", _on_property_selected)
22 | editor_selection.connect("selection_changed", _on_selection_changed)
23 |
24 | add_control_to_container(EditorPlugin.CONTAINER_CANVAS_EDITOR_BOTTOM, toolbar)
25 | add_control_to_container(EditorPlugin.CONTAINER_CANVAS_EDITOR_BOTTOM, overlay_text_edit)
26 |
27 | func _exit_tree():
28 | if toolbar:
29 | toolbar.queue_free()
30 | if overlay_text_edit:
31 | overlay_text_edit.queue_free()
32 |
33 | func _handles(object):
34 | if object is Control:
35 | _make_visible(true)
36 | return true
37 | _make_visible(false)
38 | return false
39 |
40 | func _forward_canvas_gui_input(event):
41 | if event is InputEventMouseButton:
42 | if event.button_index == MOUSE_BUTTON_LEFT:
43 | if event.double_click: # Always false when selected multiple nodes
44 | if toolbar.focused_objects:
45 | overlay_text_edit.popup()
46 | return true
47 | return false
48 |
49 | func _make_visible(visible):
50 | if toolbar:
51 | toolbar.visible = visible
52 | # overlay_text_edit only visible on double click
53 |
54 | func _on_property_selected(property):
55 | toolbar.focused_property = property
56 | toolbar.focused_inspector = editor_inspector.get_viewport().gui_get_focus_owner()
57 |
58 | func _on_selection_changed():
59 | var selections = editor_selection.get_selected_nodes()
60 | var is_visible = false
61 | var focused_objects = []
62 | if selections.size() == 1:
63 | var selection = selections[0]
64 | if selection is Control:
65 | focused_objects = [selection]
66 | is_visible = true
67 | elif selections.size() > 1:
68 | var has_non_control = false
69 | for selection in selections:
70 | if not (selection is Control):
71 | has_non_control = true
72 | break
73 | if not has_non_control:
74 | is_visible = true
75 | focused_objects = selections
76 |
77 | toolbar.visible = is_visible
78 | toolbar.focused_objects = focused_objects
79 | overlay_text_edit.focused_objects = focused_objects
80 |
81 | func _on_Toolbar_property_edited(property):
82 | pass
83 |
84 | func _on_OverlayTextEdit_property_edited(property):
85 | pass
86 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/scenes/OverlayTextEdit.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends TextEdit
3 |
4 | signal property_edited(property)
5 |
6 | var focused_objects
7 | var undo_redo
8 |
9 | var _object_orig_text = ""
10 |
11 | func _ready():
12 | set_as_top_level(true)
13 | connect("focus_exited", _on_focused_exited)
14 | connect("text_changed", _on_text_changed)
15 | hide()
16 |
17 | func _on_text_changed():
18 | if focused_objects:
19 | # TODO: Option to set bbcode_text if is RichTextLabel
20 | focused_objects.back().set("text", text)
21 |
22 | func _on_focused_exited():
23 | if get_menu().visible: # Support right-click context menu
24 | return
25 |
26 | hide()
27 | # TODO: More efficient way to handle undo/redo of text, right now, whole chunks of string is cached everytime
28 | change_text(focused_objects.back(), text)
29 |
30 | # Popup at mouse position
31 | func popup():
32 | if focused_objects == null:
33 | return
34 |
35 | var focused_object = focused_objects.back()
36 | if not ("text" in focused_object):
37 | return
38 |
39 | show()
40 | global_position = get_viewport().get_mouse_position()
41 | size = focused_object.size
42 | text = focused_object.text
43 | grab_focus()
44 |
45 | _object_orig_text = focused_object.text
46 |
47 | # Change text with undo/redo
48 | func change_text(object, to):
49 | var from = _object_orig_text
50 | undo_redo.create_action("Change Text")
51 | undo_redo.add_do_method(self, "set_object_text", object, to)
52 | undo_redo.add_undo_method(self, "set_object_text", object, from)
53 | undo_redo.commit_action()
54 | _object_orig_text = ""
55 |
56 | func set_object_text(object, text):
57 | object.set("text", text)
58 | emit_signal("property_edited", "text")
59 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/scenes/OverlayTextEdit.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=2]
2 |
3 | [ext_resource path="res://addons/ui_design_tool/scenes/OverlayTextEdit.gd" type="Script" id=1]
4 |
5 | [sub_resource type="StyleBoxFlat" id=1]
6 | bg_color = Color( 1, 1, 1, 0 )
7 |
8 | [node name="OverlayTextEdit" type="TextEdit"]
9 | offset_right = 300.0
10 | offset_bottom = 200.0
11 | minimum_size = Vector2( 300, 200 )
12 | custom_styles/read_only = SubResource( 1 )
13 | custom_styles/focus = SubResource( 1 )
14 | custom_styles/normal = SubResource( 1 )
15 | custom_styles/completion = SubResource( 1 )
16 | fold_gutter = true
17 | caret_blink = true
18 | script = ExtResource( 1 )
19 | __meta__ = {
20 | "_edit_use_anchors_": false
21 | }
22 |
23 | [node name="Panel" type="Panel" parent="."]
24 | self_modulate = Color( 1, 1, 1, 0.588235 )
25 | show_behind_parent = true
26 | anchor_right = 1.0
27 | anchor_bottom = 1.0
28 | mouse_filter = 2
29 | __meta__ = {
30 | "_edit_use_anchors_": false
31 | }
32 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/scenes/Toolbar.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends Control
3 | const Utils = preload("../scripts/Utils.gd")
4 | const FontManager = preload("../scripts/FontManager.gd")
5 |
6 | signal property_edited(name) # Emitted when property edited, mainly to notify inspector refresh
7 |
8 | # Config file to save user preference
9 | const CONFIG_DIR = "res://addons/ui_design_tool/user_pref.cfg" # Must be abosulte path
10 | const CONFIG_SECTION_META = "path"
11 | const CONFIG_KEY_FONTS_DIR = "fonts_dir" # Directory to fonts resource
12 | # Generic font properties
13 | const PROPERTY_FONT_COLOR = "theme_override_colors/font_color"
14 | const PROPERTY_FONT = "theme_override_fonts/font"
15 | const PROPERTY_FONT_SIZE = "theme_override_font_sizes/font_size"
16 | # RichTextLabel font properties
17 | const PROPERTY_FONT_NORMAL = "theme_override_fonts/normal_font"
18 | const PROPERTY_FONT_BOLD = "theme_override_fonts/bold_font"
19 | const PROPERTY_FONT_ITALIC = "theme_override_fonts/italics_font"
20 | const PROPERTY_FONT_BOLD_ITALIC = "theme_override_fonts/bold_italics_font"
21 | const PROPERTY_FONT_COLOR_DEFAULT = "theme_override_colors/default_color"
22 | # Others generic properties
23 | const PROPERTY_HIGHLIGHT = "theme_override_styles/normal"
24 | const PROPERTY_HIGHLIGHT_PANEL = "theme_override_styles/panel"
25 | const PROPERTY_HORIZONTAL_ALIGNMENT = "horizontal_alignment"
26 | const PROPERTY_VERTICAL_ALIGNMENT = "vertical_alignment"
27 |
28 | const DEFAULT_FONT_SIZE = 16
29 | const FONT_FAMILY_REFERENCE_STRING = "____________" # Reference text to calculate display size of FontFamily
30 | const FONT_FORMATTING_REFERENCE_STRING = "HEADING_1_" # Reference text to calculate display size of FontFormatting
31 |
32 | # Toolbar UI
33 | @onready var FontFamily = $FontFamily
34 | @onready var FontFamilyOptions = $FontFamilyOptions
35 | @onready var FontFamilyOptionsPopupMenu = $FontFamilyOptions/PopupMenu
36 | @onready var FontFamilyFileDialog = $FontFamilyFileDialog
37 | @onready var FontSize = $FontSize
38 | @onready var FontSizePreset = $FontSize/FontSizePreset
39 | @onready var Bold = $Bold
40 | @onready var BoldPopupMenu = $Bold/PopupMenu
41 | @onready var Italic = $Italic
42 | @onready var Underline = $Underline
43 | @onready var FontColor = $FontColor
44 | @onready var FontColorColorRect = $FontColor/ColorRect
45 | @onready var FontColorColorPicker = $FontColor/PopupPanel/ColorPicker
46 | @onready var FontColorPopupPanel = $FontColor/PopupPanel
47 | @onready var Highlight = $Highlight
48 | @onready var HighlightColorRect = $Highlight/ColorRect
49 | @onready var HighlightColorPicker = $Highlight/PopupPanel/ColorPicker
50 | @onready var HighlightPopupPanel = $Highlight/PopupPanel
51 | @onready var HorizontalAlign = $HorizontalAlign
52 | @onready var HorizontalAlignPopupMenu = $HorizontalAlign/PopupMenu
53 | @onready var VerticalAlign = $VerticalAlign
54 | @onready var VerticalAlignPopupMenu = $VerticalAlign/PopupMenu
55 | @onready var FontFormatting = $FontFormatting
56 | @onready var Tools = $Tools
57 | @onready var ToolsPopupMenu = $Tools/PopupMenu
58 |
59 | # Reference passed down from EditorPlugin
60 | var focused_objects = [] : # Editor editing object
61 | set(objs): # focused_objects setter, mainly called from EditorPlugin
62 | var has_changed = false
63 |
64 | if not objs.is_empty():
65 | if focused_objects.size() == 1 and objs.size() == 1:
66 | # Single selection changed
67 | has_changed = focused_objects.back() != objs.back()
68 | else:
69 | has_changed = true
70 | else:
71 | if not focused_objects.is_empty():
72 | has_changed = true
73 |
74 | if has_changed:
75 | focused_objects = objs
76 | _on_focused_object_changed(focused_objects)
77 | var focused_property : # Editor editing property
78 | set(prop): # focused_property setter, mainly called from EditorPlugin
79 | if focused_property != prop:
80 | focused_property = prop
81 | _on_focused_property_changed(focused_property)
82 | var focused_inspector : # Editor editing inspector
83 | set(insp): # focused_inspector setter, mainly called from EditorPlugin
84 | if focused_inspector != insp:
85 | focused_inspector = insp
86 | _on_focused_inspector_changed(focused_inspector)
87 | var undo_redo
88 |
89 | var selected_font_root_dir = "res://"
90 | var font_manager = FontManager.new() # Manager of loaded fonts from fonts_dir
91 | var config = ConfigFile.new() # Config file of user preference
92 |
93 | var _is_visible_yet = false # Always True after it has visible once, mainly used to auto load fonts
94 | var _object_orig_font_color = Color.WHITE # Font color of object when FontColor pressed
95 | var _object_orig_highlight # Highlight(StyleBoxFlat) when Highlight pressed
96 | var _object_orig_font_formatting # FontManager.FontFormatting object when FontFormatting item selected
97 |
98 |
99 | func _init():
100 | var result = config.load(CONFIG_DIR)
101 | if result:
102 | match result:
103 | ERR_FILE_NOT_FOUND:
104 | pass
105 | _:
106 | push_warning("UI Design Tool: An error occurred when trying to access %s, ERROR: %d" % [CONFIG_DIR, result])
107 |
108 | func _ready():
109 | hide()
110 | connect("visibility_changed", _on_visibility_changed)
111 | # FontFamily
112 | FontFamily.clip_text = true
113 | FontFamily.custom_minimum_size.x = Utils.get_option_button_display_size(FontFamily, FONT_FAMILY_REFERENCE_STRING).x
114 | FontFamily.connect("item_selected", _on_FontFamily_item_selected)
115 | FontFamilyOptions.connect("pressed", _on_FontFamilyOptions_pressed)
116 | FontFamilyOptionsPopupMenu.connect("id_pressed", _on_FontFamilyOptionsPopupMenu_id_pressed)
117 | FontFamilyFileDialog.connect("dir_selected", _on_FontFamilyFileDialog_dir_selected)
118 | # FontSize
119 | FontSizePreset.connect("item_selected", _on_FontSizePreset_item_selected)
120 | FontSize.connect("text_submitted", _on_FontSize_text_entered)
121 | # Bold
122 | Bold.connect("pressed", _on_Bold_pressed)
123 | BoldPopupMenu.connect("id_pressed", _on_BoldPopupMenu_id_pressed)
124 | # Italic
125 | Italic.connect("pressed", _on_Italic_pressed)
126 | # FontColor
127 | FontColor.connect("pressed", _on_FontColor_pressed)
128 | FontColorColorPicker.connect("color_changed", _on_FontColor_ColorPicker_color_changed)
129 | FontColorPopupPanel.connect("popup_hide", _on_FontColor_PopupPanel_popup_hide)
130 | # Highlight
131 | Highlight.connect("pressed", _on_Highlight_pressed)
132 | HighlightColorPicker.connect("color_changed", _on_Highlight_ColorPicker_color_changed)
133 | HighlightPopupPanel.connect("popup_hide", _on_Highlight_PopupPanel_popup_hide)
134 | # HorizontalAlign
135 | HorizontalAlign.connect("pressed", _on_HorizontalAlign_pressed)
136 | HorizontalAlignPopupMenu.connect("id_pressed", _on_HorizontalAlignPopupMenu_id_pressed)
137 | HorizontalAlignPopupMenu.set_item_metadata(0, HORIZONTAL_ALIGNMENT_LEFT)
138 | HorizontalAlignPopupMenu.set_item_metadata(1, HORIZONTAL_ALIGNMENT_CENTER)
139 | HorizontalAlignPopupMenu.set_item_metadata(2, HORIZONTAL_ALIGNMENT_RIGHT)
140 | # VerticalAlign
141 | VerticalAlign.connect("pressed", _on_VerticalAlign_pressed)
142 | VerticalAlignPopupMenu.connect("id_pressed", _on_VerticalAlignPopupMenu_id_pressed)
143 | VerticalAlignPopupMenu.set_item_metadata(0, VERTICAL_ALIGNMENT_TOP)
144 | VerticalAlignPopupMenu.set_item_metadata(1, VERTICAL_ALIGNMENT_CENTER)
145 | VerticalAlignPopupMenu.set_item_metadata(2, VERTICAL_ALIGNMENT_BOTTOM)
146 | # FontFormatting
147 | FontFormatting.clip_text = true
148 | FontFormatting.custom_minimum_size.x = Utils.get_option_button_display_size(FontFormatting, FONT_FORMATTING_REFERENCE_STRING).x
149 | FontFormatting.connect("item_selected", _on_FontFormatting_item_selected)
150 | # Tools
151 | Tools.connect("pressed", _on_Tools_pressed)
152 | ToolsPopupMenu.connect("id_pressed", _on_ToolsPopupMenu_id_pressed)
153 |
154 | func _on_visibility_changed():
155 | if not _is_visible_yet and visible:
156 | var fonts_dir = config.get_value(CONFIG_SECTION_META, CONFIG_KEY_FONTS_DIR, "")
157 | if not fonts_dir.is_empty():
158 | FontFamilyFileDialog.current_path = fonts_dir
159 | _on_FontFamilyFileDialog_dir_selected(fonts_dir)
160 | _is_visible_yet = true
161 |
162 | # Change font object with undo/redo
163 | func change_font(object, to):
164 | var from = object.get(PROPERTY_FONT)
165 | undo_redo.create_action("Change Font")
166 | undo_redo.add_do_method(self, "set_font", object, to if to else false) # Godot bug, varargs ignore null
167 | undo_redo.add_undo_method(self, "set_font", object, from if from else false)
168 | undo_redo.commit_action()
169 |
170 | # Change font data of font object with undo/redo
171 | func change_font_data(object, to):
172 | var from = object.get(PROPERTY_FONT).base_font
173 | undo_redo.create_action("Change Font Data")
174 | undo_redo.add_do_method(self, "set_font_data", object, to if to else false) # Godot bug, varargs ignore null
175 | undo_redo.add_undo_method(self, "set_font_data", object, from if from else false)
176 | undo_redo.commit_action()
177 |
178 | # Change rich text fonts with undo/redo
179 | func change_rich_text_fonts(object, to):
180 | var from = {}
181 | from["regular"] = object.get(PROPERTY_FONT_NORMAL)
182 | from["bold"] = object.get(PROPERTY_FONT_BOLD)
183 | from["regular_italic"] = object.get(PROPERTY_FONT_ITALIC)
184 | from["bold_italic"] = object.get(PROPERTY_FONT_BOLD_ITALIC)
185 | undo_redo.create_action("Change Rich Text Fonts")
186 | undo_redo.add_do_method(self, "set_rich_text_fonts", object, to if to else false) # Godot bug, varargs ignore null
187 | undo_redo.add_undo_method(self, "set_rich_text_fonts", object, from if from else false)
188 | undo_redo.commit_action()
189 |
190 | # Change font size with undo/redo
191 | func change_font_size(object, to):
192 | var from = object.get(PROPERTY_FONT_SIZE)
193 | undo_redo.create_action("Change Font Size")
194 | undo_redo.add_do_method(self, "set_font_size", object, to)
195 | undo_redo.add_undo_method(self, "set_font_size", object, from)
196 | undo_redo.commit_action()
197 |
198 | # Change font color with undo/redo
199 | func change_font_color(object, to):
200 | var from = _object_orig_font_color
201 | undo_redo.create_action("Change Font Color")
202 | undo_redo.add_do_method(self, "set_font_color", object, to if to is Color else false) # Godot bug, varargs ignore null
203 | undo_redo.add_undo_method(self, "set_font_color", object, from if from is Color else false)
204 | undo_redo.commit_action()
205 |
206 | # Change highlight(StyleBoxFlat) with undo/redo
207 | func change_highlight(object, to):
208 | var from = _object_orig_highlight
209 | undo_redo.create_action("Change Highlight")
210 | undo_redo.add_do_method(self, "set_highlight", object, to if to else false) # Godot bug, varargs ignore null
211 | undo_redo.add_undo_method(self, "set_highlight", object, from if from else false)
212 | undo_redo.commit_action()
213 |
214 | # Change horizontal alignment with undo/redo
215 | func change_horizontal_alignment(object, to):
216 | var from = object.get(PROPERTY_HORIZONTAL_ALIGNMENT)
217 | undo_redo.create_action("Change Horizontal Alignment")
218 | undo_redo.add_do_method(self, "set_horizontal_alignment", object, to)
219 | undo_redo.add_undo_method(self, "set_horizontal_alignment", object, from)
220 | undo_redo.commit_action()
221 |
222 | # Change vertical alignment with undo/redo
223 | func change_vertical_alignment(object, to):
224 | var from = object.get(PROPERTY_VERTICAL_ALIGNMENT)
225 | undo_redo.create_action("Change Vertical Alignment")
226 | undo_redo.add_do_method(self, "set_vertical_alignment", object, to)
227 | undo_redo.add_undo_method(self, "set_vertical_alignment", object, from)
228 | undo_redo.commit_action()
229 |
230 | # Change font style(FontManager.FontFormatting) with undo/redo
231 | func change_font_formatting(object, to):
232 | var from = _object_orig_font_formatting
233 | undo_redo.create_action("Change Font Style")
234 | undo_redo.add_do_method(self, "set_font_formatting", object, to if to else false) # Godot bug, varargs ignore null
235 | undo_redo.add_undo_method(self, "set_font_formatting", object, from if from else false)
236 | undo_redo.commit_action()
237 |
238 | # Reflect font name of focused_objects to toolbar
239 | func reflect_font_family_control():
240 | var obj = focused_objects.back() if focused_objects else null
241 | if not obj:
242 | return
243 |
244 | var font_variation = obj.get(PROPERTY_FONT) if obj else null
245 | if font_variation:
246 | if font_variation.base_font:
247 | var font_face = font_manager.get_font_face(font_variation.base_font)
248 | if font_face:
249 | for i in FontFamily.get_item_count():
250 | var font_family_name = FontFamily.get_item_text(i)
251 | if font_family_name == font_face.font_family:
252 | FontFamily.tooltip_text = font_family_name
253 | FontFamily.selected = i
254 | reflect_font_weight_control()
255 | return
256 |
257 | FontFamily.tooltip_text = "Font Family"
258 | reset_font_family_control()
259 |
260 | # Reflect font weight of focused_objects to toolbar, always call reflect_font_family_control first
261 | func reflect_font_weight_control():
262 | var obj = focused_objects.back() if focused_objects else null
263 | if not obj:
264 | return
265 |
266 | var font_variation = obj.get(PROPERTY_FONT) if obj else null
267 | if font_variation:
268 | if font_variation.base_font:
269 | var font_face = font_manager.get_font_face(font_variation.base_font)
270 | if font_face:
271 | var font_weight = font_face.font_weight
272 |
273 | for i in BoldPopupMenu.get_item_count():
274 | if font_weight.replace("-", "_") == BoldPopupMenu.get_item_text(i).to_lower().replace("-", "_"):
275 | Bold.tooltip_text = BoldPopupMenu.get_item_text(i)
276 | return true
277 | return false
278 |
279 | # Reflect font size of focused_objects to toolbar, always call reflect_font_family_control first
280 | func reflect_font_size_control():
281 | var obj = focused_objects.back() if focused_objects else null
282 | if not obj:
283 | return
284 |
285 | var has_font_size = PROPERTY_FONT_SIZE in obj
286 | FontSize.mouse_filter = Control.MOUSE_FILTER_IGNORE if not has_font_size else Control.MOUSE_FILTER_STOP
287 | FontSizePreset.disabled = not has_font_size
288 | var font_size_color = Color.WHITE
289 | font_size_color.a = 0.5 if not has_font_size else 1
290 | FontSize.set(PROPERTY_FONT_COLOR, font_size_color)
291 | var font_size = obj.get(PROPERTY_FONT_SIZE) if obj else null
292 | if has_font_size and font_size == null:
293 | font_size = DEFAULT_FONT_SIZE
294 | FontSize.text = str(font_size) if font_size else str(DEFAULT_FONT_SIZE)
295 |
296 | # Reflect bold/italic of focused_objects to toolbar, always call reflect_font_family_control first
297 | func reflect_bold_italic_control():
298 | var obj = focused_objects.back() if focused_objects else null
299 | if not obj:
300 | return
301 |
302 | if FontFamily.get_item_count():
303 | var font_family_name = FontFamily.get_item_text(FontFamily.selected)
304 | # TODO: Better way to get current item text from PopupMenu than tooltip_text
305 | var font_weight = Bold.tooltip_text.to_lower().replace("-", "_")
306 | var font_family = font_manager.get_font_family(font_family_name)
307 |
308 | Bold.disabled = font_family == null
309 | var font_variation = obj.get(PROPERTY_FONT) if obj else null
310 | if font_variation:
311 | var font_face = font_manager.get_font_face(font_variation.base_font)
312 | if font_face:
313 | var is_italic = font_face.font_style == FontManager.FONT_STYLE.ITALIC
314 | Italic.button_pressed = is_italic
315 | if not is_italic:
316 | if font_family:
317 | Italic.disabled = not ("italic" in font_family.get(font_weight))
318 | else:
319 | Italic.disabled = true
320 | else:
321 | Italic.disabled = false
322 | else:
323 | Italic.button_pressed = false
324 | Italic.disabled = true
325 |
326 | var is_none = font_family_name == "None"
327 | var font_weights = FontManager.FONT_WEIGHT.keys()
328 | for i in font_weights.size():
329 | var font_face = font_family.get(font_weights[i]) if font_family else null
330 | var font_data = font_face.normal if font_face else null
331 | BoldPopupMenu.set_item_disabled(i, true if is_none else font_data == null)
332 | else:
333 | Bold.disabled = true
334 | Italic.disabled = true
335 | Bold.button_pressed = false
336 | Italic.button_pressed = false
337 |
338 | # Reflect font color of focused_objects to toolbar
339 | func reflect_font_color_control():
340 | var obj = focused_objects.back() if focused_objects else null
341 | if not obj:
342 | return
343 |
344 | var focused_object_font_color = obj.get(PROPERTY_FONT_COLOR) if obj else null
345 | var font_color = Color.WHITE
346 | if focused_object_font_color != null:
347 | font_color = focused_object_font_color
348 | FontColorColorRect.color = font_color
349 | FontColorColorPicker.color = font_color
350 |
351 | # Reflect highlight color of focused_objects to toolbar
352 | func reflect_highlight_control():
353 | var obj = focused_objects.back() if focused_objects else null
354 | if not obj:
355 | return
356 |
357 | var focused_object_highlight = obj.get(PROPERTY_HIGHLIGHT) if obj else null
358 | if obj is Panel or obj is PanelContainer:
359 | focused_object_highlight = obj.get(PROPERTY_HIGHLIGHT_PANEL) if obj else null
360 |
361 | var highlight_color = Color.WHITE # default modulate color
362 | if focused_object_highlight != null:
363 | if focused_object_highlight is StyleBoxFlat:
364 | highlight_color = focused_object_highlight.bg_color
365 | HighlightColorRect.color = highlight_color
366 | HighlightColorPicker.color = highlight_color
367 |
368 | # Reflect horizontal alignment of focused_objects to toolbar
369 | func reflect_horizontal_alignment_control():
370 | var obj = focused_objects.back() if focused_objects else null
371 | if not obj:
372 | return
373 |
374 | var h_align = obj.get(PROPERTY_HORIZONTAL_ALIGNMENT) if obj else null
375 | if h_align != null:
376 | var icon
377 | HorizontalAlign.disabled = false
378 | match h_align:
379 | HORIZONTAL_ALIGNMENT_LEFT:
380 | icon = HorizontalAlignPopupMenu.get_item_icon(0)
381 | HORIZONTAL_ALIGNMENT_CENTER:
382 | icon = HorizontalAlignPopupMenu.get_item_icon(1)
383 | HORIZONTAL_ALIGNMENT_RIGHT:
384 | icon = HorizontalAlignPopupMenu.get_item_icon(2)
385 | if icon:
386 | HorizontalAlign.icon = icon
387 | else:
388 | HorizontalAlign.disabled = true
389 |
390 | func reflect_vertical_alignment_control():
391 | var obj = focused_objects.back() if focused_objects else null
392 | if not obj:
393 | return
394 |
395 | var v_align = obj.get(PROPERTY_VERTICAL_ALIGNMENT) if obj else null
396 | if v_align != null:
397 | var icon
398 | VerticalAlign.disabled = false
399 | match v_align:
400 | VERTICAL_ALIGNMENT_TOP:
401 | icon = VerticalAlignPopupMenu.get_item_icon(0)
402 | VERTICAL_ALIGNMENT_CENTER:
403 | icon = VerticalAlignPopupMenu.get_item_icon(1)
404 | VERTICAL_ALIGNMENT_BOTTOM:
405 | icon = VerticalAlignPopupMenu.get_item_icon(2)
406 | if icon:
407 | VerticalAlign.icon = icon
408 | else:
409 | VerticalAlign.disabled = true
410 |
411 | # Reflect font style of focused_objects to toolbar, it only check if focused_objects can applied with style
412 | func reflect_font_formatting_control():
413 | var obj = focused_objects.back() if focused_objects else null
414 | if not obj:
415 | return
416 |
417 | # Font Style is not required to be accurate
418 | var font_variation = obj.get(PROPERTY_FONT) if obj else null
419 | FontFormatting.disabled = font_variation == null
420 |
421 | # Reset font name on toolbar
422 | func reset_font_family_control():
423 | if FontFamily.get_item_count():
424 | FontFamily.selected = FontFamily.get_item_count() - 1
425 |
426 | func _on_FontFamily_item_selected(index):
427 | if focused_objects == null:
428 | return
429 |
430 | var font_family_name = FontFamily.get_item_text(index)
431 | if font_family_name == "None":
432 | _on_FontClear_pressed()
433 | return
434 |
435 | var font_family = font_manager.get_font_family(font_family_name)
436 | if not font_family:
437 | return
438 |
439 | for obj in focused_objects:
440 | if obj is RichTextLabel:
441 | var to = {}
442 | to["regular"] = create_new_font_obj(font_family.regular.normal.data) if font_family.regular.get("normal") else null
443 | to["bold"] = create_new_font_obj(font_family.bold.normal.data) if font_family.bold.get("normal") else null
444 | to["regular_italic"] = create_new_font_obj(font_family.regular.italic.data) if font_family.regular.get("italic") else null
445 | to["bold_italic"] = create_new_font_obj(font_family.bold.italic.data) if font_family.bold.get("italic") else null
446 | change_rich_text_fonts(obj, to)
447 | else:
448 | var font_variation = obj.get(PROPERTY_FONT)
449 | if not font_variation:
450 | var font_size = FontSizePreset.get_item_text(FontSizePreset.selected).to_int()
451 | font_variation = create_new_font_obj(font_family.regular.normal.data)
452 | change_font(obj, font_variation)
453 | else:
454 | change_font_data(obj, font_family.regular.normal.data) # TODO: Get fallback weight if regular not found
455 |
456 |
457 | func _on_FontFamilyOptions_pressed():
458 | if focused_objects:
459 | Utils.popup_on_target(FontFamilyOptionsPopupMenu, FontFamilyOptions)
460 |
461 | func _on_FontFamilyOptionsPopupMenu_id_pressed(index):
462 | match index:
463 | 0:
464 | FontFamilyFileDialog.popup_centered(Vector2(600, 400))
465 | 1:
466 | _on_FontFamilyFileDialog_dir_selected(selected_font_root_dir)
467 |
468 | func _on_FontFamilyFileDialog_dir_selected(dir):
469 | selected_font_root_dir = dir
470 | # Load fonts
471 | if font_manager.load_root_dir(dir):
472 | FontFamily.clear()
473 | for font_family in font_manager.font_families.values():
474 | FontFamily.add_item(font_family.name)
475 | FontFamily.add_item("None")
476 |
477 | reflect_font_family_control()
478 | config.set_value(CONFIG_SECTION_META, CONFIG_KEY_FONTS_DIR, dir)
479 | config.save(CONFIG_DIR)
480 | else:
481 | print("Failed to load fonts")
482 |
483 | func _on_FontSizePreset_item_selected(index):
484 | if focused_objects == null:
485 | return
486 |
487 | for obj in focused_objects:
488 | var new_font_size_str = FontSizePreset.get_item_text(index)
489 | change_font_size(obj, new_font_size_str.to_int())
490 |
491 | func _on_FontSize_text_entered(new_text):
492 | if focused_objects == null:
493 | return
494 |
495 | for obj in focused_objects:
496 | change_font_size(obj, FontSize.text.to_int())
497 |
498 | func _on_Bold_pressed():
499 | if focused_objects == null:
500 | return
501 |
502 | Utils.popup_on_target(BoldPopupMenu, Bold)
503 |
504 | func _on_BoldPopupMenu_id_pressed(index):
505 | if focused_objects == null:
506 | return
507 |
508 | var font_weight_text = BoldPopupMenu.get_item_text(index)
509 | if font_weight_text == Bold.tooltip_text:
510 | return
511 |
512 | Bold.tooltip_text = font_weight_text
513 | var font_family_name = FontFamily.get_item_text(FontFamily.selected)
514 | var font_weight = Bold.tooltip_text.to_lower().replace("-", "_")
515 | var font_family = font_manager.get_font_family(font_family_name)
516 |
517 | for obj in focused_objects:
518 | if obj is RichTextLabel:
519 | continue
520 | var font_variation = obj.get(PROPERTY_FONT)
521 | if font_variation:
522 | var font_faces = font_family.get(font_weight)
523 | var font_face = font_faces.normal
524 | if Italic.button_pressed:
525 | if font_faces.has("italic"):
526 | font_face = font_faces.italic
527 | var font_data = font_face.data
528 | change_font_data(obj, font_data)
529 |
530 | func _on_Italic_pressed():
531 | if focused_objects == null:
532 | return
533 |
534 | var font_family_name = FontFamily.get_item_text(FontFamily.selected)
535 | var font_family = font_manager.get_font_family(font_family_name)
536 | if not font_family:
537 | return
538 |
539 | var font_weight = Bold.tooltip_text.to_lower().replace("-", "_")
540 | var font_faces = font_family.get(font_weight)
541 | var font_face = font_faces.get("italic") if Italic.button_pressed else font_faces.normal
542 |
543 | for obj in focused_objects:
544 | change_font_data(obj, font_face.data)
545 |
546 | func _on_FontColor_pressed():
547 | if focused_objects == null:
548 | return
549 |
550 | Utils.popup_on_target(FontColorPopupPanel, FontColor)
551 | var obj = focused_objects.back()
552 |
553 | if obj is RichTextLabel:
554 | _object_orig_font_color = obj.get(PROPERTY_FONT_COLOR_DEFAULT)
555 | else:
556 | _object_orig_font_color = obj.get(PROPERTY_FONT_COLOR)
557 |
558 | func _on_FontColor_ColorPicker_color_changed(color):
559 | if focused_objects == null:
560 | return
561 |
562 | for obj in focused_objects:
563 | # Preview only, doesn't stack undo/redo as this is called very frequently
564 | if obj is RichTextLabel:
565 | obj.set(PROPERTY_FONT_COLOR_DEFAULT, FontColorColorPicker.color)
566 | else:
567 | obj.set(PROPERTY_FONT_COLOR, FontColorColorPicker.color)
568 | FontColorColorRect.color = FontColorColorPicker.color
569 |
570 | func _on_FontColor_PopupPanel_popup_hide():
571 | if focused_objects == null:
572 | return
573 |
574 | for obj in focused_objects:
575 | var current_font_color = obj.get(PROPERTY_FONT_COLOR)
576 | var font_color
577 | if current_font_color is Color or _object_orig_font_color is Color:
578 | font_color = FontColorColorPicker.color
579 | # Color selected
580 | change_font_color(obj, font_color)
581 |
582 | func _on_Highlight_pressed():
583 | if focused_objects == null:
584 | return
585 |
586 | Utils.popup_on_target(HighlightPopupPanel, Highlight)
587 |
588 | for obj in focused_objects:
589 | var style_box_flat = obj.get(PROPERTY_HIGHLIGHT)
590 | if obj is Panel or obj is PanelContainer:
591 | style_box_flat = obj.get(PROPERTY_HIGHLIGHT_PANEL)
592 | if style_box_flat:
593 | _object_orig_highlight = StyleBoxFlat.new()
594 | _object_orig_highlight.bg_color = style_box_flat.bg_color
595 | else:
596 | _object_orig_highlight = null
597 |
598 | func _on_Highlight_ColorPicker_color_changed(color):
599 | if focused_objects == null:
600 | return
601 |
602 | # Preview only, doesn't stack undo/redo as this is called very frequently
603 | HighlightColorRect.color = color
604 | var style_box_flat = StyleBoxFlat.new()
605 |
606 | style_box_flat.bg_color = HighlightColorPicker.color
607 |
608 | for obj in focused_objects:
609 | if obj is Panel or obj is PanelContainer:
610 | obj.set(PROPERTY_HIGHLIGHT_PANEL, style_box_flat)
611 | else:
612 | obj.set(PROPERTY_HIGHLIGHT, style_box_flat)
613 |
614 | func _on_Highlight_PopupPanel_popup_hide():
615 | if focused_objects == null:
616 | return
617 |
618 | for obj in focused_objects:
619 | var current_highlight
620 | if obj is Panel or obj is PanelContainer:
621 | current_highlight = obj.get(PROPERTY_HIGHLIGHT_PANEL)
622 | else:
623 | current_highlight = obj.get(PROPERTY_HIGHLIGHT)
624 |
625 | # Color selected
626 | var style_box_flat
627 | if current_highlight or _object_orig_highlight:
628 | style_box_flat = StyleBoxFlat.new()
629 | style_box_flat.bg_color = HighlightColorPicker.color
630 | change_highlight(obj, style_box_flat)
631 |
632 | func _on_HorizontalAlign_pressed():
633 | if focused_objects:
634 | Utils.popup_on_target(HorizontalAlignPopupMenu, HorizontalAlign)
635 |
636 | func _on_HorizontalAlignPopupMenu_id_pressed(index):
637 | if focused_objects == null:
638 | return
639 |
640 | for obj in focused_objects:
641 | HorizontalAlign.icon = HorizontalAlignPopupMenu.get_item_icon(index)
642 | var selected_align = HorizontalAlignPopupMenu.get_item_metadata(index)
643 | var current_align = obj.get(PROPERTY_HORIZONTAL_ALIGNMENT)
644 | if current_align != selected_align:
645 | change_horizontal_alignment(obj, selected_align)
646 |
647 | func _on_VerticalAlign_pressed():
648 | if focused_objects:
649 | Utils.popup_on_target(VerticalAlignPopupMenu, VerticalAlign)
650 |
651 | func _on_VerticalAlignPopupMenu_id_pressed(index):
652 | if focused_objects == null:
653 | return
654 |
655 | for obj in focused_objects:
656 | VerticalAlign.icon = VerticalAlignPopupMenu.get_item_icon(index)
657 | var selected_v_align = VerticalAlignPopupMenu.get_item_metadata(index)
658 | var current_v_align = obj.get(PROPERTY_VERTICAL_ALIGNMENT)
659 | if current_v_align != selected_v_align:
660 | change_vertical_alignment(obj, selected_v_align)
661 |
662 | func _on_FontFormatting_item_selected(index):
663 | if focused_objects == null:
664 | return
665 |
666 | var font_variation = focused_objects.back().get(PROPERTY_FONT)
667 | if not font_variation:
668 | return
669 |
670 | var font_formatting_name = FontFormatting.get_item_text(index)
671 | var font_formatting = font_manager.FONT_FORMATTINGS[font_formatting_name]
672 | FontFormatting.tooltip_text = font_formatting_name
673 | # TODO: Better way to get current item text from PopupMenu than tooltip_text
674 | _object_orig_font_formatting= FontManager.FontFormatting.new(
675 | Bold.tooltip_text.to_lower().replace("-", "_"), DEFAULT_FONT_SIZE, font_variation.spacing_glyph)
676 |
677 | for obj in focused_objects:
678 | change_font_formatting(obj, font_formatting)
679 |
680 | func _on_Tools_pressed():
681 | if focused_objects:
682 | Utils.popup_on_target(ToolsPopupMenu, Tools)
683 |
684 | func _on_ToolsPopupMenu_id_pressed(index):
685 | if focused_objects == null:
686 | return
687 |
688 | match index:
689 | 0: # Font Clear
690 | _on_FontClear_pressed()
691 | 1: # Color Clear
692 | _on_ColorClear_pressed()
693 | 2: # Rect Size Refresh
694 | _on_RectSizeRefresh_pressed()
695 |
696 | func _on_FontClear_pressed():
697 | if focused_objects == null:
698 | return
699 |
700 | for obj in focused_objects:
701 | if obj is RichTextLabel:
702 | var to = {
703 | "regular": null,
704 | "bold": null,
705 | "regular_italic": null,
706 | "bold_italic": null
707 | }
708 | change_rich_text_fonts(obj, to)
709 | else:
710 | change_font(obj, null)
711 |
712 | _on_focused_object_changed(focused_objects) # Update ui default state
713 |
714 | func _on_ColorClear_pressed():
715 | if focused_objects == null:
716 | return
717 |
718 | for obj in focused_objects:
719 | if obj is RichTextLabel:
720 | _object_orig_font_color = obj.get(PROPERTY_FONT_COLOR_DEFAULT)
721 | else:
722 | _object_orig_font_color = obj.get(PROPERTY_FONT_COLOR)
723 |
724 | if obj is Panel or obj is PanelContainer:
725 | _object_orig_highlight = obj.get(PROPERTY_HIGHLIGHT_PANEL)
726 | else:
727 | _object_orig_highlight = obj.get(PROPERTY_HIGHLIGHT)
728 | change_font_color(obj, null)
729 | change_highlight(obj, null)
730 |
731 | func _on_RectSizeRefresh_pressed():
732 | if focused_objects:
733 | for obj in focused_objects:
734 | obj.set("size", Vector2.ZERO)
735 |
736 | # focused_objects changed when user select different object in editor
737 | func _on_focused_object_changed(new_focused_object):
738 | reflect_font_family_control() # Font family must be reflected first
739 | reflect_font_size_control()
740 | reflect_font_color_control()
741 | reflect_highlight_control()
742 | reflect_bold_italic_control()
743 | reflect_horizontal_alignment_control()
744 | reflect_vertical_alignment_control()
745 | reflect_font_formatting_control()
746 |
747 | # focused_property changed when user select different property in inspector
748 | func _on_focused_property_changed(new_property):
749 | pass
750 |
751 | # focused_inspector changed when user select different inspector in editor
752 | func _on_focused_inspector_changed(new_inspector):
753 | pass
754 |
755 | # Called from setter method, handle update of font name/font weight in toolbar
756 | func _on_font_data_changed(new_font_data):
757 | var font_face = font_manager.get_font_face(new_font_data)
758 | if font_face:
759 | reflect_font_family_control()
760 |
761 | reflect_bold_italic_control()
762 | emit_signal("property_edited", PROPERTY_FONT)
763 |
764 | # Called from setter method, handle update of font name/font weight in toolbar
765 | func _on_font_changed(new_font):
766 | var font_family_name = FontFamily.get_item_text(FontFamily.selected)
767 | var font_family = font_manager.get_font_family(font_family_name)
768 | if not new_font:
769 | reset_font_family_control()
770 | else:
771 | var font_face = font_manager.get_font_face(new_font.base_font)
772 | if font_face:
773 | reflect_font_family_control()
774 | reflect_font_weight_control()
775 |
776 | reflect_font_size_control()
777 | reflect_bold_italic_control()
778 | reflect_font_formatting_control()
779 | emit_signal("property_edited", PROPERTY_FONT)
780 |
781 | # Called from setter method, handle update of font name/font weight in toolbar
782 | func _on_rich_text_fonts_changed(fonts):
783 | # TODO: Reflect font name of rich text font
784 | emit_signal("property_edited", PROPERTY_FONT)
785 |
786 | # Called from setter method, handle update of font size in toolbar
787 | func _on_font_size_changed(new_font_size):
788 | var new_font_size_str = str(new_font_size)
789 | FontSize.text = new_font_size_str
790 |
791 | emit_signal("property_edited", PROPERTY_FONT_SIZE)
792 |
793 | # Called from setter method, handle update of font color in toolbar
794 | func _on_font_color_changed(new_font_color):
795 | reflect_font_color_control()
796 |
797 | emit_signal("property_edited", PROPERTY_FONT_COLOR)
798 |
799 | # Called from setter method, handle update of highlight in toolbar
800 | func _on_highlight_changed(new_highlight):
801 | reflect_highlight_control()
802 |
803 | if focused_objects is Panel or focused_objects is PanelContainer:
804 | emit_signal("property_edited", PROPERTY_HIGHLIGHT_PANEL)
805 | else:
806 | emit_signal("property_edited", PROPERTY_HIGHLIGHT)
807 |
808 | # Called from setter method, handle update of horizontal alignment in toolbar
809 | func _on_horizontal_alignment_changed(h_align):
810 | reflect_horizontal_alignment_control()
811 |
812 | emit_signal("property_edited", PROPERTY_HORIZONTAL_ALIGNMENT)
813 |
814 | # Called from setter method, handle update of vertical alignment in toolbar
815 | func _on_vertical_alignment_changed(v_align):
816 | reflect_vertical_alignment_control()
817 |
818 | emit_signal("property_edited", PROPERTY_VERTICAL_ALIGNMENT)
819 |
820 | # font data setter, toolbar gets updated after called
821 | func set_font_data(object, font_data):
822 | font_data = font_data if font_data else null # font might be bool false, as Godot ignore null for varargs
823 | object.get(PROPERTY_FONT).base_font = font_data
824 | _on_font_data_changed(font_data)
825 |
826 | # font setter, toolbar gets updated after called
827 | func set_font(object, font):
828 | font = font if font else null
829 | object.set(PROPERTY_FONT, font)
830 | _on_font_changed(font)
831 |
832 | # rich text fonts setter, toolbar gets updated after called
833 | func set_rich_text_fonts(object, fonts):
834 | object.set(PROPERTY_FONT_NORMAL, fonts.regular)
835 | object.set(PROPERTY_FONT_BOLD, fonts.bold)
836 | object.set(PROPERTY_FONT_ITALIC, fonts.regular_italic)
837 | object.set(PROPERTY_FONT_BOLD_ITALIC, fonts.bold_italic)
838 | _on_rich_text_fonts_changed(fonts)
839 |
840 | # font size setter, toolbar gets updated after called
841 | func set_font_size(object, font_size):
842 | object.set(PROPERTY_FONT_SIZE, font_size)
843 | _on_font_size_changed(font_size)
844 |
845 | # font color setter, toolbar gets updated after called
846 | func set_font_color(object, font_color):
847 | font_color = font_color if font_color is Color else null
848 | if object is RichTextLabel:
849 | object.set(PROPERTY_FONT_COLOR_DEFAULT, font_color)
850 | else:
851 | object.set(PROPERTY_FONT_COLOR, font_color)
852 | _on_font_color_changed(font_color)
853 |
854 | # highlight setter, toolbar gets updated after called
855 | func set_highlight(object, highlight):
856 | highlight = highlight if highlight else null
857 | if object is Panel or object is PanelContainer:
858 | object.set(PROPERTY_HIGHLIGHT_PANEL, highlight)
859 | else:
860 | object.set(PROPERTY_HIGHLIGHT, highlight)
861 | _on_highlight_changed(highlight)
862 |
863 | # Horizontal alignment setter, toolbar gets updated after called
864 | func set_horizontal_alignment(object, h_align):
865 | object.set(PROPERTY_HORIZONTAL_ALIGNMENT, h_align)
866 | _on_horizontal_alignment_changed(h_align)
867 |
868 | # Vertical alignment setter, toolbar gets updated after called
869 | func set_vertical_alignment(object, v_align):
870 | object.set(PROPERTY_VERTICAL_ALIGNMENT, v_align)
871 | _on_vertical_alignment_changed(v_align)
872 |
873 | # font style setter, toolbar gets updated after called
874 | func set_font_formatting(object, font_formatting):
875 | if not font_formatting:
876 | return
877 |
878 | var font_family = font_manager.get_font_family(FontFamily.get_item_text(FontFamily.selected))
879 | var font_face = font_family.get(font_formatting.font_weight).get(FontManager.get_font_style_str(font_formatting.font_style))
880 | var font_data
881 | if font_face:
882 | font_data = font_face.data
883 | else:
884 | # Use current weight if desired weight not found
885 | font_data = object.get(PROPERTY_FONT).base_font
886 | set_font_data(object, font_data)
887 | set_font_size(object, font_formatting.size)
888 | set_font_extra_spacing_char(object, font_formatting.letter_spacing)
889 |
890 | # font letter spacing setter, toolbar gets updated after called
891 | func set_font_extra_spacing_char(object, new_spacing):
892 | object.get(PROPERTY_FONT).spacing_glyph = new_spacing
893 | # TODO: Add gui for font extra spacing
894 |
895 | # Convenience method to create font object with some default settings
896 | func create_new_font_obj(font_data, size=null):
897 | var font_variation = FontVariation.new()
898 | font_variation.base_font = font_data
899 | return font_variation
900 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/scenes/Toolbar.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=20 format=3 uid="uid://nq7vlsvxhv2p"]
2 |
3 | [ext_resource type="Script" path="res://addons/ui_design_tool/scenes/Toolbar.gd" id="1"]
4 | [ext_resource type="Texture2D" uid="uid://d3xaf7s36xuqc" path="res://addons/ui_design_tool/assets/icons/format_bold-white-18dp.svg" id="2"]
5 | [ext_resource type="Texture2D" uid="uid://ck4h5hqubttt7" path="res://addons/ui_design_tool/assets/icons/format_italic-white-18dp.svg" id="3"]
6 | [ext_resource type="Texture2D" uid="uid://b44il4qj7cem1" path="res://addons/ui_design_tool/assets/icons/format_underlined-white-18dp.svg" id="4"]
7 | [ext_resource type="Texture2D" uid="uid://b3tqua2bt1ix2" path="res://addons/ui_design_tool/assets/icons/format-color-text.png" id="5"]
8 | [ext_resource type="Texture2D" uid="uid://8qawl7hrofkj" path="res://addons/ui_design_tool/assets/icons/format_color_reset-white-18dp.svg" id="6"]
9 | [ext_resource type="Texture2D" uid="uid://cqv3uc8bew0am" path="res://addons/ui_design_tool/assets/icons/photo_size_select_small-white-18dp.svg" id="7"]
10 | [ext_resource type="Texture2D" uid="uid://d1uver224k3px" path="res://addons/ui_design_tool/assets/icons/folder_open-white-18dp.svg" id="8"]
11 | [ext_resource type="Texture2D" uid="uid://dn7q7grbfr7kh" path="res://addons/ui_design_tool/assets/icons/refresh-white-18dp.svg" id="9"]
12 | [ext_resource type="Texture2D" uid="uid://d1rj7h72swjhn" path="res://addons/ui_design_tool/assets/icons/marker.png" id="10"]
13 | [ext_resource type="Texture2D" uid="uid://xnn5xt6piaat" path="res://addons/ui_design_tool/assets/icons/format_clear-white-18dp.svg" id="11"]
14 | [ext_resource type="Texture2D" uid="uid://d0t8qupuaoigg" path="res://addons/ui_design_tool/assets/icons/format_align_right-white-18dp.svg" id="12"]
15 | [ext_resource type="Texture2D" uid="uid://i11r3de57bc3" path="res://addons/ui_design_tool/assets/icons/format_align_center-white-18dp.svg" id="13"]
16 | [ext_resource type="Texture2D" uid="uid://dtsld0omp3fy0" path="res://addons/ui_design_tool/assets/icons/format_align_left-white-18dp.svg" id="14"]
17 | [ext_resource type="Texture2D" uid="uid://rpjhdv5qake3" path="res://addons/ui_design_tool/assets/icons/vertical_align_bottom-white-18dp.svg" id="15"]
18 | [ext_resource type="Texture2D" uid="uid://cjan2dq5nvdvk" path="res://addons/ui_design_tool/assets/icons/vertical_align_top-white-18dp.svg" id="16"]
19 | [ext_resource type="Texture2D" uid="uid://ckriw8d4yelu" path="res://addons/ui_design_tool/assets/icons/vertical_align_center-white-18dp.svg" id="17"]
20 | [ext_resource type="Texture2D" uid="uid://crte1qj0ftynh" path="res://addons/ui_design_tool/assets/icons/more_vert-white-18dp.svg" id="18"]
21 | [ext_resource type="Texture2D" uid="uid://cm5d77b25dgjc" path="res://addons/ui_design_tool/assets/icons/more_horiz-white-18dp.svg" id="19"]
22 |
23 | [node name="Toolbar" type="HBoxContainer"]
24 | visible = false
25 | script = ExtResource("1")
26 |
27 | [node name="FontFamily" type="OptionButton" parent="."]
28 | custom_minimum_size = Vector2i(99, 0)
29 | layout_mode = 2
30 | offset_right = 99.0
31 | offset_bottom = 31.0
32 | size_flags_vertical = 4
33 | tooltip_text = "Font Family"
34 | clip_text = true
35 | item_count = 9
36 | selected = 0
37 | popup/item_0/text = "Alata"
38 | popup/item_0/id = 0
39 | popup/item_1/text = "Bungee"
40 | popup/item_1/id = 1
41 | popup/item_2/text = "Concert_One"
42 | popup/item_2/id = 2
43 | popup/item_3/text = "Fredoka_One"
44 | popup/item_3/id = 3
45 | popup/item_4/text = "Neuton"
46 | popup/item_4/id = 4
47 | popup/item_5/text = "Nunito"
48 | popup/item_5/id = 5
49 | popup/item_6/text = "Roboto"
50 | popup/item_6/id = 6
51 | popup/item_7/text = "Space_Mono"
52 | popup/item_7/id = 7
53 | popup/item_8/text = "None"
54 | popup/item_8/id = 8
55 |
56 | [node name="FontFamilyOptions" type="Button" parent="."]
57 | layout_mode = 2
58 | offset_left = 103.0
59 | offset_right = 129.0
60 | offset_bottom = 31.0
61 | tooltip_text = "Font Family Options"
62 | icon = ExtResource("18")
63 | flat = true
64 |
65 | [node name="PopupMenu" type="PopupMenu" parent="FontFamilyOptions"]
66 | item_count = 2
67 | item_0/text = "Load Fonts"
68 | item_0/icon = ExtResource("8")
69 | item_0/id = 0
70 | item_1/text = "Refresh Fonts"
71 | item_1/icon = ExtResource("9")
72 | item_1/id = 1
73 |
74 | [node name="FontFamilyFileDialog" type="FileDialog" parent="."]
75 | title = "Open a Directory"
76 | size = Vector2i(400, 300)
77 | min_size = Vector2i(300, 200)
78 | ok_button_text = "Select This Folder"
79 | file_mode = 2
80 |
81 | [node name="VSeparator" type="VSeparator" parent="."]
82 | layout_mode = 2
83 | offset_left = 133.0
84 | offset_right = 137.0
85 | offset_bottom = 31.0
86 |
87 | [node name="FontSize" type="LineEdit" parent="."]
88 | layout_mode = 2
89 | offset_left = 141.0
90 | offset_right = 208.0
91 | offset_bottom = 31.0
92 | tooltip_text = "Font Size"
93 |
94 | [node name="FontSizePreset" type="OptionButton" parent="FontSize"]
95 | show_behind_parent = true
96 | layout_mode = 1
97 | anchors_preset = 15
98 | anchor_right = 1.0
99 | anchor_bottom = 1.0
100 | offset_left = 27.0
101 | offset_right = 14.0
102 | grow_horizontal = 2
103 | grow_vertical = 2
104 | size_flags_horizontal = 4
105 | size_flags_vertical = 4
106 | tooltip_text = "Font Size Presets"
107 | disabled = true
108 | item_count = 17
109 | popup/item_0/text = "8"
110 | popup/item_0/id = 0
111 | popup/item_1/text = "9"
112 | popup/item_1/id = 1
113 | popup/item_2/text = "10"
114 | popup/item_2/id = 2
115 | popup/item_3/text = "11"
116 | popup/item_3/id = 3
117 | popup/item_4/text = "12"
118 | popup/item_4/id = 4
119 | popup/item_5/text = "14"
120 | popup/item_5/id = 5
121 | popup/item_6/text = "16"
122 | popup/item_6/id = 6
123 | popup/item_7/text = "18"
124 | popup/item_7/id = 7
125 | popup/item_8/text = "24"
126 | popup/item_8/id = 8
127 | popup/item_9/text = "30"
128 | popup/item_9/id = 9
129 | popup/item_10/text = "36"
130 | popup/item_10/id = 10
131 | popup/item_11/text = "48"
132 | popup/item_11/id = 11
133 | popup/item_12/text = "60"
134 | popup/item_12/id = 12
135 | popup/item_13/text = "72"
136 | popup/item_13/id = 13
137 | popup/item_14/text = "96"
138 | popup/item_14/id = 14
139 | popup/item_15/text = "128"
140 | popup/item_15/id = 15
141 | popup/item_16/text = "256"
142 | popup/item_16/id = 16
143 |
144 | [node name="PanelContainer" type="PanelContainer" parent="."]
145 | self_modulate = Color(1, 1, 1, 0)
146 | layout_mode = 2
147 | offset_left = 212.0
148 | offset_right = 212.0
149 | offset_bottom = 31.0
150 | mouse_filter = 2
151 |
152 | [node name="Bold" type="Button" parent="."]
153 | layout_mode = 2
154 | offset_left = 216.0
155 | offset_right = 242.0
156 | offset_bottom = 31.0
157 | tooltip_text = "Bold"
158 | disabled = true
159 | icon = ExtResource("2")
160 | flat = true
161 |
162 | [node name="PopupMenu" type="PopupMenu" parent="Bold"]
163 | item_count = 9
164 | item_0/text = "Thin"
165 | item_0/id = 0
166 | item_1/text = "Extra-Light"
167 | item_1/id = 1
168 | item_2/text = "Light"
169 | item_2/id = 2
170 | item_3/text = "Regular"
171 | item_3/id = 3
172 | item_4/text = "Medium"
173 | item_4/id = 4
174 | item_5/text = "Semi-Bold"
175 | item_5/id = 5
176 | item_6/text = "Bold"
177 | item_6/id = 6
178 | item_7/text = "Extra-Bold"
179 | item_7/id = 7
180 | item_8/text = "Black"
181 | item_8/id = 8
182 |
183 | [node name="Italic" type="Button" parent="."]
184 | layout_mode = 2
185 | offset_left = 246.0
186 | offset_right = 272.0
187 | offset_bottom = 31.0
188 | tooltip_text = "Italic"
189 | disabled = true
190 | toggle_mode = true
191 | icon = ExtResource("3")
192 | flat = true
193 |
194 | [node name="Underline" type="Button" parent="."]
195 | layout_mode = 2
196 | offset_left = 276.0
197 | offset_right = 302.0
198 | offset_bottom = 31.0
199 | tooltip_text = "Underline
200 | *Only supported in RichTextLabel"
201 | disabled = true
202 | toggle_mode = true
203 | icon = ExtResource("4")
204 | flat = true
205 |
206 | [node name="FontColor" type="Button" parent="."]
207 | layout_mode = 2
208 | offset_left = 306.0
209 | offset_right = 332.0
210 | offset_bottom = 31.0
211 | tooltip_text = "Font Color"
212 | icon = ExtResource("5")
213 | flat = true
214 |
215 | [node name="PopupPanel" type="PopupPanel" parent="FontColor"]
216 | size = Vector2i(116, 227)
217 |
218 | [node name="ColorPicker" type="ColorPicker" parent="FontColor/PopupPanel"]
219 | offset_left = 4.0
220 | offset_top = 4.0
221 | offset_right = 294.0
222 | offset_bottom = 511.0
223 |
224 | [node name="ColorRect" type="ColorRect" parent="FontColor"]
225 | layout_mode = 1
226 | anchors_preset = 8
227 | anchor_left = 0.5
228 | anchor_top = 0.5
229 | anchor_right = 0.5
230 | anchor_bottom = 0.5
231 | offset_left = -9.0
232 | offset_top = 8.0
233 | offset_right = 9.0
234 | offset_bottom = 11.0
235 | grow_horizontal = 2
236 | grow_vertical = 2
237 |
238 | [node name="Highlight" type="Button" parent="."]
239 | layout_mode = 2
240 | offset_left = 336.0
241 | offset_right = 362.0
242 | offset_bottom = 31.0
243 | tooltip_text = "Highlight Color"
244 | icon = ExtResource("10")
245 | flat = true
246 |
247 | [node name="PopupPanel" type="PopupPanel" parent="Highlight"]
248 | size = Vector2i(116, 227)
249 |
250 | [node name="ColorPicker" type="ColorPicker" parent="Highlight/PopupPanel"]
251 | offset_left = 4.0
252 | offset_top = 4.0
253 | offset_right = 294.0
254 | offset_bottom = 511.0
255 |
256 | [node name="ColorRect" type="ColorRect" parent="Highlight"]
257 | layout_mode = 1
258 | anchors_preset = 8
259 | anchor_left = 0.5
260 | anchor_top = 0.5
261 | anchor_right = 0.5
262 | anchor_bottom = 0.5
263 | offset_left = -9.0
264 | offset_top = 8.0
265 | offset_right = 9.0
266 | offset_bottom = 11.0
267 | grow_horizontal = 2
268 | grow_vertical = 2
269 |
270 | [node name="VSeparator2" type="VSeparator" parent="."]
271 | layout_mode = 2
272 | offset_left = 366.0
273 | offset_right = 370.0
274 | offset_bottom = 31.0
275 |
276 | [node name="HorizontalAlign" type="Button" parent="."]
277 | layout_mode = 2
278 | offset_left = 374.0
279 | offset_right = 400.0
280 | offset_bottom = 31.0
281 | tooltip_text = "Horizontal Align"
282 | toggle_mode = true
283 | icon = ExtResource("14")
284 | flat = true
285 |
286 | [node name="PopupMenu" type="PopupMenu" parent="HorizontalAlign"]
287 | item_count = 3
288 | item_0/text = ""
289 | item_0/icon = ExtResource("14")
290 | item_0/id = 0
291 | item_1/text = ""
292 | item_1/icon = ExtResource("13")
293 | item_1/id = 1
294 | item_2/text = ""
295 | item_2/icon = ExtResource("12")
296 | item_2/id = 2
297 |
298 | [node name="VerticalAlign" type="Button" parent="."]
299 | layout_mode = 2
300 | offset_left = 404.0
301 | offset_right = 430.0
302 | offset_bottom = 31.0
303 | tooltip_text = "Vertical Align"
304 | toggle_mode = true
305 | icon = ExtResource("16")
306 | flat = true
307 |
308 | [node name="PopupMenu" type="PopupMenu" parent="VerticalAlign"]
309 | item_count = 3
310 | item_0/text = ""
311 | item_0/icon = ExtResource("16")
312 | item_0/id = 0
313 | item_1/text = ""
314 | item_1/icon = ExtResource("17")
315 | item_1/id = 1
316 | item_2/text = ""
317 | item_2/icon = ExtResource("15")
318 | item_2/id = 2
319 |
320 | [node name="VSeparator3" type="VSeparator" parent="."]
321 | layout_mode = 2
322 | offset_left = 434.0
323 | offset_right = 438.0
324 | offset_bottom = 31.0
325 |
326 | [node name="FontFormatting" type="OptionButton" parent="."]
327 | custom_minimum_size = Vector2i(112, 0)
328 | layout_mode = 2
329 | offset_left = 442.0
330 | offset_right = 554.0
331 | offset_bottom = 31.0
332 | size_flags_horizontal = 4
333 | size_flags_vertical = 4
334 | tooltip_text = "Font Formatting"
335 | clip_text = true
336 | item_count = 13
337 | selected = -1
338 | popup/item_0/text = "Heading 1"
339 | popup/item_0/id = 0
340 | popup/item_1/text = "Heading 2"
341 | popup/item_1/id = 1
342 | popup/item_2/text = "Heading 3"
343 | popup/item_2/id = 2
344 | popup/item_3/text = "Heading 4"
345 | popup/item_3/id = 3
346 | popup/item_4/text = "Heading 5"
347 | popup/item_4/id = 4
348 | popup/item_5/text = "Heading 6"
349 | popup/item_5/id = 5
350 | popup/item_6/text = "Subtitle 1"
351 | popup/item_6/id = 6
352 | popup/item_7/text = "Subtitle 2"
353 | popup/item_7/id = 7
354 | popup/item_8/text = "Body 1"
355 | popup/item_8/id = 8
356 | popup/item_9/text = "Body 2"
357 | popup/item_9/id = 9
358 | popup/item_10/text = "Button"
359 | popup/item_10/id = 10
360 | popup/item_11/text = "Caption"
361 | popup/item_11/id = 11
362 | popup/item_12/text = "Overline"
363 | popup/item_12/id = 12
364 |
365 | [node name="Tools" type="Button" parent="."]
366 | layout_mode = 2
367 | offset_left = 558.0
368 | offset_right = 584.0
369 | offset_bottom = 31.0
370 | tooltip_text = "Tools"
371 | icon = ExtResource("19")
372 | flat = true
373 |
374 | [node name="PopupMenu" type="PopupMenu" parent="Tools"]
375 | item_count = 3
376 | item_0/text = "Font Clear"
377 | item_0/icon = ExtResource("11")
378 | item_0/id = 0
379 | item_1/text = "Color Clear"
380 | item_1/icon = ExtResource("6")
381 | item_1/id = 1
382 | item_2/text = "Rect Size Refresh"
383 | item_2/icon = ExtResource("7")
384 | item_2/id = 2
385 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/scripts/FontManager.gd:
--------------------------------------------------------------------------------
1 | extends Object
2 |
3 | const FONT_FILE_PATTERN = "\\.ttf$"
4 | const FONT_WEIGHT_PATTERNS = {
5 | "thin": "(?i)(-|_)thin",
6 | "extra_light": "(?i)(-|_)extralight",
7 | "light": "(?i)(-|_)light",
8 | "regular": "(?i)(-|_)regular",
9 | "medium": "(?i)(-|_)medium",
10 | "semi_bold": "(?i)(-|_)semibold",
11 | "bold": "(?i)(-|_)bold",
12 | "extra_bold": "(?i)(-|_)extrabold",
13 | "black": "(?i)(-|_)black",
14 | "extra_black": "(?i)(-|_)extrablack"
15 | }
16 | const FONT_ITALIC_PATTERN = "(?i)italic"
17 | const FONT_ITALIC_ONLY_PATTERN = "(?i)(-|_)italic"
18 | const FONT_VARIABLE_PATTERN = "(?i)(-|_)variable"
19 | var FONT_FORMATTINGS = {
20 | "Heading 1": FontFormatting.new("light", 96, -3),
21 | "Heading 2": FontFormatting.new("light", 60, -2),
22 | "Heading 3": FontFormatting.new("regular", 48),
23 | "Heading 4": FontFormatting.new("regular", 34, 1),
24 | "Heading 5": FontFormatting.new("regular", 24),
25 | "Heading 6": FontFormatting.new("medium", 20, 1),
26 | "Subtitle 1": FontFormatting.new("regular", 16),
27 | "Subtitle 2": FontFormatting.new("medium", 14, 1),
28 | "Body 1": FontFormatting.new("regular", 16, 1),
29 | "Body 2": FontFormatting.new("regular", 14, 1),
30 | "Button": FontFormatting.new("medium", 14, 1),
31 | "Caption": FontFormatting.new("regular", 12, 1),
32 | "Overline": FontFormatting.new("regular", 10)
33 | } # Typography hierarchy presets, see https://material.io/design/typography/the-type-system.html#type-scale
34 | const DIR_FOLDER_PATTERN = "\\w+(?!.*\\w)"
35 |
36 | var font_families = {}
37 |
38 | var _font_file_regex = RegEx.new()
39 | var _font_weight_regexes = {
40 | "thin": RegEx.new(),
41 | "extra_light": RegEx.new(),
42 | "light": RegEx.new(),
43 | "regular": RegEx.new(),
44 | "medium": RegEx.new(),
45 | "semi_bold": RegEx.new(),
46 | "bold": RegEx.new(),
47 | "extra_bold": RegEx.new(),
48 | "black": RegEx.new(),
49 | "extra_black": RegEx.new()
50 | }
51 | var _font_italic_regex = RegEx.new()
52 | var _font_italic_only_regex = RegEx.new()
53 | var _font_variable_regex = RegEx.new()
54 | var _dir_folder_regex = RegEx.new()
55 |
56 |
57 | func _init():
58 | if _font_file_regex.compile(FONT_FILE_PATTERN):
59 | print("Failed to compile ", FONT_FILE_PATTERN)
60 |
61 | for font_weight in _font_weight_regexes.keys():
62 | if _font_weight_regexes[font_weight].compile(FONT_WEIGHT_PATTERNS[font_weight]):
63 | print("Failed to compile ", FONT_WEIGHT_PATTERNS[font_weight])
64 |
65 | if _font_italic_regex.compile(FONT_ITALIC_PATTERN):
66 | print("Failed to compile ", FONT_ITALIC_PATTERN)
67 |
68 | if _font_italic_only_regex.compile(FONT_ITALIC_ONLY_PATTERN):
69 | print("Failed to compile ", FONT_ITALIC_ONLY_PATTERN)
70 |
71 | if _font_variable_regex.compile(FONT_VARIABLE_PATTERN):
72 | print("Failed to compile ", FONT_VARIABLE_PATTERN)
73 |
74 | if _dir_folder_regex.compile(DIR_FOLDER_PATTERN):
75 | print("Failed to compile ", DIR_FOLDER_PATTERN)
76 |
77 | # Load root dir of font resources, check Readme for directory structure
78 | func load_root_dir(root_dir):
79 | var directory = DirAccess.open(root_dir)
80 | var result = DirAccess.get_open_error()
81 | if result == OK:
82 | font_families.clear()
83 | directory.list_dir_begin() # Skip . and .. directory and hidden# TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547
84 | var dir = directory.get_next()
85 | while dir != "":
86 | if not directory.current_is_dir():
87 | dir = directory.get_next()
88 | continue
89 |
90 | load_fonts(directory.get_current_dir() + "/" + dir)
91 | dir = directory.get_next()
92 | directory.list_dir_end()
93 | else:
94 | push_warning("UI Design Tool: An error occurred when trying to access %s, ERROR: %d" % [root_dir, result])
95 | return false
96 |
97 | return true
98 |
99 | # Load fonts data from directory, check Readme for filename pattern
100 | func load_fonts(dir):
101 | var directory = DirAccess.open(dir)
102 | var result = DirAccess.get_open_error()
103 | if result == OK:
104 | var font_family_name = _dir_folder_regex.search(dir).get_string()
105 | var font_family = FontFamily.new(font_family_name)
106 | directory.list_dir_begin()
107 | var filename = directory.get_next()
108 | while filename != "":
109 | if directory.current_is_dir():
110 | filename = directory.get_next()
111 | continue
112 |
113 | if _font_file_regex.search(filename):
114 | for font_weight in _font_weight_regexes.keys():
115 | if _font_variable_regex.search(filename): # Godot doesn't support variable font
116 | continue
117 |
118 | var abs_dir = directory.get_current_dir() + "/" + filename
119 | if _font_weight_regexes[font_weight].search(filename):
120 | var font_data = load(abs_dir)
121 |
122 | if _font_italic_regex.search(filename):
123 | font_family.set_font_face(FontFace.new(font_family.name, font_weight, font_data, FONT_STYLE.ITALIC))
124 | else:
125 | font_family.set_font_face(FontFace.new(font_family.name, font_weight, font_data))
126 | break
127 | else:
128 | # Capture regular italic from {font-name}-italic.ttf
129 | if _font_italic_only_regex.search(filename):
130 | var font_data = load(abs_dir)
131 | font_family.set_font_face(FontFace.new(font_family.name, "regular", font_data, FONT_STYLE.ITALIC))
132 | break
133 | filename = directory.get_next()
134 | directory.list_dir_end()
135 |
136 | if not font_family.is_empty():
137 | font_families[font_family.name] = font_family
138 | else:
139 | push_warning("UI Design Tool: Unable to locate usable .ttf files from %s, check README.md for proper directory/filename structure" % dir)
140 | else:
141 | push_warning("UI Design Tool: An error occurred when trying to access %s, ERROR: %d" % [dir, result])
142 | return false
143 |
144 | return true
145 |
146 | func get_font_face(font_data):
147 | for res in font_families.values():
148 | for font_weight in FONT_WEIGHT.keys():
149 | var font_faces = res.get(font_weight)
150 | for font_face in font_faces.values():
151 | if font_face.data and font_data:
152 | if font_face.data.resource_path == font_data.resource_path:
153 | return font_face
154 | return null
155 |
156 | # Find font resource with font name
157 | func get_font_family(font_family_name):
158 | return font_families.get(font_family_name)
159 |
160 | static func get_font_style_str(font_style):
161 | return FONT_STYLE.keys()[font_style].to_lower()
162 |
163 | # Declaration of font type with font_faces
164 | class FontFamily:
165 | var name = ""
166 | var thin = {}
167 | var extra_light = {}
168 | var light = {}
169 | var regular = {}
170 | var medium = {}
171 | var semi_bold = {}
172 | var bold = {}
173 | var extra_bold = {}
174 | var black = {}
175 | var extra_black = {}
176 |
177 | func _init(n):
178 | name = n
179 |
180 | func set_font_face(font_face):
181 | var font_faces = get(font_face.font_weight.replace('-', '_'))
182 | font_faces[FONT_STYLE.keys()[font_face.font_style].to_lower()] = font_face
183 |
184 | func is_empty():
185 | for font_weight in FONT_WEIGHT.keys():
186 | var font_faces = get(font_weight)
187 | if not font_faces.values().is_empty():
188 | return false
189 | return true
190 |
191 | func get_class():
192 | return "FontFamily"
193 |
194 | # Font face data, see (https://developer.mozilla.org/my/docs/Web/CSS/@font-face)
195 | class FontFace:
196 | var font_family = ""
197 | var font_weight = ""
198 | var font_style = FONT_STYLE.NORMAL
199 | var data
200 |
201 | func _init(ff, fw, d, fs=FONT_STYLE.NORMAL):
202 | font_family = ff
203 | font_weight = fw
204 | font_style = fs
205 | data = d
206 |
207 | func get_class():
208 | return "FontFace"
209 |
210 | # Declaration of font style TODO: Custom resource to define font style
211 | class FontFormatting:
212 | var font_weight = "regular"
213 | var font_style = 0 # FONT_STYLE.NORMAL
214 | var size = 16
215 | var letter_spacing = 0
216 |
217 | func _init(fw, s, ls=0):
218 | font_weight = fw
219 | size = s
220 | letter_spacing = ls
221 |
222 | # List of font style, see (https://developer.mozilla.org/my/docs/Web/CSS/font-style)
223 | enum FONT_STYLE {
224 | NORMAL,
225 | ITALIC,
226 | OBLIQUE
227 | }
228 |
229 | # List of font weights, see (https://docs.microsoft.com/en-us/typography/opentype/spec/os2#usweightclass)
230 | const FONT_WEIGHT = {
231 | "thin": 100,
232 | "extra_light": 200,
233 | "light": 300,
234 | "regular": 400,
235 | "medium": 500,
236 | "semi_bold": 600,
237 | "bold": 700,
238 | "extra_bold": 800,
239 | "black": 900
240 | }
241 |
--------------------------------------------------------------------------------
/addons/ui_design_tool/scripts/Utils.gd:
--------------------------------------------------------------------------------
1 | static func markup_text_edit_selection(text_edit, start_text, end_text):
2 | if not text_edit.is_selection_active():
3 | return
4 |
5 | var selection_from_pos = Vector2(text_edit.get_selection_from_column(), text_edit.get_selection_from_line())
6 | var selection_to_pos = Vector2(text_edit.get_selection_to_column(), text_edit.get_selection_to_line())
7 | var one_line_selection = selection_from_pos.y == selection_to_pos.y
8 |
9 | text_edit.deselect()
10 | set_text_edit_cursor_pos(text_edit, selection_from_pos.x, selection_from_pos.y)
11 | text_edit.insert_text_at_cursor(start_text)
12 |
13 | if one_line_selection:
14 | selection_to_pos.x += start_text.length()
15 |
16 | set_text_edit_cursor_pos(text_edit, selection_to_pos.x, selection_to_pos.y)
17 | text_edit.insert_text_at_cursor(end_text)
18 |
19 | if one_line_selection:
20 | selection_to_pos.x += end_text.length()
21 |
22 | text_edit.select(selection_from_pos.y, selection_from_pos.x, selection_to_pos.y, selection_to_pos.x)
23 |
24 | static func get_text_edit_cursor_pos(text_edit):
25 | return Vector2(text_edit.get_caret_column(), text_edit.get_caret_line())
26 |
27 | static func set_text_edit_cursor_pos(text_edit, column, line):
28 | text_edit.set_caret_column(column)
29 | text_edit.set_caret_line(line)
30 |
31 | # Position Popup near to its target while within window, solution from ColorPickerButton source code(https://github.com/godotengine/godot/blob/6d8c14f849376905e1577f9fc3f9512bcffb1e3c/scene/gui/color_picker.cpp#L878)
32 | static func popup_on_target(popup, target):
33 | popup.size = popup.get_contents_minimum_size()
34 | var usable_rect = Rect2(Vector2.ZERO, DisplayServer.window_get_size())
35 | var cp_rect = Rect2(Vector2.ZERO, popup.get_size())
36 | for i in 4:
37 | if i > 1:
38 | cp_rect.position.y = target.global_position.y - cp_rect.size.y
39 | else:
40 | cp_rect.position.y = target.global_position.y + target.get_size().y
41 |
42 | if i & 1:
43 | cp_rect.position.x = target.global_position.x
44 | else:
45 | cp_rect.position.x = target.global_position.x - max(0, cp_rect.size.x - target.get_size().x)
46 |
47 | if usable_rect.encloses(cp_rect):
48 | break
49 | popup.set_position(cp_rect.position)
50 | popup.popup()
51 |
52 | # Roughly calculate the display size of option button regarding to the display_text
53 | static func get_option_button_display_size(option_button, display_text):
54 | # TODO: Improve accuracy
55 | # Use default theme if not assingned
56 | var theme = option_button.get_theme() if option_button.get_theme() else Theme.new()
57 | var string_size = theme.get_font("font", "fonts").get_string_size(display_text)
58 | var arrow_icon = theme.get_icon("arrow", "styles")
59 | # Takes arrow icon size into account
60 | string_size.x += arrow_icon.get_width()
61 | return string_size
62 |
--------------------------------------------------------------------------------