Implemented a quick and dirty FPS graph, other small refactorings.

This commit is contained in:
2025-06-04 04:52:19 -05:00
parent 7ac0436a1f
commit 48b56213d8
9 changed files with 150 additions and 29 deletions

View File

@@ -36,6 +36,12 @@ endif()
set_target_properties(JUI PROPERTIES LINKER_LANGUAGE CXX)
CPMAddPackage(
NAME mcolor
URL https://git.redacted.cc/maxine/mcolor/archive/Prerelease-7.4.zip
)
CPMAddPackage(
NAME Event
URL https://git.redacted.cc/josh/Event/archive/Release-12.zip
@@ -46,12 +52,6 @@ CPMAddPackage(
URL https://git.redacted.cc/josh/jlog/archive/Prerelease-18.zip
)
CPMAddPackage(
NAME mcolor
URL https://git.redacted.cc/maxine/mcolor/archive/Prerelease-7.2.zip
)
CPMAddPackage(
NAME J3ML
URL https://git.redacted.cc/josh/j3ml/archive/3.4.5.zip
@@ -59,7 +59,7 @@ CPMAddPackage(
CPMAddPackage(
NAME ReWindow
URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-32.zip
URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-33.zip
)
CPMAddPackage(

View File

@@ -14,6 +14,7 @@
#include <Color4.hpp>
#include <J3ML/LinearAlgebra/Vector2.hpp>
#include <JGL/types/Texture.h>
#include <JGL/types/RenderTarget.h>
using J3ML::LinearAlgebra::Vector2;
@@ -27,11 +28,15 @@ namespace JUI {
public:
/// The default constructor initializes this ImageBase with a null pointer texture.
ImageBase();
ImageBase(JGL::RenderTarget *content);
/// This constructor initializes this ImageBase with a JGL::Texture pointer.
explicit ImageBase(JGL::Texture* texture);
public:
[[nodiscard]] JGL::RenderTarget* RenderTarget() const { return texture;}
/// Returns the texture pointer held by this object.
[[nodiscard]] JGL::Texture* Content() const;
[[nodiscard]] const JGL::Texture* Content() const;
/// Returns the color of this object. The texture is rendered with this color.
[[nodiscard]] Color4 Color() const;
/// Returns the scale factor of this object. The texture is scaled with this value.
@@ -40,7 +45,8 @@ namespace JUI {
[[nodiscard]] Vector2 Origin() const;
/// Sets the texture of this object.
void Content(JGL::Texture* content);
void Content(const JGL::Texture* content);
void Content(JGL::RenderTarget* content);
/// Sets the color of this object.
void Color(const Color4& newColor);
/// Sets the scale factor of this object.
@@ -52,7 +58,7 @@ namespace JUI {
/// Draws the image at the given pos, manually scaled to fit the given size.
void Draw(const Vector2& pos, const Vector2& size);
protected:
JGL::Texture* texture;
JGL::RenderTarget* texture;
Color4 image_color = Color4(255,255,255);
Vector2 scale = Vector2(1,1);
Vector2 origin = Vector2(0,0);

View File

@@ -0,0 +1,93 @@
#pragma once
#include "Rect.hpp"
#include "ImageRect.hpp"
namespace JUI {
struct DataPoint {
Vector2 pos;
Color4 color;
};
class Graph : public JUI::ImageRect {
public:
protected:
private:
};
class FpsGraph : public JUI::ImageRect
{
public:
void RenderDataPoints() {
J2D::Begin(canvas, true);
DataPoint prev = data[0];
for (auto& data_pt : data) {
//J2D::DrawGradientLine(prev.color, data_pt.color, prev.pos, data_pt.pos, 1);
J2D::DrawLine(data_pt.color, data_pt.pos, {data_pt.pos.x, GetAbsoluteSize().y }, 1);
prev = data_pt;
}
float target_line_height = (1.f / 60.f) * 1000;
J2D::DrawString(Colors::Black, "60 FPS / 16.7ms (Target)", 0, 100 - target_line_height, 1.f, 10);
J2D::DrawLine(Colors::White, {0, 100 - target_line_height}, {GetAbsoluteSize().x, 100 - target_line_height}, 1);
J2D::End();
}
FpsGraph() : JUI::ImageRect() {
for (int i = 0; i < 500; i++) {
Plot({i / 1.f, 0.f}, Colors::Black);
}
canvas = new JGL::RenderTarget({500, 100});
RenderDataPoints();
Content(canvas);
};
explicit FpsGraph(Widget* parent) : FpsGraph() {
Parent(parent);
}
void Plot(const Vector2& pt, const Color4& col) {
data.push_back(DataPoint{ pt, col });
}
void Update(float delta) override {
ImageRect::Update(delta);
data.erase(data.begin());
for (auto& data_pt : data) {
data_pt.pos.x -= 1;
}
Color4 color = Colors::Green;
if (delta > 1e-3f)
color = Colors::Blue;
if (delta > 1e-2f)
color = Colors::Yellow;
if (delta > 1e-1f)
color = Colors::Red;
if (delta > 1e+1f)
color = Colors::Purples::Magenta;
if (delta > 1e+2f)
color = Colors::Black;
Plot({(data.size()-1.f), 100 - (delta*1000)}, color);
RenderDataPoints();
Content(canvas);
}
std::vector<DataPoint> data;
JGL::RenderTarget* canvas;
protected:
private:
};
}

View File

@@ -72,7 +72,7 @@ namespace JUI {
/// Returns the text displayed as the Window's title.
[[nodiscard]] std::string Title() const;
void SetTitle(const std::string& title);
void Title(const std::string& title);
/// Returns whether dragging the window about with the mouse is enabled.
/// @see class Draggable.
bool IsDraggable() const;

View File

@@ -35,6 +35,7 @@
#include <JUI/Widgets/CommandLine.hpp>
#include "JUI/Widgets/ColorPicker.hpp"
#include "JUI/Widgets/FpsGraph.hpp"
using namespace JUI;
@@ -106,7 +107,7 @@ JUI::Window* CreateNinesliceWindow(JUI::Widget* root) {
nineslice_demo_window->Name("NineSlice Demo Window");
nineslice_demo_window->CornerRounding(10);
nineslice_demo_window->Size({50_percent, 50_percent});
nineslice_demo_window->SetTitle("9-Slice Demo");
nineslice_demo_window->Title("9-Slice Demo");
nineslice_demo_window->Close();
nineslice_demo_window->TitlebarHeight(12); {
auto* nineslice = new JUI::NineSliceRect(nineslice_demo_window);
@@ -349,7 +350,7 @@ JUI::Window* CreateScrollDemoWindow(Widget* root) {
scroller_demo->Name("ScrollDemo Window");
scroller_demo->Position({10_percent, 10_percent});
scroller_demo->Size({30_percent, 25_percent});
scroller_demo->SetTitle("ScrollingRect Demonstration");
scroller_demo->Title("ScrollingRect Demonstration");
/*Tween* t = scroller_demo->TweenPosition({50_percent, 50_percent}, {.time = 5});
@@ -374,6 +375,15 @@ JUI::Scene* CreateScene() {
auto *root = new Scene();
auto* graph_window = new JUI::Window(root);
graph_window->Name("Graph Window");
graph_window->Title("Graph Window");
graph_window->Size({500_px, 100_px});
auto* graph = new JUI::FpsGraph(graph_window->Content());
graph->Name("Graph");
graph->Size({500_px, 100_px});
auto* colorpicker_wnd = new JUI::Window(root);
colorpicker_wnd->Name("Slider ColorPicker");
colorpicker_wnd->Size({100_px, 150_px});
@@ -476,6 +486,9 @@ public:
glLoadIdentity();
Draw();
if (!focused)
std::this_thread::sleep_for(std::chrono::milliseconds(48));
this->SwapBuffers();
}

View File

@@ -35,22 +35,31 @@ namespace JUI
this->texture = nullptr;
}
ImageBase::ImageBase(JGL::Texture* tex) : ImageBase()
{
this->texture = tex;
ImageBase::ImageBase(JGL::RenderTarget* content) : ImageBase() {
this->Content(content);
}
void ImageBase::Content(JGL::Texture *content) {
ImageBase::ImageBase(JGL::Texture* tex) : ImageBase()
{
this->Content(tex);
}
void ImageBase::Content(const JGL::Texture *content) {
this->texture = new JGL::RenderTarget(content);
}
void ImageBase::Content(JGL::RenderTarget *content) {
this->texture = content;
}
void ImageBase::Color(const Color4 &newColor) { this->image_color = newColor;}
void ImageBase::Scale(const Vector2 &newScale) { scale = newScale;}
void ImageBase::Origin(const Vector2 &newOrigin) { origin = newOrigin; }
JGL::Texture *ImageBase::Content() const { return texture;}
const JGL::Texture *ImageBase::Content() const { return texture->GetTexture();}
Color4 ImageBase::Color() const { return image_color;}

View File

@@ -17,7 +17,7 @@ namespace JUI
}
CommandLine::CommandLine() {
this->SetTitle("Console");
this->Title("Console");
message_log_box = new JUI::ScrollingRect(this->ViewportInstance());
message_log_box->Size(JUI::UDim2(0, -input_form_height, 1, 1));

View File

@@ -47,54 +47,54 @@ namespace JUI {
// Draw Top-Left Quad.
Vector2 tl_computed_pos = abs_pos;
auto tl_quad = TopLeftQuad();
JGL::J2D::DrawPartialSprite(texture, tl_computed_pos, tl_quad.minPoint, tl_quad.maxPoint);
JGL::J2D::DrawPartialRenderTarget(texture, tl_computed_pos, tl_quad.minPoint, tl_quad.maxPoint);
// Draw Top-Right Quad.
auto tr_quad = TopRightQuad();
Vector2 tr_computed_pos = abs_pos + Vector2(abs_size.x - tr_quad.maxPoint.x, 0);
JGL::J2D::DrawPartialSprite(texture, tr_computed_pos, tr_quad.minPoint, tr_quad.maxPoint);
JGL::J2D::DrawPartialRenderTarget(texture, tr_computed_pos, tr_quad.minPoint, tr_quad.maxPoint);
// Draw Bottom Left Quad
auto bl_quad = BottomLeftQuad();
Vector2 bl_computed_pos = abs_pos + Vector2(0, abs_size.y - bl_quad.maxPoint.y);
JGL::J2D::DrawPartialSprite(texture, bl_computed_pos, bl_quad.minPoint, bl_quad.maxPoint);
JGL::J2D::DrawPartialRenderTarget(texture, bl_computed_pos, bl_quad.minPoint, bl_quad.maxPoint);
// Draw Bottom Right Quad
auto br_quad = BottomRightQuad();
Vector2 br_computed_pos = abs_pos + abs_size - br_quad.maxPoint;
JGL::J2D::DrawPartialSprite(texture, br_computed_pos, br_quad.minPoint, br_quad.maxPoint);
JGL::J2D::DrawPartialRenderTarget(texture, br_computed_pos, br_quad.minPoint, br_quad.maxPoint);
// Draw Top-Quad.
Vector2 t_computed_pos = abs_pos + Vector2(tl_quad.maxPoint.x, 0);
auto t_quad = TopQuad();
float abs_width_minus_corners = abs_size.x - (tl_quad.maxPoint.x + tr_quad.maxPoint.x);
float t_scaling = abs_width_minus_corners / t_quad.maxPoint.x;
JGL::J2D::DrawPartialSprite(texture, t_computed_pos, t_quad.minPoint, t_quad.maxPoint, 0, {0,0}, {t_scaling, 1});
JGL::J2D::DrawPartialRenderTarget(texture, t_computed_pos, t_quad.minPoint, t_quad.maxPoint, 0, {0,0}, {t_scaling, 1});
// Draw Bottom Quad
auto b_quad = BottomQuad();
Vector2 b_computed_pos = abs_pos + Vector2(tl_quad.maxPoint.x, abs_size.y - b_quad.maxPoint.y);
float b_scaling = abs_width_minus_corners / b_quad.maxPoint.x;
JGL::J2D::DrawPartialSprite(texture, b_computed_pos, b_quad.minPoint, b_quad.maxPoint, 0, {0,0}, {b_scaling, 1});
JGL::J2D::DrawPartialRenderTarget(texture, b_computed_pos, b_quad.minPoint, b_quad.maxPoint, 0, {0,0}, {b_scaling, 1});
// Draw Left Quad
Vector2 l_computed_pos = abs_pos + Vector2(0, tl_quad.maxPoint.y);
auto l_quad = LeftQuad();
float abs_height_minus_corners = abs_size.y - (tl_quad.maxPoint.y + tr_quad.maxPoint.y);
float l_scaling = abs_height_minus_corners / l_quad.maxPoint.y;
JGL::J2D::DrawPartialSprite(texture, l_computed_pos, l_quad.minPoint, l_quad.maxPoint, 0, {0, 0}, {1, l_scaling});
JGL::J2D::DrawPartialRenderTarget(texture, l_computed_pos, l_quad.minPoint, l_quad.maxPoint, 0, {0, 0}, {1, l_scaling});
// Draw Right Quad
auto r_quad = RightQuad();
Vector2 r_computed_pos = abs_pos + Vector2(abs_size.x - tr_quad.maxPoint.x, tr_quad.maxPoint.y);
float r_scaling = abs_height_minus_corners / r_quad.maxPoint.y;
JGL::J2D::DrawPartialSprite(texture, r_computed_pos, r_quad.minPoint, r_quad.maxPoint, 0, {0,0}, {1, r_scaling});
JGL::J2D::DrawPartialRenderTarget(texture, r_computed_pos, r_quad.minPoint, r_quad.maxPoint, 0, {0,0}, {1, r_scaling});
// Draw Center Quad
auto c_quad = CenterQuad();
Vector2 c_computed_pos = abs_pos + tl_quad.maxPoint;
Vector2 c_scaling = Vector2(abs_width_minus_corners, abs_height_minus_corners) / c_quad.maxPoint;
JGL::J2D::DrawPartialSprite(texture, c_computed_pos, c_quad.minPoint, c_quad.maxPoint, 0, {0,0}, c_scaling);
JGL::J2D::DrawPartialRenderTarget(texture, c_computed_pos, c_quad.minPoint, c_quad.maxPoint, 0, {0,0}, c_scaling);
}
NineSliceRect::NineSliceRect() : Rect(), ImageBase() {

View File

@@ -232,7 +232,7 @@ namespace JUI {
//J2D::DrawString(Colors::Black, std::format("mbutton: {}", mb_state), this->GetAbsolutePosition().x, this->GetAbsolutePosition().y+10, 1.f, 10);
}
void Window::SetTitle(const std::string &title) {
void Window::Title(const std::string &title) {
TitleInstance()->Content(title);
}