Initial Commit
1
addons/script-ide/outline/icon/class.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="14" height="14" fill="#ff7085"/></svg>
|
||||
|
After Width: | Height: | Size: 127 B |
44
addons/script-ide/outline/icon/class.svg.import
Normal file
@@ -0,0 +1,44 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://csik7oxvt7tq3"
|
||||
path="res://.godot/imported/class.svg-9e3f3363c9474e8c1dcf8ba4e40e95bf.ctex"
|
||||
metadata={
|
||||
"has_editor_variant": true,
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/script-ide/outline/icon/class.svg"
|
||||
dest_files=["res://.godot/imported/class.svg-9e3f3363c9474e8c1dcf8ba4e40e95bf.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
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/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
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=true
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
1
addons/script-ide/outline/icon/constant.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-3.866 0-7 3.134-7 7 0 3.866 3.134 7 7 7s7-3.134 7-7c0-3.866-3.134-7-7-7zm0 2c2.7614 0 5 2.2386 5 5 0 2.7614-2.2386 5-5 5-2.7614 0-5-2.2386-5-5 0-2.7614 2.2386-5 5-5z" fill="#ff7085"/></svg>
|
||||
|
After Width: | Height: | Size: 268 B |
44
addons/script-ide/outline/icon/constant.svg.import
Normal file
@@ -0,0 +1,44 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cawc456ja8vf5"
|
||||
path="res://.godot/imported/constant.svg-b36d0d3f8bf0f157e4f3b418b692e11b.ctex"
|
||||
metadata={
|
||||
"has_editor_variant": true,
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/script-ide/outline/icon/constant.svg"
|
||||
dest_files=["res://.godot/imported/constant.svg-b36d0d3f8bf0f157e4f3b418b692e11b.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
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/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
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=true
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
1
addons/script-ide/outline/icon/engine_func.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-3.866 0-7 3.134-7 7 0 3.866 3.134 7 7 7 3.866 0 7-3.134 7-7 0-3.866-3.134-7-7-7z" fill="#57b3ff"/></svg>
|
||||
|
After Width: | Height: | Size: 183 B |
44
addons/script-ide/outline/icon/engine_func.svg.import
Normal file
@@ -0,0 +1,44 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cupb0polhqrwj"
|
||||
path="res://.godot/imported/engine_func.svg-eb6c615eeef058e7cc5ec3b5a17fc008.ctex"
|
||||
metadata={
|
||||
"has_editor_variant": true,
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/script-ide/outline/icon/engine_func.svg"
|
||||
dest_files=["res://.godot/imported/engine_func.svg-eb6c615eeef058e7cc5ec3b5a17fc008.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
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/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
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=true
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
1
addons/script-ide/outline/icon/export.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-3.866 0-7 3.134-7 7 0 3.866 3.134 7 7 7 3.866 0 7-3.134 7-7 0-3.866-3.134-7-7-7z" fill="#ffb273"/></svg>
|
||||
|
After Width: | Height: | Size: 183 B |
44
addons/script-ide/outline/icon/export.svg.import
Normal file
@@ -0,0 +1,44 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bvu2gnj8fv2kw"
|
||||
path="res://.godot/imported/export.svg-b7770a5f2f99766591abd69aca087dfc.ctex"
|
||||
metadata={
|
||||
"has_editor_variant": true,
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/script-ide/outline/icon/export.svg"
|
||||
dest_files=["res://.godot/imported/export.svg-b7770a5f2f99766591abd69aca087dfc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
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/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
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=true
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
1
addons/script-ide/outline/icon/func.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-3.866 0-7 3.134-7 7 0 3.866 3.134 7 7 7 3.866 0 7-3.134 7-7 0-3.866-3.134-7-7-7z" fill="#8eef97"/></svg>
|
||||
|
After Width: | Height: | Size: 183 B |
44
addons/script-ide/outline/icon/func.svg.import
Normal file
@@ -0,0 +1,44 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://rni04cl446ov"
|
||||
path="res://.godot/imported/func.svg-d034576bf2eed84b270a8dc1d6d64df6.ctex"
|
||||
metadata={
|
||||
"has_editor_variant": true,
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/script-ide/outline/icon/func.svg"
|
||||
dest_files=["res://.godot/imported/func.svg-d034576bf2eed84b270a8dc1d6d64df6.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
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/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
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=true
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
1
addons/script-ide/outline/icon/func_get.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 15c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm0.5-2a1 1 0 0 1-0.70703-0.29297l-4-4a1 1 0 0 1-0.25977-0.62695 1.0001 1.0001 0 0 1 0-0.16016 1 1 0 0 1 0.25977-0.62695l4-4a1 1 0 0 1 1.4141 0 1 1 0 0 1 0 1.4141l-2.293 2.293h4.5859a1 1 0 0 1 1 1 1 1 0 0 1-1 1h-4.5859l2.293 2.293a1 1 0 0 1 0 1.4141 1 1 0 0 1-0.70703 0.29297z" fill="#8eef97"/></svg>
|
||||
|
After Width: | Height: | Size: 435 B |
44
addons/script-ide/outline/icon/func_get.svg.import
Normal file
@@ -0,0 +1,44 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c2a3aowyhxj5x"
|
||||
path="res://.godot/imported/func_get.svg-033d200e05dd58beec3becc7967b8c7d.ctex"
|
||||
metadata={
|
||||
"has_editor_variant": true,
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/script-ide/outline/icon/func_get.svg"
|
||||
dest_files=["res://.godot/imported/func_get.svg-033d200e05dd58beec3becc7967b8c7d.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
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/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
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=true
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
1
addons/script-ide/outline/icon/func_set.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-3.866 0-7 3.134-7 7 0 3.866 3.134 7 7 7s7-3.134 7-7c0-3.866-3.134-7-7-7zm-0.5 2a1 1 0 0 1 0.70703 0.29297l4 4a1 1 0 0 1 0.25977 0.62695 1.0001 1.0001 0 0 1 0 0.16016 1 1 0 0 1-0.25977 0.62695l-4 4a1 1 0 0 1-1.4141 0 1 1 0 0 1 0-1.4141l2.293-2.293h-4.5859a1 1 0 0 1-1-1 1 1 0 0 1 1-1h4.5859l-2.293-2.293a1 1 0 0 1 0-1.4141 1 1 0 0 1 0.70703-0.29297z" fill="#8eef97"/></svg>
|
||||
|
After Width: | Height: | Size: 451 B |
44
addons/script-ide/outline/icon/func_set.svg.import
Normal file
@@ -0,0 +1,44 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bvjkrti6kj6o2"
|
||||
path="res://.godot/imported/func_set.svg-a9087ff3e7ab6aec141e34555a32a254.ctex"
|
||||
metadata={
|
||||
"has_editor_variant": true,
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/script-ide/outline/icon/func_set.svg"
|
||||
dest_files=["res://.godot/imported/func_set.svg-a9087ff3e7ab6aec141e34555a32a254.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
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/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
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=true
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
1
addons/script-ide/outline/icon/property.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-3.866 0-7 3.134-7 7 0 3.866 3.134 7 7 7 3.866 0 7-3.134 7-7 0-3.866-3.134-7-7-7z" fill="#ff7085"/></svg>
|
||||
|
After Width: | Height: | Size: 183 B |
44
addons/script-ide/outline/icon/property.svg.import
Normal file
@@ -0,0 +1,44 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dbwlgnwv5e8kl"
|
||||
path="res://.godot/imported/property.svg-a9a1c76c01653424a37bad3c0caee2de.ctex"
|
||||
metadata={
|
||||
"has_editor_variant": true,
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/script-ide/outline/icon/property.svg"
|
||||
dest_files=["res://.godot/imported/property.svg-a9a1c76c01653424a37bad3c0caee2de.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
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/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
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=true
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
1
addons/script-ide/outline/icon/signal.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-3.866 0-7 3.134-7 7 0 3.866 3.134 7 7 7 3.866 0 7-3.134 7-7 0-3.866-3.134-7-7-7z" fill="#ffdd65"/></svg>
|
||||
|
After Width: | Height: | Size: 183 B |
44
addons/script-ide/outline/icon/signal.svg.import
Normal file
@@ -0,0 +1,44 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bnccvnaloqnte"
|
||||
path="res://.godot/imported/signal.svg-65741ce388cd0a6b19f1b195a997cce3.ctex"
|
||||
metadata={
|
||||
"has_editor_variant": true,
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/script-ide/outline/icon/signal.svg"
|
||||
dest_files=["res://.godot/imported/signal.svg-65741ce388cd0a6b19f1b195a997cce3.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
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/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
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=true
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
25
addons/script-ide/outline/outline_button.gd
Normal file
@@ -0,0 +1,25 @@
|
||||
## Button that is used as in the outline for a concrete outline type.
|
||||
@tool
|
||||
extends Button
|
||||
|
||||
signal right_clicked
|
||||
|
||||
func _init() -> void:
|
||||
toggle_mode = true
|
||||
icon_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
|
||||
add_theme_stylebox_override(&"normal", StyleBoxEmpty.new())
|
||||
|
||||
add_theme_color_override(&"icon_pressed_color", Color.WHITE)
|
||||
add_theme_color_override(&"icon_hover_color", Color.WHITE)
|
||||
add_theme_color_override(&"icon_hover_pressed_color", Color.WHITE)
|
||||
add_theme_color_override(&"icon_focus_color", Color.WHITE)
|
||||
|
||||
func _gui_input(event: InputEvent) -> void:
|
||||
if event is InputEventMouseButton && event.pressed:
|
||||
if (event.button_index == MOUSE_BUTTON_RIGHT):
|
||||
button_pressed = true
|
||||
on_right_click()
|
||||
|
||||
func on_right_click():
|
||||
right_clicked.emit()
|
||||
1
addons/script-ide/outline/outline_button.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://c4fvj2xt46lgx
|
||||
544
addons/script-ide/outline/outline_container.gd
Normal file
@@ -0,0 +1,544 @@
|
||||
## The outline container shows a filter box and
|
||||
## all script members with different color coding, depending of the type.
|
||||
@tool
|
||||
extends VBoxContainer
|
||||
|
||||
const GETTER: StringName = &"get"
|
||||
const SETTER: StringName = &"set"
|
||||
const UNDERSCORE: StringName = &"_"
|
||||
const INLINE: StringName = &"@"
|
||||
const BUILT_IN_SCRIPT: StringName = &"::GDScript"
|
||||
|
||||
#region Outline type name
|
||||
const PROPERTY: StringName = &"property"
|
||||
const TYPE: StringName = &"type"
|
||||
|
||||
const ENGINE_FUNCS: StringName = &"Engine Callbacks"
|
||||
const FUNCS: StringName = &"Functions"
|
||||
const SIGNALS: StringName = &"Signals"
|
||||
const EXPORTED: StringName = &"Exported Properties"
|
||||
const PROPERTIES: StringName = &"Properties"
|
||||
const CLASSES: StringName = &"Classes"
|
||||
const CONSTANTS: StringName = &"Constants"
|
||||
|
||||
const DEFAULT_ORDER: PackedStringArray = [ENGINE_FUNCS, FUNCS, SIGNALS, EXPORTED, PROPERTIES, CONSTANTS, CLASSES]
|
||||
#endregion
|
||||
|
||||
const OutlineButton := preload("uid://c4fvj2xt46lgx")
|
||||
|
||||
const Plugin := preload("uid://bc0b5v66xdidn")
|
||||
|
||||
@onready var filter_box: HBoxContainer = %FilterBox
|
||||
@onready var outline: ItemList = %Outline
|
||||
|
||||
var plugin: Plugin
|
||||
|
||||
#region Existing Engine controls we modify
|
||||
var outline_filter_txt: LineEdit
|
||||
#endregion
|
||||
|
||||
#region Outline icons and buttons
|
||||
var engine_func_icon: Texture2D
|
||||
var func_icon: Texture2D
|
||||
var func_get_icon: Texture2D
|
||||
var func_set_icon: Texture2D
|
||||
var property_icon: Texture2D
|
||||
var export_icon: Texture2D
|
||||
var signal_icon: Texture2D
|
||||
var constant_icon: Texture2D
|
||||
var class_icon: Texture2D
|
||||
|
||||
var class_btn: Button
|
||||
var constant_btn: Button
|
||||
var signal_btn: Button
|
||||
var property_btn: Button
|
||||
var export_btn: Button
|
||||
var func_btn: Button
|
||||
var engine_func_btn: Button
|
||||
#endregion
|
||||
|
||||
var is_hide_private_members: bool = false : set = set_hide_private_members
|
||||
var outline_order: PackedStringArray : set = set_outline_order
|
||||
|
||||
var outline_type_order: Array[OutlineType] = []
|
||||
var outline_cache: OutlineCache
|
||||
|
||||
func _ready() -> void:
|
||||
init_icons()
|
||||
init_outline_order()
|
||||
outline.item_selected.connect(find_in_outline_and_goto)
|
||||
|
||||
if (plugin == null):
|
||||
return
|
||||
|
||||
engine_func_btn = create_filter_btn(engine_func_icon, ENGINE_FUNCS)
|
||||
func_btn = create_filter_btn(func_icon, FUNCS)
|
||||
signal_btn = create_filter_btn(signal_icon, SIGNALS)
|
||||
export_btn = create_filter_btn(export_icon, EXPORTED)
|
||||
property_btn = create_filter_btn(property_icon, PROPERTIES)
|
||||
class_btn = create_filter_btn(class_icon, CLASSES)
|
||||
constant_btn = create_filter_btn(constant_icon, CONSTANTS)
|
||||
|
||||
func update():
|
||||
update_outline_cache()
|
||||
update_outline()
|
||||
|
||||
func tab_changed():
|
||||
var is_script: bool = get_current_script() != null
|
||||
visible = is_script
|
||||
|
||||
update()
|
||||
|
||||
func find_in_outline_and_goto(selected_idx: int):
|
||||
var script: Script = get_current_script()
|
||||
if (!script):
|
||||
return
|
||||
|
||||
var text: String = outline.get_item_text(selected_idx)
|
||||
var metadata: Dictionary[StringName, StringName] = outline.get_item_metadata(selected_idx)
|
||||
var modifier: StringName = metadata[&"modifier"]
|
||||
var type: StringName = metadata[TYPE]
|
||||
|
||||
var type_with_text: String = type + " " + text
|
||||
if (type == &"func"):
|
||||
type_with_text = type_with_text.substr(0, type_with_text.find("("))
|
||||
|
||||
var source_code: String = script.get_source_code()
|
||||
var lines: PackedStringArray = source_code.split("\n")
|
||||
|
||||
var index: int = 0
|
||||
for line: String in lines:
|
||||
# Easy case, like 'var abc'
|
||||
if (line.begins_with(type_with_text)):
|
||||
plugin.goto_line(index)
|
||||
return
|
||||
|
||||
# We have an modifier, e.g. 'static'
|
||||
if (modifier != &"" && line.begins_with(modifier)):
|
||||
if (line.begins_with(modifier + " " + type_with_text)):
|
||||
plugin.goto_line(index)
|
||||
return
|
||||
# Special case: An 'enum' is treated different.
|
||||
elif (modifier == &"enum" && line.contains("enum " + text)):
|
||||
plugin.goto_line(index)
|
||||
return
|
||||
|
||||
# Hard case, probably something like '@onready var abc'
|
||||
if (type == &"var" && line.contains(type_with_text)):
|
||||
plugin.goto_line(index)
|
||||
return
|
||||
|
||||
index += 1
|
||||
|
||||
push_error(type_with_text + " or " + modifier + " not found in source code")
|
||||
|
||||
## Initializes all plugin icons, while respecting the editor settings.
|
||||
func init_icons():
|
||||
engine_func_icon = create_editor_texture(load_rel("icon/engine_func.svg"))
|
||||
func_icon = create_editor_texture(load_rel("icon/func.svg"))
|
||||
func_get_icon = create_editor_texture(load_rel("icon/func_get.svg"))
|
||||
func_set_icon = create_editor_texture(load_rel("icon/func_set.svg"))
|
||||
property_icon = create_editor_texture(load_rel("icon/property.svg"))
|
||||
export_icon = create_editor_texture(load_rel("icon/export.svg"))
|
||||
signal_icon = create_editor_texture(load_rel("icon/signal.svg"))
|
||||
constant_icon = create_editor_texture(load_rel("icon/constant.svg"))
|
||||
class_icon = create_editor_texture(load_rel("icon/class.svg"))
|
||||
|
||||
func create_filter_btn(icon: Texture2D, type: StringName) -> Button:
|
||||
var btn: OutlineButton = OutlineButton.new()
|
||||
btn.icon = icon
|
||||
btn.tooltip_text = type
|
||||
|
||||
var property: StringName = plugin.SCRIPT_IDE + type.to_lower().replace(" ", "_")
|
||||
btn.set_meta(PROPERTY, property)
|
||||
btn.set_meta(TYPE, type)
|
||||
btn.button_pressed = plugin.get_setting(property, true)
|
||||
|
||||
btn.toggled.connect(on_filter_button_pressed.bind(btn))
|
||||
btn.right_clicked.connect(on_right_click.bind(btn))
|
||||
|
||||
return btn
|
||||
|
||||
func on_right_click(btn: OutlineButton):
|
||||
btn.button_pressed = true
|
||||
|
||||
var pressed_state: bool = false
|
||||
for child: Node in filter_box.get_children():
|
||||
var other_btn: Button = child
|
||||
|
||||
if (btn != other_btn):
|
||||
pressed_state = pressed_state || other_btn.button_pressed
|
||||
|
||||
for child: Node in filter_box.get_children():
|
||||
var other_btn: Button = child
|
||||
|
||||
if (btn != other_btn):
|
||||
other_btn.button_pressed = !pressed_state
|
||||
|
||||
outline_filter_txt.grab_focus()
|
||||
|
||||
func on_filter_button_pressed(pressed: bool, btn: Button):
|
||||
plugin.set_setting(btn.get_meta(PROPERTY), pressed)
|
||||
|
||||
update_outline()
|
||||
|
||||
## Initializes the outline type structure and sorts it based off the outline order.
|
||||
func init_outline_order():
|
||||
var outline_type: OutlineType = OutlineType.new()
|
||||
outline_type.type_name = ENGINE_FUNCS
|
||||
outline_type.add_to_outline = func(): add_to_outline_if_selected(engine_func_btn,
|
||||
func(): add_to_outline(outline_cache.engine_funcs, engine_func_icon, &"func"))
|
||||
outline_type_order.append(outline_type)
|
||||
|
||||
outline_type = OutlineType.new()
|
||||
outline_type.type_name = FUNCS
|
||||
outline_type.add_to_outline = func(): add_to_outline_if_selected(func_btn,
|
||||
func(): add_to_outline_ext(outline_cache.funcs, get_func_icon, &"func", &"static"))
|
||||
outline_type_order.append(outline_type)
|
||||
|
||||
outline_type = OutlineType.new()
|
||||
outline_type.type_name = SIGNALS
|
||||
outline_type.add_to_outline = func(): add_to_outline_if_selected(signal_btn,
|
||||
func(): add_to_outline(outline_cache.signals, signal_icon, &"signal"))
|
||||
outline_type_order.append(outline_type)
|
||||
|
||||
outline_type = OutlineType.new()
|
||||
outline_type.type_name = EXPORTED
|
||||
outline_type.add_to_outline = func(): add_to_outline_if_selected(export_btn,
|
||||
func(): add_to_outline(outline_cache.exports, export_icon, &"var", &"@export"))
|
||||
outline_type_order.append(outline_type)
|
||||
|
||||
outline_type = OutlineType.new()
|
||||
outline_type.type_name = PROPERTIES
|
||||
outline_type.add_to_outline = func(): add_to_outline_if_selected(property_btn,
|
||||
func(): add_to_outline(outline_cache.properties, property_icon, &"var"))
|
||||
outline_type_order.append(outline_type)
|
||||
|
||||
outline_type = OutlineType.new()
|
||||
outline_type.type_name = CLASSES
|
||||
outline_type.add_to_outline = func(): add_to_outline_if_selected(class_btn,
|
||||
func(): add_to_outline(outline_cache.classes, class_icon, &"class"))
|
||||
outline_type_order.append(outline_type)
|
||||
|
||||
outline_type = OutlineType.new()
|
||||
outline_type.type_name = CONSTANTS
|
||||
outline_type.add_to_outline = func(): add_to_outline_if_selected(constant_btn,
|
||||
func(): add_to_outline(outline_cache.constants, constant_icon, &"const", &"enum"))
|
||||
outline_type_order.append(outline_type)
|
||||
|
||||
func add_to_outline_if_selected(btn: Button, action: Callable):
|
||||
if (btn.button_pressed):
|
||||
action.call()
|
||||
|
||||
func update_outline_button_order():
|
||||
var all_buttons: Array[Button] = [engine_func_btn, func_btn, signal_btn, export_btn, property_btn, class_btn, constant_btn]
|
||||
all_buttons.sort_custom(sort_buttons_by_outline_order)
|
||||
|
||||
for btn: Button in all_buttons:
|
||||
if (btn.get_parent() != null):
|
||||
filter_box.remove_child(btn)
|
||||
|
||||
for btn: Button in all_buttons:
|
||||
filter_box.add_child(btn)
|
||||
|
||||
func sort_buttons_by_outline_order(btn1: Button, btn2: Button) -> bool:
|
||||
return sort_by_outline_order(btn1.get_meta(TYPE), btn2.get_meta(TYPE))
|
||||
|
||||
func sort_types_by_outline_order(type1: OutlineType, type2: OutlineType) -> bool:
|
||||
return sort_by_outline_order(type1.type_name, type2.type_name)
|
||||
|
||||
func sort_by_outline_order(outline_type1: StringName, outline_type2: StringName) -> bool:
|
||||
return outline_order.find(outline_type1) < outline_order.find(outline_type2)
|
||||
|
||||
func get_current_script() -> Script:
|
||||
var script_editor: ScriptEditor = EditorInterface.get_script_editor()
|
||||
return script_editor.get_current_script()
|
||||
|
||||
func update_outline_cache():
|
||||
outline_cache = null
|
||||
|
||||
var script: Script = get_current_script()
|
||||
if (!script):
|
||||
return
|
||||
|
||||
# Check if built-in script. In this case we need to duplicate it for whatever reason.
|
||||
if (script.get_path().contains(BUILT_IN_SCRIPT)):
|
||||
script = script.duplicate()
|
||||
|
||||
outline_cache = OutlineCache.new()
|
||||
|
||||
# Collect all script members.
|
||||
for_each_script_member(script, func(array: Array[String], item: String): array.append(item))
|
||||
|
||||
# Remove script members that only exist in the base script (which includes the base of the base etc.).
|
||||
# Note: The method that only collects script members without including the base script(s)
|
||||
# is not exposed to GDScript.
|
||||
var base_script: Script = script.get_base_script()
|
||||
if (base_script != null):
|
||||
for_each_script_member(base_script, func(array: Array[String], item: String): array.erase(item))
|
||||
|
||||
func for_each_script_member(script: Script, consumer: Callable):
|
||||
# Functions / Methods
|
||||
for dict: Dictionary in script.get_script_method_list():
|
||||
var func_name: String = dict[&"name"]
|
||||
|
||||
if (plugin.keywords.has(func_name)):
|
||||
func_name = create_function_signature(dict)
|
||||
consumer.call(outline_cache.engine_funcs, func_name)
|
||||
else:
|
||||
if (is_hide_private_members && func_name.begins_with(UNDERSCORE)):
|
||||
continue
|
||||
|
||||
# Inline getter/setter will normally be shown as '@...getter', '@...setter'.
|
||||
# Since we already show the variable itself, we will skip those.
|
||||
if (func_name.begins_with(INLINE)):
|
||||
continue
|
||||
|
||||
func_name = create_function_signature(dict)
|
||||
consumer.call(outline_cache.funcs, func_name)
|
||||
|
||||
# Properties / Exported variables
|
||||
for dict: Dictionary in script.get_script_property_list():
|
||||
var property: String = dict[&"name"]
|
||||
if (is_hide_private_members && property.begins_with(UNDERSCORE)):
|
||||
continue
|
||||
|
||||
var usage: int = dict[&"usage"]
|
||||
|
||||
if (usage & PROPERTY_USAGE_SCRIPT_VARIABLE):
|
||||
if (usage & PROPERTY_USAGE_STORAGE && usage & PROPERTY_USAGE_EDITOR):
|
||||
consumer.call(outline_cache.exports, property)
|
||||
else:
|
||||
consumer.call(outline_cache.properties, property)
|
||||
|
||||
# Static variables (are separated for whatever reason)
|
||||
for dict: Dictionary in script.get_property_list():
|
||||
var property: String = dict[&"name"]
|
||||
if (is_hide_private_members && property.begins_with(UNDERSCORE)):
|
||||
continue
|
||||
|
||||
var usage: int = dict[&"usage"]
|
||||
|
||||
if (usage & PROPERTY_USAGE_SCRIPT_VARIABLE):
|
||||
consumer.call(outline_cache.properties, property)
|
||||
|
||||
# Signals
|
||||
for dict: Dictionary in script.get_script_signal_list():
|
||||
var signal_name: String = dict[&"name"]
|
||||
|
||||
consumer.call(outline_cache.signals, signal_name)
|
||||
|
||||
# Constants / Classes
|
||||
for name_key: String in script.get_script_constant_map():
|
||||
if (is_hide_private_members && name_key.begins_with(UNDERSCORE)):
|
||||
continue
|
||||
|
||||
var object: Variant = script.get_script_constant_map().get(name_key)
|
||||
# Inner classes have no source code, while a const of type GDScript has.
|
||||
if (object is GDScript && !object.has_source_code()):
|
||||
consumer.call(outline_cache.classes, name_key)
|
||||
else:
|
||||
consumer.call(outline_cache.constants, name_key)
|
||||
|
||||
func update_outline():
|
||||
outline.clear()
|
||||
|
||||
if (outline_cache == null):
|
||||
return
|
||||
|
||||
for outline_type: OutlineType in outline_type_order:
|
||||
outline_type.add_to_outline.call()
|
||||
|
||||
func add_to_outline(items: Array[String], icon: Texture2D, type: StringName, modifier: StringName = &""):
|
||||
add_to_outline_ext(items, func(str: String): return icon, type, modifier)
|
||||
|
||||
func add_to_outline_ext(items: Array[String], icon_callable: Callable, type: StringName, modifier: StringName = &""):
|
||||
var text: String = outline_filter_txt.get_text()
|
||||
|
||||
if (is_sorted()):
|
||||
items = items.duplicate()
|
||||
items.sort_custom(func(str1: String, str2: String): return str1.naturalnocasecmp_to(str2) < 0)
|
||||
|
||||
for item: String in items:
|
||||
if (text.is_empty() || text.is_subsequence_ofn(item)):
|
||||
var icon: Texture2D = icon_callable.call(item)
|
||||
outline.add_item(item, icon, true)
|
||||
|
||||
var dict: Dictionary[StringName, StringName] = {
|
||||
TYPE: type,
|
||||
&"modifier": modifier
|
||||
}
|
||||
outline.set_item_metadata(outline.item_count - 1, dict)
|
||||
|
||||
func get_func_icon(func_name: String) -> Texture2D:
|
||||
var icon: Texture2D = func_icon
|
||||
if (func_name.begins_with(GETTER)):
|
||||
icon = func_get_icon
|
||||
elif (func_name.begins_with(SETTER)):
|
||||
icon = func_set_icon
|
||||
|
||||
return icon
|
||||
|
||||
func save_restore_filter() -> Array[bool]:
|
||||
var button_flags: Array[bool] = []
|
||||
for child: Node in filter_box.get_children():
|
||||
var btn: Button = child
|
||||
button_flags.append(btn.button_pressed)
|
||||
|
||||
btn.set_pressed_no_signal(true)
|
||||
|
||||
return button_flags
|
||||
|
||||
func restore_filter(button_flags: Array[bool]):
|
||||
var index: int = 0
|
||||
for flag: bool in button_flags:
|
||||
var btn: Button = filter_box.get_child(index)
|
||||
btn.set_pressed_no_signal(flag)
|
||||
index += 1
|
||||
|
||||
func set_outline_order(new_outline_order: PackedStringArray):
|
||||
outline_order = new_outline_order
|
||||
|
||||
if (filter_box == null):
|
||||
return
|
||||
|
||||
outline_type_order.sort_custom(sort_types_by_outline_order)
|
||||
|
||||
update_outline_button_order()
|
||||
update_outline()
|
||||
|
||||
func set_hide_private_members(new_value: bool):
|
||||
is_hide_private_members = new_value
|
||||
|
||||
if (filter_box == null):
|
||||
return
|
||||
|
||||
update_outline_cache()
|
||||
update_outline()
|
||||
|
||||
func update_filter_buttons():
|
||||
# Update filter buttons.
|
||||
for btn_node: Node in filter_box.get_children():
|
||||
var btn: Button = btn_node
|
||||
var property: StringName = btn.get_meta(PROPERTY)
|
||||
|
||||
btn.button_pressed = plugin.get_setting(property, btn.button_pressed)
|
||||
|
||||
func create_function_signature(method: Dictionary) -> String:
|
||||
var func_name: String = method[&"name"]
|
||||
func_name += "("
|
||||
|
||||
var args: Array = method[&"args"]
|
||||
var default_args: Array = method[&"default_args"]
|
||||
|
||||
var arg_index: int = 0
|
||||
var default_arg_index: int = 0
|
||||
var arg_str: String = ""
|
||||
for arg: Dictionary in args:
|
||||
if (arg_str != ""):
|
||||
arg_str += ", "
|
||||
|
||||
arg_str += arg[&"name"]
|
||||
var type: String = get_type(arg)
|
||||
if (type != ""):
|
||||
arg_str += ": " + type
|
||||
|
||||
if (args.size() - arg_index <= default_args.size()):
|
||||
var default_arg: Variant = default_args[default_arg_index]
|
||||
if (!default_arg):
|
||||
var type_hint: int = arg[&"type"]
|
||||
if (is_dictionary(type_hint)):
|
||||
default_arg = {}
|
||||
elif (is_array(type_hint)):
|
||||
default_arg = []
|
||||
|
||||
arg_str += " = " + var_to_str(default_arg)
|
||||
|
||||
default_arg_index += 1
|
||||
|
||||
arg_index += 1
|
||||
|
||||
func_name += arg_str + ")"
|
||||
|
||||
var return_str: String = get_type(method[&"return"])
|
||||
if (return_str == ""):
|
||||
return func_name
|
||||
|
||||
func_name += " -> " + return_str
|
||||
|
||||
return func_name
|
||||
|
||||
func get_type(dict: Dictionary) -> String:
|
||||
var type: String = dict[&"class_name"]
|
||||
if (type != &""):
|
||||
if (type.begins_with(&"res://")):
|
||||
type = type.substr(type.rfind(&".") + 1)
|
||||
return type
|
||||
|
||||
var type_hint: int = dict[&"type"]
|
||||
if (type_hint == 0):
|
||||
return &""
|
||||
|
||||
type = type_string(type_hint)
|
||||
|
||||
if (is_dictionary(type_hint)):
|
||||
var generic: String = dict[&"hint_string"]
|
||||
if (generic != &""):
|
||||
var generic_parts: PackedStringArray = generic.split(";")
|
||||
if (generic_parts.size() == 2):
|
||||
return type + "[" + generic_parts[0] + ", " + generic_parts[1] + "]"
|
||||
|
||||
if (is_array(type_hint)):
|
||||
var generic: String = dict[&"hint_string"]
|
||||
if (generic != &""):
|
||||
return type + "[" + generic + "]"
|
||||
|
||||
return type
|
||||
|
||||
func is_dictionary(type_hint: int) -> bool:
|
||||
return type_hint == 27
|
||||
|
||||
func is_array(type_hint: int) -> bool:
|
||||
return type_hint == 28
|
||||
|
||||
func reset_icons():
|
||||
init_icons()
|
||||
engine_func_btn.icon = engine_func_icon
|
||||
func_btn.icon = func_icon
|
||||
signal_btn.icon = signal_icon
|
||||
export_btn.icon = export_icon
|
||||
property_btn.icon = property_icon
|
||||
class_btn.icon = class_icon
|
||||
constant_btn.icon = constant_icon
|
||||
update_outline()
|
||||
|
||||
func create_editor_texture(texture: Texture2D) -> Texture2D:
|
||||
var image: Image = texture.get_image().duplicate()
|
||||
image.adjust_bcs(1.0, 1.0, get_editor_icon_saturation())
|
||||
|
||||
return ImageTexture.create_from_image(image)
|
||||
|
||||
func load_rel(path: String) -> Variant:
|
||||
var script_path: String = get_script().get_path().get_base_dir()
|
||||
return load(script_path.path_join(path))
|
||||
|
||||
func is_sorted() -> bool:
|
||||
return EditorInterface.get_editor_settings().get_setting("text_editor/script_list/sort_members_outline_alphabetically")
|
||||
|
||||
func get_editor_icon_saturation() -> float:
|
||||
return EditorInterface.get_editor_settings().get_setting("interface/theme/icon_saturation")
|
||||
|
||||
## Cache for everything inside we collected to show in the Outline.
|
||||
class OutlineCache:
|
||||
var classes: Array[String] = []
|
||||
var constants: Array[String] = []
|
||||
var signals: Array[String] = []
|
||||
var exports: Array[String] = []
|
||||
var properties: Array[String] = []
|
||||
var funcs: Array[String] = []
|
||||
var engine_funcs: Array[String] = []
|
||||
|
||||
## Outline type for a concrete button with their items in the Outline.
|
||||
class OutlineType:
|
||||
var type_name: StringName
|
||||
var add_to_outline: Callable
|
||||
1
addons/script-ide/outline/outline_container.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://db0be00ai3tfi
|
||||
22
addons/script-ide/outline/outline_container.tscn
Normal file
@@ -0,0 +1,22 @@
|
||||
[gd_scene format=3 uid="uid://ux3ldi4ka8ji"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://db0be00ai3tfi" path="res://addons/script-ide/outline/outline_container.gd" id="1_w4vhe"]
|
||||
|
||||
[node name="OutlineContainer" type="VBoxContainer" unique_id=181236283]
|
||||
offset_right = 174.0
|
||||
offset_bottom = 253.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
script = ExtResource("1_w4vhe")
|
||||
|
||||
[node name="FilterBox" type="HBoxContainer" parent="." unique_id=1653721963]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 2
|
||||
|
||||
[node name="Outline" type="ItemList" parent="." unique_id=160258583]
|
||||
unique_name_in_owner = true
|
||||
auto_translate_mode = 2
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
allow_reselect = true
|
||||