diff --git a/assets/Shaders/rectangle.frag b/assets/Shaders/rectangle.frag index 722f3e2f2..04ccf1fdd 100644 --- a/assets/Shaders/rectangle.frag +++ b/assets/Shaders/rectangle.frag @@ -1,17 +1,39 @@ #version 150 core in vec2 textureCoord; +in vec2 fragOffset; uniform vec2 uAlphaTest; uniform bool uRectangleHasColour; uniform vec4 uColor; uniform sampler2D uTexture; +uniform vec2 uSize; +uniform float uCornerRadius; out vec4 fragColor; +float roundSDF(vec2 p, vec2 b, float r) +{ + vec2 q = abs(p) - b + r; + return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - r; +} + void main(void) { vec4 textureColour = texture(uTexture, textureCoord); - vec4 finalColor = textureColour * uColor; + if (uCornerRadius > 0.0) + { + vec2 halfSize = uSize * 0.5; + vec2 pos = (fragOffset - 0.5) * uSize; + float dist = roundSDF(pos, halfSize, uCornerRadius); + + float alpha = 1.0 - smoothstep(-0.5, 0.5, dist); + if (alpha <= 0.0) + { + discard; + } + finalColor.a *= alpha; + } + /* * NOTES: * Unused alpha functions must not be added to the shader diff --git a/assets/Shaders/rectangle.vert b/assets/Shaders/rectangle.vert index 49ece19d9..5bf4d2221 100644 --- a/assets/Shaders/rectangle.vert +++ b/assets/Shaders/rectangle.vert @@ -5,40 +5,24 @@ uniform vec2 uPoint; uniform vec2 uSize; uniform vec2 uCoordinates; out vec2 textureCoord; -vec4 viewPos = vec4(0,0,0,0); +out vec2 fragOffset; + +// Offset lookup table to map gl_VertexID to quad corners without branching +const vec2 offsets[6] = vec2[]( + vec2(0.0, 0.0), // Top-left + vec2(1.0, 0.0), // Top-right + vec2(1.0, 1.0), // Bottom-right + vec2(0.0, 0.0), // Top-left (second triangle) + vec2(0.0, 1.0), // Bottom-left + vec2(1.0, 1.0) // Bottom-right +); void main() { - if(gl_VertexID == 0) - { - viewPos = uCurrentModelViewMatrix * vec4(vec3(uPoint.x, uPoint.y, 0), 1.0); - textureCoord = vec2(0,0); - } - else if (gl_VertexID == 1) - { - viewPos = uCurrentModelViewMatrix * vec4(vec3(uPoint.x + uSize.x, uPoint.y, 0), 1.0); - textureCoord = vec2(uCoordinates.x,0); - } - else if (gl_VertexID == 2) - { - viewPos = uCurrentModelViewMatrix * vec4(vec3(uPoint.x + uSize.x, uPoint.y + uSize.y, 0), 1.0); - textureCoord = uCoordinates; - } - else if (gl_VertexID == 3) - { - viewPos = uCurrentModelViewMatrix * vec4(vec3(uPoint.x, uPoint.y, 0), 1.0); - textureCoord = vec2(0,0); - } - else if (gl_VertexID == 4) - { - viewPos = uCurrentModelViewMatrix * vec4(vec3(uPoint.x, uPoint.y + uSize.y, 0), 1.0); - textureCoord = vec2(0, uCoordinates.y); - } - else if (gl_VertexID == 5) - { - viewPos = uCurrentModelViewMatrix * vec4(vec3(uPoint.x + uSize.x, uPoint.y + uSize.y, 0), 1.0); - textureCoord = uCoordinates; - } - + // Calculate vertex position and texture coordinates based on current vertex ID offsets + vec2 offset = offsets[gl_VertexID]; + vec4 viewPos = uCurrentModelViewMatrix * vec4(uPoint + offset * uSize, 0.0, 1.0); + textureCoord = offset * uCoordinates; + fragOffset = offset; gl_Position = uCurrentProjectionMatrix * viewPos; } diff --git a/source/LibRender2/BaseRenderer.cs b/source/LibRender2/BaseRenderer.cs index 57f4ca951..a11e781e5 100644 --- a/source/LibRender2/BaseRenderer.cs +++ b/source/LibRender2/BaseRenderer.cs @@ -27,6 +27,7 @@ using OpenBveApi.FileSystem; using OpenBveApi.Hosts; using OpenBveApi.Interface; +using OpenBveApi.Graphics; using OpenBveApi.Math; using OpenBveApi.Objects; using OpenBveApi.Routes; @@ -42,7 +43,7 @@ namespace LibRender2 { - public abstract class BaseRenderer + public abstract class BaseRenderer : OpenBveApi.Graphics.IGLRenderer { // constants protected const float inv255 = 1.0f / 255.0f; @@ -1873,5 +1874,29 @@ public void RunInRenderThread(ThreadStart job, int timeout) Monitor.Wait(job, timeout); } } + + /// + public bool LoadTexture(ref Texture texture, OpenGlTextureWrapMode wrapMode) + { + return currentHost.LoadTexture(ref texture, wrapMode); + } + + /// + public void DrawRectangle(Texture texture, Vector2 location, Vector2 size, Color128 color, OpenGlTextureWrapMode? wrapMode = null, float cornerRadius = 0f) + { + Rectangle.Draw(texture, location, size, color, null, wrapMode, cornerRadius); + } + + /// + public void DrawRectangleAlpha(Texture texture, Vector2 location, Vector2 size, Color128 color, Vector2 scale, OpenGlTextureWrapMode? wrapMode = null, float cornerRadius = 0f) + { + Rectangle.DrawAlpha(texture, location, size, color, scale, wrapMode, cornerRadius); + } + + /// + public void DrawText(string text, Vector2 location, Color128 color) + { + OpenGlString.Draw(Fonts.NormalFont, text, location, TextAlignment.TopLeft, color); + } } } diff --git a/source/LibRender2/LibRender2.csproj b/source/LibRender2/LibRender2.csproj index dcea6d70e..482595deb 100644 --- a/source/LibRender2/LibRender2.csproj +++ b/source/LibRender2/LibRender2.csproj @@ -100,6 +100,7 @@ + diff --git a/source/LibRender2/Primitives/Button.cs b/source/LibRender2/Primitives/Button.cs index cff490b7d..2d4946ce0 100644 --- a/source/LibRender2/Primitives/Button.cs +++ b/source/LibRender2/Primitives/Button.cs @@ -1,4 +1,4 @@ -//Simplified BSD License (BSD-2-Clause) +//Simplified BSD License (BSD-2-Clause) // //Copyright (c) 2023, Christopher Lees, The OpenBVE Project // @@ -38,7 +38,7 @@ public string Text set { _text = value; - Size = Font.MeasureString(Text) * 1.5 * Renderer.currentOptions.UserInterfaceScaleFactor; + Size = Font.MeasureString(Text) * 1.5 * baseRenderer.currentOptions.UserInterfaceScaleFactor; } } @@ -57,9 +57,11 @@ public string Text /// The font for the button public OpenGlFont Font; - public Button(BaseRenderer renderer, string text) : base(renderer) + private BaseRenderer baseRenderer => Renderer as BaseRenderer; + + public Button(IGLRenderer renderer, string text) : base(renderer) { - Font = Renderer.Fonts.LargeFont; + Font = baseRenderer.Fonts.LargeFont; Text = text; Enabled = true; // default colors to match GLMenu @@ -75,12 +77,12 @@ public override void Draw() { return; } - Renderer.Rectangle.Draw(Texture, Location, Size, BackgroundColor); + baseRenderer.Rectangle.Draw(Texture, Location, Size, BackgroundColor, null, null, CornerRadius); if (CurrentlySelected && Enabled) { - Renderer.Rectangle.Draw(Texture, Location + Size * 0.1, Size - (Size * 0.2), HighlightColor); + baseRenderer.Rectangle.Draw(Texture, Location + Size * 0.1, Size - (Size * 0.2), HighlightColor, null, null, CornerRadius * 0.8f); } - Renderer.OpenGlString.Draw(Font, Text, Location + (Size * 0.15), TextAlignment.TopLeft, Enabled ? EnabledTextColor : DisabledTextColor); + baseRenderer.OpenGlString.Draw(Font, Text, Location + (Size * 0.15), TextAlignment.TopLeft, Enabled ? EnabledTextColor : DisabledTextColor); } public override void MouseMove(int x, int y) diff --git a/source/LibRender2/Primitives/GLControl.cs b/source/LibRender2/Primitives/GLControl.cs index 43ff49f02..cb691484a 100644 --- a/source/LibRender2/Primitives/GLControl.cs +++ b/source/LibRender2/Primitives/GLControl.cs @@ -1,4 +1,4 @@ -//Simplified BSD License (BSD-2-Clause) +//Simplified BSD License (BSD-2-Clause) // //Copyright (c) 2023, Christopher Lees, The OpenBVE Project // @@ -24,6 +24,7 @@ using System; using OpenBveApi.Colors; +using OpenBveApi.Graphics; using OpenBveApi.Math; using OpenBveApi.Textures; @@ -32,8 +33,8 @@ namespace LibRender2.Primitives /// An abstract OpenGL based control public abstract class GLControl { - /// Holds a reference to the base renderer - internal readonly BaseRenderer Renderer; + /// Holds a reference to the base renderer interface + public readonly IGLRenderer Renderer; /// The background color for the control public Color128 BackgroundColor; /// The texture for the control @@ -42,6 +43,8 @@ public abstract class GLControl public Vector2 Location; /// The stored size for the control public Vector2 Size; + /// The corner radius for rounded corners (in pixels) + public float CornerRadius; /// Whether the control is currently selected by the mouse public bool CurrentlySelected; /// The event handler for the OnClick event @@ -49,7 +52,7 @@ public abstract class GLControl /// Whether the control is currently visible public bool IsVisible; - protected GLControl(BaseRenderer renderer) + protected GLControl(IGLRenderer renderer) { Renderer = renderer; } diff --git a/source/LibRender2/Primitives/Label.cs b/source/LibRender2/Primitives/Label.cs index 710fbc4a6..8601267d2 100644 --- a/source/LibRender2/Primitives/Label.cs +++ b/source/LibRender2/Primitives/Label.cs @@ -1,4 +1,4 @@ -//Simplified BSD License (BSD-2-Clause) +//Simplified BSD License (BSD-2-Clause) // //Copyright (c) 2022, Christopher Lees, The OpenBVE Project // @@ -37,10 +37,12 @@ public class Label : GLControl /// The font for the label public OpenGlFont Font; - public Label(BaseRenderer renderer, string text) : base(renderer) + private BaseRenderer baseRenderer => Renderer as BaseRenderer; + + public Label(IGLRenderer renderer, string text) : base(renderer) { Text = text; - Font = Renderer.Fonts.LargeFont; + Font = baseRenderer.Fonts.LargeFont; Size = Font.MeasureString(Text) * 1.5; // default colors to match GLMenu BackgroundColor = Color128.Black; @@ -49,8 +51,8 @@ public Label(BaseRenderer renderer, string text) : base(renderer) public override void Draw() { - Renderer.Rectangle.Draw(Texture, Location, Size, BackgroundColor); - Renderer.OpenGlString.Draw(Font, Text, Location + (Size * 0.15), TextAlignment.TopLeft, TextColor); + baseRenderer.Rectangle.Draw(Texture, Location, Size, BackgroundColor, null, null, CornerRadius); + baseRenderer.OpenGlString.Draw(Font, Text, Location + (Size * 0.15), TextAlignment.TopLeft, TextColor); } } } diff --git a/source/LibRender2/Primitives/Picturebox.cs b/source/LibRender2/Primitives/Picturebox.cs index 986db85fe..21fddc4a5 100644 --- a/source/LibRender2/Primitives/Picturebox.cs +++ b/source/LibRender2/Primitives/Picturebox.cs @@ -1,4 +1,5 @@ using OpenBveApi.Colors; +using OpenBveApi.Graphics; using OpenBveApi.Math; using OpenBveApi.Textures; using OpenTK.Graphics.OpenGL; @@ -13,14 +14,14 @@ public class Picturebox : GLControl private bool flipX; private bool flipY; - public Picturebox(BaseRenderer renderer) : base(renderer) + public Picturebox(IGLRenderer renderer) : base(renderer) { SizeMode = ImageSizeMode.Zoom; } public override void Draw() { - if (!Renderer.currentHost.LoadTexture(ref Texture, OpenGlTextureWrapMode.ClampClamp)) + if (!Renderer.LoadTexture(ref Texture, OpenGlTextureWrapMode.ClampClamp)) { return; } @@ -31,7 +32,7 @@ public override void Draw() { case ImageSizeMode.Normal: //Draw box containing backing color first - Renderer.Rectangle.Draw(Texture, Location, Size, BackgroundColor); + Renderer.DrawRectangle(Texture, Location, Size, BackgroundColor); //Calculate the new size newSize = Texture.Size; if (newSize.X > Size.X) @@ -44,11 +45,11 @@ public override void Draw() newSize.Y = Size.Y; } //Two-pass draw the texture in appropriate place - Renderer.Rectangle.DrawAlpha(Texture, Location, newSize, Color128.White, new Vector2(newSize / Size)); + Renderer.DrawRectangleAlpha(Texture, Location, newSize, Color128.White, new Vector2(newSize / Size)); break; case ImageSizeMode.Center: //Draw box containing backing color first - Renderer.Rectangle.Draw(Texture, Location, Size, BackgroundColor); + Renderer.DrawRectangle(Texture, Location, Size, BackgroundColor); //Calculate the new size newSize = Texture.Size; if (newSize.X > Size.X) @@ -61,15 +62,15 @@ public override void Draw() newSize.Y = Size.Y; } //Two-pass draw the texture in appropriate place - Renderer.Rectangle.DrawAlpha(Texture, Location + new Vector2(newSize - Size) / 2, newSize, Color128.White, new Vector2(newSize / Size)); + Renderer.DrawRectangleAlpha(Texture, Location + new Vector2(newSize - Size) / 2, newSize, Color128.White, new Vector2(newSize / Size)); break; case ImageSizeMode.Stretch: //No need to draw a backing color box as texture covers the whole thing - Renderer.Rectangle.Draw(Texture, Location, Size, BackgroundColor); + Renderer.DrawRectangle(Texture, Location, Size, BackgroundColor); break; case ImageSizeMode.Zoom: //Draw box containing backing color first - Renderer.Rectangle.Draw(null, Location, Size, BackgroundColor); + Renderer.DrawRectangle(null, Location, Size, BackgroundColor); //Calculate the new size Vector2 ratio = Size / Texture.Size; double newRatio = ratio.X < ratio.Y ? ratio.X : ratio.Y; @@ -84,7 +85,7 @@ public override void Draw() { wrapMode = wrapMode == OpenGlTextureWrapMode.RepeatClamp ? OpenGlTextureWrapMode.RepeatRepeat : OpenGlTextureWrapMode.ClampRepeat; } - Renderer.Rectangle.DrawAlpha(Texture, new Vector2(Location.X + (Size.X - newSize.X) / 2,Location.Y + (Size.Y - newSize.Y) / 2), newSize, Color128.White, new Vector2(flipX ? -1 : 1,flipY ? -1 : 1), wrapMode); + Renderer.DrawRectangleAlpha(Texture, new Vector2(Location.X + (Size.X - newSize.X) / 2,Location.Y + (Size.Y - newSize.Y) / 2), newSize, Color128.White, new Vector2(flipX ? -1 : 1,flipY ? -1 : 1), wrapMode); break; } } diff --git a/source/LibRender2/Primitives/Rectangle.cs b/source/LibRender2/Primitives/Rectangle.cs index 93f096506..80f85b3a6 100644 --- a/source/LibRender2/Primitives/Rectangle.cs +++ b/source/LibRender2/Primitives/Rectangle.cs @@ -60,16 +60,17 @@ internal Rectangle(BaseRenderer renderer) /// The color, or a null reference. /// The texture coordinates to be applied /// A wrap mode if overriding that of the texture - public void DrawAlpha(Texture texture, Vector2 point, Vector2 size, Color128? color = null, Vector2? textureCoordinates = null, OpenGlTextureWrapMode? wrapMode = null) + /// Corner radius in pixels for rounded corners + public void DrawAlpha(Texture texture, Vector2 point, Vector2 size, Color128? color = null, Vector2? textureCoordinates = null, OpenGlTextureWrapMode? wrapMode = null, float cornerRadius = 0f) { renderer.UnsetBlendFunc(); renderer.SetAlphaFunc(AlphaFunction.Equal, 1.0f); GL.DepthMask(true); - Draw(texture, point, size, color, textureCoordinates, wrapMode); + Draw(texture, point, size, color, textureCoordinates, wrapMode, cornerRadius); renderer.SetBlendFunc(); renderer.SetAlphaFunc(AlphaFunction.Less, 1.0f); GL.DepthMask(false); - Draw(texture, point, size, color, textureCoordinates, wrapMode); + Draw(texture, point, size, color, textureCoordinates, wrapMode, cornerRadius); renderer.SetAlphaFunc(AlphaFunction.Equal, 1.0f); } @@ -102,17 +103,18 @@ public void DrawAlpha(Texture texture, Vector2 point, Color128? color = null, Ve /// The color, or a null reference. /// The texture coordinates to be applied /// A wrap mode if overriding that of the texture - public void Draw(Texture texture, Vector2 point, Vector2 size, Color128? color = null, Vector2? textureCoordinates = null, OpenGlTextureWrapMode? wrapMode = null) + /// Corner radius in pixels for rounded corners + public void Draw(Texture texture, Vector2 point, Vector2 size, Color128? color = null, Vector2? textureCoordinates = null, OpenGlTextureWrapMode? wrapMode = null, float cornerRadius = 0f) { if (renderer.AvailableNewRenderer && Shader != null) { if (textureCoordinates == null) { - DrawWithShader(texture, point, size, color, Vector2.One, wrapMode); + DrawWithShader(texture, point, size, color, Vector2.One, wrapMode, cornerRadius); } else { - DrawWithShader(texture, point, size, color, (Vector2)textureCoordinates, wrapMode); + DrawWithShader(texture, point, size, color, (Vector2)textureCoordinates, wrapMode, cornerRadius); } } else @@ -234,7 +236,7 @@ private void DrawImmediate(Texture texture, Vector2 point, Vector2 size, Color12 GL.PopMatrix(); } - private void DrawWithShader(Texture texture, Vector2 point, Vector2 size, Color128? color, Vector2 coordinates, OpenGlTextureWrapMode? wrapMode = null) + private void DrawWithShader(Texture texture, Vector2 point, Vector2 size, Color128? color, Vector2 coordinates, OpenGlTextureWrapMode? wrapMode = null, float cornerRadius = 0f) { Shader.Activate(); if (wrapMode == null) @@ -258,6 +260,7 @@ private void DrawWithShader(Texture texture, Vector2 point, Vector2 size, Color1 Shader.SetPoint(point); Shader.SetSize(size); Shader.SetCoordinates(coordinates); + Shader.SetCornerRadius(cornerRadius); /* * In order to call GL.DrawArrays with procedural data within the shader, * we first need to bind a dummy VAO diff --git a/source/LibRender2/Primitives/Textbox.cs b/source/LibRender2/Primitives/Textbox.cs index 0d224d2a0..e12cf9406 100644 --- a/source/LibRender2/Primitives/Textbox.cs +++ b/source/LibRender2/Primitives/Textbox.cs @@ -86,7 +86,9 @@ private List WrappedLines(int width) return wrappedLines; } - public Textbox(BaseRenderer Renderer, OpenGlFont Font, Color128 FontColor, Color128 backgroundColor) : base(Renderer) + private BaseRenderer baseRenderer => Renderer as BaseRenderer; + + public Textbox(IGLRenderer Renderer, OpenGlFont Font, Color128 FontColor, Color128 backgroundColor) : base(Renderer) { myFont = Font; myFontColor = FontColor; @@ -108,7 +110,7 @@ public void VerticalScroll(int numberOfLines) public override void Draw() { - Renderer.Rectangle.Draw(Texture, Location, Size, BackgroundColor); //Draw the backing rectangle first + baseRenderer.Rectangle.Draw(Texture, Location, Size, BackgroundColor); //Draw the backing rectangle first if (string.IsNullOrEmpty(Text)) { return; @@ -118,7 +120,7 @@ public override void Draw() if (splitString.Count == 1) { //DRAW SINGLE LINE - Renderer.OpenGlString.Draw(myFont, Text, new Vector2(Location.X + Border, Location.Y + Border), TextAlignment.TopLeft, myFontColor); + baseRenderer.OpenGlString.Draw(myFont, Text, new Vector2(Location.X + Border, Location.Y + Border), TextAlignment.TopLeft, myFontColor); CanScroll = false; } else @@ -131,14 +133,14 @@ public override void Draw() CanScroll = maxFittingLines < splitString.Count; if (CanScroll) { - Renderer.Rectangle.Draw(null, new Vector2(Location.X + Size.X - 12, Location.Y + 2), new Vector2(8, Size.Y - 4), Color128.Grey); //Backing rectangle + baseRenderer.Rectangle.Draw(null, new Vector2(Location.X + Size.X - 12, Location.Y + 2), new Vector2(8, Size.Y - 4), Color128.Grey); //Backing rectangle } //DRAW SPLIT LINES int currentLine = topLine; int bottomLine = Math.Min(maxFittingLines, splitString.Count); for (int i = 0; i < bottomLine; i++) { - Renderer.OpenGlString.Draw(myFont, splitString[currentLine], new Vector2(Location.X + Border, Location.Y + Border + myFont.FontSize * i), TextAlignment.TopLeft, myFontColor); + baseRenderer.OpenGlString.Draw(myFont, splitString[currentLine], new Vector2(Location.X + Border, Location.Y + Border + myFont.FontSize * i), TextAlignment.TopLeft, myFontColor); currentLine++; } @@ -146,7 +148,7 @@ public override void Draw() { double scrollBarHeight = (Size.Y - 4) * maxFittingLines / splitString.Count; double percentageScroll = topLine / (double)(splitString.Count - maxFittingLines); - Renderer.Rectangle.Draw(null, new Vector2(Location.X + Size.X - 13, Location.Y + (Size.Y - scrollBarHeight) * percentageScroll), new Vector2(10, scrollBarHeight), myScrollbarColor); + baseRenderer.Rectangle.Draw(null, new Vector2(Location.X + Size.X - 13, Location.Y + (Size.Y - scrollBarHeight) * percentageScroll), new Vector2(10, scrollBarHeight), myScrollbarColor); } } @@ -157,11 +159,11 @@ public override void MouseMove(int x, int y) if (x > Location.X && x < Location.X + Size.X && y > Location.Y && y < Location.Y + Size.Y) { CurrentlySelected = true; - Renderer.SetCursor(CanScroll ? AvailableCursors.ScrollCursor : OpenTK.MouseCursor.Default); + baseRenderer.SetCursor(CanScroll ? AvailableCursors.ScrollCursor : OpenTK.MouseCursor.Default); } else { - Renderer.SetCursor(OpenTK.MouseCursor.Default); + baseRenderer.SetCursor(OpenTK.MouseCursor.Default); CurrentlySelected = false; } } diff --git a/source/LibRender2/Primitives/VerticalLayoutGroup.cs b/source/LibRender2/Primitives/VerticalLayoutGroup.cs new file mode 100644 index 000000000..50140bf33 --- /dev/null +++ b/source/LibRender2/Primitives/VerticalLayoutGroup.cs @@ -0,0 +1,90 @@ +using System.Collections.Generic; +using OpenBveApi.Graphics; +using OpenBveApi.Math; + +namespace LibRender2.Primitives +{ + /// A container control that automatically positions its children vertically + public class VerticalLayoutGroup : GLControl + { + /// The child controls of this layout group + public readonly List Children = new List(); + + /// The vertical spacing between child controls + public double Spacing = 10.0; + + /// The padding inside the layout group borders + public Vector2 Padding = new Vector2(10.0, 10.0); + + /// Creates a new VerticalLayoutGroup + public VerticalLayoutGroup(IGLRenderer renderer) : base(renderer) + { + } + + /// Draws the layout group and positions/draws all visible children + public override void Draw() + { + if (!IsVisible) + { + return; + } + + // Draw background if background color is set and size is non-zero + if (BackgroundColor.A > 0.0f && Size.X > 0f && Size.Y > 0f) + { + Renderer.DrawRectangle(Texture, Location, Size, BackgroundColor, null, (float)CornerRadius); + } + + double currentY = Location.Y + Padding.Y; + foreach (var child in Children) + { + if (!child.IsVisible) + { + continue; + } + + child.Location.X = Location.X + Padding.X; + child.Location.Y = currentY; + child.Size.X = Size.X - (Padding.X * 2); + + child.Draw(); + + currentY += child.Size.Y + Spacing; + } + } + + /// Passes mouse down events to children + public override void MouseDown(int x, int y) + { + if (!IsVisible) + { + return; + } + + foreach (var child in Children) + { + if (child.IsVisible) + { + child.MouseDown(x, y); + } + } + } + + /// Passes mouse move events to children + public override void MouseMove(int x, int y) + { + if (!IsVisible) + { + return; + } + + foreach (var child in Children) + { + if (child.IsVisible) + { + child.MouseMove(x, y); + } + } + } + } +} diff --git a/source/LibRender2/Shaders/Shader.cs b/source/LibRender2/Shaders/Shader.cs index d2a97bd39..dd59fb947 100644 --- a/source/LibRender2/Shaders/Shader.cs +++ b/source/LibRender2/Shaders/Shader.cs @@ -67,6 +67,7 @@ public class Shader : AbstractShader private readonly int uLightSpaceMatrix3Location; private readonly int uModelMatrixLocation; private readonly int uCurrentViewMatrixLocation; + private readonly int uCornerRadiusLocation; /// @@ -103,6 +104,7 @@ public Shader(BaseRenderer Renderer, string vertexShaderName, string fragmentSha uLightSpaceMatrix3Location = GL.GetUniformLocation(Handle, "uLightSpaceMatrix3"); uModelMatrixLocation = GL.GetUniformLocation(Handle, "uModelMatrix"); uCurrentViewMatrixLocation = GL.GetUniformLocation(Handle, "uCurrentViewMatrix"); + uCornerRadiusLocation = GL.GetUniformLocation(Handle, "uCornerRadius"); VertexLayout = GetVertexLayout(); UniformLayout = GetUniformLayout(); @@ -399,6 +401,11 @@ public void SetSize(Vector2 size) GL.ProgramUniform2(Handle, UniformLayout.Size, (float)size.X, (float) size.Y); } + public void SetCornerRadius(float radius) + { + GL.ProgramUniform1(Handle, uCornerRadiusLocation, radius); + } + public void SetColor(Color128 color) { GL.ProgramUniform4(Handle, UniformLayout.Color, color.R, color.G, color.B, color.A); diff --git a/source/OpenBveApi/Graphics/IGLRenderer.cs b/source/OpenBveApi/Graphics/IGLRenderer.cs new file mode 100644 index 000000000..9487790ee --- /dev/null +++ b/source/OpenBveApi/Graphics/IGLRenderer.cs @@ -0,0 +1,22 @@ +using OpenBveApi.Colors; +using OpenBveApi.Math; +using OpenBveApi.Textures; + +namespace OpenBveApi.Graphics +{ + /// Defines a platform-independent interface for basic 2D drawing capabilities + public interface IGLRenderer + { + /// Loads a texture into the graphics device + bool LoadTexture(ref Texture texture, OpenGlTextureWrapMode wrapMode); + + /// Draws a simple solid-colored rectangle or textured rectangle + void DrawRectangle(Texture texture, Vector2 location, Vector2 size, Color128 color, OpenGlTextureWrapMode? wrapMode = null, float cornerRadius = 0f); + + /// Draws a rectangle with alpha scaling + void DrawRectangleAlpha(Texture texture, Vector2 location, Vector2 size, Color128 color, Vector2 scale, OpenGlTextureWrapMode? wrapMode = null, float cornerRadius = 0f); + + /// Draws text on screen + void DrawText(string text, Vector2 location, Color128 color); + } +} diff --git a/source/OpenBveApi/OpenBveApi.csproj b/source/OpenBveApi/OpenBveApi.csproj index c75e05d79..2a96e8784 100644 --- a/source/OpenBveApi/OpenBveApi.csproj +++ b/source/OpenBveApi/OpenBveApi.csproj @@ -118,6 +118,7 @@ +