using System.Collections.Generic; using System.Linq; using FlaxEngine; namespace Game; public class ConsoleInputTextBox : ConsoleTextBoxBase { private readonly ConsoleContentTextBox contentBox; private int inputHistoryIndex = -1; public ConsoleInputTextBox() { } public ConsoleInputTextBox(ConsoleContentTextBox contentBox, float x, float y, float width, float height) : base(x, y, width, height) { this.contentBox = contentBox; IsMultiline = true; // Not really but behaves better than single-line box } public override string TextPrefix => Console.LinePrefix; protected override Rectangle TextRectangle => new Rectangle(0, 0, Width, Height); protected override Rectangle TextClipRectangle => new Rectangle(0, 0, Width, Height); private bool IsConsoleKeyPressed(KeyboardKeys key = KeyboardKeys.None) { // Ignore any characters generated by the key which opens the console string inputTextLower = Input.InputText.ToLowerInvariant(); IEnumerable consoleKeyMappings; if (key == KeyboardKeys.None) consoleKeyMappings = Input.ActionMappings.Where(x => x.Name == "Console" && x.Key != KeyboardKeys.None); else consoleKeyMappings = Input.ActionMappings.Where(x => x.Name == "Console" && x.Key == key); foreach (ActionConfig mapping in consoleKeyMappings) { if (inputTextLower.Length > 0) { // TODO: Remove this shit when scancode input is implemented in the engine if ((mapping.Key == KeyboardKeys.Backslash || mapping.Key == KeyboardKeys.BackQuote) && (inputTextLower.Contains('ö') || inputTextLower.Contains('æ') || inputTextLower.Contains('ø'))) continue; // Scandinavian keyboard layouts if (mapping.Key == KeyboardKeys.BackQuote && inputTextLower.Contains('\'')) continue; if (mapping.Key == KeyboardKeys.Backslash && (inputTextLower.Contains('\\') || inputTextLower.Contains('|'))) continue; } if (Input.GetKey(mapping.Key)) return true; } return false; } public override bool OnCharInput(char c) { if (IsConsoleKeyPressed()) return true; return base.OnCharInput(c); } public override bool OnKeyDown(KeyboardKeys key) { bool shiftDown = Root.GetKey(KeyboardKeys.Shift); bool ctrlDown = Root.GetKey(KeyboardKeys.Control); if (IsConsoleKeyPressed(key)) { Clear(); return true; } if (key == KeyboardKeys.Escape) { Console.Close(); Clear(); return true; } if (key == KeyboardKeys.Return) { try { Console.Execute(Text, true); inputHistoryIndex = -1; } finally { Clear(); } contentBox.ScrollOffset = 0; return true; } if (key == KeyboardKeys.ArrowUp) { inputHistoryIndex++; string line = Console.GetBufferHistory(inputHistoryIndex); if (line == null) { inputHistoryIndex--; return true; } SetText(line); SetSelection(TextLength); return true; } if (key == KeyboardKeys.ArrowDown) { if (inputHistoryIndex > 0) inputHistoryIndex--; string line = Console.GetBufferHistory(inputHistoryIndex); if (line == null) return true; SetText(line); SetSelection(TextLength); return true; } if (key == KeyboardKeys.PageUp || key == KeyboardKeys.PageDown) return contentBox.OnKeyDown(key); #if FLAX_EDITOR if (key == KeyboardKeys.F5) return false; #endif return base.OnKeyDown(key); } public override void OnLostFocus() { // Prevent caret location getting reset back to beginning, // and submitting the value when focus is lost. bool oldEditing = _isEditing; _isEditing = false; try { base.OnLostFocus(); } finally { _isEditing = oldEditing; } } public override bool OnMouseDown(Float2 location, MouseButton button) { base.OnMouseDown(location, button); return true; } public override bool OnMouseWheel(Float2 location, float delta) { return contentBox.OnMouseWheel(location, delta); } public override void Draw() { Profiler.BeginEvent("ConsoleInputTextBoxDraw"); base.Draw(); Profiler.EndEvent(); } }