diff --git a/Runtime/CommandTerminal/Input/TerminalControlTypes.cs b/Runtime/CommandTerminal/Input/TerminalControlTypes.cs index b8835bc..eb84eb0 100644 --- a/Runtime/CommandTerminal/Input/TerminalControlTypes.cs +++ b/Runtime/CommandTerminal/Input/TerminalControlTypes.cs @@ -14,5 +14,6 @@ public enum TerminalControlTypes ToggleSmall = 6, CompleteForward = 7, CompleteBackward = 8, + ToggleLauncher = 9, } } diff --git a/Runtime/CommandTerminal/Input/TerminalKeyboardController.cs b/Runtime/CommandTerminal/Input/TerminalKeyboardController.cs index 6bdd3f3..850e090 100644 --- a/Runtime/CommandTerminal/Input/TerminalKeyboardController.cs +++ b/Runtime/CommandTerminal/Input/TerminalKeyboardController.cs @@ -54,6 +54,9 @@ public bool ShouldHandleInputThisFrame [SerializeField] public string toggleFullHotkey = "#`"; + [SerializeField] + public string toggleLauncherHotkey = "#space"; + [SerializeField] public string completeHotkey = "tab"; @@ -80,6 +83,7 @@ public bool ShouldHandleInputThisFrame TerminalControlTypes.EnterCommand, TerminalControlTypes.Previous, TerminalControlTypes.Next, + TerminalControlTypes.ToggleLauncher, TerminalControlTypes.ToggleFull, TerminalControlTypes.ToggleSmall, TerminalControlTypes.CompleteBackward, @@ -98,6 +102,7 @@ public TerminalKeyboardController() _inputChecks[TerminalControlTypes.Next] = IsNextPressed; _inputChecks[TerminalControlTypes.ToggleFull] = IsToggleFullPressed; _inputChecks[TerminalControlTypes.ToggleSmall] = IsToggleSmallPressed; + _inputChecks[TerminalControlTypes.ToggleLauncher] = IsToggleLauncherPressed; _inputChecks[TerminalControlTypes.CompleteBackward] = IsCompleteBackwardPressed; _inputChecks[TerminalControlTypes.CompleteForward] = IsCompletePressed; @@ -108,6 +113,7 @@ public TerminalKeyboardController() _controlHandlerActions[TerminalControlTypes.Next] = Next; _controlHandlerActions[TerminalControlTypes.ToggleFull] = ToggleFull; _controlHandlerActions[TerminalControlTypes.ToggleSmall] = ToggleSmall; + _controlHandlerActions[TerminalControlTypes.ToggleLauncher] = ToggleLauncher; _controlHandlerActions[TerminalControlTypes.CompleteBackward] = CompleteBackward; _controlHandlerActions[TerminalControlTypes.CompleteForward] = Complete; } @@ -240,6 +246,15 @@ protected virtual void ToggleSmall() terminal.ToggleSmall(); } + protected virtual void ToggleLauncher() + { + if (terminal == null) + { + return; + } + terminal.ToggleLauncher(); + } + protected virtual void Complete() { if (terminal == null) @@ -289,6 +304,11 @@ protected virtual bool IsToggleSmallPressed() return InputHelpers.IsKeyPressed(toggleHotkey, inputMode); } + protected virtual bool IsToggleLauncherPressed() + { + return InputHelpers.IsKeyPressed(toggleLauncherHotkey, inputMode); + } + protected virtual bool IsCompleteBackwardPressed() { return InputHelpers.IsKeyPressed(reverseCompleteHotkey, inputMode); diff --git a/Runtime/CommandTerminal/UI/TerminalState.cs b/Runtime/CommandTerminal/UI/TerminalState.cs index 5c0aea3..4fcd97f 100644 --- a/Runtime/CommandTerminal/UI/TerminalState.cs +++ b/Runtime/CommandTerminal/UI/TerminalState.cs @@ -9,5 +9,6 @@ public enum TerminalState Closed = 1, OpenSmall = 2, OpenFull = 3, + OpenLauncher = 4, } } diff --git a/Runtime/CommandTerminal/UI/TerminalUI.cs b/Runtime/CommandTerminal/UI/TerminalUI.cs index d61d7c6..712d8cc 100644 --- a/Runtime/CommandTerminal/UI/TerminalUI.cs +++ b/Runtime/CommandTerminal/UI/TerminalUI.cs @@ -39,6 +39,7 @@ private enum ScrollBarCaptureState public bool IsClosed => _state != TerminalState.OpenFull && _state != TerminalState.OpenSmall + && _state != TerminalState.OpenLauncher && Mathf.Approximately(_currentWindowHeight, _targetWindowHeight); public string CurrentTheme => @@ -84,6 +85,27 @@ private enum ScrollBarCaptureState [Tooltip("Duration for the ease-in animation in seconds")] public float easeInTime = 0.5f; + [Header("Launcher")] + [Range(0.2f, 1f)] + [Tooltip("Width of the launcher as a ratio of screen width")] + public float launcherWidth = 0.5f; + + [Range(100f, 600f)] + [Tooltip("Base height of the launcher in pixels")] + public float launcherBaseHeight = 250f; + + [Range(20f, 100f)] + [Tooltip("Height per history item in launcher mode")] + public float launcherHistoryItemHeight = 25f; + + [Range(1, 10)] + [Tooltip("Maximum history items to show in launcher")] + public int launcherMaxHistoryItems = 5; + + [Range(20f, 100f)] + [Tooltip("Height per autocomplete item in launcher mode")] + public float launcherAutoCompleteItemHeight = 30f; + [Header("System")] [SerializeField] private int _logBufferSize = 256; @@ -670,6 +692,12 @@ private void ResetAutoComplete() { _lastCompletionBuffer.Add(completion); } + + // Recalculate height if in launcher mode + if (_state == TerminalState.OpenLauncher) + { + ResetWindowIdempotent(); + } } } else @@ -700,6 +728,12 @@ private void ResetWindowIdempotent() _targetWindowHeight = _realWindowHeight; break; } + case TerminalState.OpenLauncher: + { + _realWindowHeight = CalculateLauncherHeight(); + _targetWindowHeight = _realWindowHeight; + break; + } default: { _realWindowHeight = height * maxHeight * smallTerminalRatio; @@ -718,6 +752,28 @@ private void ResetWindowIdempotent() } } + private float CalculateLauncherHeight() + { + float height = launcherBaseHeight; + + // Add height for history items + int historyCount = Terminal.History?.Count ?? 0; + int visibleHistoryItems = Mathf.Min(historyCount, launcherMaxHistoryItems); + height += visibleHistoryItems * launcherHistoryItemHeight; + + // Add height for autocomplete if active + if (hintDisplayMode is HintDisplayMode.Always or HintDisplayMode.AutoCompleteOnly) + { + int autoCompleteCount = _lastCompletionBuffer?.Count ?? 0; + if (autoCompleteCount > 0) + { + height += autoCompleteCount * launcherAutoCompleteItemHeight; + } + } + + return Mathf.Clamp(height, launcherBaseHeight, Screen.height * 0.8f); + } + private void SetupUI() { if (_uiDocument == null) @@ -1105,7 +1161,27 @@ private void RefreshUI() _uiDocument.rootVisualElement.style.height = _currentWindowHeight; _terminalContainer.style.height = _currentWindowHeight; - _terminalContainer.style.width = Screen.width; + + // Position and size based on state + if (_state == TerminalState.OpenLauncher) + { + // Center the launcher and use limited width + float width = Screen.width * launcherWidth; + float left = (Screen.width - width) / 2f; + _terminalContainer.style.width = width; + _terminalContainer.style.left = left; + _terminalContainer.style.top = 0; + _terminalContainer.style.position = Position.Absolute; + } + else + { + // Full width for normal terminal modes + _terminalContainer.style.width = Screen.width; + _terminalContainer.style.left = 0; + _terminalContainer.style.top = 0; + _terminalContainer.style.position = Position.Relative; + } + DisplayStyle commandInputStyle = _currentWindowHeight <= 30 ? DisplayStyle.None : DisplayStyle.Flex; @@ -1594,6 +1670,16 @@ private void RefreshStateButtons() secondButton.text = smallButtonText; } break; + case TerminalState.OpenLauncher: + if (!string.IsNullOrWhiteSpace(closeButtonText)) + { + firstButton.text = closeButtonText; + } + if (!string.IsNullOrWhiteSpace(smallButtonText)) + { + secondButton.text = smallButtonText; + } + break; default: throw new InvalidEnumArgumentException( nameof(_state), @@ -1615,6 +1701,7 @@ void FirstClicked() break; case TerminalState.OpenSmall: case TerminalState.OpenFull: + case TerminalState.OpenLauncher: if (!string.IsNullOrWhiteSpace(closeButtonText)) { SetState(TerminalState.Closed); @@ -1646,6 +1733,12 @@ void SecondClicked() SetState(TerminalState.OpenSmall); } break; + case TerminalState.OpenLauncher: + if (!string.IsNullOrWhiteSpace(smallButtonText)) + { + SetState(TerminalState.OpenSmall); + } + break; default: throw new InvalidEnumArgumentException( nameof(_state), @@ -1916,6 +2009,11 @@ public void ToggleFull() ToggleState(TerminalState.OpenFull); } + public void ToggleLauncher() + { + ToggleState(TerminalState.OpenLauncher); + } + public void EnterCommand() { if (_state == TerminalState.Closed) @@ -2042,6 +2140,12 @@ public void CompleteCommand(bool searchForward = true) _lastCompletionBuffer.Add(item); } _previousLastCompletionIndex = null; + + // Recalculate height if in launcher mode + if (_state == TerminalState.OpenLauncher) + { + ResetWindowIdempotent(); + } } _previousLastCompletionIndex ??= _lastCompletionIndex;