diff --git a/Content/Scenes/MainScene.scene b/Content/Scenes/MainScene.scene index 856927e..aaa2f0b 100644 --- a/Content/Scenes/MainScene.scene +++ b/Content/Scenes/MainScene.scene @@ -40,8 +40,8 @@ "V": { "Order": -999999999, "Size": { - "X": 1439.0, - "Y": 818.0 + "X": 1456.0, + "Y": 813.0 } } }, @@ -52,6 +52,7 @@ "V": { "ConsoleHeight": 0.635, "ConsoleFont": "43f32bec443158643f53699f07b2e09c", + "BackgroundTexture": "16a2d3f1465e834c8ac965bd072c1dca", "BackgroundColor": { "R": 0.0, "G": 0.0, @@ -69,7 +70,7 @@ "Transform": { "Translation": { "X": -82.89323425292969, - "Y": 108.37522888183594, + "Y": 111.32740783691406, "Z": 114.5750503540039 } }, @@ -99,7 +100,7 @@ "Transform": { "Translation": { "X": 0.0, - "Y": 22.328903198242189, + "Y": 28.7337646484375, "Z": 0.0 } }, @@ -137,8 +138,8 @@ }, "V": { "Size": { - "X": 1439.0, - "Y": 818.0 + "X": 1456.0, + "Y": 813.0 } } }, @@ -158,13 +159,13 @@ "Transform": { "Translation": { "X": 0.0, - "Y": 738.0, + "Y": 733.0, "Z": 0.0 } }, "Control": "FlaxEngine.GUI.Label", "Data": { - "Text": "FPS: 690\nrFPS: 690\nCon: NaNms\nDirectX11\nGC memory: 6.903736MB", + "Text": "FPS: 15\nrFPS: 11\nCon: NaNms\nDirectX11\nGC memory: 13.52053MB", "TextColor": { "R": 1.0, "G": 1.0, diff --git a/Source/Game/Cabrito/Console/Console.cs b/Source/Game/Cabrito/Console/Console.cs index b964a43..3cdfece 100644 --- a/Source/Game/Cabrito/Console/Console.cs +++ b/Source/Game/Cabrito/Console/Console.cs @@ -183,9 +183,9 @@ namespace Cabrito OnClose -= instance.OnConsoleClose; } - public static IReadOnlyCollection GetLines() + public static IReadOnlyCollection Lines { - return consoleLines.AsReadOnly(); + get => consoleLines.AsReadOnly(); } // Echoes text to Console. diff --git a/Source/Game/Cabrito/Console/ConsoleContainerControl.cs b/Source/Game/Cabrito/Console/ConsoleContainerControl.cs index 4af1143..9589591 100644 --- a/Source/Game/Cabrito/Console/ConsoleContainerControl.cs +++ b/Source/Game/Cabrito/Console/ConsoleContainerControl.cs @@ -22,6 +22,10 @@ namespace Cabrito { } + public ConsoleContainerControl(Rectangle bounds) : base(bounds) + { + } + public override void OnGotFocus() { base.OnGotFocus(); diff --git a/Source/Game/Cabrito/Console/ConsoleContentTextBox.cs b/Source/Game/Cabrito/Console/ConsoleContentTextBox.cs index 0ad4e19..8493050 100644 --- a/Source/Game/Cabrito/Console/ConsoleContentTextBox.cs +++ b/Source/Game/Cabrito/Console/ConsoleContentTextBox.cs @@ -11,6 +11,13 @@ namespace Cabrito { public class ConsoleContentTextBox : Control { + struct LineInfo + { + public int lineIndex; + public int lineOffset; + public int lineLength; + } + [HideInEditor] public ConsoleInputTextBox inputBox; @@ -30,20 +37,32 @@ namespace Cabrito public Color BorderColor; public Color TextColor = Color.White; public int DefaultMargin = 1; + public int ScrollOffset = 0; + public int ScrollMouseLines = 3; - private Vector2 scrollOffset = new Vector2(0); + private float heightMultiplier = 1.0f; + public float HeightMultiplier + { + get => heightMultiplier; + set + { + heightMultiplier = value; + Height = Screen.Size.Y * HeightMultiplier; + } + } private int selectionStartLine = 0; private int selectionStartChar = 0; private int selectionEndLine = 0; private int selectionEndChar = 0; + + private bool selectionActive; public bool HasSelection => !(selectionStartLine == selectionEndLine && selectionStartChar == selectionEndChar); public ConsoleContentTextBox() : base() { - } public ConsoleContentTextBox(ConsoleInputTextBox inputBox, float x, float y, float width, float height) : base(x, y, width, height) @@ -55,6 +74,7 @@ namespace Cabrito _layout.VerticalAlignment = TextAlignment.Near; _layout.TextWrapping = TextWrapping.WrapChars; _layout.Bounds = new Rectangle(DefaultMargin, 1, Width - 2 * DefaultMargin, Height - 2); + //IsMultiline = true; //IsReadOnly = true; @@ -62,6 +82,14 @@ namespace Cabrito AutoFocus = false; } + private int GetFontCharacterWidth() + { + var font = Font.GetFont(); + if (!font) + return 0; + return (int)font.MeasureText("a").X; // hacky, but works for fixed-size fonts... + } + public int GetFontHeight() { var font = Font.GetFont(); @@ -71,13 +99,22 @@ namespace Cabrito return (int)Mathf.Round(LineSpacing * (font.Height / Platform.DpiScale) * Scale.Y); } - struct LineInfo + private int GetHeightInLines() { - public int lineIndex; - public int lineOffset; - public int lineLength; + var font = Font.GetFont(); + if (!font) + return 0; + return (int)(Height / (font.Height / Platform.DpiScale)); // number of fully visible lines } + + public override void OnParentResized() + { + Height = Screen.Size.Y * HeightMultiplier; + base.OnParentResized(); + } + + private void CalculateVisibleLines(IReadOnlyCollection lines, out int firstVisibleLine, out int lastVisibleLine, out LineInfo[] wrappedLines) { wrappedLines = null; @@ -88,14 +125,21 @@ namespace Cabrito if (!font) return; - float fontWidth = (int)font.MeasureText("a").X; // hacky, but works for fixed-size fonts... + float fontWidth = GetFontCharacterWidth(); int lineMaxChars = (int)(Width / fontWidth); - int lineMaxLines = (int)(Height / (font.Height / Platform.DpiScale)); // number of fully visible lines + int lineMaxLines = GetHeightInLines(); int numLines = 0; - int lineIndex = lines.Count - 1; + int lineIndex = lines.Count; List lineInfos = new List(lineMaxLines+1); + int linesSkipped = 0; foreach (string line in lines.Reverse()) { + lineIndex--; + if (linesSkipped < ScrollOffset) + { + linesSkipped++; + continue; + } int numChars = 0; int startIndex = lineInfos.Count; while (numChars < line.Length) @@ -111,7 +155,6 @@ namespace Cabrito if (lineInfos.Count - startIndex > 1) lineInfos.Reverse(startIndex, lineInfos.Count - startIndex); numLines++; - lineIndex--; if (lineInfos.Count > lineMaxLines) break; @@ -121,8 +164,8 @@ namespace Cabrito wrappedLines = lineInfos.ToArray(); //return lines[lines.Count - numLines .. lines.Count]; // C# 8.0... - firstVisibleLine = lines.Count - numLines; - lastVisibleLine = lines.Count; + lastVisibleLine = lineIndex; + firstVisibleLine = lastVisibleLine - numLines; } public static double accumDrawTime = 0.0; @@ -149,7 +192,7 @@ namespace Cabrito if (borderColor.A > 0.0f) Render2D.DrawRectangle(rect, borderColor); - var lines = Console.GetLines(); + var lines = Console.Lines; if (lines.Count > 0) { @@ -157,51 +200,10 @@ namespace Cabrito // Apply view offset and clip mask var textClipRectangle = new Rectangle(1, 1, Width - 2, Height - 2); Render2D.PushClip(textClipRectangle); - /*bool useViewOffset = !_viewOffset.IsZero; - if (useViewOffset) - Render2D.PushTransform(Matrix3x3.Translation2D(-_viewOffset));*/ - - // Check if any text is selected to draw selection - //if (HasSelection) - { - /*Vector2 leftEdge = font.GetCharPosition(text, SelectionLeft + TextPrefix.Length, ref _layout); - Vector2 rightEdge = font.GetCharPosition(text, SelectionRight + TextPrefix.Length, ref _layout); - float fontHeight = GetFontHeight(); - float spacing = GetRealLineSpacing(); - - // Draw selection background - float alpha = Mathf.Min(1.0f, Mathf.Cos(_animateTime * BackgroundSelectedFlashSpeed) * 0.5f + 1.3f); - alpha = alpha * alpha; - Color selectionColor = SelectionColor * alpha; - - int selectedLinesCount = 1 + Mathf.FloorToInt((rightEdge.Y - leftEdge.Y) / fontHeight); - if (selectedLinesCount == 1) // Selected is part of single line - { - Rectangle r1 = new Rectangle(leftEdge.X, leftEdge.Y, rightEdge.X - leftEdge.X, fontHeight); - Render2D.FillRectangle(r1, selectionColor); - } - else // Selected is more than one line - { - float leftMargin = _layout.Bounds.Location.X; - Rectangle r1 = new Rectangle(leftEdge.X, leftEdge.Y, 1000000000, fontHeight); - Render2D.FillRectangle(r1, selectionColor); - - for (int i = 3; i <= selectedLinesCount; i++) - { - leftEdge.Y += fontHeight; - Rectangle r = new Rectangle(leftMargin, leftEdge.Y, 1000000000, fontHeight); - Render2D.FillRectangle(r, selectionColor); - } - - Rectangle r2 = new Rectangle(leftMargin, rightEdge.Y, rightEdge.X - leftMargin, fontHeight); - Render2D.FillRectangle(r2, selectionColor); - }*/ - } - + // Make sure lengthy lines are split CalculateVisibleLines(lines, out int startLine, out int lastLine, out LineInfo[] wrappedLines); - float lineHeight = font.Height / Platform.DpiScale; float accumHeight = wrappedLines.Length * lineHeight; @@ -228,6 +230,7 @@ namespace Cabrito Color selectionColor = SelectionColor;// * alpha; TextLayoutOptions layout = _layout; + layout.Bounds = rect; layout.Bounds.Y -= accumHeight - Height; //for (int i = startLine; i < lastLine; i++) foreach (LineInfo li in wrappedLines) @@ -301,6 +304,7 @@ namespace Cabrito // render lines { TextLayoutOptions layout = _layout; + layout.Bounds = rect; layout.Bounds.Y -= accumHeight - Height; foreach (LineInfo li in wrappedLines) { @@ -322,10 +326,6 @@ namespace Cabrito Render2D.FillRectangle(caretBounds, CaretColor * alpha); }*/ - // Restore rendering state - //if (useViewOffset) - // Render2D.PopTransform(); - Render2D.PopClip(); } sw.Stop(); @@ -361,10 +361,11 @@ namespace Cabrito if (font == null) return false; - var lines = Console.GetLines(); + var lines = Console.Lines; CalculateVisibleLines(lines, out int startLine, out int lastLine, out LineInfo[] wrappedLines); TextLayoutOptions layout = _layout; + layout.Bounds = new Rectangle(0, 0, Size); float lineHeightNormalized = font.Height; float lineHeight = lineHeightNormalized / Platform.DpiScale; float visibleHeight = wrappedLines.Length * lineHeight; @@ -413,11 +414,43 @@ namespace Cabrito Copy(); return true; } + else if (key == KeyboardKeys.PageUp) + { + ScrollOffset += GetHeightInLines() / 2; + var maxOffset = Console.Lines.Count - GetHeightInLines(); + if (ScrollOffset > maxOffset) + ScrollOffset = maxOffset; + } + else if (key == KeyboardKeys.PageDown) + { + ScrollOffset -= GetHeightInLines() / 2; + if (ScrollOffset < 0) + ScrollOffset = 0; + } //else if (ctrlDown && key == KeyboardKeys.A) // SelectAll(); return base.OnKeyDown(key); } + public override bool OnMouseWheel(Vector2 location, float delta) + { + if (delta < 0) + { + ScrollOffset -= ScrollMouseLines; + if (ScrollOffset < 0) + ScrollOffset = 0; + + } + else if (delta > 0) + { + ScrollOffset += ScrollMouseLines; + var maxOffset = Console.Lines.Count - GetHeightInLines(); + if (ScrollOffset > maxOffset) + ScrollOffset = maxOffset; + } + return false; + } + public override bool OnMouseDown(Vector2 location, MouseButton button) { bool ret = false; @@ -427,8 +460,7 @@ namespace Cabrito ret = true; } - var lines = Console.GetLines(); - if (button == MouseButton.Left && lines.Count > 0) + if (button == MouseButton.Left && Console.Lines.Count > 0) { bool selectionStarted = !selectionActive; Focus(); @@ -512,7 +544,7 @@ namespace Cabrito selectionRightChar = selectionStartChar; } - var lines = Console.GetLines(); + var lines = Console.Lines; CalculateVisibleLines(lines, out int startLine, out int lastLine, out LineInfo[] wrappedLines); StringBuilder selectedText = new StringBuilder(); diff --git a/Source/Game/Cabrito/Console/ConsoleInputTextBox.cs b/Source/Game/Cabrito/Console/ConsoleInputTextBox.cs index 14db8e2..4a75ec5 100644 --- a/Source/Game/Cabrito/Console/ConsoleInputTextBox.cs +++ b/Source/Game/Cabrito/Console/ConsoleInputTextBox.cs @@ -90,6 +90,7 @@ namespace Cabrito { Clear(); } + contentBox.ScrollOffset = 0; return true; } else if (key == KeyboardKeys.ArrowUp || key == KeyboardKeys.ArrowDown) diff --git a/Source/Game/Cabrito/Console/ConsoleScript.cs b/Source/Game/Cabrito/Console/ConsoleScript.cs index 4c1d7b1..5c0491e 100644 --- a/Source/Game/Cabrito/Console/ConsoleScript.cs +++ b/Source/Game/Cabrito/Console/ConsoleScript.cs @@ -50,7 +50,6 @@ namespace Cabrito private UIControl rootControl; private ConsoleContentTextBox consoleBox; private ConsoleInputTextBox consoleInputBox; - private Image backgroundImage; internal InputEvent consoleInputEvent; @@ -71,49 +70,59 @@ namespace Cabrito int fontHeight = fontRaw.Height; // root actor which holds all the elements - var rootContainerControl = new ContainerControl(0, 0, screenSize.X, screenSize.Y); + //var rootContainerControl = new ContainerControl(new Rectangle(0, 0, screenSize.X, screenSize.Y)); + var rootContainerControl = new ContainerControl(new Rectangle()); + rootContainerControl.SetAnchorPreset(AnchorPresets.StretchAll, false); + rootControl = Actor.AddChild(); rootControl.Name = "ConsoleRoot"; rootControl.Control = rootContainerControl; - if (backgroundImage == null) - { - backgroundImage = new Image(0, 0, consoleSize.X, consoleSize.Y); - if (BackgroundTexture != null) - { - backgroundImage.Brush = new TextureBrush(BackgroundTexture); - - } - else - { - backgroundImage.Brush = new SolidColorBrush(BackgroundColor); - backgroundImage.KeepAspectRatio = false; - } - - var locationFix = backgroundImage.Location; - var parentControl = rootControl.AddChild(); - parentControl.Name = "ConsoleBackground"; - parentControl.Control = backgroundImage; - backgroundImage.Location = locationFix; // workaround to UIControl.Control overriding the old position - backgroundImage.Enabled = false; - } - // Create a container that keeps the focus in the input box when clicked outside the console window. // The container must be created before the content box so interacting with the console lines wont get // stolen by this container. - var containerControl = new ConsoleContainerControl(0, 0, screenSize.X, screenSize.Y); - var focusControl = rootControl.AddChild(); + var containerControl = new ConsoleContainerControl(new Rectangle()); + containerControl.SetAnchorPreset(AnchorPresets.StretchAll, false); + /*var focusControl = rootControl.AddChild(); focusControl.Name = "ConsoleInputContainer"; - focusControl.Control = containerControl; + focusControl.Control = containerControl;*/ + var focusControl = new UIControl() + { + Parent = rootControl, + Name = "ConsoleInputContainer", + Control = containerControl + }; + + var contentContainer = new VerticalPanel() + { + AutoSize = true, + Margin = Margin.Zero, + Spacing = 0, + Bounds = new Rectangle(), + BackgroundColor = BackgroundColor + }; + contentContainer.SetAnchorPreset(AnchorPresets.StretchAll, true); + + + var contentContainerControl = rootControl.AddChild(); + contentContainerControl.Name = "ContentContainer"; + contentContainerControl.Control = contentContainer; { if (consoleBox == null) { - consoleBox = new ConsoleContentTextBox(null, 0, 0, consoleSize.X, consoleSize.Y - fontHeight); + //consoleBox = new ConsoleContentTextBox(null, 0, 0, consoleSize.X, consoleSize.Y - fontHeight); + consoleBox = new ConsoleContentTextBox(null, 0, 0, 0, 0); + + + consoleBox.SetAnchorPreset(AnchorPresets.HorizontalStretchTop, false); + //consoleBox.AnchorMax = new Vector2(1.0f, ConsoleHeight); + consoleBox.Height = consoleSize.Y - fontHeight; consoleBox.Font = fontReference; //consoleBox.HorizontalAlignment = TextAlignment.Near; //consoleBox.VerticalAlignment = TextAlignment.Near; + consoleBox.HeightMultiplier = ConsoleHeight; consoleBox.Wrapping = TextWrapping.WrapWords; consoleBox.BackgroundColor = Color.Transparent; consoleBox.BackgroundSelectedColor = Color.Transparent; @@ -124,7 +133,7 @@ namespace Cabrito } var locationFix = consoleBox.Location; - var parentControl = rootControl.AddChild(); + var parentControl = contentContainerControl.AddChild(); parentControl.Name = "ConsoleContent"; parentControl.Control = consoleBox; consoleBox.Location = locationFix; // workaround to UIControl.Control overriding the old position @@ -133,7 +142,12 @@ namespace Cabrito { if (consoleInputBox == null) { - consoleInputBox = new ConsoleInputTextBox(consoleBox, 0, consoleSize.Y - fontHeight, consoleSize.X, fontHeight); + //consoleInputBox = new ConsoleInputTextBox(consoleBox, 0, consoleSize.Y - fontHeight, consoleSize.X, fontHeight); + consoleInputBox = new ConsoleInputTextBox(consoleBox, 0, 0, 0, 0); + consoleInputBox.SetAnchorPreset(AnchorPresets.HorizontalStretchTop, false); + //consoleInputBox.Location = new Vector2(0, consoleSize.Y - fontHeight); + consoleInputBox.Height = fontHeight; + consoleInputBox.Font = fontReference; consoleBox.inputBox = consoleInputBox; @@ -147,7 +161,7 @@ namespace Cabrito containerControl.inputBox = consoleInputBox; var locationFix = consoleInputBox.Location; - var parentControl = rootControl.AddChild(); + var parentControl = contentContainerControl.AddChild(); parentControl.Name = "ConsoleInput"; parentControl.Control = consoleInputBox; consoleInputBox.Location = locationFix; // workaround to UIControl.Control overriding the old position @@ -259,8 +273,6 @@ namespace Cabrito //consoleInputEvent.Triggered -= OnConsoleInputEvent; consoleInputEvent?.Dispose(); consoleBox?.Dispose(); - backgroundImage?.DisposeChildren(); - backgroundImage?.Dispose(); Debug.Logger.LogHandler.SendLog -= OnSendLog; Debug.Logger.LogHandler.SendExceptionLog -= OnSendExceptionLog; @@ -271,7 +283,21 @@ namespace Cabrito if (consoleBox == null || consoleInputBox == null) return; - float fontHeight = consoleBox.GetFontHeight(); + //consoleBox.SetAnchorPreset(AnchorPresets.StretchAll, true); + //consoleBox.AnchorMax = new Vector2(1.0f, ConsoleHeight); + + + Vector2 screenSize = Screen.Size; + Vector2 consoleSize = new Vector2(screenSize.X, screenSize.Y * ConsoleHeight); + + //consoleBox.Height = consoleSize.Y - consoleBox.GetFontHeight(); + + //consoleInputBox.SetAnchorPreset(AnchorPresets.HorizontalStretchTop, true); + //consoleInputBox.Location = new Vector2(0, consoleBox.Bottom); + //Font fontRaw = consoleBox.Font.GetFont(); + //consoleBox.Height -= fontRaw.Height; + + /*float fontHeight = consoleBox.GetFontHeight(); Vector2 screenSize = Screen.Size; Vector2 consoleSize = new Vector2(screenSize.X, screenSize.Y * ConsoleHeight); @@ -279,7 +305,7 @@ namespace Cabrito consoleInputBox.Location = new Vector2(0, consoleBox.Height); consoleInputBox.Height = fontHeight; - consoleInputBox.ScrollToCaret(); + consoleInputBox.ScrollToCaret();*/ } private void OnConsoleInputEvent() diff --git a/Source/Game/PlayerMovement.cs b/Source/Game/PlayerMovement.cs index 3c67c3e..fef9868 100644 --- a/Source/Game/PlayerMovement.cs +++ b/Source/Game/PlayerMovement.cs @@ -20,35 +20,35 @@ namespace Game public override void OnAwake() { base.OnAwake(); - /* + onExit.Triggered += () => { if (Console.IsSafeToQuit) Engine.RequestExit(); }; - rootActor = Actor.GetChild(0);*/ + rootActor = Actor.GetChild(0); } public override void OnDestroy() { - /*base.OnDestroy(); + base.OnDestroy(); - onExit.Dispose();*/ + onExit.Dispose(); } public override void OnStart() { - /*var initialEulerAngles = Actor.Orientation.EulerAngles; + var initialEulerAngles = Actor.Orientation.EulerAngles; viewPitch = initialEulerAngles.X; viewYaw = initialEulerAngles.Y; - viewRoll = initialEulerAngles.Z;*/ + viewRoll = initialEulerAngles.Z; } Vector3 wishVelocity = new Vector3(0); public override void OnFixedUpdate() { - /*if (Console.IsOpen) + if (Console.IsOpen) return; var camera = rootActor.GetChild(); @@ -87,12 +87,12 @@ namespace Game rigidBody.LinearVelocity += accel; //rigidBody.LinearVelocity = wishVelocity; //rigidBody.LinearVelocity /= Time.DeltaTime; - */ + } public override void OnUpdate() { - /*float xAxis = InputManager.GetAxis("Mouse X"); + float xAxis = InputManager.GetAxis("Mouse X"); float yAxis = InputManager.GetAxis("Mouse Y"); if (xAxis != 0.0f || yAxis != 0.0f) { @@ -110,7 +110,7 @@ namespace Game camera.Transform = camTrans; rootActor.Transform = rootTrans; - }*/ + } } } }