From 431d7cceb25db86f31a8c89440f3cdd2c7bf061f Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Thu, 12 Dec 2024 20:45:49 +0100 Subject: load font almost working --- src/crepe/api/Text.cpp | 2 +- src/crepe/api/Text.h | 49 ++++++---- src/crepe/facade/Font.cpp | 4 +- src/crepe/facade/Font.h | 15 +-- src/crepe/facade/SDLContext.cpp | 202 ++++++++++++++++++++++++++-------------- src/example/loadfont.cpp | 13 +-- 6 files changed, 181 insertions(+), 104 deletions(-) diff --git a/src/crepe/api/Text.cpp b/src/crepe/api/Text.cpp index dd44dd9..12d01f1 100644 --- a/src/crepe/api/Text.cpp +++ b/src/crepe/api/Text.cpp @@ -2,5 +2,5 @@ using namespace crepe; -Text::Text(game_object_id_t id,const vec2 & dimensions, const vec2 & offset, const Asset & font) : UIObject(id,dimensions,offset),source(font){} +Text::Text(game_object_id_t id,const vec2 & dimensions, const vec2 & offset,std::string text,std::string font_family) : UIObject(id,dimensions,offset),text(text), font_family(font_family){} diff --git a/src/crepe/api/Text.h b/src/crepe/api/Text.h index d5f47fa..51bab98 100644 --- a/src/crepe/api/Text.h +++ b/src/crepe/api/Text.h @@ -9,27 +9,42 @@ #include "UIObject.h" namespace crepe{ + +/** + * \brief Text UIObject component for displaying text + * + * This class can be used to display text on screen. By setting the font_family to a font already stored on the current device it will automatically be loaded in. + */ class Text : public UIObject{ public: - Text(game_object_id_t id,const vec2 & dimensions, const vec2 & offset, const Asset & font); + Text(game_object_id_t id,const vec2 & dimensions, const vec2 & offset,std::string text,std::string font_family); + //! Text data that does not have to be set in the constructor + struct Data { + //! Label text color. + Color text_color = Color::BLACK; + /** + * \brief fontsize for text rendering + * + * \note this is not the actual font size that is loaded in. + * + * Since SDL_TTF requires the font size when loading in the font it is not possible to switch the font size. + * The default font size that is loaded is set in the Config. + * Instead this value is used to upscale the font texture which can cause blurring or distorted text when upscaling or downscaling too much. + */ + unsigned int font_size = 16; + //! Layer sorting level of the text + const int sorting_in_layer = 0; + //! Order within the sorting text + const int order_in_layer = 0; + }; +public: + //! font family name such as (Arial,Helvetica,Inter) + std::string font_family = ""; //! Label text. - std::string text; - //! Label text color. - Color text_color = Color::BLACK; - /** - * \brief fontsize for text rendering - * - * \note this is not the actual font size that is loaded in. - * - * Since SDL_TTF requires the font size when loading in the font it is not possible to switch the font size. - * The default font size that is loaded is set in the Config. - * Instead this value is used to upscale the font texture which can cause blurring or distorted text when upscaling or downscaling too much. - */ - unsigned int font_size = 16; - //! Font asset - const Asset source; -private: + std::string text = ""; + // Data instance for data not gotten from constructor + Data data; }; } // namespace crepe diff --git a/src/crepe/facade/Font.cpp b/src/crepe/facade/Font.cpp index b600b01..66835ee 100644 --- a/src/crepe/facade/Font.cpp +++ b/src/crepe/facade/Font.cpp @@ -23,6 +23,6 @@ Font::Font(std::unique_ptr res){ this->load(std::move(res)); } -const TTF_Font& Font::get_font() const{ - return this->font; +TTF_Font* Font::get_font() const{ + return this->font.get(); } diff --git a/src/crepe/facade/Font.h b/src/crepe/facade/Font.h index 8bf9fc9..dd1cebf 100644 --- a/src/crepe/facade/Font.h +++ b/src/crepe/facade/Font.h @@ -17,17 +17,20 @@ class Font : public Resource{ public: /** * \param src Asset with font data to load. - * \param mediator use the SDLContext reference to load text + * \param mediator use the SDLContext reference to get_font() */ - Font( src, Mediator & mediator); + Font(const Asset & src, Mediator & mediator); - - ~Font() = default - const TTF_Font& get_font() const; + /** + * \brief getter for TTF_Font + * + * \param src Asset with font data to load. + * \param mediator use the SDLContext reference to get_font() + */ + TTF_Font* get_font() const; private: //! The SDL_ttf font object with custom deleter. std::unique_ptr font; - unsigned int default_font_size = Config::get_instance().font.size; }; } // namespace crepe diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index d71a9c8..8f6c02c 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -18,18 +18,23 @@ #include "../api/Color.h" #include "../api/Config.h" #include "../api/Sprite.h" +#include "../api/Texture.h" #include "../util/Log.h" -#include "manager/Mediator.h" #include "SDLContext.h" -#include "Texture.h" #include "types.h" using namespace crepe; using namespace std; -SDLContext::SDLContext(Mediator & mediator) { +SDLContext & SDLContext::get_instance() { + static SDLContext instance; + return instance; +} + +SDLContext::SDLContext() { dbg_trace(); + if (SDL_Init(SDL_INIT_VIDEO) != 0) { throw runtime_error(format("SDLContext: SDL_Init error: {}", SDL_GetError())); } @@ -57,8 +62,6 @@ SDLContext::SDLContext(Mediator & mediator) { if (!(IMG_Init(img_flags) & img_flags)) { throw runtime_error("SDLContext: SDL_image could not initialize!"); } - - mediator.sdl_context = *this; } SDLContext::~SDLContext() { @@ -74,11 +77,12 @@ SDLContext::~SDLContext() { SDL_Quit(); } -Keycode SDLContext::sdl_to_keycode(SDL_Keycode sdl_key) { +Keycode SDLContext::sdl_to_keycode(SDL_Scancode sdl_key) { static const std::array LOOKUP_TABLE = [] { std::array table{}; table.fill(Keycode::NONE); + // Map all SDL scancodes to Keycodes table[SDL_SCANCODE_SPACE] = Keycode::SPACE; table[SDL_SCANCODE_APOSTROPHE] = Keycode::APOSTROPHE; table[SDL_SCANCODE_COMMA] = Keycode::COMMA; @@ -180,13 +184,27 @@ Keycode SDLContext::sdl_to_keycode(SDL_Keycode sdl_key) { return table; }(); - if (sdl_key < 0 || sdl_key >= SDL_NUM_SCANCODES) { return Keycode::NONE; } - return LOOKUP_TABLE[sdl_key]; } +std::array SDLContext::get_keyboard_state() { + // Array to hold the key states (true if pressed, false if not) + std::array keyState{}; + SDL_PumpEvents(); + const Uint8 * current_state = SDL_GetKeyboardState(nullptr); + + for (int i = 0; i < SDL_NUM_SCANCODES; ++i) { + Keycode key = sdl_to_keycode(static_cast(i)); + + if (key != Keycode::NONE) { + keyState[key] = current_state[i] != 0; + } + } + + return keyState; +} MouseButton SDLContext::sdl_to_mousebutton(Uint8 sdl_button) { static const std::array MOUSE_BUTTON_LOOKUP_TABLE = [] { @@ -218,19 +236,25 @@ void SDLContext::present_screen() { SDL_RenderPresent(this->game_renderer.get()); } +SDL_Rect SDLContext::get_src_rect(const Sprite & sprite) const { + return SDL_Rect{ + .x = sprite.mask.x, + .y = sprite.mask.y, + .w = sprite.mask.w, + .h = sprite.mask.h, + }; +} + SDL_FRect SDLContext::get_dst_rect(const DestinationRectangleData & ctx) const { const Sprite::Data & data = ctx.sprite.data; - float aspect_ratio - = (ctx.sprite.aspect_ratio == 0) ? ctx.texture.get_ratio() : ctx.sprite.aspect_ratio; - vec2 size = data.size; if (data.size.x == 0 && data.size.y != 0) { - size.x = data.size.y * aspect_ratio; + size.x = data.size.y * ctx.sprite.aspect_ratio; } if (data.size.y == 0 && data.size.x != 0) { - size.y = data.size.x / aspect_ratio; + size.y = data.size.x / ctx.sprite.aspect_ratio; } const CameraValues & cam = ctx.cam; @@ -251,24 +275,15 @@ SDL_FRect SDLContext::get_dst_rect(const DestinationRectangleData & ctx) const { } void SDLContext::draw(const RenderContext & ctx) { + const Sprite::Data & data = ctx.sprite.data; SDL_RendererFlip render_flip = (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * data.flip.flip_x) | (SDL_FLIP_VERTICAL * data.flip.flip_y)); - SDL_Rect srcrect; - SDL_Rect * srcrect_ptr = NULL; - if (ctx.sprite.mask.w != 0 || ctx.sprite.mask.h != 0) { - srcrect.w = ctx.sprite.mask.w; - srcrect.h = ctx.sprite.mask.h; - srcrect.x = ctx.sprite.mask.x; - srcrect.y = ctx.sprite.mask.y; - srcrect_ptr = &srcrect; - } - + SDL_Rect srcrect = this->get_src_rect(ctx.sprite); SDL_FRect dstrect = this->get_dst_rect(SDLContext::DestinationRectangleData{ .sprite = ctx.sprite, - .texture = ctx.texture, .cam = ctx.cam, .pos = ctx.pos, .img_scale = ctx.scale, @@ -276,9 +291,9 @@ void SDLContext::draw(const RenderContext & ctx) { double angle = ctx.angle + data.angle_offset; - this->set_color_texture(ctx.texture, ctx.sprite.data.color); - SDL_RenderCopyExF(this->game_renderer.get(), ctx.texture.get_img(), srcrect_ptr, &dstrect, - angle, NULL, render_flip); + this->set_color_texture(ctx.sprite.texture, ctx.sprite.data.color); + SDL_RenderCopyExF(this->game_renderer.get(), ctx.sprite.texture.texture.get(), &srcrect, + &dstrect, angle, NULL, render_flip); } SDLContext::CameraValues SDLContext::set_camera(const Camera & cam) { @@ -340,6 +355,8 @@ SDLContext::CameraValues SDLContext::set_camera(const Camera & cam) { return ret_cam; } +uint64_t SDLContext::get_ticks() const { return SDL_GetTicks64(); } + std::unique_ptr> SDLContext::texture_from_path(const std::string & path) { @@ -366,71 +383,112 @@ SDLContext::texture_from_path(const std::string & path) { ivec2 SDLContext::get_size(const Texture & ctx) { ivec2 size; - SDL_QueryTexture(ctx.get_img(), NULL, NULL, &size.x, &size.y); + SDL_QueryTexture(ctx.texture.get(), NULL, NULL, &size.x, &size.y); return size; } +void SDLContext::delay(int ms) const { SDL_Delay(ms); } + std::vector SDLContext::get_events() { std::vector event_list; SDL_Event event; + + // Handle general SDL events while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: - event_list.push_back(EventData{ - .event_type = SDLContext::EventType::SHUTDOWN, - }); + event_list.push_back({SDLContext::EventType::SHUTDOWN, {}, {}, {}}); break; case SDL_KEYDOWN: - event_list.push_back(EventData{ - .event_type = SDLContext::EventType::KEYDOWN, - .key = sdl_to_keycode(event.key.keysym.scancode), - .key_repeat = (event.key.repeat != 0), - }); + event_list.push_back( + {SDLContext::EventType::KEYDOWN, + {sdl_to_keycode(event.key.keysym.scancode), event.key.repeat != 0}, + {}, + {}}); break; case SDL_KEYUP: - event_list.push_back(EventData{ - .event_type = SDLContext::EventType::KEYUP, - .key = sdl_to_keycode(event.key.keysym.scancode), - }); + event_list.push_back({SDLContext::EventType::KEYUP, + {sdl_to_keycode(event.key.keysym.scancode), false}, + {}, + {}}); break; case SDL_MOUSEBUTTONDOWN: - event_list.push_back(EventData{ - .event_type = SDLContext::EventType::MOUSEDOWN, - .mouse_button = sdl_to_mousebutton(event.button.button), - .mouse_position = {event.button.x, event.button.y}, - }); + event_list.push_back({SDLContext::EventType::MOUSEDOWN, + {}, + {sdl_to_mousebutton(event.button.button), + {event.button.x, event.button.y}}, + {}}); + break; + case SDL_MOUSEBUTTONUP: + event_list.push_back({SDLContext::EventType::MOUSEUP, + {}, + {sdl_to_mousebutton(event.button.button), + {event.button.x, event.button.y}}, + {}}); + break; + case SDL_MOUSEMOTION: + event_list.push_back({SDLContext::EventType::MOUSEMOVE, + {}, + {{}, + {event.motion.x, event.motion.y}, + -1, + INFINITY, + {event.motion.xrel, event.motion.yrel}}, + {}}); break; - case SDL_MOUSEBUTTONUP: { - int x, y; - SDL_GetMouseState(&x, &y); - event_list.push_back(EventData{ - .event_type = SDLContext::EventType::MOUSEUP, - .mouse_button = sdl_to_mousebutton(event.button.button), - .mouse_position = {event.button.x, event.button.y}, - }); - } break; - - case SDL_MOUSEMOTION: { + case SDL_MOUSEWHEEL: event_list.push_back( - EventData{.event_type = SDLContext::EventType::MOUSEMOVE, - .mouse_position = {event.motion.x, event.motion.y}, - .rel_mouse_move = {event.motion.xrel, event.motion.yrel}}); - } break; - - case SDL_MOUSEWHEEL: { - event_list.push_back(EventData{ - .event_type = SDLContext::EventType::MOUSEWHEEL, - .mouse_position = {event.motion.x, event.motion.y}, - // TODO: why is this needed? - .scroll_direction = event.wheel.y < 0 ? -1 : 1, - .scroll_delta = event.wheel.preciseY, - }); - } break; + {SDLContext::EventType::MOUSEWHEEL, + {}, + {{}, {}, event.wheel.y < 0 ? -1 : 1, event.wheel.preciseY, {}}, + {}}); + break; + + // Forward window events for further processing + case SDL_WINDOWEVENT: + this->handle_window_event(event.window, event_list); + break; } } + return event_list; } + +// Separate function for SDL_WINDOWEVENT subtypes +void SDLContext::handle_window_event(const SDL_WindowEvent & window_event, + std::vector & event_list) { + switch (window_event.event) { + case SDL_WINDOWEVENT_EXPOSED: + event_list.push_back({SDLContext::EventType::WINDOW_EXPOSE, {}, {}, {}}); + break; + case SDL_WINDOWEVENT_RESIZED: + event_list.push_back({SDLContext::EventType::WINDOW_RESIZE, + {}, + {}, + {{}, {window_event.data1, window_event.data2}}}); + break; + case SDL_WINDOWEVENT_MOVED: + event_list.push_back({SDLContext::EventType::WINDOW_MOVE, + {}, + {}, + {{window_event.data1, window_event.data2}, {}}}); + break; + case SDL_WINDOWEVENT_MINIMIZED: + event_list.push_back({SDLContext::EventType::WINDOW_MINIMIZE, {}, {}, {}}); + break; + case SDL_WINDOWEVENT_MAXIMIZED: + event_list.push_back({SDLContext::EventType::WINDOW_MAXIMIZE, {}, {}, {}}); + break; + case SDL_WINDOWEVENT_FOCUS_GAINED: + event_list.push_back({SDLContext::EventType::WINDOW_FOCUS_GAIN, {}, {}, {}}); + break; + case SDL_WINDOWEVENT_FOCUS_LOST: + event_list.push_back({SDLContext::EventType::WINDOW_FOCUS_LOST, {}, {}, {}}); + break; + } +} + void SDLContext::set_color_texture(const Texture & texture, const Color & color) { - SDL_SetTextureColorMod(texture.get_img(), color.r, color.g, color.b); - SDL_SetTextureAlphaMod(texture.get_img(), color.a); + SDL_SetTextureColorMod(texture.texture.get(), color.r, color.g, color.b); + SDL_SetTextureAlphaMod(texture.texture.get(), color.a); } diff --git a/src/example/loadfont.cpp b/src/example/loadfont.cpp index 0002026..fe5466f 100644 --- a/src/example/loadfont.cpp +++ b/src/example/loadfont.cpp @@ -3,18 +3,19 @@ #include #include #include - +#include +#include using namespace crepe; int main() { SDLFontContext font_facade; - - // Create a unique pointer to the font asset - std::unique_ptr asset = font_facade.get_font_asset("OpenSymbol"); - std::cout << "path: " << asset->get_path() << std::endl; + Mediator mediator; try{ // Correct way to create a unique pointer for Text - std::unique_ptr label = std::make_unique(1, vec2(100, 100), vec2(0, 0), *asset); + std::unique_ptr label = std::make_unique(1, vec2(100, 100), vec2(0, 0), "test test","OpenSymbol"); + std::unique_ptr asset = font_facade.get_font_asset(label->font_family); + std::cout << "path: " << asset->get_path() << std::endl; + std::unique_ptr font = make_unique(asset,mediator) }catch (const std::exception& e) { std::cout << "Standard exception thrown: " << e.what() << std::endl; } -- cgit v1.2.3