Refactor of project structure...
This commit is contained in:
@@ -73,15 +73,18 @@ CPMAddPackage(
|
||||
NAME FontCache
|
||||
GITHUB_REPOSITORY scientiist/SDL_FontCache
|
||||
#SOURCE_SUBDIR SDL_FontCache
|
||||
GIT_TAG test
|
||||
)
|
||||
GIT_TAG test)
|
||||
find_package(FontCache REQUIRED)
|
||||
target_link_libraries(JUI PUBLIC FontCache)
|
||||
|
||||
CPMAddPackage("gh:nlohmann/json#v3.11.2")
|
||||
|
||||
# Create JUI_Demo executable
|
||||
add_executable(JUI_Demo ${TEST_SRC_FILES})
|
||||
#add_executable(JUI_Demo ${TEST_SRC_FILES})
|
||||
|
||||
# Link JUI library to the executable
|
||||
target_link_libraries(JUI_Demo PUBLIC JUI)
|
||||
#target_link_libraries(JUI_Demo PUBLIC JUI)
|
||||
|
||||
add_subdirectory("src/Demos/MinimalSDLIntegrationDemo")
|
||||
add_subdirectory("src/Demos/MockMenu")
|
||||
add_subdirectory("src/Demos/GameInterface")
|
||||
|
10
README.md
10
README.md
@@ -13,6 +13,16 @@ A Modern (tm) C++ Module that implements a toolkit of graphical Widgets for inte
|
||||
*
|
||||
|
||||
|
||||
## Planned Features
|
||||
* Advanced Widgets;
|
||||
* Checkbox
|
||||
* RadioButton
|
||||
* DropDownMenuButton
|
||||
* ScrollableRect
|
||||
* Slider
|
||||
* Widget Serialization Capability
|
||||
* Lua Scripting Integration - Add JUI as a dependency and add your menu scripts with no extra hassle!
|
||||
|
||||
|
||||
# Modules
|
||||
<details>
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include "JUI/Types/Event.hpp"
|
||||
#include <JUI/common.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include <SDL_image.h>
|
||||
|
||||
using namespace JUI;
|
||||
@@ -62,12 +63,11 @@ public:
|
||||
#pragma endregion
|
||||
#pragma region Getters
|
||||
float GetLastFrameTime() const { return frameDelta; }
|
||||
float GetFramerate() const { return frames_per_second; }
|
||||
bool GetFocused() const;
|
||||
v2i GetWindowSize() const;
|
||||
float GetFramerate() const { return frames_per_second; }
|
||||
bool GetFocused() const;
|
||||
v2i GetWindowSize() const;
|
||||
bool GetCapFPSUnfocused() const;
|
||||
v2f GetMouseCoordinates()
|
||||
{
|
||||
v2f GetMouseCoordinates() {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
SDL_GetMouseState(&x, &y);
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
void SetWindowTitle(const std::string& title);
|
||||
void SetWindowSize(int x, int y);
|
||||
void SetWindowSize(v2f const &v);
|
||||
void SetCappedFPSLimit(int cap);;
|
||||
void SetCappedFPSLimit(int cap);
|
||||
void SetCapFPSUnfocused(bool noCap);
|
||||
// While the mouse is in relative mode:
|
||||
// * The cursor is hidden
|
||||
|
@@ -80,6 +80,7 @@ namespace JUI {
|
||||
connection Connect(delegate callback);
|
||||
void Disconnect(connection &conn);
|
||||
connection operator+=(delegate callback) { return Connect(callback); }
|
||||
|
||||
#pragma endregion
|
||||
private:
|
||||
std::vector <event_ptr> listeners;
|
||||
|
@@ -48,7 +48,7 @@ namespace JUI {
|
||||
#pragma region Getters
|
||||
SDL_Color GetPixel (int x, int y) const;
|
||||
SDL_Rect GetClipRect () const;
|
||||
v2i GetCanvasSize () const;
|
||||
v2i GetCanvasSize () const;
|
||||
SDL_BlendMode GetBlendingMode () const;
|
||||
#pragma endregion
|
||||
|
||||
|
@@ -1,3 +1,4 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <JUI/Widgets/Widget.hpp>
|
||||
@@ -8,28 +9,18 @@
|
||||
namespace JUI {
|
||||
|
||||
struct MouseButtonState {
|
||||
bool LMB;
|
||||
bool RMB;
|
||||
bool MMB;
|
||||
bool LMB; bool RMB; bool MMB;
|
||||
bool Mouse4;
|
||||
bool Mouse5;
|
||||
bool Mouse6;
|
||||
bool Mouse7;
|
||||
};
|
||||
|
||||
enum ButtonState {Pressed, Released};
|
||||
|
||||
|
||||
enum class MouseButtonID : uint32_t {
|
||||
NONE = 0,
|
||||
LMB = 1,
|
||||
MMB = 2,
|
||||
RMB = 4,
|
||||
MM4 = 8,
|
||||
MM5 = 16};
|
||||
enum class ButtonState {Pressed, Released};
|
||||
enum class MouseButtonID : uint32_t {NONE = 0, LMB = 1, MMB = 2, RMB = 4, MM4 = 8, MM5 = 16};
|
||||
|
||||
/* The Rect Widget renders a rectangle and also serves
|
||||
* as a versatile container for other widgets.
|
||||
* as a versatile container for laying out other widgets.
|
||||
*/
|
||||
class Rect : public Widget {
|
||||
#pragma region Interface
|
||||
@@ -41,15 +32,12 @@ namespace JUI {
|
||||
#pragma region Event
|
||||
Event<v2f> MouseEnter;
|
||||
Event<v2f> MouseExit;
|
||||
|
||||
Event<v2f> InputPressed;
|
||||
Event<v2f> InputReleased;
|
||||
|
||||
Event<MouseButtonID> MousePressed;
|
||||
Event<MouseButtonID> MouseReleased;
|
||||
Event<v2f> TouchPressed;
|
||||
Event<v2f> TouchReleased;
|
||||
|
||||
#pragma endregion
|
||||
#pragma region Member Methods
|
||||
void Draw (SDL_Renderer* target) override;
|
||||
@@ -65,6 +53,7 @@ namespace JUI {
|
||||
bool GetClipsDescendants () const;
|
||||
float GetBorderRadius () const;
|
||||
bool GetAutoSizing () const {}
|
||||
bool GetDrag() const { return dragging; }
|
||||
|
||||
#pragma endregion
|
||||
#pragma region Setters
|
||||
@@ -75,13 +64,20 @@ namespace JUI {
|
||||
void SetClipsDescendants(bool enabled);
|
||||
void SetBorderRadius(float degrees);
|
||||
|
||||
v2f GetMouseCoordinates() const {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
SDL_GetMouseState(&x, &y);
|
||||
v2f mc{x, y};
|
||||
return mc;
|
||||
};
|
||||
void SetDrag(bool b);
|
||||
// This is horrific hack! Fix Soon! (tm)
|
||||
int d = 0;
|
||||
int* drag = &d;
|
||||
#pragma endregion
|
||||
#pragma endregion
|
||||
#pragma region Events
|
||||
|
||||
#pragma endregion
|
||||
#pragma endregion
|
||||
#pragma region Internals
|
||||
@@ -91,9 +87,10 @@ namespace JUI {
|
||||
SDL_Color border_color{192,192,192,255}; // {RGBA} format color struct
|
||||
bool clips_descendants = false; // Controls if child objects can render outside of the rectangle bounds.
|
||||
float border_radius = 0; // Curves the rectangle corners by n degrees
|
||||
|
||||
MouseButtonState prev_state{false, false, false};
|
||||
MouseButtonState prev_state = {false, false, false};
|
||||
bool was_clicked = false;
|
||||
v2f initial_drag_offset = {0,0};
|
||||
bool dragging = false;
|
||||
private:
|
||||
bool mouse_hover = false;
|
||||
#pragma endregion
|
||||
|
@@ -2,9 +2,18 @@
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <SDL2/SDL.h>
|
||||
#include "JUI/Types/Font.hpp"
|
||||
|
||||
namespace JUI {
|
||||
|
||||
// All this is just for implementing default font
|
||||
// Is there a better approach?
|
||||
|
||||
JUI::Font* GetDefaultFont();
|
||||
|
||||
void Load(SDL_Renderer* renderer);
|
||||
|
||||
void Cleanup();
|
||||
|
||||
// Aliases for GLM types
|
||||
using v2f = glm::vec<2, float>; // Floating-point 2D Vector
|
||||
@@ -14,6 +23,11 @@ namespace JUI {
|
||||
using matrix = glm::mat4x4;
|
||||
using quaternion = glm::quat;
|
||||
|
||||
void draw_simple_text(SDL_Renderer* gfx, std::string text, v2i coords);
|
||||
|
||||
void draw_simple_text(SDL_Renderer* gfx, std::string text, int x, int y);
|
||||
|
||||
|
||||
// Common funcs
|
||||
inline float naive_lerp(float a, float b, float t) { return a + t * (b - a); }
|
||||
|
||||
|
@@ -3,9 +3,6 @@
|
||||
#include <SDL2/SDL.h>
|
||||
#include <JUI/common.h>
|
||||
|
||||
|
||||
|
||||
|
||||
enum gradient_dir{HORIZ, VERT};
|
||||
|
||||
// Implemented directly as 2 predefined directions
|
||||
|
@@ -8,46 +8,20 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL_render.h>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
|
||||
#include <JUI/common.h>
|
||||
#include <JUI/Types/Event.hpp>
|
||||
#include <JUI/Types/Font.hpp>
|
||||
//#include <JUI/Types/glm.hpp>
|
||||
#include <JUI/Types/UDim.hpp>
|
||||
#include <JUI/Types/UDim2.hpp>
|
||||
#include <JUI/Widgets/Scene.hpp>
|
||||
#include <JUI/Widgets/Rect.hpp>
|
||||
#include <JUI/Widgets/Texture.hpp>
|
||||
#include <JUI/Widgets/Text.hpp>
|
||||
#include <JUI/Widgets/LayoutContainers.hpp>
|
||||
|
||||
namespace JUI {
|
||||
|
||||
struct precision_timestamp {};
|
||||
|
||||
struct Metrics {
|
||||
precision_timestamp last_update_time;
|
||||
//precision_timestamp last_update_time;
|
||||
};
|
||||
|
||||
|
||||
Font* default_font;
|
||||
|
||||
void Initialize() {}
|
||||
|
||||
void Load(SDL_Renderer* renderer)
|
||||
{
|
||||
default_font = new Font(renderer, "fonts/FreeSans.ttf", 12);
|
||||
}
|
||||
|
||||
void Cleanup() {
|
||||
delete default_font;
|
||||
}
|
||||
|
||||
void draw_simple_text(SDL_Renderer* gfx, std::string text, v2i coords)
|
||||
{
|
||||
FC_SetDefaultColor(default_font->font_ptr, {255, 255, 255, 255});
|
||||
FC_DrawAlign(default_font->font_ptr, gfx, coords.x, coords.y, FC_ALIGN_LEFT, text.c_str());
|
||||
}
|
||||
|
||||
void draw_simple_text(SDL_Renderer* gfx, std::string text, int x, int y) { draw_simple_text(gfx, text, {x, y}); }
|
||||
|
||||
// Resources
|
||||
// https://discourse.libsdl.org/t/gradient-examples/8568/4
|
||||
//
|
||||
@@ -61,62 +35,4 @@ namespace JUI {
|
||||
// https://discourse.libsdl.org/t/font-color-gradients/15238/5
|
||||
// https://wiki.libsdl.org/SDL2/SDL_Surface
|
||||
// https://wiki.libsdl.org/SDL2/SDL_BlitSurface
|
||||
|
||||
template <class T>
|
||||
concept integral = std::is_integral<T>::value;
|
||||
|
||||
template<class T>
|
||||
concept signed_integral = integral<T> && std::is_signed<T>::value;
|
||||
|
||||
struct ColorSequence
|
||||
{
|
||||
SDL_Color start;
|
||||
SDL_Color end;
|
||||
std::vector<std::pair<float, SDL_Color>> inbetween;
|
||||
};
|
||||
|
||||
void sample_gradient(float angle, SDL_Color start, SDL_Color end, std::vector<std::pair<float, SDL_Color>> between) {
|
||||
float end_to_end_pixel_length = 0;
|
||||
//int line_count = 50;
|
||||
//for (int idx = 0; idx > line_count; idx++)
|
||||
//{
|
||||
// SDL_Color computed_color {};
|
||||
// SDL_RenderDrawLine(nullptr, 0, 0, 1, 1);
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
void draw_vert_gradient(SDL_Renderer* renderer, SDL_Rect rect, SDL_Color begin, SDL_Color end)
|
||||
{
|
||||
for (int y = 0; y > 1024; y++)
|
||||
{
|
||||
//SDL_RenderDrawLine();
|
||||
}
|
||||
}
|
||||
|
||||
void create_vert_gradient_texture() {}
|
||||
|
||||
void draw_horiz_gradient(SDL_Renderer* renderer, SDL_Rect rect, SDL_Color begin, SDL_Color end)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void create_horiz_gradient_texture() {}
|
||||
|
||||
|
||||
Uint32 get_pixel(SDL_Surface *surface, int x, int y)
|
||||
{
|
||||
// Convert the pixels to 32 bit
|
||||
Uint32 *pixels = (Uint32 *)surface->pixels;
|
||||
|
||||
return pixels[ ( y * surface->w) + x];
|
||||
}
|
||||
|
||||
void set_pixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
|
||||
{
|
||||
Uint8 *target_pixel = (Uint8 *)surface->pixels + y * surface->pitch + x * 4;
|
||||
*(Uint32 *)target_pixel = pixel;
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -6,13 +6,12 @@
|
||||
#include <JUI/Widgets/Rect.hpp>
|
||||
#include <JUI/Types/Font.hpp>
|
||||
#include <JUI/Widgets/Text.hpp>
|
||||
#include <JUI/jui.h>
|
||||
#include <JUI/common.h>
|
||||
#include <Demos/JUIDemoGame.hpp>
|
||||
|
||||
|
||||
void JUIDemoGame::Initialize() {
|
||||
SDLGame::Initialize();
|
||||
JUI::Initialize();
|
||||
JUI::Load(this->renderer);
|
||||
|
||||
Gui = new JUI::Scene(window, renderer);
|
||||
@@ -118,23 +117,8 @@ void JUIDemoGame::Initialize() {
|
||||
rect->SetAnchorPoint({0.5f, 0.5f});
|
||||
rect->SetParent(Gui);
|
||||
|
||||
rect->MousePressed += [rect] (MouseButtonID id) mutable {
|
||||
//*dragging = 1;
|
||||
*rect->drag = 1;
|
||||
};
|
||||
|
||||
this->MouseMoved += [rect, this](SDL_MouseMotionEvent c) mutable {
|
||||
if (*(rect->drag) == 1) { //*dragging==1) {
|
||||
auto delta = this->GetMouseDelta();
|
||||
UDim2 shift = UDim2(delta, {0,0});
|
||||
rect->SetPosition(rect->GetPosition() + shift);
|
||||
}
|
||||
};
|
||||
|
||||
rect->MouseReleased += [rect](MouseButtonID id) mutable {
|
||||
//if (id != MouseButtonID::LMB) { return; }
|
||||
*rect->drag = 0;
|
||||
};
|
||||
rect->MousePressed += [rect] (MouseButtonID id) mutable { if (!rect->GetDrag()) rect->SetDrag(true); };
|
||||
rect->MouseReleased += [rect](MouseButtonID id) mutable { if (rect->GetDrag()) rect->SetDrag(false); };
|
||||
|
||||
auto* topbar = new JUI::Rect();
|
||||
|
||||
@@ -195,15 +179,11 @@ void JUIDemoGame::Initialize() {
|
||||
tb1->SetSize({0, 30, 1.0f, 0.0f});
|
||||
tb1->SetBackgroundColor({128, 128, 128, 255});
|
||||
tb1->SetBorderRadius(2);
|
||||
tb1->MousePressed += [tb1](MouseButtonID id) {
|
||||
if (id == MouseButtonID::LMB) {
|
||||
tb1->SetBackgroundColor({64, 64, 64, 255});
|
||||
}
|
||||
auto _submit_press = tb1->MousePressed += [tb1](MouseButtonID id) {
|
||||
if (id == MouseButtonID::LMB) { tb1->SetBackgroundColor({64, 64, 64, 255}); }
|
||||
};
|
||||
auto conn = tb1->MouseReleased += [tb1](MouseButtonID id) {
|
||||
if (id == MouseButtonID::LMB) {
|
||||
tb1->SetBackgroundColor({128, 128, 128, 255});
|
||||
}
|
||||
auto _submit_confirm = tb1->MouseReleased += [tb1](MouseButtonID id) {
|
||||
if (id == MouseButtonID::LMB) { tb1->SetBackgroundColor({128, 128, 128, 255}); }
|
||||
};
|
||||
|
||||
|
||||
|
9
src/Demos/MinimalSDLIntegrationDemo/CMakeLists.txt
Normal file
9
src/Demos/MinimalSDLIntegrationDemo/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
project("MinimalSDLIntegrationDemo")
|
||||
|
||||
set(SRC_FILES "")
|
||||
file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS "*.h" "*.cpp")
|
||||
|
||||
add_executable(MinimalSDLIntegrationDemo ${SRC_FILES})
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC JUI)
|
||||
include_directories("include")
|
44
src/Demos/MinimalSDLIntegrationDemo/main.cpp
Normal file
44
src/Demos/MinimalSDLIntegrationDemo/main.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <JUI/jui.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL_image.h>
|
||||
#include <SDL_video.h>
|
||||
|
||||
// This is a demo of a Minimal SDL2 rendering setup, and how to integrate JUI
|
||||
// into it as such, as opposed to the abstraction layer of SDLGame.hpp cluttering
|
||||
// the involved logic
|
||||
// Basically, simplest demo:
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
// Initializes window and graphics state
|
||||
SDL_Window* window;
|
||||
SDL_Renderer* renderer;
|
||||
|
||||
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
|
||||
std::cerr << "SDL_Error: " << SDL_GetError() << std::endl;
|
||||
|
||||
window = SDL_CreateWindow("SDL Game", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1152, 864, SDL_WINDOW_SHOWN);
|
||||
|
||||
SDL_SetWindowResizable(window, SDL_TRUE);
|
||||
|
||||
if (window == nullptr) {
|
||||
std::cerr << "SDL_Error: " << SDL_GetError() << std::endl;
|
||||
}
|
||||
int imgFlags = IMG_INIT_PNG;
|
||||
if (!(IMG_Init(imgFlags) & imgFlags))
|
||||
std::cerr << "SDL_Error: " << "Couldn't init SDL_Image." << std::endl;
|
||||
|
||||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
||||
if(renderer == nullptr){
|
||||
std::cerr << "SDL_Error: " << "Couldn't init SDL_Renderer." << std::endl;
|
||||
}
|
||||
|
||||
SDL_GL_SetSwapInterval(0);
|
||||
SDL_RenderSetVSync(renderer, 0);
|
||||
|
||||
// Creates a demo scene
|
||||
|
||||
auto demo_scene = new JUI::Scene(window, renderer);
|
||||
}
|
0
src/Demos/MockMenu/CMakeLists.txt
Normal file
0
src/Demos/MockMenu/CMakeLists.txt
Normal file
@@ -1,7 +1,9 @@
|
||||
#include <Demos/JUIDemoGame.hpp>
|
||||
#include "Demos/JUIDemoGame.hpp"
|
||||
#include <chrono>
|
||||
|
||||
|
||||
// TODO: Move this file to MockMenu/
|
||||
|
||||
int main() {
|
||||
using std::literals::chrono_literals::operator""ms;
|
||||
|
@@ -29,7 +29,6 @@ void SDLGame::Initialize() {
|
||||
SDL_GL_SetSwapInterval(0);
|
||||
//SDL_UpdateWindowSurface(window);
|
||||
SDL_RenderSetVSync(renderer, 0);
|
||||
|
||||
}
|
||||
|
||||
v2i SDLGame::GetWindowSize() const {
|
||||
@@ -69,8 +68,6 @@ void SDLGame::Render() {
|
||||
OnPostRender.Invoke(renderer);
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
|
||||
void SDLGame::handleEvents() {
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT) {
|
||||
@@ -154,14 +151,8 @@ void SDLGame::handleEvents() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void SDLGame::Run() { Gameloop(); }
|
||||
|
||||
void SDLGame::Gameloop() {
|
||||
while (!requestQuit) { RunFrame(); }
|
||||
}
|
||||
|
||||
|
||||
void SDLGame::Gameloop() { while (!requestQuit) { RunFrame(); } }
|
||||
void SDLGame::RunFrame()
|
||||
{
|
||||
this->handleEvents(); // Include this in timing?
|
||||
|
@@ -177,6 +177,11 @@ namespace JUI {
|
||||
}
|
||||
mouse_hover = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (dragging)
|
||||
this->SetPosition(UDim2{this->GetMouseCoordinates() - this->initial_drag_offset, {0.f,0.f}});
|
||||
}
|
||||
|
||||
SDL_Color Rect::GetBackgroundColor() const
|
||||
@@ -228,7 +233,12 @@ namespace JUI {
|
||||
|
||||
|
||||
|
||||
void Rect::SetDrag(bool b) {
|
||||
this->initial_drag_offset = this->GetAbsolutePosition() - this->GetMouseCoordinates();
|
||||
this->dragging = b;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -4,7 +4,7 @@
|
||||
namespace JUI
|
||||
{
|
||||
Text::Text() : Widget() {
|
||||
this->font = JUI::default_font;
|
||||
this->font = JUI::GetDefaultFont();
|
||||
}
|
||||
|
||||
Text::~Text() {}
|
||||
|
21
src/JUI/common.cpp
Normal file
21
src/JUI/common.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <JUI/common.h>
|
||||
JUI::Font* default_font;
|
||||
|
||||
JUI::Font* JUI::GetDefaultFont() {
|
||||
return default_font;
|
||||
}
|
||||
|
||||
void JUI::Load(SDL_Renderer *renderer) {
|
||||
default_font = new Font(renderer, "fonts/FreeSans.ttf", 12);
|
||||
}
|
||||
|
||||
void JUI::Cleanup() {
|
||||
delete default_font;
|
||||
}
|
||||
|
||||
void JUI::draw_simple_text(SDL_Renderer *gfx, std::string text, JUI::v2i coords) {
|
||||
FC_SetDefaultColor(default_font->font_ptr, {255, 255, 255, 255});
|
||||
FC_DrawAlign(default_font->font_ptr, gfx, coords.x, coords.y, FC_ALIGN_LEFT, text.c_str());
|
||||
}
|
||||
|
||||
void JUI::draw_simple_text(SDL_Renderer *gfx, std::string text, int x, int y) { draw_simple_text(gfx, text, {x, y}); }
|
Reference in New Issue
Block a user