diff --git a/.gitmodules b/.gitmodules index a104f39..4a995c9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "Assets"] path = Assets url = http://185.216.25.221/lucastucious/ChatBoat-Assets +[submodule "addons/limbo_console"] + path = addons/limbo_console + url = https://github.com/limbonaut/limbo_console.git diff --git a/addons/Todo_Manager/ColourPicker.gd b/addons/Todo_Manager/ColourPicker.gd new file mode 100644 index 0000000..39a3f9a --- /dev/null +++ b/addons/Todo_Manager/ColourPicker.gd @@ -0,0 +1,17 @@ +@tool +extends HBoxContainer + +var colour : Color +var title : String: + set = set_title +var index : int + +@onready var colour_picker := $TODOColourPickerButton + +func _ready() -> void: + $TODOColourPickerButton.color = colour + $Label.text = title + +func set_title(value: String) -> void: + title = value + $Label.text = value diff --git a/addons/Todo_Manager/ColourPicker.gd.uid b/addons/Todo_Manager/ColourPicker.gd.uid new file mode 100644 index 0000000..643398e --- /dev/null +++ b/addons/Todo_Manager/ColourPicker.gd.uid @@ -0,0 +1 @@ +uid://dewmmp4a7khmp diff --git a/addons/Todo_Manager/Current.gd b/addons/Todo_Manager/Current.gd new file mode 100644 index 0000000..d3961c9 --- /dev/null +++ b/addons/Todo_Manager/Current.gd @@ -0,0 +1,44 @@ +@tool +extends Panel + +signal tree_built # used for debugging + +const Todo := preload("res://addons/Todo_Manager/todo_class.gd") +const TodoItem := preload("res://addons/Todo_Manager/todoItem_class.gd") + +var _sort_alphabetical := true + +@onready var tree := $Tree as Tree + +func build_tree(todo_item : TodoItem, patterns : Array, cased_patterns : Array[String]) -> void: + tree.clear() + var root := tree.create_item() + root.set_text(0, "Scripts") + var script := tree.create_item(root) + script.set_text(0, todo_item.get_short_path() + " -------") + script.set_metadata(0, todo_item) + for todo in todo_item.todos: + var item := tree.create_item(script) + var content_header : String = todo.content + if "\n" in todo.content: + content_header = content_header.split("\n")[0] + "..." + item.set_text(0, "(%0) - %1".format([todo.line_number, content_header], "%_")) + item.set_tooltip_text(0, todo.content) + item.set_metadata(0, todo) + for i in range(0, len(cased_patterns)): + if cased_patterns[i] == todo.pattern: + item.set_custom_color(0, patterns[i][1]) + emit_signal("tree_built") + + +func sort_alphabetical(a, b) -> bool: + if a.script_path > b.script_path: + return true + else: + return false + +func sort_backwards(a, b) -> bool: + if a.script_path < b.script_path: + return true + else: + return false diff --git a/addons/Todo_Manager/Current.gd.uid b/addons/Todo_Manager/Current.gd.uid new file mode 100644 index 0000000..aa435a1 --- /dev/null +++ b/addons/Todo_Manager/Current.gd.uid @@ -0,0 +1 @@ +uid://df4rogqmo2xmg diff --git a/addons/Todo_Manager/Dock.gd b/addons/Todo_Manager/Dock.gd new file mode 100644 index 0000000..c71b6b2 --- /dev/null +++ b/addons/Todo_Manager/Dock.gd @@ -0,0 +1,297 @@ +@tool +extends Control + +#signal tree_built # used for debugging +enum { CASE_INSENSITIVE, CASE_SENSITIVE } + +const Project := preload("res://addons/Todo_Manager/Project.gd") +const Current := preload("res://addons/Todo_Manager/Current.gd") + +const Todo := preload("res://addons/Todo_Manager/todo_class.gd") +const TodoItem := preload("res://addons/Todo_Manager/todoItem_class.gd") +const ColourPicker := preload("res://addons/Todo_Manager/UI/ColourPicker.tscn") +const Pattern := preload("res://addons/Todo_Manager/UI/Pattern.tscn") +const DEFAULT_PATTERNS := [["\\bTODO\\b", Color("96f1ad"), CASE_INSENSITIVE], ["\\bHACK\\b", Color("d5bc70"), CASE_INSENSITIVE], ["\\bFIXME\\b", Color("d57070"), CASE_INSENSITIVE]] +const DEFAULT_SCRIPT_COLOUR := Color("ccced3") +const DEFAULT_SCRIPT_NAME := false +const DEFAULT_SORT := true + +var plugin : EditorPlugin + +var todo_items : Array + +var script_colour := Color("ccced3") +var ignore_paths : Array[String] = [] +var full_path := false +var auto_refresh := true +var builtin_enabled := false +var _sort_alphabetical := true + +var patterns := [["\\bTODO\\b", Color("96f1ad"), CASE_INSENSITIVE], ["\\bHACK\\b", Color("d5bc70"), CASE_INSENSITIVE], ["\\bFIXME\\b", Color("d57070"), CASE_INSENSITIVE]] + + +@onready var tabs := $VBoxContainer/TabContainer as TabContainer +@onready var project := $VBoxContainer/TabContainer/Project as Project +@onready var current := $VBoxContainer/TabContainer/Current as Current +@onready var project_tree := $VBoxContainer/TabContainer/Project/Tree as Tree +@onready var current_tree := $VBoxContainer/TabContainer/Current/Tree as Tree +@onready var settings_panel := $VBoxContainer/TabContainer/Settings as Panel +@onready var colours_container := $VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer3/Colours as VBoxContainer +@onready var pattern_container := $VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer4/Patterns as VBoxContainer +@onready var ignore_textbox := $VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/IgnorePaths/TextEdit as LineEdit +@onready var auto_refresh_button := $VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5/Patterns/RefreshCheckButton as CheckButton + +func _ready() -> void: + load_config() + populate_settings() + + +func build_tree() -> void: + if tabs: + match tabs.current_tab: + 0: + project.build_tree(todo_items, ignore_paths, patterns, plugin.cased_patterns, _sort_alphabetical, full_path) + create_config_file() + 1: + current.build_tree(get_active_script(), patterns, plugin.cased_patterns) + create_config_file() + 2: + pass + _: + pass + + +func get_active_script() -> TodoItem: + var current_script : Script = plugin.get_editor_interface().get_script_editor().get_current_script() + if current_script: + var script_path = current_script.resource_path + for todo_item in todo_items: + if todo_item.script_path == script_path: + return todo_item + + # nothing found + var todo_item := TodoItem.new(script_path, []) + return todo_item + else: + # not a script + var todo_item := TodoItem.new("res://Documentation", []) + return todo_item + + +func go_to_script(script_path: String, line_number : int = 0) -> void: + if plugin.get_editor_interface().get_editor_settings().get_setting("text_editor/external/use_external_editor"): + var exec_path = plugin.get_editor_interface().get_editor_settings().get_setting("text_editor/external/exec_path") + var args := get_exec_flags(exec_path, script_path, line_number) + OS.execute(exec_path, args) + else: + var script := load(script_path) + plugin.get_editor_interface().edit_resource(script) + plugin.get_editor_interface().get_script_editor().goto_line(line_number - 1) + +func get_exec_flags(editor_path : String, script_path : String, line_number : int) -> PackedStringArray: + var args : PackedStringArray + var script_global_path = ProjectSettings.globalize_path(script_path) + + if editor_path.ends_with("code.cmd") or editor_path.ends_with("code"): ## VS Code + args.append(ProjectSettings.globalize_path("res://")) + args.append("--goto") + args.append(script_global_path + ":" + str(line_number)) + + elif editor_path.ends_with("rider64.exe") or editor_path.ends_with("rider"): ## Rider + args.append("--line") + args.append(str(line_number)) + args.append(script_global_path) + + else: ## Atom / Sublime + args.append(script_global_path + ":" + str(line_number)) + + return args + +func sort_alphabetical(a, b) -> bool: + if a.script_path > b.script_path: + return true + else: + return false + +func sort_backwards(a, b) -> bool: + if a.script_path < b.script_path: + return true + else: + return false + + +func populate_settings() -> void: + for i in patterns.size(): + ## Create Colour Pickers + var colour_picker: Variant = ColourPicker.instantiate() + colour_picker.colour = patterns[i][1] + colour_picker.title = patterns[i][0] + colour_picker.index = i + colours_container.add_child(colour_picker) + colour_picker.colour_picker.color_changed.connect(change_colour.bind(i)) + + ## Create Patterns + var pattern_edit: Variant = Pattern.instantiate() + pattern_edit.text = patterns[i][0] + pattern_edit.index = i + pattern_container.add_child(pattern_edit) + pattern_edit.line_edit.text_changed.connect(change_pattern.bind(i, + colour_picker)) + pattern_edit.remove_button.pressed.connect(remove_pattern.bind(i, + pattern_edit, colour_picker)) + pattern_edit.case_checkbox.button_pressed = patterns[i][2] + pattern_edit.case_checkbox.toggled.connect(case_sensitive_pattern.bind(i)) + + var pattern_button := $VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer4/Patterns/AddPatternButton + $VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer4/Patterns.move_child(pattern_button, 0) + + # path filtering + var ignore_paths_field := ignore_textbox + if not ignore_paths_field.is_connected("text_changed", _on_ignore_paths_changed): + ignore_paths_field.connect("text_changed", _on_ignore_paths_changed) + var ignore_paths_text := "" + for path in ignore_paths: + ignore_paths_text += path + ", " + ignore_paths_text = ignore_paths_text.trim_suffix(", ") + ignore_paths_field.text = ignore_paths_text + + auto_refresh_button.button_pressed = auto_refresh + + +func rebuild_settings() -> void: + for node in colours_container.get_children(): + node.queue_free() + for node in pattern_container.get_children(): + if node is Button: + continue + node.queue_free() + populate_settings() + + +#### CONFIG FILE #### +func create_config_file() -> void: + var config = ConfigFile.new() + config.set_value("scripts", "full_path", full_path) + config.set_value("scripts", "sort_alphabetical", _sort_alphabetical) + config.set_value("scripts", "script_colour", script_colour) + config.set_value("scripts", "ignore_paths", ignore_paths) + + config.set_value("patterns", "patterns", patterns) + + config.set_value("config", "auto_refresh", auto_refresh) + config.set_value("config", "builtin_enabled", builtin_enabled) + + var err = config.save("res://addons/Todo_Manager/todo.cfg") + + +func load_config() -> void: + var config := ConfigFile.new() + if config.load("res://addons/Todo_Manager/todo.cfg") == OK: + full_path = config.get_value("scripts", "full_path", DEFAULT_SCRIPT_NAME) + _sort_alphabetical = config.get_value("scripts", "sort_alphabetical", DEFAULT_SORT) + script_colour = config.get_value("scripts", "script_colour", DEFAULT_SCRIPT_COLOUR) + ignore_paths = config.get_value("scripts", "ignore_paths", [] as Array[String]) + patterns = config.get_value("patterns", "patterns", DEFAULT_PATTERNS) + auto_refresh = config.get_value("config", "auto_refresh", true) + builtin_enabled = config.get_value("config", "builtin_enabled", false) + else: + create_config_file() + + +#### Events #### +func _on_SettingsButton_toggled(button_pressed: bool) -> void: + settings_panel.visible = button_pressed + if button_pressed == false: + create_config_file() +# plugin.find_tokens_from_path(plugin.script_cache) + if auto_refresh: + plugin.rescan_files(true) + +func _on_Tree_item_activated() -> void: + var item : TreeItem + match tabs.current_tab: + 0: + item = project_tree.get_selected() + 1: + item = current_tree.get_selected() + if item.get_metadata(0) is Todo: + var todo : Todo = item.get_metadata(0) + call_deferred("go_to_script", todo.script_path, todo.line_number) + else: + var todo_item = item.get_metadata(0) + call_deferred("go_to_script", todo_item.script_path) + +func _on_FullPathCheckBox_toggled(button_pressed: bool) -> void: + full_path = button_pressed + +func _on_ScriptColourPickerButton_color_changed(color: Color) -> void: + script_colour = color + +func _on_RescanButton_pressed() -> void: + plugin.rescan_files(true) + +func change_colour(colour: Color, index: int) -> void: + patterns[index][1] = colour + +func change_pattern(value: String, index: int, this_colour: Node) -> void: + patterns[index][0] = value + this_colour.title = value + plugin.rescan_files(true) + +func remove_pattern(index: int, this: Node, this_colour: Node) -> void: + patterns.remove_at(index) + this.queue_free() + this_colour.queue_free() + plugin.rescan_files(true) + +func case_sensitive_pattern(active: bool, index: int) -> void: + if active: + patterns[index][2] = CASE_SENSITIVE + else: + patterns[index][2] = CASE_INSENSITIVE + plugin.rescan_files(true) + +func _on_DefaultButton_pressed() -> void: + patterns = DEFAULT_PATTERNS.duplicate(true) + _sort_alphabetical = DEFAULT_SORT + script_colour = DEFAULT_SCRIPT_COLOUR + full_path = DEFAULT_SCRIPT_NAME + rebuild_settings() + plugin.rescan_files(true) + +func _on_AlphSortCheckBox_toggled(button_pressed: bool) -> void: + _sort_alphabetical = button_pressed + plugin.rescan_files(true) + +func _on_AddPatternButton_pressed() -> void: + patterns.append(["\\bplaceholder\\b", Color.WHITE, CASE_INSENSITIVE]) + rebuild_settings() + +func _on_RefreshCheckButton_toggled(button_pressed: bool) -> void: + auto_refresh = button_pressed + +func _on_Timer_timeout() -> void: + plugin.refresh_lock = false + +func _on_ignore_paths_changed(new_text: String) -> void: + var text = ignore_textbox.text + var split: Array = text.split(',') + ignore_paths.clear() + for elem in split: + if elem == " " || elem == "": + continue + ignore_paths.push_front(elem.lstrip(' ').rstrip(' ')) + # validate so no empty string slips through (all paths ignored) + var i := 0 + for path in ignore_paths: + if (path == "" || path == " "): + ignore_paths.remove_at(i) + i += 1 + plugin.rescan_files(true) + +func _on_TabContainer_tab_changed(tab: int) -> void: + build_tree() + +func _on_BuiltInCheckButton_toggled(button_pressed: bool) -> void: + builtin_enabled = button_pressed + plugin.rescan_files(true) diff --git a/addons/Todo_Manager/Dock.gd.uid b/addons/Todo_Manager/Dock.gd.uid new file mode 100644 index 0000000..e76a903 --- /dev/null +++ b/addons/Todo_Manager/Dock.gd.uid @@ -0,0 +1 @@ +uid://r8brklggblcc diff --git a/addons/Todo_Manager/Pattern.gd b/addons/Todo_Manager/Pattern.gd new file mode 100644 index 0000000..4e610af --- /dev/null +++ b/addons/Todo_Manager/Pattern.gd @@ -0,0 +1,21 @@ +@tool +extends HBoxContainer + + +var text : String : set = set_text +var disabled : bool +var index : int + +@onready var line_edit := $LineEdit as LineEdit +@onready var remove_button := $RemoveButton as Button +@onready var case_checkbox := %CaseSensativeCheckbox as CheckBox + +func _ready() -> void: + line_edit.text = text + remove_button.disabled = disabled + + +func set_text(value: String) -> void: + text = value + if line_edit: + line_edit.text = value diff --git a/addons/Todo_Manager/Pattern.gd.uid b/addons/Todo_Manager/Pattern.gd.uid new file mode 100644 index 0000000..ef6307f --- /dev/null +++ b/addons/Todo_Manager/Pattern.gd.uid @@ -0,0 +1 @@ +uid://bvsdmdsamrro4 diff --git a/addons/Todo_Manager/Project.gd b/addons/Todo_Manager/Project.gd new file mode 100644 index 0000000..4af0847 --- /dev/null +++ b/addons/Todo_Manager/Project.gd @@ -0,0 +1,73 @@ +@tool +extends Panel + +signal tree_built # used for debugging + +const Todo := preload("res://addons/Todo_Manager/todo_class.gd") + +var _sort_alphabetical := true +var _full_path := false + +@onready var tree := $Tree as Tree + +func build_tree(todo_items : Array, ignore_paths : Array, patterns : Array, cased_patterns: Array[String], sort_alphabetical : bool, full_path : bool) -> void: + _full_path = full_path + tree.clear() + if sort_alphabetical: + todo_items.sort_custom(Callable(self, "sort_alphabetical")) + else: + todo_items.sort_custom(Callable(self, "sort_backwards")) + var root := tree.create_item() + root.set_text(0, "Scripts") + for todo_item in todo_items: + var ignore := false + for ignore_path in ignore_paths: + var script_path : String = todo_item.script_path + if script_path.begins_with(ignore_path) or script_path.begins_with("res://" + ignore_path) or script_path.begins_with("res:///" + ignore_path): + ignore = true + break + if ignore: + continue + var script := tree.create_item(root) + if full_path: + script.set_text(0, todo_item.script_path + " -------") + else: + script.set_text(0, todo_item.get_short_path() + " -------") + script.set_metadata(0, todo_item) + for todo in todo_item.todos: + var item := tree.create_item(script) + var content_header : String = todo.content + if "\n" in todo.content: + content_header = content_header.split("\n")[0] + "..." + item.set_text(0, "(%0) - %1".format([todo.line_number, content_header], "%_")) + item.set_tooltip_text(0, todo.content) + item.set_metadata(0, todo) + for i in range(0, len(cased_patterns)): + if cased_patterns[i] == todo.pattern: + item.set_custom_color(0, patterns[i][1]) + emit_signal("tree_built") + + +func sort_alphabetical(a, b) -> bool: + if _full_path: + if a.script_path < b.script_path: + return true + else: + return false + else: + if a.get_short_path() < b.get_short_path(): + return true + else: + return false + +func sort_backwards(a, b) -> bool: + if _full_path: + if a.script_path > b.script_path: + return true + else: + return false + else: + if a.get_short_path() > b.get_short_path(): + return true + else: + return false diff --git a/addons/Todo_Manager/Project.gd.uid b/addons/Todo_Manager/Project.gd.uid new file mode 100644 index 0000000..3515dbe --- /dev/null +++ b/addons/Todo_Manager/Project.gd.uid @@ -0,0 +1 @@ +uid://d3c0kr6mvkcup diff --git a/addons/Todo_Manager/UI/ColourPicker.tscn b/addons/Todo_Manager/UI/ColourPicker.tscn new file mode 100644 index 0000000..650899f --- /dev/null +++ b/addons/Todo_Manager/UI/ColourPicker.tscn @@ -0,0 +1,21 @@ +[gd_scene load_steps=2 format=3 uid="uid://bie1xn8v1kd66"] + +[ext_resource type="Script" path="res://addons/Todo_Manager/ColourPicker.gd" id="1"] + +[node name="TODOColour" type="HBoxContainer"] +offset_right = 105.0 +offset_bottom = 31.0 +script = ExtResource("1") +metadata/_edit_use_custom_anchors = false + +[node name="Label" type="Label" parent="."] +offset_top = 4.0 +offset_right = 1.0 +offset_bottom = 27.0 + +[node name="TODOColourPickerButton" type="ColorPickerButton" parent="."] +custom_minimum_size = Vector2(40, 0) +offset_left = 65.0 +offset_right = 105.0 +offset_bottom = 31.0 +size_flags_horizontal = 10 diff --git a/addons/Todo_Manager/UI/Dock.tscn b/addons/Todo_Manager/UI/Dock.tscn new file mode 100644 index 0000000..096662a --- /dev/null +++ b/addons/Todo_Manager/UI/Dock.tscn @@ -0,0 +1,315 @@ +[gd_scene load_steps=6 format=3 uid="uid://b6k0dtftankcx"] + +[ext_resource type="Script" path="res://addons/Todo_Manager/Dock.gd" id="1"] +[ext_resource type="Script" path="res://addons/Todo_Manager/Project.gd" id="2"] +[ext_resource type="Script" path="res://addons/Todo_Manager/Current.gd" id="3"] + +[sub_resource type="ButtonGroup" id="ButtonGroup_kqxcu"] + +[sub_resource type="ButtonGroup" id="ButtonGroup_kltg3"] + +[node name="Dock" type="Control"] +custom_minimum_size = Vector2(0, 200) +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_vertical = 3 +script = ExtResource("1") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_top = 4.0 +grow_horizontal = 2 +grow_vertical = 2 +metadata/_edit_layout_mode = 1 + +[node name="Header" type="HBoxContainer" parent="VBoxContainer"] +visible = false +layout_mode = 2 + +[node name="HeaderLeft" type="HBoxContainer" parent="VBoxContainer/Header"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Title" type="Label" parent="VBoxContainer/Header/HeaderLeft"] +layout_mode = 2 +text = "Todo Dock:" + +[node name="HeaderRight" type="HBoxContainer" parent="VBoxContainer/Header"] +layout_mode = 2 +size_flags_horizontal = 3 +alignment = 2 + +[node name="SettingsButton" type="Button" parent="VBoxContainer/Header/HeaderRight"] +visible = false +layout_mode = 2 +toggle_mode = true +text = "Settings" + +[node name="TabContainer" type="TabContainer" parent="VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="Project" type="Panel" parent="VBoxContainer/TabContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = ExtResource("2") + +[node name="Tree" type="Tree" parent="VBoxContainer/TabContainer/Project"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +hide_root = true + +[node name="Current" type="Panel" parent="VBoxContainer/TabContainer"] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = ExtResource("3") + +[node name="Tree" type="Tree" parent="VBoxContainer/TabContainer/Current"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +hide_folding = true +hide_root = true + +[node name="Settings" type="Panel" parent="VBoxContainer/TabContainer"] +visible = false +layout_mode = 2 + +[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer/TabContainer/Settings"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="Scripts" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/Scripts"] +layout_mode = 2 +text = "Scripts:" + +[node name="HSeparator" type="HSeparator" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/Scripts"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 5 + +[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer"] +layout_mode = 2 + +[node name="VSeparator" type="VSeparator" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2"] +layout_mode = 2 + +[node name="Scripts" type="VBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2"] +layout_mode = 2 + +[node name="ScriptName" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptName"] +layout_mode = 2 +text = "Script Name:" + +[node name="FullPathCheckBox" type="CheckBox" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptName"] +layout_mode = 2 +button_group = SubResource("ButtonGroup_kqxcu") +text = "Full path" + +[node name="ShortNameCheckBox" type="CheckBox" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptName"] +layout_mode = 2 +button_pressed = true +button_group = SubResource("ButtonGroup_kqxcu") +text = "Short name" + +[node name="ScriptSort" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptSort"] +layout_mode = 2 +text = "Sort Order:" + +[node name="AlphSortCheckBox" type="CheckBox" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptSort"] +layout_mode = 2 +button_pressed = true +button_group = SubResource("ButtonGroup_kltg3") +text = "Alphabetical" + +[node name="RAlphSortCheckBox" type="CheckBox" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptSort"] +layout_mode = 2 +button_group = SubResource("ButtonGroup_kltg3") +text = "Reverse Alphabetical" + +[node name="ScriptColour" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptColour"] +layout_mode = 2 +text = "Script Colour:" + +[node name="ScriptColourPickerButton" type="ColorPickerButton" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptColour"] +custom_minimum_size = Vector2(40, 0) +layout_mode = 2 +color = Color(0.8, 0.807843, 0.827451, 1) + +[node name="IgnorePaths" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/IgnorePaths"] +layout_mode = 2 +text = "Ignore Paths:" + +[node name="TextEdit" type="LineEdit" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/IgnorePaths"] +custom_minimum_size = Vector2(100, 0) +layout_mode = 2 +expand_to_text_length = true + +[node name="Label3" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/IgnorePaths"] +layout_mode = 2 +text = "(Separated by commas)" + +[node name="TODOColours" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/TODOColours"] +layout_mode = 2 +text = "TODO Colours:" + +[node name="HSeparator" type="HSeparator" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/TODOColours"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="HBoxContainer3" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="VSeparator" type="VSeparator" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer3"] +layout_mode = 2 + +[node name="Colours" type="VBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer3"] +layout_mode = 2 + +[node name="Patterns" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/Patterns"] +layout_mode = 2 +text = "Patterns:" + +[node name="HSeparator" type="HSeparator" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/Patterns"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="HBoxContainer4" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="VSeparator" type="VSeparator" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer4"] +layout_mode = 2 + +[node name="Patterns" type="VBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer4"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="AddPatternButton" type="Button" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer4/Patterns"] +layout_mode = 2 +size_flags_horizontal = 0 +text = "Add" + +[node name="Config" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/Config"] +layout_mode = 2 +text = "Config:" + +[node name="HSeparator" type="HSeparator" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/Config"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="HBoxContainer5" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="VSeparator" type="VSeparator" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5"] +layout_mode = 2 + +[node name="Patterns" type="VBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5"] +layout_mode = 2 + +[node name="RefreshCheckButton" type="CheckButton" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5/Patterns"] +layout_mode = 2 +size_flags_horizontal = 0 +button_pressed = true +text = "Auto Refresh" + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5/Patterns"] +layout_mode = 2 + +[node name="BuiltInCheckButton" type="CheckButton" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5/Patterns/HBoxContainer"] +layout_mode = 2 +text = "Scan Built-in Scripts" + +[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5/Patterns/HBoxContainer"] +layout_mode = 2 + +[node name="DefaultButton" type="Button" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5/Patterns"] +layout_mode = 2 +size_flags_horizontal = 0 +text = "Reset to default" + +[node name="Timer" type="Timer" parent="."] +one_shot = true + +[node name="RescanButton" type="Button" parent="."] +layout_mode = 1 +anchors_preset = 1 +anchor_left = 1.0 +anchor_right = 1.0 +offset_left = -102.0 +offset_top = 3.0 +offset_bottom = 34.0 +grow_horizontal = 0 +text = "Rescan Files" +flat = true + +[connection signal="toggled" from="VBoxContainer/Header/HeaderRight/SettingsButton" to="." method="_on_SettingsButton_toggled"] +[connection signal="tab_changed" from="VBoxContainer/TabContainer" to="." method="_on_TabContainer_tab_changed"] +[connection signal="item_activated" from="VBoxContainer/TabContainer/Project/Tree" to="." method="_on_Tree_item_activated"] +[connection signal="item_activated" from="VBoxContainer/TabContainer/Current/Tree" to="." method="_on_Tree_item_activated"] +[connection signal="toggled" from="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptName/FullPathCheckBox" to="." method="_on_FullPathCheckBox_toggled"] +[connection signal="toggled" from="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptSort/AlphSortCheckBox" to="." method="_on_AlphSortCheckBox_toggled"] +[connection signal="color_changed" from="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptColour/ScriptColourPickerButton" to="." method="_on_ScriptColourPickerButton_color_changed"] +[connection signal="pressed" from="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer4/Patterns/AddPatternButton" to="." method="_on_AddPatternButton_pressed"] +[connection signal="toggled" from="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5/Patterns/RefreshCheckButton" to="." method="_on_RefreshCheckButton_toggled"] +[connection signal="toggled" from="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5/Patterns/HBoxContainer/BuiltInCheckButton" to="." method="_on_BuiltInCheckButton_toggled"] +[connection signal="pressed" from="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5/Patterns/DefaultButton" to="." method="_on_DefaultButton_pressed"] +[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"] +[connection signal="pressed" from="RescanButton" to="." method="_on_RescanButton_pressed"] diff --git a/addons/Todo_Manager/UI/Pattern.tscn b/addons/Todo_Manager/UI/Pattern.tscn new file mode 100644 index 0000000..fb45615 --- /dev/null +++ b/addons/Todo_Manager/UI/Pattern.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=2 format=3 uid="uid://bx11sel2q5wli"] + +[ext_resource type="Script" path="res://addons/Todo_Manager/Pattern.gd" id="1"] + +[node name="Pattern" type="HBoxContainer"] +script = ExtResource("1") + +[node name="LineEdit" type="LineEdit" parent="."] +layout_mode = 2 +size_flags_horizontal = 0 +expand_to_text_length = true + +[node name="RemoveButton" type="Button" parent="."] +layout_mode = 2 +text = "-" + +[node name="MarginContainer" type="MarginContainer" parent="."] +custom_minimum_size = Vector2(20, 0) +layout_mode = 2 +size_flags_horizontal = 0 + +[node name="CaseSensativeCheckbox" type="CheckBox" parent="."] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 0 +text = "Case Sensitive" diff --git a/addons/Todo_Manager/doc/images/Instruct1.png b/addons/Todo_Manager/doc/images/Instruct1.png new file mode 100644 index 0000000..ba508bc --- /dev/null +++ b/addons/Todo_Manager/doc/images/Instruct1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:817dbaab7a63ba4c17665822f3871052c49cf9784255466eef6fc9ee831602f8 +size 113683 diff --git a/addons/Todo_Manager/doc/images/Instruct1.png.import b/addons/Todo_Manager/doc/images/Instruct1.png.import new file mode 100644 index 0000000..d5cf41f --- /dev/null +++ b/addons/Todo_Manager/doc/images/Instruct1.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bd8u4ctpdkgy1" +path="res://.godot/imported/Instruct1.png-698c6faa3ef3ac4960807faa3e028bd6.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/Todo_Manager/doc/images/Instruct1.png" +dest_files=["res://.godot/imported/Instruct1.png-698c6faa3ef3ac4960807faa3e028bd6.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 diff --git a/addons/Todo_Manager/doc/images/Instruct2.png b/addons/Todo_Manager/doc/images/Instruct2.png new file mode 100644 index 0000000..b0420e0 --- /dev/null +++ b/addons/Todo_Manager/doc/images/Instruct2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8168430474734117424045014415f25aec8130e66101e86e3ce5505617ab60c0 +size 12144 diff --git a/addons/Todo_Manager/doc/images/Instruct2.png.import b/addons/Todo_Manager/doc/images/Instruct2.png.import new file mode 100644 index 0000000..acbb36a --- /dev/null +++ b/addons/Todo_Manager/doc/images/Instruct2.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://doh78hu0hvjxm" +path="res://.godot/imported/Instruct2.png-4e8664e49d00a397bbd539f7dee976ff.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/Todo_Manager/doc/images/Instruct2.png" +dest_files=["res://.godot/imported/Instruct2.png-4e8664e49d00a397bbd539f7dee976ff.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 diff --git a/addons/Todo_Manager/doc/images/Instruct3.png b/addons/Todo_Manager/doc/images/Instruct3.png new file mode 100644 index 0000000..77f09f3 --- /dev/null +++ b/addons/Todo_Manager/doc/images/Instruct3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:33ea8ddedf88d044c9f7bf7cd32c6cbfc190e4013543852fb2ed99c25300681e +size 58592 diff --git a/addons/Todo_Manager/doc/images/Instruct3.png.import b/addons/Todo_Manager/doc/images/Instruct3.png.import new file mode 100644 index 0000000..56f4dfb --- /dev/null +++ b/addons/Todo_Manager/doc/images/Instruct3.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://csrqvbb2kmp84" +path="res://.godot/imported/Instruct3.png-3cc62ed99bf29d90b803cb8eb40881e9.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/Todo_Manager/doc/images/Instruct3.png" +dest_files=["res://.godot/imported/Instruct3.png-3cc62ed99bf29d90b803cb8eb40881e9.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 diff --git a/addons/Todo_Manager/doc/images/Instruct4.png b/addons/Todo_Manager/doc/images/Instruct4.png new file mode 100644 index 0000000..eb81149 --- /dev/null +++ b/addons/Todo_Manager/doc/images/Instruct4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d04d6ff24a5f047f715d70a50f0c52be36d2a2c537e45d332d3255e36226abcf +size 20209 diff --git a/addons/Todo_Manager/doc/images/Instruct4.png.import b/addons/Todo_Manager/doc/images/Instruct4.png.import new file mode 100644 index 0000000..3df66bc --- /dev/null +++ b/addons/Todo_Manager/doc/images/Instruct4.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dtl1esndls1cr" +path="res://.godot/imported/Instruct4.png-bf5aa1cffc066175cecf9281b0774809.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/Todo_Manager/doc/images/Instruct4.png" +dest_files=["res://.godot/imported/Instruct4.png-bf5aa1cffc066175cecf9281b0774809.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 diff --git a/addons/Todo_Manager/doc/images/Instruct5.png b/addons/Todo_Manager/doc/images/Instruct5.png new file mode 100644 index 0000000..d1e91dc --- /dev/null +++ b/addons/Todo_Manager/doc/images/Instruct5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2e011e32e069d7405bd86b1662e15b3d06a8216c757556a2b8ae80948334d93d +size 48950 diff --git a/addons/Todo_Manager/doc/images/Instruct5.png.import b/addons/Todo_Manager/doc/images/Instruct5.png.import new file mode 100644 index 0000000..80bafa0 --- /dev/null +++ b/addons/Todo_Manager/doc/images/Instruct5.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dfqgra6mowfhy" +path="res://.godot/imported/Instruct5.png-001538ed8b5682dcf232de08035aab38.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/Todo_Manager/doc/images/Instruct5.png" +dest_files=["res://.godot/imported/Instruct5.png-001538ed8b5682dcf232de08035aab38.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 diff --git a/addons/Todo_Manager/doc/images/TODO_Manager_Logo.png b/addons/Todo_Manager/doc/images/TODO_Manager_Logo.png new file mode 100644 index 0000000..f386245 --- /dev/null +++ b/addons/Todo_Manager/doc/images/TODO_Manager_Logo.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a7ae04fab31bf96556ed4d3a93a09b200df8e5bd54c90aa1f054331cd1a7719f +size 23697 diff --git a/addons/Todo_Manager/doc/images/TODO_Manager_Logo.png.import b/addons/Todo_Manager/doc/images/TODO_Manager_Logo.png.import new file mode 100644 index 0000000..0ea157d --- /dev/null +++ b/addons/Todo_Manager/doc/images/TODO_Manager_Logo.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b7ehd6tjasial" +path="res://.godot/imported/TODO_Manager_Logo.png-e07d7ec75201c66b732ef87ec1bece15.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/Todo_Manager/doc/images/TODO_Manager_Logo.png" +dest_files=["res://.godot/imported/TODO_Manager_Logo.png-e07d7ec75201c66b732ef87ec1bece15.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 diff --git a/addons/Todo_Manager/doc/images/TodoExternal.gif b/addons/Todo_Manager/doc/images/TodoExternal.gif new file mode 100644 index 0000000..25d0850 Binary files /dev/null and b/addons/Todo_Manager/doc/images/TodoExternal.gif differ diff --git a/addons/Todo_Manager/doc/images/example1.png b/addons/Todo_Manager/doc/images/example1.png new file mode 100644 index 0000000..1b3f68c --- /dev/null +++ b/addons/Todo_Manager/doc/images/example1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4937360a6d57d237888599d0ddd9f963fc6a986a4a3813d2d6b448686f4fa12f +size 29788 diff --git a/addons/Todo_Manager/doc/images/example1.png.import b/addons/Todo_Manager/doc/images/example1.png.import new file mode 100644 index 0000000..a3c767f --- /dev/null +++ b/addons/Todo_Manager/doc/images/example1.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dm4238rk6sken" +path="res://.godot/imported/example1.png-6386c332ca46e1e62ea061b956a901cd.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/Todo_Manager/doc/images/example1.png" +dest_files=["res://.godot/imported/example1.png-6386c332ca46e1e62ea061b956a901cd.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 diff --git a/addons/Todo_Manager/doc/images/example2.png b/addons/Todo_Manager/doc/images/example2.png new file mode 100644 index 0000000..c4a6584 --- /dev/null +++ b/addons/Todo_Manager/doc/images/example2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad39820b0814908951ebf8226c1a6c7d88a8d797a815345a0f1fd4377a1c2595 +size 30958 diff --git a/addons/Todo_Manager/doc/images/example2.png.import b/addons/Todo_Manager/doc/images/example2.png.import new file mode 100644 index 0000000..85454a6 --- /dev/null +++ b/addons/Todo_Manager/doc/images/example2.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bkabjahxfyyob" +path="res://.godot/imported/example2.png-2e3a8f9cd1e178daf22b83dc0513f37a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/Todo_Manager/doc/images/example2.png" +dest_files=["res://.godot/imported/example2.png-2e3a8f9cd1e178daf22b83dc0513f37a.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 diff --git a/addons/Todo_Manager/plugin.cfg b/addons/Todo_Manager/plugin.cfg new file mode 100644 index 0000000..256be46 --- /dev/null +++ b/addons/Todo_Manager/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="Todo Manager" +description="Dock for housing TODO messages." +author="Peter de Vroom" +version="2.3.1" +script="plugin.gd" diff --git a/addons/Todo_Manager/plugin.gd b/addons/Todo_Manager/plugin.gd new file mode 100644 index 0000000..511458d --- /dev/null +++ b/addons/Todo_Manager/plugin.gd @@ -0,0 +1,286 @@ +@tool +extends EditorPlugin + +const DockScene := preload("res://addons/Todo_Manager/UI/Dock.tscn") +const Dock := preload("res://addons/Todo_Manager/Dock.gd") +const Todo := preload("res://addons/Todo_Manager/todo_class.gd") +const TodoItem := preload("res://addons/Todo_Manager/todoItem_class.gd") + +var _dockUI : Dock + +class TodoCacheValue: + var todos: Array + var last_modified_time: int + + func _init(todos: Array, last_modified_time: int): + self.todos = todos + self.last_modified_time = last_modified_time + +var todo_cache : Dictionary # { key: script_path, value: TodoCacheValue } +var remove_queue : Array +var combined_pattern : String +var cased_patterns : Array[String] + +var refresh_lock := false # makes sure _on_filesystem_changed only triggers once + + +func _enter_tree() -> void: + _dockUI = DockScene.instantiate() as Control + add_control_to_bottom_panel(_dockUI, "TODO") + get_editor_interface().get_resource_filesystem().connect("filesystem_changed", + _on_filesystem_changed) + get_editor_interface().get_file_system_dock().connect("file_removed", queue_remove) + get_editor_interface().get_script_editor().connect("editor_script_changed", + _on_active_script_changed) + _dockUI.plugin = self + + combined_pattern = combine_patterns(_dockUI.patterns) + find_tokens_from_path(find_scripts()) + _dockUI.build_tree() + + +func _exit_tree() -> void: + _dockUI.create_config_file() + remove_control_from_bottom_panel(_dockUI) + _dockUI.free() + + +func queue_remove(file: String): + for i in _dockUI.todo_items.size() - 1: + if _dockUI.todo_items[i].script_path == file: + _dockUI.todo_items.remove_at(i) + + +func find_tokens_from_path(scripts: Array[String]) -> void: + for script_path in scripts: + var file := FileAccess.open(script_path, FileAccess.READ) + var contents := file.get_as_text() + if script_path.ends_with(".tscn"): + handle_built_in_scripts(contents, script_path) + else: + find_tokens(contents, script_path) + + +func handle_built_in_scripts(contents: String, resource_path: String): + var s := contents.split("sub_resource type=\"GDScript\"") + if s.size() <= 1: + return + for i in range(1, s.size()): + var script_components := s[i].split("script/source") + var script_name = script_components[0].substr(5, 14) + find_tokens(script_components[1], resource_path + "::" + script_name) + + +func find_tokens(text: String, script_path: String) -> void: + var cached_todos = get_cached_todos(script_path) + if cached_todos.size() != 0: +# var i := 0 +# for todo_item in _dockUI.todo_items: +# if todo_item.script_path == script_path: +# _dockUI.todo_items.remove_at(i) +# i += 1 + var todo_item := TodoItem.new(script_path, cached_todos) + _dockUI.todo_items.append(todo_item) + else: + var regex = RegEx.new() + # if regex.compile("#\\s*\\bTODO\\b.*|#\\s*\\bHACK\\b.*") == OK: + if regex.compile(combined_pattern) == OK: + var result : Array[RegExMatch] = regex.search_all(text) + if result.is_empty(): + for i in _dockUI.todo_items.size(): + if _dockUI.todo_items[i].script_path == script_path: + _dockUI.todo_items.remove_at(i) + return # No tokens found + var match_found : bool + var i := 0 + for todo_item in _dockUI.todo_items: + if todo_item.script_path == script_path: + match_found = true + var updated_todo_item := update_todo_item(todo_item, result, text, script_path) + _dockUI.todo_items.remove_at(i) + _dockUI.todo_items.insert(i, updated_todo_item) + break + i += 1 + if !match_found: + _dockUI.todo_items.append(create_todo_item(result, text, script_path)) + + +func create_todo_item(regex_results: Array[RegExMatch], text: String, script_path: String) -> TodoItem: + var todo_item = TodoItem.new(script_path, []) + todo_item.script_path = script_path + var last_line_number := 0 + var lines := text.split("\n") + for r in regex_results: + var new_todo : Todo = create_todo(r.get_string(), script_path) + new_todo.line_number = get_line_number(r.get_string(), text, last_line_number) + # GD Multiline comment + var trailing_line := new_todo.line_number + var should_break = false + while trailing_line < lines.size() and lines[trailing_line].dedent().begins_with("#"): + for other_r in regex_results: + if lines[trailing_line] in other_r.get_string(): + should_break = true + break + if should_break: + break + + new_todo.content += "\n" + lines[trailing_line] + trailing_line += 1 + + last_line_number = new_todo.line_number + todo_item.todos.append(new_todo) + cache_todos(todo_item.todos, script_path) + return todo_item + + +func update_todo_item(todo_item: TodoItem, regex_results: Array[RegExMatch], text: String, script_path: String) -> TodoItem: + todo_item.todos.clear() + var lines := text.split("\n") + for r in regex_results: + var new_todo : Todo = create_todo(r.get_string(), script_path) + new_todo.line_number = get_line_number(r.get_string(), text) + # GD Multiline comment + var trailing_line := new_todo.line_number + var should_break = false + while trailing_line < lines.size() and lines[trailing_line].dedent().begins_with("#"): + for other_r in regex_results: + if lines[trailing_line] in other_r.get_string(): + should_break = true + break + if should_break: + break + + new_todo.content += "\n" + lines[trailing_line] + trailing_line += 1 + todo_item.todos.append(new_todo) + return todo_item + + +func get_line_number(what: String, from: String, start := 0) -> int: + what = what.split('\n')[0] # Match first line of multiline C# comments + var temp_array := from.split('\n') + var lines := Array(temp_array) + var line_number# = lines.find(what) + 1 + for i in range(start, lines.size()): + if what in lines[i]: + line_number = i + 1 # +1 to account of 0-based array vs 1-based line numbers + break + else: + line_number = 0 # This is an error + return line_number + + +func _on_filesystem_changed() -> void: + if !refresh_lock: + if _dockUI.auto_refresh: + refresh_lock = true + _dockUI.get_node("Timer").start() + rescan_files(false) + + +func find_scripts() -> Array[String]: + var scripts : Array[String] + var directory_queue : Array[String] + var dir := DirAccess.open("res://") + if dir.get_open_error() == OK: + get_dir_contents(dir, scripts, directory_queue) + else: + printerr("TODO_Manager: There was an error during find_scripts()") + + while not directory_queue.is_empty(): + if dir.change_dir(directory_queue[0]) == OK: + get_dir_contents(dir, scripts, directory_queue) + else: + printerr("TODO_Manager: There was an error at: " + directory_queue[0]) + directory_queue.pop_front() + + return scripts + + +func cache_todos(todos: Array, script_path: String) -> void: + var last_modified_time = FileAccess.get_modified_time(script_path) + todo_cache[script_path] = TodoCacheValue.new(todos, last_modified_time) + + +func get_cached_todos(script_path: String) -> Array: + if todo_cache.has(script_path) and !script_path.contains("tscn::"): + var cached_value: TodoCacheValue = todo_cache[script_path] + if cached_value.last_modified_time == FileAccess.get_modified_time(script_path): + + return cached_value.todos + return [] + +func get_dir_contents(dir: DirAccess, scripts: Array[String], directory_queue: Array[String]) -> void: + dir.include_navigational = false + dir.include_hidden = false + dir.list_dir_begin() + var file_name : String = dir.get_next() + + while file_name != "": + if dir.current_is_dir(): + if file_name == ".import" or file_name == ".mono": # Skip .import folder which should never have scripts + pass + else: + directory_queue.append(dir.get_current_dir().path_join(file_name)) + else: + if file_name.ends_with(".gd") or file_name.ends_with(".cs") \ + or file_name.ends_with(".c") or file_name.ends_with(".cpp") or file_name.ends_with(".h") \ + or ((file_name.ends_with(".tscn") and _dockUI.builtin_enabled)): + scripts.append(dir.get_current_dir().path_join(file_name)) + file_name = dir.get_next() + + +func rescan_files(clear_cache: bool) -> void: + _dockUI.todo_items.clear() + if clear_cache: + todo_cache.clear() + combined_pattern = combine_patterns(_dockUI.patterns) + find_tokens_from_path(find_scripts()) + _dockUI.build_tree() + + +func combine_patterns(patterns: Array) -> String: + # Case Sensitivity + cased_patterns = [] + for pattern in patterns: + if pattern[2] == _dockUI.CASE_INSENSITIVE: + cased_patterns.append(pattern[0].insert(0, "((?i)") + ")") + else: + cased_patterns.append("(" + pattern[0] + ")") + + if patterns.size() == 1: + return cased_patterns[0] + else: + var pattern_string := "((\\/\\*)|(#|\\/\\/))\\s*(" + for i in range(patterns.size()): + if i == 0: + pattern_string += cased_patterns[i] + else: + pattern_string += "|" + cased_patterns[i] + pattern_string += ")(?(2)[\\s\\S]*?\\*\\/|.*)" + return pattern_string + + +func create_todo(todo_string: String, script_path: String) -> Todo: + var todo := Todo.new() + var regex = RegEx.new() + for pattern in cased_patterns: + if regex.compile(pattern) == OK: + var result : RegExMatch = regex.search(todo_string) + if result: + todo.pattern = pattern + todo.title = result.strings[0] + else: + continue + else: + printerr("Error compiling " + pattern) + + todo.content = todo_string + todo.script_path = script_path + return todo + + +func _on_active_script_changed(script) -> void: + if _dockUI: + if _dockUI.tabs.current_tab == 1: + _dockUI.build_tree() diff --git a/addons/Todo_Manager/plugin.gd.uid b/addons/Todo_Manager/plugin.gd.uid new file mode 100644 index 0000000..bdd5f5d --- /dev/null +++ b/addons/Todo_Manager/plugin.gd.uid @@ -0,0 +1 @@ +uid://cgdk1p15pdupx diff --git a/addons/Todo_Manager/todo.cfg b/addons/Todo_Manager/todo.cfg new file mode 100644 index 0000000..ac8e4bd --- /dev/null +++ b/addons/Todo_Manager/todo.cfg @@ -0,0 +1,15 @@ +[scripts] + +full_path=false +sort_alphabetical=true +script_colour=Color(0.8, 0.807843, 0.827451, 1) +ignore_paths=Array[String](["addons/limbo_console"]) + +[patterns] + +patterns=[["\\bTODO\\b", Color(0.588235, 0.945098, 0.678431, 1), 0], ["\\bHACK\\b", Color(0.835294, 0.737255, 0.439216, 1), 0], ["\\bFIXME\\b", Color(0.835294, 0.439216, 0.439216, 1), 0], ["\\bIDEA\\b", Color(0.677887, 0.701582, 0.894531, 1), 0]] + +[config] + +auto_refresh=true +builtin_enabled=true diff --git a/addons/Todo_Manager/todoItem_class.gd b/addons/Todo_Manager/todoItem_class.gd new file mode 100644 index 0000000..9bcb000 --- /dev/null +++ b/addons/Todo_Manager/todoItem_class.gd @@ -0,0 +1,18 @@ +@tool +extends RefCounted + +var script_path : String +var todos : Array + +func _init(script_path: String, todos: Array): + self.script_path = script_path + self.todos = todos + +func get_short_path() -> String: + var temp_array := script_path.rsplit('/', false, 1) + var short_path : String + if not temp_array.size() > 1: + short_path = "(!)" + temp_array[0] + else: + short_path = temp_array[1] + return short_path diff --git a/addons/Todo_Manager/todoItem_class.gd.uid b/addons/Todo_Manager/todoItem_class.gd.uid new file mode 100644 index 0000000..2f69fbc --- /dev/null +++ b/addons/Todo_Manager/todoItem_class.gd.uid @@ -0,0 +1 @@ +uid://d06d0j7pckcem diff --git a/addons/Todo_Manager/todo_class.gd b/addons/Todo_Manager/todo_class.gd new file mode 100644 index 0000000..af6b26b --- /dev/null +++ b/addons/Todo_Manager/todo_class.gd @@ -0,0 +1,9 @@ +@tool +extends RefCounted + + +var pattern : String +var title : String +var content : String +var script_path : String +var line_number : int diff --git a/addons/Todo_Manager/todo_class.gd.uid b/addons/Todo_Manager/todo_class.gd.uid new file mode 100644 index 0000000..52a052c --- /dev/null +++ b/addons/Todo_Manager/todo_class.gd.uid @@ -0,0 +1 @@ +uid://deig38x4vrohy diff --git a/addons/limbo_console b/addons/limbo_console new file mode 160000 index 0000000..d6eb8d2 --- /dev/null +++ b/addons/limbo_console @@ -0,0 +1 @@ +Subproject commit d6eb8d2257477b8b88d33c0c0f8c3542d49ea16e diff --git a/addons/limbo_console.cfg b/addons/limbo_console.cfg new file mode 100644 index 0000000..f09f986 --- /dev/null +++ b/addons/limbo_console.cfg @@ -0,0 +1,38 @@ +[main] + +aliases={ +"exit": "quit", +"source": "exec", +"usage": "help" +} +disable_in_release_build=false +print_to_stdout=false +commands_disabled_in_release=["eval"] + +[appearance] + +custom_theme="res://addons/limbo_console_theme.tres" +height_ratio=0.5 +open_speed=5.0 +opacity=1.0 +sparse_mode=false + +[greet] + +greet_user=true +greeting_message="{project_name}" +greet_using_ascii_art=true + +[history] + +persist_history=true +history_lines=1000 + +[autocomplete] + +autocomplete_use_history_with_matches=true + +[autoexec] + +autoexec_script="user://autoexec.lcs" +autoexec_auto_create=true diff --git a/project.godot b/project.godot index 5a581bf..0c50285 100644 --- a/project.godot +++ b/project.godot @@ -17,10 +17,18 @@ run/main_scene="uid://bhwuawppmqk4" config/features=PackedStringArray("4.4", "Forward Plus") config/icon="res://icon.svg" +[autoload] + +LimboConsole="*res://addons/limbo_console/limbo_console.gd" + [display] -window/size/viewport_width=360 -window/size/viewport_height=240 +window/size/viewport_width=1920 +window/size/viewport_height=1080 + +[editor_plugins] + +enabled=PackedStringArray("res://addons/Todo_Manager/plugin.cfg", "res://addons/limbo_console/plugin.cfg") [global_group] @@ -64,6 +72,21 @@ camera_left={ "events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":2,"axis_value":-1.0,"script":null) ] } +limbo_console_toggle={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":96,"key_label":0,"unicode":178,"location":0,"echo":false,"script":null) +] +} +limbo_auto_complete_reverse={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194306,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} +limbo_console_search_history={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":true,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":82,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} [physics]