diff --git a/demo/.idea/.idea.SofiaConsole/.idea/vcs.xml b/demo/.idea/.idea.SofiaConsole/.idea/vcs.xml index 94a25f7..288b36b 100644 --- a/demo/.idea/.idea.SofiaConsole/.idea/vcs.xml +++ b/demo/.idea/.idea.SofiaConsole/.idea/vcs.xml @@ -1,6 +1,7 @@ + \ No newline at end of file diff --git a/demo/SofiaConsole.csproj b/demo/SofiaConsole.csproj index 8ee8c44..578eae2 100644 --- a/demo/SofiaConsole.csproj +++ b/demo/SofiaConsole.csproj @@ -1,4 +1,4 @@ - + net6.0 true diff --git a/demo/addons/sofiaconsole/Console.cs b/demo/addons/sofiaconsole/Console.cs index 55b07c3..3e893e7 100644 --- a/demo/addons/sofiaconsole/Console.cs +++ b/demo/addons/sofiaconsole/Console.cs @@ -16,9 +16,12 @@ public partial class Console : Node public static Console Instance; public List Commands = new(); private readonly List _commandHistory = new(); + private List _suggestions = new List(); + private int _currentSuggestionIndex = -1; public bool Open; + [Export] private int _maxSuggestions = 15; [Export] private CanvasLayer _consoleCanvas; [Export] private Panel _background; [Export] private Button _closeButton; @@ -26,6 +29,8 @@ public partial class Console : Node [Export] private Button _commandSendButton; [Export] private ScrollContainer _historyScrollContainer; [Export] private VBoxContainer _historyContent; + [Export] private VBoxContainer _suggestionsContent; + [Export] private PanelContainer _suggestionsPanel; public override void _EnterTree() { @@ -36,13 +41,19 @@ public override void _EnterTree() _closeButton.Pressed += () => { SetConsole(false); }; _commandSendButton.Pressed += () => { ProcessCommand(_commandInput.Text); }; - _commandInput.TextSubmitted += ProcessCommand; + _commandInput.TextSubmitted += (t) => + { + ProcessCommand(t); + UpdateUi(true); + }; LoadCommands(); Print("[SofiaConsole] Version 1.2.0", PrintType.Success); Space(); + GenerateSuggestionsNode(); + GD.Print("[SofiaConsole] Done"); } @@ -63,22 +74,61 @@ public override void _Input(InputEvent @event) { ToggleConsole(); } - - // Press Up to toggle between previous commands - if (eventKey.Keycode == Key.Up && _commandInput.HasFocus() && _commandHistory.Count > 0) + + if (eventKey.Keycode == Key.Down && _commandInput.HasFocus() && _suggestions.Count > 0) + { + _currentSuggestionIndex = (_currentSuggestionIndex + 1) % _suggestions.Count; + } + else if (eventKey.Keycode == Key.Up && _commandInput.HasFocus() && _suggestions.Count > 0) + { + _currentSuggestionIndex = (_currentSuggestionIndex - 1) % _suggestions.Count; + if (_currentSuggestionIndex < 0) + _currentSuggestionIndex = _suggestions.Count - 1; + } + else if (eventKey.Keycode == Key.Tab || eventKey.Keycode == Key.Enter && _commandInput.HasFocus() && _suggestions.Count > 0 && _currentSuggestionIndex < _suggestions.Count) { - var historyIndex = _commandHistory.FindIndex(x => x == _commandInput.Text); - if (historyIndex == -1) + if (_suggestions.Count > 0 && _currentSuggestionIndex >= 0) { - historyIndex = _commandHistory.Count; + _commandInput.Text = ""; + _commandInput.InsertTextAtCaret(_suggestions[_currentSuggestionIndex]); + _commandInput.GrabFocus(); } + } + } + + if (@event is InputEventKey inputEventKey) + { + string inputText = _commandInput.Text; + + if (inputText.Trim() == "") + { + _suggestions.Clear(); - if (historyIndex == 0) + // Press Up to toggle between previous commands + if (inputEventKey.Keycode == Key.Up && _commandInput.HasFocus() && _commandHistory.Count > 0) { - historyIndex = _commandHistory.Count; + var historyIndex = _commandHistory.FindIndex(x => x == _commandInput.Text); + if (historyIndex == -1) + { + historyIndex = _commandHistory.Count; + } + + if (historyIndex == 0) + { + historyIndex = _commandHistory.Count; + } + + _commandInput.Text = _commandHistory[historyIndex - 1]; } - - _commandInput.Text = _commandHistory[historyIndex - 1]; + } + else + { + // Filter suggestions + _suggestions = Commands + .Where(cmd => cmd.Command.StartsWith(inputText)) + .OrderBy(cmd => cmd.Command.IndexOf(inputText, StringComparison.CurrentCulture)) + .Select(cmd => cmd.Command) + .ToList(); } } @@ -88,6 +138,71 @@ public override void _Input(InputEvent @event) _commandInput.ReleaseFocus(); _commandSendButton.ReleaseFocus(); } + + UpdateUi(); + } + + // Generate suggestions node when enter tree, to improve performance. + private void GenerateSuggestionsNode() + { + for (int i = 0; i < _maxSuggestions; i++) + { + var newLabel = new Label + { + Text = "", + Theme = new Theme + { + DefaultFontSize = 30 + } + }; + + _suggestionsContent.AddChild(newLabel); + newLabel.Hide(); + } + } + + private void UpdateUi(bool close = false) + { + if (!Open) return; + if (close) return; + + foreach (var node in _suggestionsContent.GetChildren()) + { + if (node is Label label) + { + label.Hide(); + } + } + + if (_suggestions.Count == 0) + { + _suggestionsPanel.Hide(); + return; + } + + _suggestionsPanel.Show(); + + for (int i = 0; i < Mathf.Min(_maxSuggestions, _suggestions.Count); i++) + { + Label suggestionLabel = _suggestionsContent.GetChild(i) as Label; + if (suggestionLabel == null) continue; + + suggestionLabel.Text = _suggestions[i]; + suggestionLabel.Show(); + + if (_currentSuggestionIndex >= 0 && _suggestions.Count > 0 && + _currentSuggestionIndex < _suggestions.Count && + _suggestions[_currentSuggestionIndex] == _suggestions[i]) + { + // Background color for selected suggestion + suggestionLabel.AddThemeStyleboxOverride("normal", GD.Load("res://addons/sofiaconsole/SelectedSuggestion.tres")); + } + else + { + // Background color for suggestion + suggestionLabel.RemoveThemeStyleboxOverride("normal"); + } + } } public void ToggleConsole() @@ -101,7 +216,8 @@ private void SetConsole(bool open) _consoleCanvas.Visible = Open; _background.MouseFilter = Open ? Control.MouseFilterEnum.Stop : Control.MouseFilterEnum.Ignore; - + GetTree().Paused = Open; + if (Open) { _commandInput.GrabFocus(); @@ -229,7 +345,7 @@ public async void Print(string text, PrintType type = PrintType.Default) Text = text, Theme = new Theme { - DefaultFontSize = 12 + DefaultFontSize = 30 } }; diff --git a/demo/addons/sofiaconsole/Console.tscn b/demo/addons/sofiaconsole/Console.tscn index 377c501..03e0fc0 100644 --- a/demo/addons/sofiaconsole/Console.tscn +++ b/demo/addons/sofiaconsole/Console.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=13 format=3 uid="uid://dyya4j4ywm1k6"] +[gd_scene load_steps=14 format=3 uid="uid://dyya4j4ywm1k6"] [ext_resource type="Script" path="res://addons/sofiaconsole/Console.cs" id="1_dw41g"] [ext_resource type="Script" path="res://addons/sofiaconsole/Commands/FpsCounterCommand.cs" id="2_nkfel"] @@ -39,6 +39,9 @@ content_margin_right = 10.0 content_margin_bottom = 10.0 bg_color = Color(0.133333, 0.133333, 0.133333, 0) +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_wpanm"] +bg_color = Color(0.0900985, 0.0900985, 0.0900985, 1) + [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_25al0"] content_margin_left = 10.0 content_margin_top = 10.0 @@ -58,15 +61,18 @@ outline_color = Color(0, 0, 0, 1) shadow_size = 5 shadow_color = Color(0, 0, 0, 1) -[node name="Console" type="Node" node_paths=PackedStringArray("_consoleCanvas", "_background", "_closeButton", "_commandInput", "_commandSendButton", "_historyScrollContainer", "_historyContent")] +[node name="Console" type="Node" node_paths=PackedStringArray("_consoleCanvas", "_background", "_closeButton", "_commandInput", "_commandSendButton", "_historyScrollContainer", "_historyContent", "_suggestionsContent", "_suggestionsPanel")] +process_mode = 3 script = ExtResource("1_dw41g") _consoleCanvas = NodePath("ConsoleCanvas") _background = NodePath("ConsoleCanvas/Background") -_closeButton = NodePath("ConsoleCanvas/Background/Window/Content/Header/HBoxContainer/CloseButton") -_commandInput = NodePath("ConsoleCanvas/Background/Window/Content/Input/HBoxContainer/CommandInput") -_commandSendButton = NodePath("ConsoleCanvas/Background/Window/Content/Input/HBoxContainer/CommandSendButton") -_historyScrollContainer = NodePath("ConsoleCanvas/Background/Window/Content/History/ScrollContainer") -_historyContent = NodePath("ConsoleCanvas/Background/Window/Content/History/ScrollContainer/Content") +_closeButton = NodePath("ConsoleCanvas/Background/MarginContainer/Window/Content/Header/HBoxContainer/CloseButton") +_commandInput = NodePath("ConsoleCanvas/Background/MarginContainer/Window/Content/Input/HBoxContainer/CommandInput") +_commandSendButton = NodePath("ConsoleCanvas/Background/MarginContainer/Window/Content/Input/HBoxContainer/CommandSendButton") +_historyScrollContainer = NodePath("ConsoleCanvas/Background/MarginContainer/Window/Content/History/ScrollContainer") +_historyContent = NodePath("ConsoleCanvas/Background/MarginContainer/Window/Content/History/ScrollContainer/Content") +_suggestionsContent = NodePath("ConsoleCanvas/Background/MarginContainer/Window/Content/History/SuggestionsPanel/Suggestions/Suggestions") +_suggestionsPanel = NodePath("ConsoleCanvas/Background/MarginContainer/Window/Content/History/SuggestionsPanel") [node name="ConsoleCanvas" type="CanvasLayer" parent="."] layer = 128 @@ -81,23 +87,24 @@ grow_vertical = 2 mouse_filter = 2 theme_override_styles/panel = SubResource("StyleBoxFlat_cvk4f") -[node name="Window" type="Panel" parent="ConsoleCanvas/Background"] -custom_minimum_size = Vector2(600, 400) +[node name="MarginContainer" type="MarginContainer" parent="ConsoleCanvas/Background"] layout_mode = 1 -anchors_preset = 8 -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -offset_left = -350.0 -offset_top = -250.0 -offset_right = 350.0 -offset_bottom = 250.0 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 +theme_override_constants/margin_left = 50 +theme_override_constants/margin_top = 50 +theme_override_constants/margin_right = 50 +theme_override_constants/margin_bottom = 50 + +[node name="Window" type="Panel" parent="ConsoleCanvas/Background/MarginContainer"] +custom_minimum_size = Vector2(600, 400) +layout_mode = 2 theme_override_styles/panel = SubResource("StyleBoxFlat_lpjvy") -[node name="Content" type="VBoxContainer" parent="ConsoleCanvas/Background/Window"] +[node name="Content" type="VBoxContainer" parent="ConsoleCanvas/Background/MarginContainer/Window"] layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 @@ -106,63 +113,87 @@ grow_horizontal = 2 grow_vertical = 2 theme_override_constants/separation = 0 -[node name="Header" type="PanelContainer" parent="ConsoleCanvas/Background/Window/Content"] +[node name="Header" type="PanelContainer" parent="ConsoleCanvas/Background/MarginContainer/Window/Content"] +custom_minimum_size = Vector2(0, 80) layout_mode = 2 theme_override_styles/panel = SubResource("StyleBoxFlat_t5a6w") -[node name="HBoxContainer" type="HBoxContainer" parent="ConsoleCanvas/Background/Window/Content/Header"] +[node name="HBoxContainer" type="HBoxContainer" parent="ConsoleCanvas/Background/MarginContainer/Window/Content/Header"] layout_mode = 2 theme_override_constants/separation = 15 alignment = 1 -[node name="Label" type="Label" parent="ConsoleCanvas/Background/Window/Content/Header/HBoxContainer"] +[node name="Label" type="Label" parent="ConsoleCanvas/Background/MarginContainer/Window/Content/Header/HBoxContainer"] layout_mode = 2 size_flags_horizontal = 3 +theme_override_font_sizes/font_size = 40 text = "Console" -[node name="CloseButton" type="Button" parent="ConsoleCanvas/Background/Window/Content/Header/HBoxContainer"] +[node name="CloseButton" type="Button" parent="ConsoleCanvas/Background/MarginContainer/Window/Content/Header/HBoxContainer"] custom_minimum_size = Vector2(65, 0) layout_mode = 2 size_flags_horizontal = 8 +focus_mode = 0 text = "Close" -[node name="History" type="PanelContainer" parent="ConsoleCanvas/Background/Window/Content"] +[node name="History" type="PanelContainer" parent="ConsoleCanvas/Background/MarginContainer/Window/Content"] layout_mode = 2 size_flags_vertical = 3 theme_override_styles/panel = SubResource("StyleBoxFlat_rquom") -[node name="ScrollContainer" type="ScrollContainer" parent="ConsoleCanvas/Background/Window/Content/History"] +[node name="ScrollContainer" type="ScrollContainer" parent="ConsoleCanvas/Background/MarginContainer/Window/Content/History"] layout_mode = 2 size_flags_vertical = 3 theme_override_styles/panel = SubResource("StyleBoxFlat_fbsm3") horizontal_scroll_mode = 0 vertical_scroll_mode = 2 -[node name="Content" type="VBoxContainer" parent="ConsoleCanvas/Background/Window/Content/History/ScrollContainer"] +[node name="Content" type="VBoxContainer" parent="ConsoleCanvas/Background/MarginContainer/Window/Content/History/ScrollContainer"] layout_mode = 2 size_flags_horizontal = 3 theme_override_constants/separation = 0 -[node name="Input" type="PanelContainer" parent="ConsoleCanvas/Background/Window/Content"] +[node name="SuggestionsPanel" type="PanelContainer" parent="ConsoleCanvas/Background/MarginContainer/Window/Content/History"] +visible = false +layout_mode = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_wpanm") + +[node name="Suggestions" type="ScrollContainer" parent="ConsoleCanvas/Background/MarginContainer/Window/Content/History/SuggestionsPanel"] +layout_mode = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_fbsm3") +horizontal_scroll_mode = 0 +vertical_scroll_mode = 2 + +[node name="Suggestions" type="VBoxContainer" parent="ConsoleCanvas/Background/MarginContainer/Window/Content/History/SuggestionsPanel/Suggestions"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_constants/separation = 0 +alignment = 2 + +[node name="Input" type="PanelContainer" parent="ConsoleCanvas/Background/MarginContainer/Window/Content"] layout_mode = 2 size_flags_vertical = 8 theme_override_styles/panel = SubResource("StyleBoxFlat_25al0") -[node name="HBoxContainer" type="HBoxContainer" parent="ConsoleCanvas/Background/Window/Content/Input"] +[node name="HBoxContainer" type="HBoxContainer" parent="ConsoleCanvas/Background/MarginContainer/Window/Content/Input"] custom_minimum_size = Vector2(0, 40) layout_mode = 2 theme_override_constants/separation = 15 -[node name="CommandInput" type="LineEdit" parent="ConsoleCanvas/Background/Window/Content/Input/HBoxContainer"] +[node name="CommandInput" type="LineEdit" parent="ConsoleCanvas/Background/MarginContainer/Window/Content/Input/HBoxContainer"] layout_mode = 2 size_flags_horizontal = 3 +theme_override_font_sizes/font_size = 40 placeholder_text = "Enter \"help\" for a list of commands" flat = true +caret_blink = true -[node name="CommandSendButton" type="Button" parent="ConsoleCanvas/Background/Window/Content/Input/HBoxContainer"] +[node name="CommandSendButton" type="Button" parent="ConsoleCanvas/Background/MarginContainer/Window/Content/Input/HBoxContainer"] custom_minimum_size = Vector2(80, 0) layout_mode = 2 size_flags_horizontal = 8 +focus_mode = 0 text = "Send" [node name="BuiltinCommands" type="Node" parent="."] diff --git a/demo/addons/sofiaconsole/SelectedSuggestion.tres b/demo/addons/sofiaconsole/SelectedSuggestion.tres new file mode 100644 index 0000000..379b751 --- /dev/null +++ b/demo/addons/sofiaconsole/SelectedSuggestion.tres @@ -0,0 +1,10 @@ +[gd_resource type="StyleBoxFlat" format=3 uid="uid://b2ac5b6b26qbc"] + +[resource] +bg_color = Color(0.300523, 0.695688, 0.398018, 1) +border_width_left = 5 +border_color = Color(0.301961, 0.694118, 0.396078, 1) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 diff --git a/demo/models/gdbot/gdbot.glb.import b/demo/models/gdbot/gdbot.glb.import index 8aee40d..34bd0da 100644 --- a/demo/models/gdbot/gdbot.glb.import +++ b/demo/models/gdbot/gdbot.glb.import @@ -22,6 +22,7 @@ meshes/generate_lods=true meshes/create_shadow_meshes=true meshes/light_baking=1 meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false skins/use_named_skins=true animation/import=true animation/fps=30 @@ -9027,4 +9028,5 @@ _subresources={ } } } +gltf/naming_version=0 gltf/embedded_image_handling=3 diff --git a/demo/models/gdbot/materials/heart_core_mat.tres b/demo/models/gdbot/materials/heart_core_mat.tres index 9a20dfe..49eff02 100644 --- a/demo/models/gdbot/materials/heart_core_mat.tres +++ b/demo/models/gdbot/materials/heart_core_mat.tres @@ -4,4 +4,4 @@ albedo_color = Color(0, 0, 0, 1) emission_enabled = true emission = Color(0, 1, 0.392157, 1) -emission_energy_multiplier = 2.25453 +emission_energy_multiplier = 2.26158 diff --git a/demo/project.godot b/demo/project.godot index e7791e7..19631f8 100644 --- a/demo/project.godot +++ b/demo/project.godot @@ -12,7 +12,7 @@ config_version=5 config/name="SofiaConsole" run/main_scene="res://demo.tscn" -config/features=PackedStringArray("4.1", "C#", "Forward Plus") +config/features=PackedStringArray("4.2", "C#", "Forward Plus") config/icon="res://icon.svg" [autoload]