Code stuff
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0z" fill="none"/><path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 12H4V8h16v10z"/></svg>
|
After Width: | Height: | Size: 262 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://d1uver224k3px"
|
||||
path="res://.godot/imported/folder_open-white-18dp.svg-b9b09b2c311e4324f6ceb8d836d92307.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ui_design_tool/assets/icons/folder_open-white-18dp.svg"
|
||||
dest_files=["res://.godot/imported/folder_open-white-18dp.svg-b9b09b2c311e4324f6ceb8d836d92307.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
BIN
addons/ui_design_tool/assets/icons/format-color-text.png
Normal file
After Width: | Height: | Size: 480 B |
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b3tqua2bt1ix2"
|
||||
path="res://.godot/imported/format-color-text.png-cb1d0e154a77178073ac1079d1806720.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ui_design_tool/assets/icons/format-color-text.png"
|
||||
dest_files=["res://.godot/imported/format-color-text.png-cb1d0e154a77178073ac1079d1806720.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0z" fill="none"/><path d="M7 15v2h10v-2H7zm-4 6h18v-2H3v2zm0-8h18v-2H3v2zm4-6v2h10V7H7zM3 3v2h18V3H3z"/></svg>
|
After Width: | Height: | Size: 230 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://i11r3de57bc3"
|
||||
path="res://.godot/imported/format_align_center-white-18dp.svg-223e2eb74ca8e39f9d4bf989291c7829.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ui_design_tool/assets/icons/format_align_center-white-18dp.svg"
|
||||
dest_files=["res://.godot/imported/format_align_center-white-18dp.svg-223e2eb74ca8e39f9d4bf989291c7829.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0z" fill="none"/><path d="M15 15H3v2h12v-2zm0-8H3v2h12V7zM3 13h18v-2H3v2zm0 8h18v-2H3v2zM3 3v2h18V3H3z"/></svg>
|
After Width: | Height: | Size: 231 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dtsld0omp3fy0"
|
||||
path="res://.godot/imported/format_align_left-white-18dp.svg-f4e62d6e31b71bc8605b920932857161.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ui_design_tool/assets/icons/format_align_left-white-18dp.svg"
|
||||
dest_files=["res://.godot/imported/format_align_left-white-18dp.svg-f4e62d6e31b71bc8605b920932857161.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0z" fill="none"/><path d="M3 21h18v-2H3v2zm6-4h12v-2H9v2zm-6-4h18v-2H3v2zm6-4h12V7H9v2zM3 3v2h18V3H3z"/></svg>
|
After Width: | Height: | Size: 230 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://d0t8qupuaoigg"
|
||||
path="res://.godot/imported/format_align_right-white-18dp.svg-639ae8d469d29b7a7afdff99480dfa70.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ui_design_tool/assets/icons/format_align_right-white-18dp.svg"
|
||||
dest_files=["res://.godot/imported/format_align_right-white-18dp.svg-639ae8d469d29b7a7afdff99480dfa70.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0z" fill="none"/><path d="M15.6 10.79c.97-.67 1.65-1.77 1.65-2.79 0-2.26-1.75-4-4-4H7v14h7.04c2.09 0 3.71-1.7 3.71-3.79 0-1.52-.86-2.82-2.15-3.42zM10 6.5h3c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5h-3v-3zm3.5 9H10v-3h3.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5z"/></svg>
|
After Width: | Height: | Size: 384 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://d3xaf7s36xuqc"
|
||||
path="res://.godot/imported/format_bold-white-18dp.svg-dd70eba3f014196757627e0aea4304f1.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ui_design_tool/assets/icons/format_bold-white-18dp.svg"
|
||||
dest_files=["res://.godot/imported/format_bold-white-18dp.svg-dd70eba3f014196757627e0aea4304f1.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0z" fill="none"/><path d="M3.27 5L2 6.27l6.97 6.97L6.5 19h3l1.57-3.66L16.73 21 18 19.73 3.55 5.27 3.27 5zM6 5v.18L8.82 8h2.4l-.72 1.68 2.1 2.1L14.21 8H20V5H6z"/></svg>
|
After Width: | Height: | Size: 287 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://xnn5xt6piaat"
|
||||
path="res://.godot/imported/format_clear-white-18dp.svg-47d87e370b9f3dc70b33de4a26f02608.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ui_design_tool/assets/icons/format_clear-white-18dp.svg"
|
||||
dest_files=["res://.godot/imported/format_clear-white-18dp.svg-47d87e370b9f3dc70b33de4a26f02608.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0zm0 0h24v24H0zm0 0h24v24H0z" fill="none"/><path d="M18 14c0-4-6-10.8-6-10.8s-1.33 1.51-2.73 3.52l8.59 8.59c.09-.42.14-.86.14-1.31zm-.88 3.12L12.5 12.5 5.27 5.27 4 6.55l3.32 3.32C6.55 11.32 6 12.79 6 14c0 3.31 2.69 6 6 6 1.52 0 2.9-.57 3.96-1.5l2.63 2.63 1.27-1.27-2.74-2.74z"/></svg>
|
After Width: | Height: | Size: 404 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://8qawl7hrofkj"
|
||||
path="res://.godot/imported/format_color_reset-white-18dp.svg-e433d2e99c38830ed08d7fa1f97f9a11.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ui_design_tool/assets/icons/format_color_reset-white-18dp.svg"
|
||||
dest_files=["res://.godot/imported/format_color_reset-white-18dp.svg-e433d2e99c38830ed08d7fa1f97f9a11.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0z" fill="none"/><path d="M10 4v3h2.21l-3.42 8H6v3h8v-3h-2.21l3.42-8H18V4z"/></svg>
|
After Width: | Height: | Size: 203 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://ck4h5hqubttt7"
|
||||
path="res://.godot/imported/format_italic-white-18dp.svg-7e46946409e5ba47a73f9c86ddf1ce61.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ui_design_tool/assets/icons/format_italic-white-18dp.svg"
|
||||
dest_files=["res://.godot/imported/format_italic-white-18dp.svg-7e46946409e5ba47a73f9c86ddf1ce61.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 17c3.31 0 6-2.69 6-6V3h-2.5v8c0 1.93-1.57 3.5-3.5 3.5S8.5 12.93 8.5 11V3H6v8c0 3.31 2.69 6 6 6zm-7 2v2h14v-2H5z"/></svg>
|
After Width: | Height: | Size: 270 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b44il4qj7cem1"
|
||||
path="res://.godot/imported/format_underlined-white-18dp.svg-b2765a4e60c3b18727158aebc6b78640.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ui_design_tool/assets/icons/format_underlined-white-18dp.svg"
|
||||
dest_files=["res://.godot/imported/format_underlined-white-18dp.svg-b2765a4e60c3b18727158aebc6b78640.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
BIN
addons/ui_design_tool/assets/icons/marker.png
Normal file
After Width: | Height: | Size: 483 B |
34
addons/ui_design_tool/assets/icons/marker.png.import
Normal file
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://d1rj7h72swjhn"
|
||||
path="res://.godot/imported/marker.png-3deee63f805205d2092032fd6772df3e.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ui_design_tool/assets/icons/marker.png"
|
||||
dest_files=["res://.godot/imported/marker.png-3deee63f805205d2092032fd6772df3e.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0z" fill="none"/><path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></svg>
|
After Width: | Height: | Size: 302 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cm5d77b25dgjc"
|
||||
path="res://.godot/imported/more_horiz-white-18dp.svg-2292c39c5fef87774f0dcabbf9749663.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ui_design_tool/assets/icons/more_horiz-white-18dp.svg"
|
||||
dest_files=["res://.godot/imported/more_horiz-white-18dp.svg-2292c39c5fef87774f0dcabbf9749663.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></svg>
|
After Width: | Height: | Size: 300 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://crte1qj0ftynh"
|
||||
path="res://.godot/imported/more_vert-white-18dp.svg-f9ce1c1392fbe43035b0f9c38f40fd8c.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ui_design_tool/assets/icons/more_vert-white-18dp.svg"
|
||||
dest_files=["res://.godot/imported/more_vert-white-18dp.svg-f9ce1c1392fbe43035b0f9c38f40fd8c.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0V0zm24 24H0V0h24v24z" fill="none"/><path d="M23 15h-2v2h2v-2zm0-4h-2v2h2v-2zm0 8h-2v2c1 0 2-1 2-2zM15 3h-2v2h2V3zm8 4h-2v2h2V7zm-2-4v2h2c0-1-1-2-2-2zM3 21h8v-6H1v4c0 1.1.9 2 2 2zM3 7H1v2h2V7zm12 12h-2v2h2v-2zm4-16h-2v2h2V3zm0 16h-2v2h2v-2zM3 3C2 3 1 4 1 5h2V3zm0 8H1v2h2v-2zm8-8H9v2h2V3zM7 3H5v2h2V3z"/></svg>
|
After Width: | Height: | Size: 430 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cqv3uc8bew0am"
|
||||
path="res://.godot/imported/photo_size_select_small-white-18dp.svg-a132cc84485fb38b8289f82a1cfb4be4.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ui_design_tool/assets/icons/photo_size_select_small-white-18dp.svg"
|
||||
dest_files=["res://.godot/imported/photo_size_select_small-white-18dp.svg-a132cc84485fb38b8289f82a1cfb4be4.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0z" fill="none"/><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/></svg>
|
After Width: | Height: | Size: 357 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dn7q7grbfr7kh"
|
||||
path="res://.godot/imported/refresh-white-18dp.svg-8592ca638cd7e6c945a15796e8610b7c.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ui_design_tool/assets/icons/refresh-white-18dp.svg"
|
||||
dest_files=["res://.godot/imported/refresh-white-18dp.svg-8592ca638cd7e6c945a15796e8610b7c.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0z" fill="none"/><path d="M16 13h-3V3h-2v10H8l4 4 4-4zM4 19v2h16v-2H4z"/></svg>
|
After Width: | Height: | Size: 199 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://rpjhdv5qake3"
|
||||
path="res://.godot/imported/vertical_align_bottom-white-18dp.svg-d38142e787fc53732b40c7e09204caed.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ui_design_tool/assets/icons/vertical_align_bottom-white-18dp.svg"
|
||||
dest_files=["res://.godot/imported/vertical_align_bottom-white-18dp.svg-d38142e787fc53732b40c7e09204caed.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0z" fill="none"/><path d="M8 19h3v4h2v-4h3l-4-4-4 4zm8-14h-3V1h-2v4H8l4 4 4-4zM4 11v2h16v-2H4z"/></svg>
|
After Width: | Height: | Size: 223 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://ckriw8d4yelu"
|
||||
path="res://.godot/imported/vertical_align_center-white-18dp.svg-ff9e4504ee166be50beb982105c87414.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ui_design_tool/assets/icons/vertical_align_center-white-18dp.svg"
|
||||
dest_files=["res://.godot/imported/vertical_align_center-white-18dp.svg-ff9e4504ee166be50beb982105c87414.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0z" fill="none"/><path d="M8 11h3v10h2V11h3l-4-4-4 4zM4 3v2h16V3H4z"/></svg>
|
After Width: | Height: | Size: 196 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cjan2dq5nvdvk"
|
||||
path="res://.godot/imported/vertical_align_top-white-18dp.svg-baa4704503a2c09de95348bc71c911d2.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ui_design_tool/assets/icons/vertical_align_top-white-18dp.svg"
|
||||
dest_files=["res://.godot/imported/vertical_align_top-white-18dp.svg-baa4704503a2c09de95348bc71c911d2.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
7
addons/ui_design_tool/plugin.cfg
Normal file
|
@ -0,0 +1,7 @@
|
|||
[plugin]
|
||||
|
||||
name="UI Design Tool"
|
||||
description=""
|
||||
author="imjp94"
|
||||
version="0.2.2"
|
||||
script="plugin.gd"
|
85
addons/ui_design_tool/plugin.gd
Normal file
|
@ -0,0 +1,85 @@
|
|||
@tool
|
||||
extends EditorPlugin
|
||||
const Toolbar = preload("scenes/Toolbar.tscn")
|
||||
const OverlayTextEdit = preload("scenes/OverlayTextEdit.tscn")
|
||||
|
||||
var toolbar
|
||||
var overlay_text_edit
|
||||
|
||||
var editor_inspector = get_editor_interface().get_inspector()
|
||||
var editor_selection = get_editor_interface().get_selection()
|
||||
|
||||
|
||||
func _enter_tree():
|
||||
toolbar = Toolbar.instantiate()
|
||||
toolbar.undo_redo = get_undo_redo()
|
||||
toolbar.connect("property_edited", _on_Toolbar_property_edited)
|
||||
overlay_text_edit = OverlayTextEdit.instantiate()
|
||||
overlay_text_edit.undo_redo = get_undo_redo()
|
||||
overlay_text_edit.connect("property_edited", _on_OverlayTextEdit_property_edited)
|
||||
|
||||
editor_inspector.connect("property_selected", _on_property_selected)
|
||||
editor_selection.connect("selection_changed", _on_selection_changed)
|
||||
|
||||
add_control_to_container(EditorPlugin.CONTAINER_CANVAS_EDITOR_BOTTOM, toolbar)
|
||||
add_control_to_container(EditorPlugin.CONTAINER_CANVAS_EDITOR_BOTTOM, overlay_text_edit)
|
||||
|
||||
func _exit_tree():
|
||||
if toolbar:
|
||||
toolbar.queue_free()
|
||||
if overlay_text_edit:
|
||||
overlay_text_edit.queue_free()
|
||||
|
||||
func _handles(object):
|
||||
if object is Control:
|
||||
_make_visible(true)
|
||||
return true
|
||||
_make_visible(false)
|
||||
return false
|
||||
|
||||
func _forward_canvas_gui_input(event):
|
||||
if event is InputEventMouseButton:
|
||||
if event.button_index == MOUSE_BUTTON_LEFT:
|
||||
if event.double_click: # Always false when selected multiple nodes
|
||||
if toolbar.focused_objects:
|
||||
overlay_text_edit.popup()
|
||||
return true
|
||||
return false
|
||||
|
||||
func _make_visible(visible):
|
||||
if toolbar:
|
||||
toolbar.visible = visible
|
||||
# overlay_text_edit only visible on double click
|
||||
|
||||
func _on_property_selected(property):
|
||||
toolbar.focused_property = property
|
||||
toolbar.focused_inspector = editor_inspector.get_viewport().gui_get_focus_owner()
|
||||
|
||||
func _on_selection_changed():
|
||||
var selections = editor_selection.get_selected_nodes()
|
||||
var is_visible = false
|
||||
var focused_objects = []
|
||||
if selections.size() == 1:
|
||||
var selection = selections[0]
|
||||
if selection is Control:
|
||||
focused_objects = [selection]
|
||||
is_visible = true
|
||||
elif selections.size() > 1:
|
||||
var has_non_control = false
|
||||
for selection in selections:
|
||||
if not (selection is Control):
|
||||
has_non_control = true
|
||||
break
|
||||
if not has_non_control:
|
||||
is_visible = true
|
||||
focused_objects = selections
|
||||
|
||||
toolbar.visible = is_visible
|
||||
toolbar.focused_objects = focused_objects
|
||||
overlay_text_edit.focused_objects = focused_objects
|
||||
|
||||
func _on_Toolbar_property_edited(property):
|
||||
pass
|
||||
|
||||
func _on_OverlayTextEdit_property_edited(property):
|
||||
pass
|
58
addons/ui_design_tool/scenes/OverlayTextEdit.gd
Normal file
|
@ -0,0 +1,58 @@
|
|||
@tool
|
||||
extends TextEdit
|
||||
|
||||
signal property_edited(property)
|
||||
|
||||
var focused_objects
|
||||
var undo_redo
|
||||
|
||||
var _object_orig_text = ""
|
||||
|
||||
func _ready():
|
||||
set_as_top_level(true)
|
||||
connect("focus_exited", _on_focused_exited)
|
||||
connect("text_changed", _on_text_changed)
|
||||
hide()
|
||||
|
||||
func _on_text_changed():
|
||||
if focused_objects:
|
||||
# TODO: Option to set bbcode_text if is RichTextLabel
|
||||
focused_objects.back().set("text", text)
|
||||
|
||||
func _on_focused_exited():
|
||||
if get_menu().visible: # Support right-click context menu
|
||||
return
|
||||
|
||||
hide()
|
||||
# TODO: More efficient way to handle undo/redo of text, right now, whole chunks of string is cached everytime
|
||||
change_text(focused_objects.back(), text)
|
||||
|
||||
# Popup at mouse position
|
||||
func popup():
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
var focused_object = focused_objects.back()
|
||||
if not ("text" in focused_object):
|
||||
return
|
||||
|
||||
show()
|
||||
global_position = get_viewport().get_mouse_position()
|
||||
size = focused_object.size
|
||||
text = focused_object.text
|
||||
grab_focus()
|
||||
|
||||
_object_orig_text = focused_object.text
|
||||
|
||||
# Change text with undo/redo
|
||||
func change_text(object, to):
|
||||
var from = _object_orig_text
|
||||
undo_redo.create_action("Change Text")
|
||||
undo_redo.add_do_method(self, "set_object_text", object, to)
|
||||
undo_redo.add_undo_method(self, "set_object_text", object, from)
|
||||
undo_redo.commit_action()
|
||||
_object_orig_text = ""
|
||||
|
||||
func set_object_text(object, text):
|
||||
object.set("text", text)
|
||||
emit_signal("property_edited", "text")
|
31
addons/ui_design_tool/scenes/OverlayTextEdit.tscn
Normal file
|
@ -0,0 +1,31 @@
|
|||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://addons/ui_design_tool/scenes/OverlayTextEdit.gd" type="Script" id=1]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=1]
|
||||
bg_color = Color( 1, 1, 1, 0 )
|
||||
|
||||
[node name="OverlayTextEdit" type="TextEdit"]
|
||||
offset_right = 300.0
|
||||
offset_bottom = 200.0
|
||||
minimum_size = Vector2( 300, 200 )
|
||||
custom_styles/read_only = SubResource( 1 )
|
||||
custom_styles/focus = SubResource( 1 )
|
||||
custom_styles/normal = SubResource( 1 )
|
||||
custom_styles/completion = SubResource( 1 )
|
||||
fold_gutter = true
|
||||
caret_blink = true
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Panel" type="Panel" parent="."]
|
||||
self_modulate = Color( 1, 1, 1, 0.588235 )
|
||||
show_behind_parent = true
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
mouse_filter = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
899
addons/ui_design_tool/scenes/Toolbar.gd
Normal file
|
@ -0,0 +1,899 @@
|
|||
@tool
|
||||
extends Control
|
||||
const Utils = preload("../scripts/Utils.gd")
|
||||
const FontManager = preload("../scripts/FontManager.gd")
|
||||
|
||||
signal property_edited(name) # Emitted when property edited, mainly to notify inspector refresh
|
||||
|
||||
# Config file to save user preference
|
||||
const CONFIG_DIR = "res://addons/ui_design_tool/user_pref.cfg" # Must be abosulte path
|
||||
const CONFIG_SECTION_META = "path"
|
||||
const CONFIG_KEY_FONTS_DIR = "fonts_dir" # Directory to fonts resource
|
||||
# Generic font properties
|
||||
const PROPERTY_FONT_COLOR = "theme_override_colors/font_color"
|
||||
const PROPERTY_FONT = "theme_override_fonts/font"
|
||||
const PROPERTY_FONT_SIZE = "theme_override_font_sizes/font_size"
|
||||
# RichTextLabel font properties
|
||||
const PROPERTY_FONT_NORMAL = "theme_override_fonts/normal_font"
|
||||
const PROPERTY_FONT_BOLD = "theme_override_fonts/bold_font"
|
||||
const PROPERTY_FONT_ITALIC = "theme_override_fonts/italics_font"
|
||||
const PROPERTY_FONT_BOLD_ITALIC = "theme_override_fonts/bold_italics_font"
|
||||
const PROPERTY_FONT_COLOR_DEFAULT = "theme_override_colors/default_color"
|
||||
# Others generic properties
|
||||
const PROPERTY_HIGHLIGHT = "theme_override_styles/normal"
|
||||
const PROPERTY_HIGHLIGHT_PANEL = "theme_override_styles/panel"
|
||||
const PROPERTY_HORIZONTAL_ALIGNMENT = "horizontal_alignment"
|
||||
const PROPERTY_VERTICAL_ALIGNMENT = "vertical_alignment"
|
||||
|
||||
const DEFAULT_FONT_SIZE = 16
|
||||
const FONT_FAMILY_REFERENCE_STRING = "____________" # Reference text to calculate display size of FontFamily
|
||||
const FONT_FORMATTING_REFERENCE_STRING = "HEADING_1_" # Reference text to calculate display size of FontFormatting
|
||||
|
||||
# Toolbar UI
|
||||
@onready var FontFamily = $FontFamily
|
||||
@onready var FontFamilyOptions = $FontFamilyOptions
|
||||
@onready var FontFamilyOptionsPopupMenu = $FontFamilyOptions/PopupMenu
|
||||
@onready var FontFamilyFileDialog = $FontFamilyFileDialog
|
||||
@onready var FontSize = $FontSize
|
||||
@onready var FontSizePreset = $FontSize/FontSizePreset
|
||||
@onready var Bold = $Bold
|
||||
@onready var BoldPopupMenu = $Bold/PopupMenu
|
||||
@onready var Italic = $Italic
|
||||
@onready var Underline = $Underline
|
||||
@onready var FontColor = $FontColor
|
||||
@onready var FontColorColorRect = $FontColor/ColorRect
|
||||
@onready var FontColorColorPicker = $FontColor/PopupPanel/ColorPicker
|
||||
@onready var FontColorPopupPanel = $FontColor/PopupPanel
|
||||
@onready var Highlight = $Highlight
|
||||
@onready var HighlightColorRect = $Highlight/ColorRect
|
||||
@onready var HighlightColorPicker = $Highlight/PopupPanel/ColorPicker
|
||||
@onready var HighlightPopupPanel = $Highlight/PopupPanel
|
||||
@onready var HorizontalAlign = $HorizontalAlign
|
||||
@onready var HorizontalAlignPopupMenu = $HorizontalAlign/PopupMenu
|
||||
@onready var VerticalAlign = $VerticalAlign
|
||||
@onready var VerticalAlignPopupMenu = $VerticalAlign/PopupMenu
|
||||
@onready var FontFormatting = $FontFormatting
|
||||
@onready var Tools = $Tools
|
||||
@onready var ToolsPopupMenu = $Tools/PopupMenu
|
||||
|
||||
# Reference passed down from EditorPlugin
|
||||
var focused_objects = [] : # Editor editing object
|
||||
set(objs): # focused_objects setter, mainly called from EditorPlugin
|
||||
var has_changed = false
|
||||
|
||||
if not objs.is_empty():
|
||||
if focused_objects.size() == 1 and objs.size() == 1:
|
||||
# Single selection changed
|
||||
has_changed = focused_objects.back() != objs.back()
|
||||
else:
|
||||
has_changed = true
|
||||
else:
|
||||
if not focused_objects.is_empty():
|
||||
has_changed = true
|
||||
|
||||
if has_changed:
|
||||
focused_objects = objs
|
||||
_on_focused_object_changed(focused_objects)
|
||||
var focused_property : # Editor editing property
|
||||
set(prop): # focused_property setter, mainly called from EditorPlugin
|
||||
if focused_property != prop:
|
||||
focused_property = prop
|
||||
_on_focused_property_changed(focused_property)
|
||||
var focused_inspector : # Editor editing inspector
|
||||
set(insp): # focused_inspector setter, mainly called from EditorPlugin
|
||||
if focused_inspector != insp:
|
||||
focused_inspector = insp
|
||||
_on_focused_inspector_changed(focused_inspector)
|
||||
var undo_redo
|
||||
|
||||
var selected_font_root_dir = "res://"
|
||||
var font_manager = FontManager.new() # Manager of loaded fonts from fonts_dir
|
||||
var config = ConfigFile.new() # Config file of user preference
|
||||
|
||||
var _is_visible_yet = false # Always True after it has visible once, mainly used to auto load fonts
|
||||
var _object_orig_font_color = Color.WHITE # Font color of object when FontColor pressed
|
||||
var _object_orig_highlight # Highlight(StyleBoxFlat) when Highlight pressed
|
||||
var _object_orig_font_formatting # FontManager.FontFormatting object when FontFormatting item selected
|
||||
|
||||
|
||||
func _init():
|
||||
var result = config.load(CONFIG_DIR)
|
||||
if result:
|
||||
match result:
|
||||
ERR_FILE_NOT_FOUND:
|
||||
pass
|
||||
_:
|
||||
push_warning("UI Design Tool: An error occurred when trying to access %s, ERROR: %d" % [CONFIG_DIR, result])
|
||||
|
||||
func _ready():
|
||||
hide()
|
||||
connect("visibility_changed", _on_visibility_changed)
|
||||
# FontFamily
|
||||
FontFamily.clip_text = true
|
||||
FontFamily.custom_minimum_size.x = Utils.get_option_button_display_size(FontFamily, FONT_FAMILY_REFERENCE_STRING).x
|
||||
FontFamily.connect("item_selected", _on_FontFamily_item_selected)
|
||||
FontFamilyOptions.connect("pressed", _on_FontFamilyOptions_pressed)
|
||||
FontFamilyOptionsPopupMenu.connect("id_pressed", _on_FontFamilyOptionsPopupMenu_id_pressed)
|
||||
FontFamilyFileDialog.connect("dir_selected", _on_FontFamilyFileDialog_dir_selected)
|
||||
# FontSize
|
||||
FontSizePreset.connect("item_selected", _on_FontSizePreset_item_selected)
|
||||
FontSize.connect("text_submitted", _on_FontSize_text_entered)
|
||||
# Bold
|
||||
Bold.connect("pressed", _on_Bold_pressed)
|
||||
BoldPopupMenu.connect("id_pressed", _on_BoldPopupMenu_id_pressed)
|
||||
# Italic
|
||||
Italic.connect("pressed", _on_Italic_pressed)
|
||||
# FontColor
|
||||
FontColor.connect("pressed", _on_FontColor_pressed)
|
||||
FontColorColorPicker.connect("color_changed", _on_FontColor_ColorPicker_color_changed)
|
||||
FontColorPopupPanel.connect("popup_hide", _on_FontColor_PopupPanel_popup_hide)
|
||||
# Highlight
|
||||
Highlight.connect("pressed", _on_Highlight_pressed)
|
||||
HighlightColorPicker.connect("color_changed", _on_Highlight_ColorPicker_color_changed)
|
||||
HighlightPopupPanel.connect("popup_hide", _on_Highlight_PopupPanel_popup_hide)
|
||||
# HorizontalAlign
|
||||
HorizontalAlign.connect("pressed", _on_HorizontalAlign_pressed)
|
||||
HorizontalAlignPopupMenu.connect("id_pressed", _on_HorizontalAlignPopupMenu_id_pressed)
|
||||
HorizontalAlignPopupMenu.set_item_metadata(0, HORIZONTAL_ALIGNMENT_LEFT)
|
||||
HorizontalAlignPopupMenu.set_item_metadata(1, HORIZONTAL_ALIGNMENT_CENTER)
|
||||
HorizontalAlignPopupMenu.set_item_metadata(2, HORIZONTAL_ALIGNMENT_RIGHT)
|
||||
# VerticalAlign
|
||||
VerticalAlign.connect("pressed", _on_VerticalAlign_pressed)
|
||||
VerticalAlignPopupMenu.connect("id_pressed", _on_VerticalAlignPopupMenu_id_pressed)
|
||||
VerticalAlignPopupMenu.set_item_metadata(0, VERTICAL_ALIGNMENT_TOP)
|
||||
VerticalAlignPopupMenu.set_item_metadata(1, VERTICAL_ALIGNMENT_CENTER)
|
||||
VerticalAlignPopupMenu.set_item_metadata(2, VERTICAL_ALIGNMENT_BOTTOM)
|
||||
# FontFormatting
|
||||
FontFormatting.clip_text = true
|
||||
FontFormatting.custom_minimum_size.x = Utils.get_option_button_display_size(FontFormatting, FONT_FORMATTING_REFERENCE_STRING).x
|
||||
FontFormatting.connect("item_selected", _on_FontFormatting_item_selected)
|
||||
# Tools
|
||||
Tools.connect("pressed", _on_Tools_pressed)
|
||||
ToolsPopupMenu.connect("id_pressed", _on_ToolsPopupMenu_id_pressed)
|
||||
|
||||
func _on_visibility_changed():
|
||||
if not _is_visible_yet and visible:
|
||||
var fonts_dir = config.get_value(CONFIG_SECTION_META, CONFIG_KEY_FONTS_DIR, "")
|
||||
if not fonts_dir.is_empty():
|
||||
FontFamilyFileDialog.current_path = fonts_dir
|
||||
_on_FontFamilyFileDialog_dir_selected(fonts_dir)
|
||||
_is_visible_yet = true
|
||||
|
||||
# Change font object with undo/redo
|
||||
func change_font(object, to):
|
||||
var from = object.get(PROPERTY_FONT)
|
||||
undo_redo.create_action("Change Font")
|
||||
undo_redo.add_do_method(self, "set_font", object, to if to else false) # Godot bug, varargs ignore null
|
||||
undo_redo.add_undo_method(self, "set_font", object, from if from else false)
|
||||
undo_redo.commit_action()
|
||||
|
||||
# Change font data of font object with undo/redo
|
||||
func change_font_data(object, to):
|
||||
var from = object.get(PROPERTY_FONT).base_font
|
||||
undo_redo.create_action("Change Font Data")
|
||||
undo_redo.add_do_method(self, "set_font_data", object, to if to else false) # Godot bug, varargs ignore null
|
||||
undo_redo.add_undo_method(self, "set_font_data", object, from if from else false)
|
||||
undo_redo.commit_action()
|
||||
|
||||
# Change rich text fonts with undo/redo
|
||||
func change_rich_text_fonts(object, to):
|
||||
var from = {}
|
||||
from["regular"] = object.get(PROPERTY_FONT_NORMAL)
|
||||
from["bold"] = object.get(PROPERTY_FONT_BOLD)
|
||||
from["regular_italic"] = object.get(PROPERTY_FONT_ITALIC)
|
||||
from["bold_italic"] = object.get(PROPERTY_FONT_BOLD_ITALIC)
|
||||
undo_redo.create_action("Change Rich Text Fonts")
|
||||
undo_redo.add_do_method(self, "set_rich_text_fonts", object, to if to else false) # Godot bug, varargs ignore null
|
||||
undo_redo.add_undo_method(self, "set_rich_text_fonts", object, from if from else false)
|
||||
undo_redo.commit_action()
|
||||
|
||||
# Change font size with undo/redo
|
||||
func change_font_size(object, to):
|
||||
var from = object.get(PROPERTY_FONT_SIZE)
|
||||
undo_redo.create_action("Change Font Size")
|
||||
undo_redo.add_do_method(self, "set_font_size", object, to)
|
||||
undo_redo.add_undo_method(self, "set_font_size", object, from)
|
||||
undo_redo.commit_action()
|
||||
|
||||
# Change font color with undo/redo
|
||||
func change_font_color(object, to):
|
||||
var from = _object_orig_font_color
|
||||
undo_redo.create_action("Change Font Color")
|
||||
undo_redo.add_do_method(self, "set_font_color", object, to if to is Color else false) # Godot bug, varargs ignore null
|
||||
undo_redo.add_undo_method(self, "set_font_color", object, from if from is Color else false)
|
||||
undo_redo.commit_action()
|
||||
|
||||
# Change highlight(StyleBoxFlat) with undo/redo
|
||||
func change_highlight(object, to):
|
||||
var from = _object_orig_highlight
|
||||
undo_redo.create_action("Change Highlight")
|
||||
undo_redo.add_do_method(self, "set_highlight", object, to if to else false) # Godot bug, varargs ignore null
|
||||
undo_redo.add_undo_method(self, "set_highlight", object, from if from else false)
|
||||
undo_redo.commit_action()
|
||||
|
||||
# Change horizontal alignment with undo/redo
|
||||
func change_horizontal_alignment(object, to):
|
||||
var from = object.get(PROPERTY_HORIZONTAL_ALIGNMENT)
|
||||
undo_redo.create_action("Change Horizontal Alignment")
|
||||
undo_redo.add_do_method(self, "set_horizontal_alignment", object, to)
|
||||
undo_redo.add_undo_method(self, "set_horizontal_alignment", object, from)
|
||||
undo_redo.commit_action()
|
||||
|
||||
# Change vertical alignment with undo/redo
|
||||
func change_vertical_alignment(object, to):
|
||||
var from = object.get(PROPERTY_VERTICAL_ALIGNMENT)
|
||||
undo_redo.create_action("Change Vertical Alignment")
|
||||
undo_redo.add_do_method(self, "set_vertical_alignment", object, to)
|
||||
undo_redo.add_undo_method(self, "set_vertical_alignment", object, from)
|
||||
undo_redo.commit_action()
|
||||
|
||||
# Change font style(FontManager.FontFormatting) with undo/redo
|
||||
func change_font_formatting(object, to):
|
||||
var from = _object_orig_font_formatting
|
||||
undo_redo.create_action("Change Font Style")
|
||||
undo_redo.add_do_method(self, "set_font_formatting", object, to if to else false) # Godot bug, varargs ignore null
|
||||
undo_redo.add_undo_method(self, "set_font_formatting", object, from if from else false)
|
||||
undo_redo.commit_action()
|
||||
|
||||
# Reflect font name of focused_objects to toolbar
|
||||
func reflect_font_family_control():
|
||||
var obj = focused_objects.back() if focused_objects else null
|
||||
if not obj:
|
||||
return
|
||||
|
||||
var font_variation = obj.get(PROPERTY_FONT) if obj else null
|
||||
if font_variation:
|
||||
if font_variation.base_font:
|
||||
var font_face = font_manager.get_font_face(font_variation.base_font)
|
||||
if font_face:
|
||||
for i in FontFamily.get_item_count():
|
||||
var font_family_name = FontFamily.get_item_text(i)
|
||||
if font_family_name == font_face.font_family:
|
||||
FontFamily.tooltip_text = font_family_name
|
||||
FontFamily.selected = i
|
||||
reflect_font_weight_control()
|
||||
return
|
||||
|
||||
FontFamily.tooltip_text = "Font Family"
|
||||
reset_font_family_control()
|
||||
|
||||
# Reflect font weight of focused_objects to toolbar, always call reflect_font_family_control first
|
||||
func reflect_font_weight_control():
|
||||
var obj = focused_objects.back() if focused_objects else null
|
||||
if not obj:
|
||||
return
|
||||
|
||||
var font_variation = obj.get(PROPERTY_FONT) if obj else null
|
||||
if font_variation:
|
||||
if font_variation.base_font:
|
||||
var font_face = font_manager.get_font_face(font_variation.base_font)
|
||||
if font_face:
|
||||
var font_weight = font_face.font_weight
|
||||
|
||||
for i in BoldPopupMenu.get_item_count():
|
||||
if font_weight.replace("-", "_") == BoldPopupMenu.get_item_text(i).to_lower().replace("-", "_"):
|
||||
Bold.tooltip_text = BoldPopupMenu.get_item_text(i)
|
||||
return true
|
||||
return false
|
||||
|
||||
# Reflect font size of focused_objects to toolbar, always call reflect_font_family_control first
|
||||
func reflect_font_size_control():
|
||||
var obj = focused_objects.back() if focused_objects else null
|
||||
if not obj:
|
||||
return
|
||||
|
||||
var has_font_size = PROPERTY_FONT_SIZE in obj
|
||||
FontSize.mouse_filter = Control.MOUSE_FILTER_IGNORE if not has_font_size else Control.MOUSE_FILTER_STOP
|
||||
FontSizePreset.disabled = not has_font_size
|
||||
var font_size_color = Color.WHITE
|
||||
font_size_color.a = 0.5 if not has_font_size else 1
|
||||
FontSize.set(PROPERTY_FONT_COLOR, font_size_color)
|
||||
var font_size = obj.get(PROPERTY_FONT_SIZE) if obj else null
|
||||
if has_font_size and font_size == null:
|
||||
font_size = DEFAULT_FONT_SIZE
|
||||
FontSize.text = str(font_size) if font_size else str(DEFAULT_FONT_SIZE)
|
||||
|
||||
# Reflect bold/italic of focused_objects to toolbar, always call reflect_font_family_control first
|
||||
func reflect_bold_italic_control():
|
||||
var obj = focused_objects.back() if focused_objects else null
|
||||
if not obj:
|
||||
return
|
||||
|
||||
if FontFamily.get_item_count():
|
||||
var font_family_name = FontFamily.get_item_text(FontFamily.selected)
|
||||
# TODO: Better way to get current item text from PopupMenu than tooltip_text
|
||||
var font_weight = Bold.tooltip_text.to_lower().replace("-", "_")
|
||||
var font_family = font_manager.get_font_family(font_family_name)
|
||||
|
||||
Bold.disabled = font_family == null
|
||||
var font_variation = obj.get(PROPERTY_FONT) if obj else null
|
||||
if font_variation:
|
||||
var font_face = font_manager.get_font_face(font_variation.base_font)
|
||||
if font_face:
|
||||
var is_italic = font_face.font_style == FontManager.FONT_STYLE.ITALIC
|
||||
Italic.button_pressed = is_italic
|
||||
if not is_italic:
|
||||
if font_family:
|
||||
Italic.disabled = not ("italic" in font_family.get(font_weight))
|
||||
else:
|
||||
Italic.disabled = true
|
||||
else:
|
||||
Italic.disabled = false
|
||||
else:
|
||||
Italic.button_pressed = false
|
||||
Italic.disabled = true
|
||||
|
||||
var is_none = font_family_name == "None"
|
||||
var font_weights = FontManager.FONT_WEIGHT.keys()
|
||||
for i in font_weights.size():
|
||||
var font_face = font_family.get(font_weights[i]) if font_family else null
|
||||
var font_data = font_face.normal if font_face else null
|
||||
BoldPopupMenu.set_item_disabled(i, true if is_none else font_data == null)
|
||||
else:
|
||||
Bold.disabled = true
|
||||
Italic.disabled = true
|
||||
Bold.button_pressed = false
|
||||
Italic.button_pressed = false
|
||||
|
||||
# Reflect font color of focused_objects to toolbar
|
||||
func reflect_font_color_control():
|
||||
var obj = focused_objects.back() if focused_objects else null
|
||||
if not obj:
|
||||
return
|
||||
|
||||
var focused_object_font_color = obj.get(PROPERTY_FONT_COLOR) if obj else null
|
||||
var font_color = Color.WHITE
|
||||
if focused_object_font_color != null:
|
||||
font_color = focused_object_font_color
|
||||
FontColorColorRect.color = font_color
|
||||
FontColorColorPicker.color = font_color
|
||||
|
||||
# Reflect highlight color of focused_objects to toolbar
|
||||
func reflect_highlight_control():
|
||||
var obj = focused_objects.back() if focused_objects else null
|
||||
if not obj:
|
||||
return
|
||||
|
||||
var focused_object_highlight = obj.get(PROPERTY_HIGHLIGHT) if obj else null
|
||||
if obj is Panel or obj is PanelContainer:
|
||||
focused_object_highlight = obj.get(PROPERTY_HIGHLIGHT_PANEL) if obj else null
|
||||
|
||||
var highlight_color = Color.WHITE # default modulate color
|
||||
if focused_object_highlight != null:
|
||||
if focused_object_highlight is StyleBoxFlat:
|
||||
highlight_color = focused_object_highlight.bg_color
|
||||
HighlightColorRect.color = highlight_color
|
||||
HighlightColorPicker.color = highlight_color
|
||||
|
||||
# Reflect horizontal alignment of focused_objects to toolbar
|
||||
func reflect_horizontal_alignment_control():
|
||||
var obj = focused_objects.back() if focused_objects else null
|
||||
if not obj:
|
||||
return
|
||||
|
||||
var h_align = obj.get(PROPERTY_HORIZONTAL_ALIGNMENT) if obj else null
|
||||
if h_align != null:
|
||||
var icon
|
||||
HorizontalAlign.disabled = false
|
||||
match h_align:
|
||||
HORIZONTAL_ALIGNMENT_LEFT:
|
||||
icon = HorizontalAlignPopupMenu.get_item_icon(0)
|
||||
HORIZONTAL_ALIGNMENT_CENTER:
|
||||
icon = HorizontalAlignPopupMenu.get_item_icon(1)
|
||||
HORIZONTAL_ALIGNMENT_RIGHT:
|
||||
icon = HorizontalAlignPopupMenu.get_item_icon(2)
|
||||
if icon:
|
||||
HorizontalAlign.icon = icon
|
||||
else:
|
||||
HorizontalAlign.disabled = true
|
||||
|
||||
func reflect_vertical_alignment_control():
|
||||
var obj = focused_objects.back() if focused_objects else null
|
||||
if not obj:
|
||||
return
|
||||
|
||||
var v_align = obj.get(PROPERTY_VERTICAL_ALIGNMENT) if obj else null
|
||||
if v_align != null:
|
||||
var icon
|
||||
VerticalAlign.disabled = false
|
||||
match v_align:
|
||||
VERTICAL_ALIGNMENT_TOP:
|
||||
icon = VerticalAlignPopupMenu.get_item_icon(0)
|
||||
VERTICAL_ALIGNMENT_CENTER:
|
||||
icon = VerticalAlignPopupMenu.get_item_icon(1)
|
||||
VERTICAL_ALIGNMENT_BOTTOM:
|
||||
icon = VerticalAlignPopupMenu.get_item_icon(2)
|
||||
if icon:
|
||||
VerticalAlign.icon = icon
|
||||
else:
|
||||
VerticalAlign.disabled = true
|
||||
|
||||
# Reflect font style of focused_objects to toolbar, it only check if focused_objects can applied with style
|
||||
func reflect_font_formatting_control():
|
||||
var obj = focused_objects.back() if focused_objects else null
|
||||
if not obj:
|
||||
return
|
||||
|
||||
# Font Style is not required to be accurate
|
||||
var font_variation = obj.get(PROPERTY_FONT) if obj else null
|
||||
FontFormatting.disabled = font_variation == null
|
||||
|
||||
# Reset font name on toolbar
|
||||
func reset_font_family_control():
|
||||
if FontFamily.get_item_count():
|
||||
FontFamily.selected = FontFamily.get_item_count() - 1
|
||||
|
||||
func _on_FontFamily_item_selected(index):
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
var font_family_name = FontFamily.get_item_text(index)
|
||||
if font_family_name == "None":
|
||||
_on_FontClear_pressed()
|
||||
return
|
||||
|
||||
var font_family = font_manager.get_font_family(font_family_name)
|
||||
if not font_family:
|
||||
return
|
||||
|
||||
for obj in focused_objects:
|
||||
if obj is RichTextLabel:
|
||||
var to = {}
|
||||
to["regular"] = create_new_font_obj(font_family.regular.normal.data) if font_family.regular.get("normal") else null
|
||||
to["bold"] = create_new_font_obj(font_family.bold.normal.data) if font_family.bold.get("normal") else null
|
||||
to["regular_italic"] = create_new_font_obj(font_family.regular.italic.data) if font_family.regular.get("italic") else null
|
||||
to["bold_italic"] = create_new_font_obj(font_family.bold.italic.data) if font_family.bold.get("italic") else null
|
||||
change_rich_text_fonts(obj, to)
|
||||
else:
|
||||
var font_variation = obj.get(PROPERTY_FONT)
|
||||
if not font_variation:
|
||||
var font_size = FontSizePreset.get_item_text(FontSizePreset.selected).to_int()
|
||||
font_variation = create_new_font_obj(font_family.regular.normal.data)
|
||||
change_font(obj, font_variation)
|
||||
else:
|
||||
change_font_data(obj, font_family.regular.normal.data) # TODO: Get fallback weight if regular not found
|
||||
|
||||
|
||||
func _on_FontFamilyOptions_pressed():
|
||||
if focused_objects:
|
||||
Utils.popup_on_target(FontFamilyOptionsPopupMenu, FontFamilyOptions)
|
||||
|
||||
func _on_FontFamilyOptionsPopupMenu_id_pressed(index):
|
||||
match index:
|
||||
0:
|
||||
FontFamilyFileDialog.popup_centered(Vector2(600, 400))
|
||||
1:
|
||||
_on_FontFamilyFileDialog_dir_selected(selected_font_root_dir)
|
||||
|
||||
func _on_FontFamilyFileDialog_dir_selected(dir):
|
||||
selected_font_root_dir = dir
|
||||
# Load fonts
|
||||
if font_manager.load_root_dir(dir):
|
||||
FontFamily.clear()
|
||||
for font_family in font_manager.font_families.values():
|
||||
FontFamily.add_item(font_family.name)
|
||||
FontFamily.add_item("None")
|
||||
|
||||
reflect_font_family_control()
|
||||
config.set_value(CONFIG_SECTION_META, CONFIG_KEY_FONTS_DIR, dir)
|
||||
config.save(CONFIG_DIR)
|
||||
else:
|
||||
print("Failed to load fonts")
|
||||
|
||||
func _on_FontSizePreset_item_selected(index):
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
for obj in focused_objects:
|
||||
var new_font_size_str = FontSizePreset.get_item_text(index)
|
||||
change_font_size(obj, new_font_size_str.to_int())
|
||||
|
||||
func _on_FontSize_text_entered(new_text):
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
for obj in focused_objects:
|
||||
change_font_size(obj, FontSize.text.to_int())
|
||||
|
||||
func _on_Bold_pressed():
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
Utils.popup_on_target(BoldPopupMenu, Bold)
|
||||
|
||||
func _on_BoldPopupMenu_id_pressed(index):
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
var font_weight_text = BoldPopupMenu.get_item_text(index)
|
||||
if font_weight_text == Bold.tooltip_text:
|
||||
return
|
||||
|
||||
Bold.tooltip_text = font_weight_text
|
||||
var font_family_name = FontFamily.get_item_text(FontFamily.selected)
|
||||
var font_weight = Bold.tooltip_text.to_lower().replace("-", "_")
|
||||
var font_family = font_manager.get_font_family(font_family_name)
|
||||
|
||||
for obj in focused_objects:
|
||||
if obj is RichTextLabel:
|
||||
continue
|
||||
var font_variation = obj.get(PROPERTY_FONT)
|
||||
if font_variation:
|
||||
var font_faces = font_family.get(font_weight)
|
||||
var font_face = font_faces.normal
|
||||
if Italic.button_pressed:
|
||||
if font_faces.has("italic"):
|
||||
font_face = font_faces.italic
|
||||
var font_data = font_face.data
|
||||
change_font_data(obj, font_data)
|
||||
|
||||
func _on_Italic_pressed():
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
var font_family_name = FontFamily.get_item_text(FontFamily.selected)
|
||||
var font_family = font_manager.get_font_family(font_family_name)
|
||||
if not font_family:
|
||||
return
|
||||
|
||||
var font_weight = Bold.tooltip_text.to_lower().replace("-", "_")
|
||||
var font_faces = font_family.get(font_weight)
|
||||
var font_face = font_faces.get("italic") if Italic.button_pressed else font_faces.normal
|
||||
|
||||
for obj in focused_objects:
|
||||
change_font_data(obj, font_face.data)
|
||||
|
||||
func _on_FontColor_pressed():
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
Utils.popup_on_target(FontColorPopupPanel, FontColor)
|
||||
var obj = focused_objects.back()
|
||||
|
||||
if obj is RichTextLabel:
|
||||
_object_orig_font_color = obj.get(PROPERTY_FONT_COLOR_DEFAULT)
|
||||
else:
|
||||
_object_orig_font_color = obj.get(PROPERTY_FONT_COLOR)
|
||||
|
||||
func _on_FontColor_ColorPicker_color_changed(color):
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
for obj in focused_objects:
|
||||
# Preview only, doesn't stack undo/redo as this is called very frequently
|
||||
if obj is RichTextLabel:
|
||||
obj.set(PROPERTY_FONT_COLOR_DEFAULT, FontColorColorPicker.color)
|
||||
else:
|
||||
obj.set(PROPERTY_FONT_COLOR, FontColorColorPicker.color)
|
||||
FontColorColorRect.color = FontColorColorPicker.color
|
||||
|
||||
func _on_FontColor_PopupPanel_popup_hide():
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
for obj in focused_objects:
|
||||
var current_font_color = obj.get(PROPERTY_FONT_COLOR)
|
||||
var font_color
|
||||
if current_font_color is Color or _object_orig_font_color is Color:
|
||||
font_color = FontColorColorPicker.color
|
||||
# Color selected
|
||||
change_font_color(obj, font_color)
|
||||
|
||||
func _on_Highlight_pressed():
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
Utils.popup_on_target(HighlightPopupPanel, Highlight)
|
||||
|
||||
for obj in focused_objects:
|
||||
var style_box_flat = obj.get(PROPERTY_HIGHLIGHT)
|
||||
if obj is Panel or obj is PanelContainer:
|
||||
style_box_flat = obj.get(PROPERTY_HIGHLIGHT_PANEL)
|
||||
if style_box_flat:
|
||||
_object_orig_highlight = StyleBoxFlat.new()
|
||||
_object_orig_highlight.bg_color = style_box_flat.bg_color
|
||||
else:
|
||||
_object_orig_highlight = null
|
||||
|
||||
func _on_Highlight_ColorPicker_color_changed(color):
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
# Preview only, doesn't stack undo/redo as this is called very frequently
|
||||
HighlightColorRect.color = color
|
||||
var style_box_flat = StyleBoxFlat.new()
|
||||
|
||||
style_box_flat.bg_color = HighlightColorPicker.color
|
||||
|
||||
for obj in focused_objects:
|
||||
if obj is Panel or obj is PanelContainer:
|
||||
obj.set(PROPERTY_HIGHLIGHT_PANEL, style_box_flat)
|
||||
else:
|
||||
obj.set(PROPERTY_HIGHLIGHT, style_box_flat)
|
||||
|
||||
func _on_Highlight_PopupPanel_popup_hide():
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
for obj in focused_objects:
|
||||
var current_highlight
|
||||
if obj is Panel or obj is PanelContainer:
|
||||
current_highlight = obj.get(PROPERTY_HIGHLIGHT_PANEL)
|
||||
else:
|
||||
current_highlight = obj.get(PROPERTY_HIGHLIGHT)
|
||||
|
||||
# Color selected
|
||||
var style_box_flat
|
||||
if current_highlight or _object_orig_highlight:
|
||||
style_box_flat = StyleBoxFlat.new()
|
||||
style_box_flat.bg_color = HighlightColorPicker.color
|
||||
change_highlight(obj, style_box_flat)
|
||||
|
||||
func _on_HorizontalAlign_pressed():
|
||||
if focused_objects:
|
||||
Utils.popup_on_target(HorizontalAlignPopupMenu, HorizontalAlign)
|
||||
|
||||
func _on_HorizontalAlignPopupMenu_id_pressed(index):
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
for obj in focused_objects:
|
||||
HorizontalAlign.icon = HorizontalAlignPopupMenu.get_item_icon(index)
|
||||
var selected_align = HorizontalAlignPopupMenu.get_item_metadata(index)
|
||||
var current_align = obj.get(PROPERTY_HORIZONTAL_ALIGNMENT)
|
||||
if current_align != selected_align:
|
||||
change_horizontal_alignment(obj, selected_align)
|
||||
|
||||
func _on_VerticalAlign_pressed():
|
||||
if focused_objects:
|
||||
Utils.popup_on_target(VerticalAlignPopupMenu, VerticalAlign)
|
||||
|
||||
func _on_VerticalAlignPopupMenu_id_pressed(index):
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
for obj in focused_objects:
|
||||
VerticalAlign.icon = VerticalAlignPopupMenu.get_item_icon(index)
|
||||
var selected_v_align = VerticalAlignPopupMenu.get_item_metadata(index)
|
||||
var current_v_align = obj.get(PROPERTY_VERTICAL_ALIGNMENT)
|
||||
if current_v_align != selected_v_align:
|
||||
change_vertical_alignment(obj, selected_v_align)
|
||||
|
||||
func _on_FontFormatting_item_selected(index):
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
var font_variation = focused_objects.back().get(PROPERTY_FONT)
|
||||
if not font_variation:
|
||||
return
|
||||
|
||||
var font_formatting_name = FontFormatting.get_item_text(index)
|
||||
var font_formatting = font_manager.FONT_FORMATTINGS[font_formatting_name]
|
||||
FontFormatting.tooltip_text = font_formatting_name
|
||||
# TODO: Better way to get current item text from PopupMenu than tooltip_text
|
||||
_object_orig_font_formatting= FontManager.FontFormatting.new(
|
||||
Bold.tooltip_text.to_lower().replace("-", "_"), DEFAULT_FONT_SIZE, font_variation.spacing_glyph)
|
||||
|
||||
for obj in focused_objects:
|
||||
change_font_formatting(obj, font_formatting)
|
||||
|
||||
func _on_Tools_pressed():
|
||||
if focused_objects:
|
||||
Utils.popup_on_target(ToolsPopupMenu, Tools)
|
||||
|
||||
func _on_ToolsPopupMenu_id_pressed(index):
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
match index:
|
||||
0: # Font Clear
|
||||
_on_FontClear_pressed()
|
||||
1: # Color Clear
|
||||
_on_ColorClear_pressed()
|
||||
2: # Rect Size Refresh
|
||||
_on_RectSizeRefresh_pressed()
|
||||
|
||||
func _on_FontClear_pressed():
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
for obj in focused_objects:
|
||||
if obj is RichTextLabel:
|
||||
var to = {
|
||||
"regular": null,
|
||||
"bold": null,
|
||||
"regular_italic": null,
|
||||
"bold_italic": null
|
||||
}
|
||||
change_rich_text_fonts(obj, to)
|
||||
else:
|
||||
change_font(obj, null)
|
||||
|
||||
_on_focused_object_changed(focused_objects) # Update ui default state
|
||||
|
||||
func _on_ColorClear_pressed():
|
||||
if focused_objects == null:
|
||||
return
|
||||
|
||||
for obj in focused_objects:
|
||||
if obj is RichTextLabel:
|
||||
_object_orig_font_color = obj.get(PROPERTY_FONT_COLOR_DEFAULT)
|
||||
else:
|
||||
_object_orig_font_color = obj.get(PROPERTY_FONT_COLOR)
|
||||
|
||||
if obj is Panel or obj is PanelContainer:
|
||||
_object_orig_highlight = obj.get(PROPERTY_HIGHLIGHT_PANEL)
|
||||
else:
|
||||
_object_orig_highlight = obj.get(PROPERTY_HIGHLIGHT)
|
||||
change_font_color(obj, null)
|
||||
change_highlight(obj, null)
|
||||
|
||||
func _on_RectSizeRefresh_pressed():
|
||||
if focused_objects:
|
||||
for obj in focused_objects:
|
||||
obj.set("size", Vector2.ZERO)
|
||||
|
||||
# focused_objects changed when user select different object in editor
|
||||
func _on_focused_object_changed(new_focused_object):
|
||||
reflect_font_family_control() # Font family must be reflected first
|
||||
reflect_font_size_control()
|
||||
reflect_font_color_control()
|
||||
reflect_highlight_control()
|
||||
reflect_bold_italic_control()
|
||||
reflect_horizontal_alignment_control()
|
||||
reflect_vertical_alignment_control()
|
||||
reflect_font_formatting_control()
|
||||
|
||||
# focused_property changed when user select different property in inspector
|
||||
func _on_focused_property_changed(new_property):
|
||||
pass
|
||||
|
||||
# focused_inspector changed when user select different inspector in editor
|
||||
func _on_focused_inspector_changed(new_inspector):
|
||||
pass
|
||||
|
||||
# Called from setter method, handle update of font name/font weight in toolbar
|
||||
func _on_font_data_changed(new_font_data):
|
||||
var font_face = font_manager.get_font_face(new_font_data)
|
||||
if font_face:
|
||||
reflect_font_family_control()
|
||||
|
||||
reflect_bold_italic_control()
|
||||
emit_signal("property_edited", PROPERTY_FONT)
|
||||
|
||||
# Called from setter method, handle update of font name/font weight in toolbar
|
||||
func _on_font_changed(new_font):
|
||||
var font_family_name = FontFamily.get_item_text(FontFamily.selected)
|
||||
var font_family = font_manager.get_font_family(font_family_name)
|
||||
if not new_font:
|
||||
reset_font_family_control()
|
||||
else:
|
||||
var font_face = font_manager.get_font_face(new_font.base_font)
|
||||
if font_face:
|
||||
reflect_font_family_control()
|
||||
reflect_font_weight_control()
|
||||
|
||||
reflect_font_size_control()
|
||||
reflect_bold_italic_control()
|
||||
reflect_font_formatting_control()
|
||||
emit_signal("property_edited", PROPERTY_FONT)
|
||||
|
||||
# Called from setter method, handle update of font name/font weight in toolbar
|
||||
func _on_rich_text_fonts_changed(fonts):
|
||||
# TODO: Reflect font name of rich text font
|
||||
emit_signal("property_edited", PROPERTY_FONT)
|
||||
|
||||
# Called from setter method, handle update of font size in toolbar
|
||||
func _on_font_size_changed(new_font_size):
|
||||
var new_font_size_str = str(new_font_size)
|
||||
FontSize.text = new_font_size_str
|
||||
|
||||
emit_signal("property_edited", PROPERTY_FONT_SIZE)
|
||||
|
||||
# Called from setter method, handle update of font color in toolbar
|
||||
func _on_font_color_changed(new_font_color):
|
||||
reflect_font_color_control()
|
||||
|
||||
emit_signal("property_edited", PROPERTY_FONT_COLOR)
|
||||
|
||||
# Called from setter method, handle update of highlight in toolbar
|
||||
func _on_highlight_changed(new_highlight):
|
||||
reflect_highlight_control()
|
||||
|
||||
if focused_objects is Panel or focused_objects is PanelContainer:
|
||||
emit_signal("property_edited", PROPERTY_HIGHLIGHT_PANEL)
|
||||
else:
|
||||
emit_signal("property_edited", PROPERTY_HIGHLIGHT)
|
||||
|
||||
# Called from setter method, handle update of horizontal alignment in toolbar
|
||||
func _on_horizontal_alignment_changed(h_align):
|
||||
reflect_horizontal_alignment_control()
|
||||
|
||||
emit_signal("property_edited", PROPERTY_HORIZONTAL_ALIGNMENT)
|
||||
|
||||
# Called from setter method, handle update of vertical alignment in toolbar
|
||||
func _on_vertical_alignment_changed(v_align):
|
||||
reflect_vertical_alignment_control()
|
||||
|
||||
emit_signal("property_edited", PROPERTY_VERTICAL_ALIGNMENT)
|
||||
|
||||
# font data setter, toolbar gets updated after called
|
||||
func set_font_data(object, font_data):
|
||||
font_data = font_data if font_data else null # font might be bool false, as Godot ignore null for varargs
|
||||
object.get(PROPERTY_FONT).base_font = font_data
|
||||
_on_font_data_changed(font_data)
|
||||
|
||||
# font setter, toolbar gets updated after called
|
||||
func set_font(object, font):
|
||||
font = font if font else null
|
||||
object.set(PROPERTY_FONT, font)
|
||||
_on_font_changed(font)
|
||||
|
||||
# rich text fonts setter, toolbar gets updated after called
|
||||
func set_rich_text_fonts(object, fonts):
|
||||
object.set(PROPERTY_FONT_NORMAL, fonts.regular)
|
||||
object.set(PROPERTY_FONT_BOLD, fonts.bold)
|
||||
object.set(PROPERTY_FONT_ITALIC, fonts.regular_italic)
|
||||
object.set(PROPERTY_FONT_BOLD_ITALIC, fonts.bold_italic)
|
||||
_on_rich_text_fonts_changed(fonts)
|
||||
|
||||
# font size setter, toolbar gets updated after called
|
||||
func set_font_size(object, font_size):
|
||||
object.set(PROPERTY_FONT_SIZE, font_size)
|
||||
_on_font_size_changed(font_size)
|
||||
|
||||
# font color setter, toolbar gets updated after called
|
||||
func set_font_color(object, font_color):
|
||||
font_color = font_color if font_color is Color else null
|
||||
if object is RichTextLabel:
|
||||
object.set(PROPERTY_FONT_COLOR_DEFAULT, font_color)
|
||||
else:
|
||||
object.set(PROPERTY_FONT_COLOR, font_color)
|
||||
_on_font_color_changed(font_color)
|
||||
|
||||
# highlight setter, toolbar gets updated after called
|
||||
func set_highlight(object, highlight):
|
||||
highlight = highlight if highlight else null
|
||||
if object is Panel or object is PanelContainer:
|
||||
object.set(PROPERTY_HIGHLIGHT_PANEL, highlight)
|
||||
else:
|
||||
object.set(PROPERTY_HIGHLIGHT, highlight)
|
||||
_on_highlight_changed(highlight)
|
||||
|
||||
# Horizontal alignment setter, toolbar gets updated after called
|
||||
func set_horizontal_alignment(object, h_align):
|
||||
object.set(PROPERTY_HORIZONTAL_ALIGNMENT, h_align)
|
||||
_on_horizontal_alignment_changed(h_align)
|
||||
|
||||
# Vertical alignment setter, toolbar gets updated after called
|
||||
func set_vertical_alignment(object, v_align):
|
||||
object.set(PROPERTY_VERTICAL_ALIGNMENT, v_align)
|
||||
_on_vertical_alignment_changed(v_align)
|
||||
|
||||
# font style setter, toolbar gets updated after called
|
||||
func set_font_formatting(object, font_formatting):
|
||||
if not font_formatting:
|
||||
return
|
||||
|
||||
var font_family = font_manager.get_font_family(FontFamily.get_item_text(FontFamily.selected))
|
||||
var font_face = font_family.get(font_formatting.font_weight).get(FontManager.get_font_style_str(font_formatting.font_style))
|
||||
var font_data
|
||||
if font_face:
|
||||
font_data = font_face.data
|
||||
else:
|
||||
# Use current weight if desired weight not found
|
||||
font_data = object.get(PROPERTY_FONT).base_font
|
||||
set_font_data(object, font_data)
|
||||
set_font_size(object, font_formatting.size)
|
||||
set_font_extra_spacing_char(object, font_formatting.letter_spacing)
|
||||
|
||||
# font letter spacing setter, toolbar gets updated after called
|
||||
func set_font_extra_spacing_char(object, new_spacing):
|
||||
object.get(PROPERTY_FONT).spacing_glyph = new_spacing
|
||||
# TODO: Add gui for font extra spacing
|
||||
|
||||
# Convenience method to create font object with some default settings
|
||||
func create_new_font_obj(font_data, size=null):
|
||||
var font_variation = FontVariation.new()
|
||||
font_variation.base_font = font_data
|
||||
return font_variation
|
384
addons/ui_design_tool/scenes/Toolbar.tscn
Normal file
|
@ -0,0 +1,384 @@
|
|||
[gd_scene load_steps=20 format=3 uid="uid://nq7vlsvxhv2p"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/ui_design_tool/scenes/Toolbar.gd" id="1"]
|
||||
[ext_resource type="Texture2D" uid="uid://d3xaf7s36xuqc" path="res://addons/ui_design_tool/assets/icons/format_bold-white-18dp.svg" id="2"]
|
||||
[ext_resource type="Texture2D" uid="uid://ck4h5hqubttt7" path="res://addons/ui_design_tool/assets/icons/format_italic-white-18dp.svg" id="3"]
|
||||
[ext_resource type="Texture2D" uid="uid://b44il4qj7cem1" path="res://addons/ui_design_tool/assets/icons/format_underlined-white-18dp.svg" id="4"]
|
||||
[ext_resource type="Texture2D" uid="uid://b3tqua2bt1ix2" path="res://addons/ui_design_tool/assets/icons/format-color-text.png" id="5"]
|
||||
[ext_resource type="Texture2D" uid="uid://8qawl7hrofkj" path="res://addons/ui_design_tool/assets/icons/format_color_reset-white-18dp.svg" id="6"]
|
||||
[ext_resource type="Texture2D" uid="uid://cqv3uc8bew0am" path="res://addons/ui_design_tool/assets/icons/photo_size_select_small-white-18dp.svg" id="7"]
|
||||
[ext_resource type="Texture2D" uid="uid://d1uver224k3px" path="res://addons/ui_design_tool/assets/icons/folder_open-white-18dp.svg" id="8"]
|
||||
[ext_resource type="Texture2D" uid="uid://dn7q7grbfr7kh" path="res://addons/ui_design_tool/assets/icons/refresh-white-18dp.svg" id="9"]
|
||||
[ext_resource type="Texture2D" uid="uid://d1rj7h72swjhn" path="res://addons/ui_design_tool/assets/icons/marker.png" id="10"]
|
||||
[ext_resource type="Texture2D" uid="uid://xnn5xt6piaat" path="res://addons/ui_design_tool/assets/icons/format_clear-white-18dp.svg" id="11"]
|
||||
[ext_resource type="Texture2D" uid="uid://d0t8qupuaoigg" path="res://addons/ui_design_tool/assets/icons/format_align_right-white-18dp.svg" id="12"]
|
||||
[ext_resource type="Texture2D" uid="uid://i11r3de57bc3" path="res://addons/ui_design_tool/assets/icons/format_align_center-white-18dp.svg" id="13"]
|
||||
[ext_resource type="Texture2D" uid="uid://dtsld0omp3fy0" path="res://addons/ui_design_tool/assets/icons/format_align_left-white-18dp.svg" id="14"]
|
||||
[ext_resource type="Texture2D" uid="uid://rpjhdv5qake3" path="res://addons/ui_design_tool/assets/icons/vertical_align_bottom-white-18dp.svg" id="15"]
|
||||
[ext_resource type="Texture2D" uid="uid://cjan2dq5nvdvk" path="res://addons/ui_design_tool/assets/icons/vertical_align_top-white-18dp.svg" id="16"]
|
||||
[ext_resource type="Texture2D" uid="uid://ckriw8d4yelu" path="res://addons/ui_design_tool/assets/icons/vertical_align_center-white-18dp.svg" id="17"]
|
||||
[ext_resource type="Texture2D" uid="uid://crte1qj0ftynh" path="res://addons/ui_design_tool/assets/icons/more_vert-white-18dp.svg" id="18"]
|
||||
[ext_resource type="Texture2D" uid="uid://cm5d77b25dgjc" path="res://addons/ui_design_tool/assets/icons/more_horiz-white-18dp.svg" id="19"]
|
||||
|
||||
[node name="Toolbar" type="HBoxContainer"]
|
||||
visible = false
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="FontFamily" type="OptionButton" parent="."]
|
||||
custom_minimum_size = Vector2i(99, 0)
|
||||
layout_mode = 2
|
||||
offset_right = 99.0
|
||||
offset_bottom = 31.0
|
||||
size_flags_vertical = 4
|
||||
tooltip_text = "Font Family"
|
||||
clip_text = true
|
||||
item_count = 9
|
||||
selected = 0
|
||||
popup/item_0/text = "Alata"
|
||||
popup/item_0/id = 0
|
||||
popup/item_1/text = "Bungee"
|
||||
popup/item_1/id = 1
|
||||
popup/item_2/text = "Concert_One"
|
||||
popup/item_2/id = 2
|
||||
popup/item_3/text = "Fredoka_One"
|
||||
popup/item_3/id = 3
|
||||
popup/item_4/text = "Neuton"
|
||||
popup/item_4/id = 4
|
||||
popup/item_5/text = "Nunito"
|
||||
popup/item_5/id = 5
|
||||
popup/item_6/text = "Roboto"
|
||||
popup/item_6/id = 6
|
||||
popup/item_7/text = "Space_Mono"
|
||||
popup/item_7/id = 7
|
||||
popup/item_8/text = "None"
|
||||
popup/item_8/id = 8
|
||||
|
||||
[node name="FontFamilyOptions" type="Button" parent="."]
|
||||
layout_mode = 2
|
||||
offset_left = 103.0
|
||||
offset_right = 129.0
|
||||
offset_bottom = 31.0
|
||||
tooltip_text = "Font Family Options"
|
||||
icon = ExtResource("18")
|
||||
flat = true
|
||||
|
||||
[node name="PopupMenu" type="PopupMenu" parent="FontFamilyOptions"]
|
||||
item_count = 2
|
||||
item_0/text = "Load Fonts"
|
||||
item_0/icon = ExtResource("8")
|
||||
item_0/id = 0
|
||||
item_1/text = "Refresh Fonts"
|
||||
item_1/icon = ExtResource("9")
|
||||
item_1/id = 1
|
||||
|
||||
[node name="FontFamilyFileDialog" type="FileDialog" parent="."]
|
||||
title = "Open a Directory"
|
||||
size = Vector2i(400, 300)
|
||||
min_size = Vector2i(300, 200)
|
||||
ok_button_text = "Select This Folder"
|
||||
file_mode = 2
|
||||
|
||||
[node name="VSeparator" type="VSeparator" parent="."]
|
||||
layout_mode = 2
|
||||
offset_left = 133.0
|
||||
offset_right = 137.0
|
||||
offset_bottom = 31.0
|
||||
|
||||
[node name="FontSize" type="LineEdit" parent="."]
|
||||
layout_mode = 2
|
||||
offset_left = 141.0
|
||||
offset_right = 208.0
|
||||
offset_bottom = 31.0
|
||||
tooltip_text = "Font Size"
|
||||
|
||||
[node name="FontSizePreset" type="OptionButton" parent="FontSize"]
|
||||
show_behind_parent = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = 27.0
|
||||
offset_right = 14.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 4
|
||||
tooltip_text = "Font Size Presets"
|
||||
disabled = true
|
||||
item_count = 17
|
||||
popup/item_0/text = "8"
|
||||
popup/item_0/id = 0
|
||||
popup/item_1/text = "9"
|
||||
popup/item_1/id = 1
|
||||
popup/item_2/text = "10"
|
||||
popup/item_2/id = 2
|
||||
popup/item_3/text = "11"
|
||||
popup/item_3/id = 3
|
||||
popup/item_4/text = "12"
|
||||
popup/item_4/id = 4
|
||||
popup/item_5/text = "14"
|
||||
popup/item_5/id = 5
|
||||
popup/item_6/text = "16"
|
||||
popup/item_6/id = 6
|
||||
popup/item_7/text = "18"
|
||||
popup/item_7/id = 7
|
||||
popup/item_8/text = "24"
|
||||
popup/item_8/id = 8
|
||||
popup/item_9/text = "30"
|
||||
popup/item_9/id = 9
|
||||
popup/item_10/text = "36"
|
||||
popup/item_10/id = 10
|
||||
popup/item_11/text = "48"
|
||||
popup/item_11/id = 11
|
||||
popup/item_12/text = "60"
|
||||
popup/item_12/id = 12
|
||||
popup/item_13/text = "72"
|
||||
popup/item_13/id = 13
|
||||
popup/item_14/text = "96"
|
||||
popup/item_14/id = 14
|
||||
popup/item_15/text = "128"
|
||||
popup/item_15/id = 15
|
||||
popup/item_16/text = "256"
|
||||
popup/item_16/id = 16
|
||||
|
||||
[node name="PanelContainer" type="PanelContainer" parent="."]
|
||||
self_modulate = Color(1, 1, 1, 0)
|
||||
layout_mode = 2
|
||||
offset_left = 212.0
|
||||
offset_right = 212.0
|
||||
offset_bottom = 31.0
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="Bold" type="Button" parent="."]
|
||||
layout_mode = 2
|
||||
offset_left = 216.0
|
||||
offset_right = 242.0
|
||||
offset_bottom = 31.0
|
||||
tooltip_text = "Bold"
|
||||
disabled = true
|
||||
icon = ExtResource("2")
|
||||
flat = true
|
||||
|
||||
[node name="PopupMenu" type="PopupMenu" parent="Bold"]
|
||||
item_count = 9
|
||||
item_0/text = "Thin"
|
||||
item_0/id = 0
|
||||
item_1/text = "Extra-Light"
|
||||
item_1/id = 1
|
||||
item_2/text = "Light"
|
||||
item_2/id = 2
|
||||
item_3/text = "Regular"
|
||||
item_3/id = 3
|
||||
item_4/text = "Medium"
|
||||
item_4/id = 4
|
||||
item_5/text = "Semi-Bold"
|
||||
item_5/id = 5
|
||||
item_6/text = "Bold"
|
||||
item_6/id = 6
|
||||
item_7/text = "Extra-Bold"
|
||||
item_7/id = 7
|
||||
item_8/text = "Black"
|
||||
item_8/id = 8
|
||||
|
||||
[node name="Italic" type="Button" parent="."]
|
||||
layout_mode = 2
|
||||
offset_left = 246.0
|
||||
offset_right = 272.0
|
||||
offset_bottom = 31.0
|
||||
tooltip_text = "Italic"
|
||||
disabled = true
|
||||
toggle_mode = true
|
||||
icon = ExtResource("3")
|
||||
flat = true
|
||||
|
||||
[node name="Underline" type="Button" parent="."]
|
||||
layout_mode = 2
|
||||
offset_left = 276.0
|
||||
offset_right = 302.0
|
||||
offset_bottom = 31.0
|
||||
tooltip_text = "Underline
|
||||
*Only supported in RichTextLabel"
|
||||
disabled = true
|
||||
toggle_mode = true
|
||||
icon = ExtResource("4")
|
||||
flat = true
|
||||
|
||||
[node name="FontColor" type="Button" parent="."]
|
||||
layout_mode = 2
|
||||
offset_left = 306.0
|
||||
offset_right = 332.0
|
||||
offset_bottom = 31.0
|
||||
tooltip_text = "Font Color"
|
||||
icon = ExtResource("5")
|
||||
flat = true
|
||||
|
||||
[node name="PopupPanel" type="PopupPanel" parent="FontColor"]
|
||||
size = Vector2i(116, 227)
|
||||
|
||||
[node name="ColorPicker" type="ColorPicker" parent="FontColor/PopupPanel"]
|
||||
offset_left = 4.0
|
||||
offset_top = 4.0
|
||||
offset_right = 294.0
|
||||
offset_bottom = 511.0
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="FontColor"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -9.0
|
||||
offset_top = 8.0
|
||||
offset_right = 9.0
|
||||
offset_bottom = 11.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="Highlight" type="Button" parent="."]
|
||||
layout_mode = 2
|
||||
offset_left = 336.0
|
||||
offset_right = 362.0
|
||||
offset_bottom = 31.0
|
||||
tooltip_text = "Highlight Color"
|
||||
icon = ExtResource("10")
|
||||
flat = true
|
||||
|
||||
[node name="PopupPanel" type="PopupPanel" parent="Highlight"]
|
||||
size = Vector2i(116, 227)
|
||||
|
||||
[node name="ColorPicker" type="ColorPicker" parent="Highlight/PopupPanel"]
|
||||
offset_left = 4.0
|
||||
offset_top = 4.0
|
||||
offset_right = 294.0
|
||||
offset_bottom = 511.0
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="Highlight"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -9.0
|
||||
offset_top = 8.0
|
||||
offset_right = 9.0
|
||||
offset_bottom = 11.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="VSeparator2" type="VSeparator" parent="."]
|
||||
layout_mode = 2
|
||||
offset_left = 366.0
|
||||
offset_right = 370.0
|
||||
offset_bottom = 31.0
|
||||
|
||||
[node name="HorizontalAlign" type="Button" parent="."]
|
||||
layout_mode = 2
|
||||
offset_left = 374.0
|
||||
offset_right = 400.0
|
||||
offset_bottom = 31.0
|
||||
tooltip_text = "Horizontal Align"
|
||||
toggle_mode = true
|
||||
icon = ExtResource("14")
|
||||
flat = true
|
||||
|
||||
[node name="PopupMenu" type="PopupMenu" parent="HorizontalAlign"]
|
||||
item_count = 3
|
||||
item_0/text = ""
|
||||
item_0/icon = ExtResource("14")
|
||||
item_0/id = 0
|
||||
item_1/text = ""
|
||||
item_1/icon = ExtResource("13")
|
||||
item_1/id = 1
|
||||
item_2/text = ""
|
||||
item_2/icon = ExtResource("12")
|
||||
item_2/id = 2
|
||||
|
||||
[node name="VerticalAlign" type="Button" parent="."]
|
||||
layout_mode = 2
|
||||
offset_left = 404.0
|
||||
offset_right = 430.0
|
||||
offset_bottom = 31.0
|
||||
tooltip_text = "Vertical Align"
|
||||
toggle_mode = true
|
||||
icon = ExtResource("16")
|
||||
flat = true
|
||||
|
||||
[node name="PopupMenu" type="PopupMenu" parent="VerticalAlign"]
|
||||
item_count = 3
|
||||
item_0/text = ""
|
||||
item_0/icon = ExtResource("16")
|
||||
item_0/id = 0
|
||||
item_1/text = ""
|
||||
item_1/icon = ExtResource("17")
|
||||
item_1/id = 1
|
||||
item_2/text = ""
|
||||
item_2/icon = ExtResource("15")
|
||||
item_2/id = 2
|
||||
|
||||
[node name="VSeparator3" type="VSeparator" parent="."]
|
||||
layout_mode = 2
|
||||
offset_left = 434.0
|
||||
offset_right = 438.0
|
||||
offset_bottom = 31.0
|
||||
|
||||
[node name="FontFormatting" type="OptionButton" parent="."]
|
||||
custom_minimum_size = Vector2i(112, 0)
|
||||
layout_mode = 2
|
||||
offset_left = 442.0
|
||||
offset_right = 554.0
|
||||
offset_bottom = 31.0
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 4
|
||||
tooltip_text = "Font Formatting"
|
||||
clip_text = true
|
||||
item_count = 13
|
||||
selected = -1
|
||||
popup/item_0/text = "Heading 1"
|
||||
popup/item_0/id = 0
|
||||
popup/item_1/text = "Heading 2"
|
||||
popup/item_1/id = 1
|
||||
popup/item_2/text = "Heading 3"
|
||||
popup/item_2/id = 2
|
||||
popup/item_3/text = "Heading 4"
|
||||
popup/item_3/id = 3
|
||||
popup/item_4/text = "Heading 5"
|
||||
popup/item_4/id = 4
|
||||
popup/item_5/text = "Heading 6"
|
||||
popup/item_5/id = 5
|
||||
popup/item_6/text = "Subtitle 1"
|
||||
popup/item_6/id = 6
|
||||
popup/item_7/text = "Subtitle 2"
|
||||
popup/item_7/id = 7
|
||||
popup/item_8/text = "Body 1"
|
||||
popup/item_8/id = 8
|
||||
popup/item_9/text = "Body 2"
|
||||
popup/item_9/id = 9
|
||||
popup/item_10/text = "Button"
|
||||
popup/item_10/id = 10
|
||||
popup/item_11/text = "Caption"
|
||||
popup/item_11/id = 11
|
||||
popup/item_12/text = "Overline"
|
||||
popup/item_12/id = 12
|
||||
|
||||
[node name="Tools" type="Button" parent="."]
|
||||
layout_mode = 2
|
||||
offset_left = 558.0
|
||||
offset_right = 584.0
|
||||
offset_bottom = 31.0
|
||||
tooltip_text = "Tools"
|
||||
icon = ExtResource("19")
|
||||
flat = true
|
||||
|
||||
[node name="PopupMenu" type="PopupMenu" parent="Tools"]
|
||||
item_count = 3
|
||||
item_0/text = "Font Clear"
|
||||
item_0/icon = ExtResource("11")
|
||||
item_0/id = 0
|
||||
item_1/text = "Color Clear"
|
||||
item_1/icon = ExtResource("6")
|
||||
item_1/id = 1
|
||||
item_2/text = "Rect Size Refresh"
|
||||
item_2/icon = ExtResource("7")
|
||||
item_2/id = 2
|
240
addons/ui_design_tool/scripts/FontManager.gd
Normal file
|
@ -0,0 +1,240 @@
|
|||
extends Object
|
||||
|
||||
const FONT_FILE_PATTERN = "\\.ttf$"
|
||||
const FONT_WEIGHT_PATTERNS = {
|
||||
"thin": "(?i)(-|_)thin",
|
||||
"extra_light": "(?i)(-|_)extralight",
|
||||
"light": "(?i)(-|_)light",
|
||||
"regular": "(?i)(-|_)regular",
|
||||
"medium": "(?i)(-|_)medium",
|
||||
"semi_bold": "(?i)(-|_)semibold",
|
||||
"bold": "(?i)(-|_)bold",
|
||||
"extra_bold": "(?i)(-|_)extrabold",
|
||||
"black": "(?i)(-|_)black",
|
||||
"extra_black": "(?i)(-|_)extrablack"
|
||||
}
|
||||
const FONT_ITALIC_PATTERN = "(?i)italic"
|
||||
const FONT_ITALIC_ONLY_PATTERN = "(?i)(-|_)italic"
|
||||
const FONT_VARIABLE_PATTERN = "(?i)(-|_)variable"
|
||||
var FONT_FORMATTINGS = {
|
||||
"Heading 1": FontFormatting.new("light", 96, -3),
|
||||
"Heading 2": FontFormatting.new("light", 60, -2),
|
||||
"Heading 3": FontFormatting.new("regular", 48),
|
||||
"Heading 4": FontFormatting.new("regular", 34, 1),
|
||||
"Heading 5": FontFormatting.new("regular", 24),
|
||||
"Heading 6": FontFormatting.new("medium", 20, 1),
|
||||
"Subtitle 1": FontFormatting.new("regular", 16),
|
||||
"Subtitle 2": FontFormatting.new("medium", 14, 1),
|
||||
"Body 1": FontFormatting.new("regular", 16, 1),
|
||||
"Body 2": FontFormatting.new("regular", 14, 1),
|
||||
"Button": FontFormatting.new("medium", 14, 1),
|
||||
"Caption": FontFormatting.new("regular", 12, 1),
|
||||
"Overline": FontFormatting.new("regular", 10)
|
||||
} # Typography hierarchy presets, see https://material.io/design/typography/the-type-system.html#type-scale
|
||||
const DIR_FOLDER_PATTERN = "\\w+(?!.*\\w)"
|
||||
|
||||
var font_families = {}
|
||||
|
||||
var _font_file_regex = RegEx.new()
|
||||
var _font_weight_regexes = {
|
||||
"thin": RegEx.new(),
|
||||
"extra_light": RegEx.new(),
|
||||
"light": RegEx.new(),
|
||||
"regular": RegEx.new(),
|
||||
"medium": RegEx.new(),
|
||||
"semi_bold": RegEx.new(),
|
||||
"bold": RegEx.new(),
|
||||
"extra_bold": RegEx.new(),
|
||||
"black": RegEx.new(),
|
||||
"extra_black": RegEx.new()
|
||||
}
|
||||
var _font_italic_regex = RegEx.new()
|
||||
var _font_italic_only_regex = RegEx.new()
|
||||
var _font_variable_regex = RegEx.new()
|
||||
var _dir_folder_regex = RegEx.new()
|
||||
|
||||
|
||||
func _init():
|
||||
if _font_file_regex.compile(FONT_FILE_PATTERN):
|
||||
print("Failed to compile ", FONT_FILE_PATTERN)
|
||||
|
||||
for font_weight in _font_weight_regexes.keys():
|
||||
if _font_weight_regexes[font_weight].compile(FONT_WEIGHT_PATTERNS[font_weight]):
|
||||
print("Failed to compile ", FONT_WEIGHT_PATTERNS[font_weight])
|
||||
|
||||
if _font_italic_regex.compile(FONT_ITALIC_PATTERN):
|
||||
print("Failed to compile ", FONT_ITALIC_PATTERN)
|
||||
|
||||
if _font_italic_only_regex.compile(FONT_ITALIC_ONLY_PATTERN):
|
||||
print("Failed to compile ", FONT_ITALIC_ONLY_PATTERN)
|
||||
|
||||
if _font_variable_regex.compile(FONT_VARIABLE_PATTERN):
|
||||
print("Failed to compile ", FONT_VARIABLE_PATTERN)
|
||||
|
||||
if _dir_folder_regex.compile(DIR_FOLDER_PATTERN):
|
||||
print("Failed to compile ", DIR_FOLDER_PATTERN)
|
||||
|
||||
# Load root dir of font resources, check Readme for directory structure
|
||||
func load_root_dir(root_dir):
|
||||
var directory = DirAccess.open(root_dir)
|
||||
var result = DirAccess.get_open_error()
|
||||
if result == OK:
|
||||
font_families.clear()
|
||||
directory.list_dir_begin() # Skip . and .. directory and hidden# TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547
|
||||
var dir = directory.get_next()
|
||||
while dir != "":
|
||||
if not directory.current_is_dir():
|
||||
dir = directory.get_next()
|
||||
continue
|
||||
|
||||
load_fonts(directory.get_current_dir() + "/" + dir)
|
||||
dir = directory.get_next()
|
||||
directory.list_dir_end()
|
||||
else:
|
||||
push_warning("UI Design Tool: An error occurred when trying to access %s, ERROR: %d" % [root_dir, result])
|
||||
return false
|
||||
|
||||
return true
|
||||
|
||||
# Load fonts data from directory, check Readme for filename pattern
|
||||
func load_fonts(dir):
|
||||
var directory = DirAccess.open(dir)
|
||||
var result = DirAccess.get_open_error()
|
||||
if result == OK:
|
||||
var font_family_name = _dir_folder_regex.search(dir).get_string()
|
||||
var font_family = FontFamily.new(font_family_name)
|
||||
directory.list_dir_begin()
|
||||
var filename = directory.get_next()
|
||||
while filename != "":
|
||||
if directory.current_is_dir():
|
||||
filename = directory.get_next()
|
||||
continue
|
||||
|
||||
if _font_file_regex.search(filename):
|
||||
for font_weight in _font_weight_regexes.keys():
|
||||
if _font_variable_regex.search(filename): # Godot doesn't support variable font
|
||||
continue
|
||||
|
||||
var abs_dir = directory.get_current_dir() + "/" + filename
|
||||
if _font_weight_regexes[font_weight].search(filename):
|
||||
var font_data = load(abs_dir)
|
||||
|
||||
if _font_italic_regex.search(filename):
|
||||
font_family.set_font_face(FontFace.new(font_family.name, font_weight, font_data, FONT_STYLE.ITALIC))
|
||||
else:
|
||||
font_family.set_font_face(FontFace.new(font_family.name, font_weight, font_data))
|
||||
break
|
||||
else:
|
||||
# Capture regular italic from {font-name}-italic.ttf
|
||||
if _font_italic_only_regex.search(filename):
|
||||
var font_data = load(abs_dir)
|
||||
font_family.set_font_face(FontFace.new(font_family.name, "regular", font_data, FONT_STYLE.ITALIC))
|
||||
break
|
||||
filename = directory.get_next()
|
||||
directory.list_dir_end()
|
||||
|
||||
if not font_family.is_empty():
|
||||
font_families[font_family.name] = font_family
|
||||
else:
|
||||
push_warning("UI Design Tool: Unable to locate usable .ttf files from %s, check README.md for proper directory/filename structure" % dir)
|
||||
else:
|
||||
push_warning("UI Design Tool: An error occurred when trying to access %s, ERROR: %d" % [dir, result])
|
||||
return false
|
||||
|
||||
return true
|
||||
|
||||
func get_font_face(font_data):
|
||||
for res in font_families.values():
|
||||
for font_weight in FONT_WEIGHT.keys():
|
||||
var font_faces = res.get(font_weight)
|
||||
for font_face in font_faces.values():
|
||||
if font_face.data and font_data:
|
||||
if font_face.data.resource_path == font_data.resource_path:
|
||||
return font_face
|
||||
return null
|
||||
|
||||
# Find font resource with font name
|
||||
func get_font_family(font_family_name):
|
||||
return font_families.get(font_family_name)
|
||||
|
||||
static func get_font_style_str(font_style):
|
||||
return FONT_STYLE.keys()[font_style].to_lower()
|
||||
|
||||
# Declaration of font type with font_faces
|
||||
class FontFamily:
|
||||
var name = ""
|
||||
var thin = {}
|
||||
var extra_light = {}
|
||||
var light = {}
|
||||
var regular = {}
|
||||
var medium = {}
|
||||
var semi_bold = {}
|
||||
var bold = {}
|
||||
var extra_bold = {}
|
||||
var black = {}
|
||||
var extra_black = {}
|
||||
|
||||
func _init(n):
|
||||
name = n
|
||||
|
||||
func set_font_face(font_face):
|
||||
var font_faces = get(font_face.font_weight.replace('-', '_'))
|
||||
font_faces[FONT_STYLE.keys()[font_face.font_style].to_lower()] = font_face
|
||||
|
||||
func is_empty():
|
||||
for font_weight in FONT_WEIGHT.keys():
|
||||
var font_faces = get(font_weight)
|
||||
if not font_faces.values().is_empty():
|
||||
return false
|
||||
return true
|
||||
|
||||
func get_class():
|
||||
return "FontFamily"
|
||||
|
||||
# Font face data, see (https://developer.mozilla.org/my/docs/Web/CSS/@font-face)
|
||||
class FontFace:
|
||||
var font_family = ""
|
||||
var font_weight = ""
|
||||
var font_style = FONT_STYLE.NORMAL
|
||||
var data
|
||||
|
||||
func _init(ff, fw, d, fs=FONT_STYLE.NORMAL):
|
||||
font_family = ff
|
||||
font_weight = fw
|
||||
font_style = fs
|
||||
data = d
|
||||
|
||||
func get_class():
|
||||
return "FontFace"
|
||||
|
||||
# Declaration of font style TODO: Custom resource to define font style
|
||||
class FontFormatting:
|
||||
var font_weight = "regular"
|
||||
var font_style = 0 # FONT_STYLE.NORMAL
|
||||
var size = 16
|
||||
var letter_spacing = 0
|
||||
|
||||
func _init(fw, s, ls=0):
|
||||
font_weight = fw
|
||||
size = s
|
||||
letter_spacing = ls
|
||||
|
||||
# List of font style, see (https://developer.mozilla.org/my/docs/Web/CSS/font-style)
|
||||
enum FONT_STYLE {
|
||||
NORMAL,
|
||||
ITALIC,
|
||||
OBLIQUE
|
||||
}
|
||||
|
||||
# List of font weights, see (https://docs.microsoft.com/en-us/typography/opentype/spec/os2#usweightclass)
|
||||
const FONT_WEIGHT = {
|
||||
"thin": 100,
|
||||
"extra_light": 200,
|
||||
"light": 300,
|
||||
"regular": 400,
|
||||
"medium": 500,
|
||||
"semi_bold": 600,
|
||||
"bold": 700,
|
||||
"extra_bold": 800,
|
||||
"black": 900
|
||||
}
|
61
addons/ui_design_tool/scripts/Utils.gd
Normal file
|
@ -0,0 +1,61 @@
|
|||
static func markup_text_edit_selection(text_edit, start_text, end_text):
|
||||
if not text_edit.is_selection_active():
|
||||
return
|
||||
|
||||
var selection_from_pos = Vector2(text_edit.get_selection_from_column(), text_edit.get_selection_from_line())
|
||||
var selection_to_pos = Vector2(text_edit.get_selection_to_column(), text_edit.get_selection_to_line())
|
||||
var one_line_selection = selection_from_pos.y == selection_to_pos.y
|
||||
|
||||
text_edit.deselect()
|
||||
set_text_edit_cursor_pos(text_edit, selection_from_pos.x, selection_from_pos.y)
|
||||
text_edit.insert_text_at_cursor(start_text)
|
||||
|
||||
if one_line_selection:
|
||||
selection_to_pos.x += start_text.length()
|
||||
|
||||
set_text_edit_cursor_pos(text_edit, selection_to_pos.x, selection_to_pos.y)
|
||||
text_edit.insert_text_at_cursor(end_text)
|
||||
|
||||
if one_line_selection:
|
||||
selection_to_pos.x += end_text.length()
|
||||
|
||||
text_edit.select(selection_from_pos.y, selection_from_pos.x, selection_to_pos.y, selection_to_pos.x)
|
||||
|
||||
static func get_text_edit_cursor_pos(text_edit):
|
||||
return Vector2(text_edit.get_caret_column(), text_edit.get_caret_line())
|
||||
|
||||
static func set_text_edit_cursor_pos(text_edit, column, line):
|
||||
text_edit.set_caret_column(column)
|
||||
text_edit.set_caret_line(line)
|
||||
|
||||
# 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)
|
||||
static func popup_on_target(popup, target):
|
||||
popup.size = popup.get_contents_minimum_size()
|
||||
var usable_rect = Rect2(Vector2.ZERO, DisplayServer.window_get_size())
|
||||
var cp_rect = Rect2(Vector2.ZERO, popup.get_size())
|
||||
for i in 4:
|
||||
if i > 1:
|
||||
cp_rect.position.y = target.global_position.y - cp_rect.size.y
|
||||
else:
|
||||
cp_rect.position.y = target.global_position.y + target.get_size().y
|
||||
|
||||
if i & 1:
|
||||
cp_rect.position.x = target.global_position.x
|
||||
else:
|
||||
cp_rect.position.x = target.global_position.x - max(0, cp_rect.size.x - target.get_size().x)
|
||||
|
||||
if usable_rect.encloses(cp_rect):
|
||||
break
|
||||
popup.set_position(cp_rect.position)
|
||||
popup.popup()
|
||||
|
||||
# Roughly calculate the display size of option button regarding to the display_text
|
||||
static func get_option_button_display_size(option_button, display_text):
|
||||
# TODO: Improve accuracy
|
||||
# Use default theme if not assingned
|
||||
var theme = option_button.get_theme() if option_button.get_theme() else Theme.new()
|
||||
var string_size = theme.get_font("font", "fonts").get_string_size(display_text)
|
||||
var arrow_icon = theme.get_icon("arrow", "styles")
|
||||
# Takes arrow icon size into account
|
||||
string_size.x += arrow_icon.get_width()
|
||||
return string_size
|