From ed53c8bd1f474617ddd6bdbc018f2b731e157172 Mon Sep 17 00:00:00 2001 From: Maschell Date: Mon, 7 Sep 2020 20:26:22 +0200 Subject: [PATCH] WIP multiscreen support --- CMakeLists.txt | 6 +- src/gui/GuiImage.cpp | 24 +++-- src/gui/GuiImage.h | 13 ++- src/gui/GuiText.cpp | 10 +- src/gui/GuiTextureData.cpp | 5 - src/main.cpp | 16 ++- src/menu/MainWindow.cpp | 166 ++++++++++------------------- src/menu/MainWindow.h | 59 ++++++---- src/menu/MainWindowDRC.cpp | 123 +++++++++++++++++++++ src/menu/MainWindowDRC.h | 31 ++++++ src/menu/MainWindowTV.cpp | 124 +++++++++++++++++++++ src/menu/MainWindowTV.h | 30 ++++++ src/resources/Resources.cpp | 43 +++++--- src/resources/Resources.h | 17 +-- src/system/SDLSystem.cpp | 68 +++++++++--- src/system/SDLSystem.h | 9 +- src/system/video/Renderer.h | 16 ++- src/system/video/SDL_FontCache.cpp | 62 +++++------ 18 files changed, 592 insertions(+), 230 deletions(-) create mode 100644 src/menu/MainWindowDRC.cpp create mode 100644 src/menu/MainWindowDRC.h create mode 100644 src/menu/MainWindowTV.cpp create mode 100644 src/menu/MainWindowTV.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 5bfb342..014858b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,11 @@ add_executable(${PROJECT_NAME} src/fs/CFile.hpp src/fs/FSUtils.cpp src/fs/FSUtils.h - src/input/SDLController.h src/menu/MainWindow.cpp src/menu/MainWindow.h src/input/SDLControllerJoystick.h src/input/SDLControllerMouse.h + src/menu/MainWindow.cpp + src/menu/MainWindow.h + src/menu/MainWindowDRC.cpp + src/menu/MainWindowDRC.h + src/input/SDLController.h src/menu/MainWindowTV.cpp src/menu/MainWindowTV.h src/input/SDLControllerJoystick.h src/input/SDLControllerMouse.h src/input/SDLControllerWiiUGamepad.h src/input/SDLControllerWiiUProContoller.h src/gui/GuiTextureData.cpp src/gui/GuiTextureData.h diff --git a/src/gui/GuiImage.cpp b/src/gui/GuiImage.cpp index cd5ee0e..3026481 100644 --- a/src/gui/GuiImage.cpp +++ b/src/gui/GuiImage.cpp @@ -22,8 +22,13 @@ GuiImage::GuiImage(GuiTextureData *texture) { setTexture(texture); } +GuiImage::GuiImage(SDL_Color color, float width, float height) { + this->color = color; + this->setSize(width, height); +} + GuiImage::~GuiImage() { - if(this->texture && freeTextureData){ + if (this->texture && freeTextureData) { delete this->texture; } } @@ -33,13 +38,20 @@ void GuiImage::draw(Renderer *renderer) { return; } + SDL_Rect rect; + rect.x = (int) getLeft(); + rect.y = (int) getTop(); + rect.w = (int) (getScaleX() * getWidth()); + rect.h = (int) (getScaleY() * getHeight()); + if (texture) { - SDL_Rect rect; - rect.x = (int) getLeft(); - rect.y = (int) getTop(); - rect.w = (int) (getScaleX() * getWidth()); - rect.h = (int) (getScaleY() * getHeight()); texture->draw(renderer, rect, getAngle()); + } else { + SDL_SetRenderDrawColor(renderer->getRenderer(), color.r, color.g, color.b, color.a); + SDL_RenderFillRect(renderer->getRenderer(), &rect); + if(getAngle() != 0.0f){ + DEBUG_FUNCTION_LINE("Drawing a rotated rect is not supported yet"); + } } } diff --git a/src/gui/GuiImage.h b/src/gui/GuiImage.h index 05b5e39..e5b80ed 100644 --- a/src/gui/GuiImage.h +++ b/src/gui/GuiImage.h @@ -23,19 +23,28 @@ //!Display, manage, and manipulate images in the GUI class GuiImage : public GuiElement { public: - //!\overload - //!\param img Pointer to GuiImageData element + GuiImage() = default; + //! Draws an image from an existing texture + //!\param texture Pointer to GuiTextureData element explicit GuiImage(GuiTextureData *texture); + //! Draws a colored rectangle + //!\param texture Pointer to GuiTextureData element + explicit GuiImage(SDL_Color color, float width, float height); + //!Destructor ~GuiImage() override; void draw(Renderer *r) override; void setTexture(GuiTextureData *tex); + private: GuiTextureData *texture = nullptr; bool freeTextureData = false; + + // Color of the rect that's drawn if the picture has no texture. + SDL_Color color = {0, 0, 0, 0}; }; diff --git a/src/gui/GuiText.cpp b/src/gui/GuiText.cpp index 7caa8a0..07960f8 100644 --- a/src/gui/GuiText.cpp +++ b/src/gui/GuiText.cpp @@ -76,10 +76,18 @@ void GuiText::updateTexture(Renderer *renderer) { textureData->setBlendMode(SDL_BLENDMODE_BLEND); texture.setTexture(textureData); + // Set render target to texture SDL_SetRenderTarget(renderer->getRenderer(), temp); + + // Clear texture. + SDL_SetRenderDrawColor(renderer->getRenderer(), 0, 0, 0, 0); SDL_RenderClear(renderer->getRenderer()); + + // Draw text to texture FC_DrawColumn(fc_font, renderer->getRenderer(), 0, 0, maxWidth, text.c_str()); - SDL_SetRenderTarget(renderer->getRenderer(), NULL); + + // Restore render target + SDL_SetRenderTarget(renderer->getRenderer(), nullptr); } else { DEBUG_FUNCTION_LINE("Failed to create texture"); } diff --git a/src/gui/GuiTextureData.cpp b/src/gui/GuiTextureData.cpp index 7885583..52a4d94 100644 --- a/src/gui/GuiTextureData.cpp +++ b/src/gui/GuiTextureData.cpp @@ -59,11 +59,6 @@ GuiTextureData::~GuiTextureData() { void GuiTextureData::draw(Renderer *renderer, const SDL_Rect& dest, float angle) { if (texture == nullptr && imgSurface) { - SDL_Surface *optimizedSurface = SDL_ConvertSurfaceFormat(imgSurface, renderer->getPixelFormat(), 0); - if (optimizedSurface != nullptr) { - SDL_FreeSurface(imgSurface); - imgSurface = optimizedSurface; - } texture = SDL_CreateTextureFromSurface(renderer->getRenderer(), imgSurface); } if (!texture) { diff --git a/src/main.cpp b/src/main.cpp index f5f87bd..1f217f8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,10 +3,11 @@ #include "gui/GuiFrame.h" #include "gui/GuiButton.h" #include "gui/GuiController.h" -#include "menu/MainWindow.h" +#include "menu/MainWindowTV.h" #include "input/SDLController.h" #include "input/SDLControllerMouse.h" #include "input/ControllerManager.h" +#include "menu/MainWindow.h" #include #include @@ -70,7 +71,9 @@ int main(int argc, char *args[]) { WHBLogUdpInit(); #endif - auto * frame = new MainWindow(system->getWidth(), system->getHeight(), system->getRenderer()); + DEBUG_FUNCTION_LINE("%0.1f %0.1f", system->getWidth(), system->getHeight()); + + auto * frame = new MainWindow(system); auto * controllerM = new ControllerManager(system->getWidth(), system->getHeight()); @@ -132,16 +135,9 @@ int main(int argc, char *args[]) { frame->process(); - // clear the screen - SDL_RenderClear(system->getRenderer()->getRenderer()); - - frame->draw(system->getRenderer()); + frame->draw(); frame->updateEffects(); - - // flip the backbuffer - // this means that everything that we prepared behind the screens is actually shown - SDL_RenderPresent(system->getRenderer()->getRenderer()); } delete frame; diff --git a/src/menu/MainWindow.cpp b/src/menu/MainWindow.cpp index aeeade9..e0a0d2f 100644 --- a/src/menu/MainWindow.cpp +++ b/src/menu/MainWindow.cpp @@ -1,53 +1,39 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ +#include #include "MainWindow.h" +#include "../gui/GuiImage.h" +#include "MainWindowTV.h" #include "../resources/Resources.h" +#include "MainWindowDRC.h" -MainWindow::~MainWindow() { - delete label; - delete touchTrigger; - delete buttonTrigger; - delete sound; - delete image; - delete image2; - delete image3; - delete image4; - delete image5; - delete image; - delete label; - delete button; - delete bgMusic; -} +MainWindow::MainWindow(SDLSystem* sdlSystem): + sdlSystem(sdlSystem){ + + if(TTF_Init() < 0){ + DEBUG_FUNCTION_LINE("Failed to init TTF"); + } + + currentTvFrame = new MainWindowTV(sdlSystem->getWidth(), sdlSystem->getHeight(), sdlSystem->getRendererTV()); + currentDrcFrame = new MainWindowDRC(sdlSystem->getWidth(), sdlSystem->getHeight(), sdlSystem->getRendererDRC()); -MainWindow::MainWindow(int32_t w, int32_t h, Renderer* renderer) : GuiFrame(w, h) { - auto picture_path = "button.png"; - auto font_path = "FreeSans.ttf"; auto bgMusic_path = "bgMusic.ogg"; - auto music_click = "button_click.mp3"; - TTF_Init(); - TTF_Font *font; - - SDL_RWops *rw = SDL_RWFromMem((void *) Resources::GetFile(font_path), Resources::GetFileSize(font_path)); - - DEBUG_FUNCTION_LINE("load font %08X %d", Resources::GetFile(font_path), Resources::GetFileSize(font_path)); - - font = TTF_OpenFontRW(rw, 0, 28); - if(!font){ - DEBUG_FUNCTION_LINE("Failed to load the font"); - return; - } - - FC_Font* fc_font = FC_CreateFont(); - if(!fc_font){ - DEBUG_FUNCTION_LINE("Failed to create font"); - } - - auto res = FC_LoadFontFromTTF(fc_font, renderer->getRenderer(), font, {255, 255, 255, 255}); - DEBUG_FUNCTION_LINE("FontCache init %d", res); - - label = new GuiText("This is a test.", {255, 255, 0, 255}, fc_font); - - - bgMusic = Resources::GetSound(bgMusic_path); + bgMusic = Resources::GetSound(Renderer::TARGET_TV, bgMusic_path); if(!bgMusic){ DEBUG_FUNCTION_LINE("Failed to load %s", bgMusic_path); return; @@ -55,79 +41,35 @@ MainWindow::MainWindow(int32_t w, int32_t h, Renderer* renderer) : GuiFrame(w, h bgMusic->SetLoop(true); bgMusic->Play(); - image = new GuiImage(Resources::GetTexture(picture_path)); - image2 = new GuiImage(Resources::GetTexture(picture_path)); - image3 = new GuiImage(Resources::GetTexture(picture_path)); - image4 = new GuiImage(Resources::GetTexture(picture_path)); - image5 = new GuiImage(Resources::GetTexture(picture_path)); - if(!image){ - DEBUG_FUNCTION_LINE("Failed to add image"); - return; - } - if(!image2){ - DEBUG_FUNCTION_LINE("Failed to add image"); - return; - } - if(!image3){ - DEBUG_FUNCTION_LINE("Failed to add image"); - return; - } - if(!image4){ - DEBUG_FUNCTION_LINE("Failed to add image"); - return; - } +} - if(!image5){ - DEBUG_FUNCTION_LINE("Failed to add image"); - return; - } +MainWindow::~MainWindow() { + delete currentTvFrame; + delete currentDrcFrame; + Resources::RemoveSound(Renderer::TARGET_TV, bgMusic); +} - button = new GuiButton(image5->getWidth(), image5->getHeight()); - - this->setAlignment(ALIGN_TOP_LEFT); - this->append(button); - this->append(image); - this->append(image2); - this->append(image3); - this->append(image4); - - image->setAlignment(ALIGN_TOP_LEFT); - image2->setAlignment(ALIGN_TOP_RIGHT); - image3->setAlignment(ALIGN_BOTTOM | ALIGN_LEFT); - image4->setAlignment(ALIGN_BOTTOM | ALIGN_RIGHT); - - button->setAlignment(ALIGN_CENTERED); - button->setImage(image5); - - sound = Resources::GetSound(music_click); - - touchTrigger = new GuiTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::TOUCHED); - buttonTrigger = new GuiTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_A, true); - button->setTrigger(touchTrigger); - button->setTrigger(buttonTrigger); - button->setEffectGrow(); - label->setAlignment(ALIGN_CENTERED); - button->setLabel(label); - label->setMaxWidth(button->getWidth()); - button->setSoundClick(sound); - - button->clicked.connect(this, &MainWindow::test); +void MainWindow::updateEffects() { + currentTvFrame->updateEffects(); + currentDrcFrame->updateEffects(); } void MainWindow::process() { - GuiFrame::process(); - - if(!button){ - return; - } - // Rotate the button for fun. - auto res = button->getAngle() + 0.1f; - if(res > 360){ - res = 0; - } - button->setAngle(res); + currentTvFrame->process(); + currentDrcFrame->process(); } -void MainWindow::test(GuiButton *, const GuiController *, GuiTrigger *) { - DEBUG_FUNCTION_LINE("Hello, you have clicked the button"); +void MainWindow::update(GuiController *controller) { + currentTvFrame->update(controller); + currentDrcFrame->update(controller); } + +void MainWindow::draw() { + SDL_RenderClear(sdlSystem->getRendererTV()->getRenderer()); + currentTvFrame->draw(sdlSystem->getRendererTV()); + SDL_RenderPresent(sdlSystem->getRendererTV()->getRenderer()); + + SDL_RenderClear(sdlSystem->getRendererDRC()->getRenderer()); + currentDrcFrame->draw(sdlSystem->getRendererDRC()); + SDL_RenderPresent(sdlSystem->getRendererDRC()->getRenderer()); +} \ No newline at end of file diff --git a/src/menu/MainWindow.h b/src/menu/MainWindow.h index 925b249..6ef57ea 100644 --- a/src/menu/MainWindow.h +++ b/src/menu/MainWindow.h @@ -1,29 +1,46 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ #pragma once -#include +#include +#include +#include "../gui/sigslot.h" +#include "../gui/GuiElement.h" #include "../gui/GuiFrame.h" -#include "../gui/GuiButton.h" -#include "../utils/logger.h" -#include "../gui/GuiImage.h" +#include "../gui/GuiSound.h" -class MainWindow : public GuiFrame, public sigslot::has_slots<> { +class Renderer; + +class MainWindow : public sigslot::has_slots<> { public: - void test(GuiButton *, const GuiController *, GuiTrigger *); - + explicit MainWindow(SDLSystem* sdlSystem); ~MainWindow() override; - MainWindow(int32_t w, int32_t h, Renderer* renderer); - void process() override; + void draw(); + + void update(GuiController *controller); + void updateEffects(); + void process(); + private: - GuiText *label = nullptr; - GuiTrigger *touchTrigger = nullptr; - GuiTrigger *buttonTrigger = nullptr; - GuiSound *sound = nullptr; - GuiImage *image = nullptr; - GuiImage *image2 = nullptr; - GuiImage *image3 = nullptr; - GuiImage *image4 = nullptr; - GuiImage *image5 = nullptr; - GuiButton *button = nullptr; - GuiSound *bgMusic = nullptr; -}; + int32_t width, height; + + GuiFrame * currentTvFrame; + GuiFrame * currentDrcFrame; + SDLSystem* sdlSystem; + GuiSound* bgMusic; +}; \ No newline at end of file diff --git a/src/menu/MainWindowDRC.cpp b/src/menu/MainWindowDRC.cpp new file mode 100644 index 0000000..1f2da82 --- /dev/null +++ b/src/menu/MainWindowDRC.cpp @@ -0,0 +1,123 @@ +#include "MainWindowDRC.h" +#include "../resources/Resources.h" + +MainWindowDRC::~MainWindowDRC() { + delete label; + delete touchTrigger; + delete buttonTrigger; + delete sound; + delete image; + delete image2; + delete image3; + delete image4; + delete image5; + delete image; + delete label; + delete button; +} + +MainWindowDRC::MainWindowDRC(int32_t w, int32_t h, Renderer* renderer) : GuiFrame(w, h), bgImage({100, 0, 0, 255}, w, h) { + auto picture_path = "button.png"; + auto font_path = "FreeSans.ttf"; + auto music_click = "button_click.mp3"; + + append(&bgImage); + + TTF_Font *font; + + SDL_RWops *rw = SDL_RWFromMem((void *) Resources::GetFile(font_path), Resources::GetFileSize(font_path)); + + DEBUG_FUNCTION_LINE("load font %08X %d", Resources::GetFile(font_path), Resources::GetFileSize(font_path)); + + font = TTF_OpenFontRW(rw, 0, 28); + if(!font){ + DEBUG_FUNCTION_LINE("Failed to load the font %s", SDL_GetError()); + return; + } + + FC_Font* fc_font = FC_CreateFont(); + if(!fc_font){ + DEBUG_FUNCTION_LINE("Failed to create font"); + } + + auto res = FC_LoadFontFromTTF(fc_font, renderer->getRenderer(), font, {255, 255, 255, 255}); + DEBUG_FUNCTION_LINE("FontCache init %d", res); + + label = new GuiText("This is a test.", {255, 255, 0, 255}, fc_font); + + image = new GuiImage(Resources::GetTexture(renderer->getTarget(), picture_path)); + image2 = new GuiImage(Resources::GetTexture(renderer->getTarget(), picture_path)); + image3 = new GuiImage(Resources::GetTexture(renderer->getTarget(), picture_path)); + image4 = new GuiImage(Resources::GetTexture(renderer->getTarget(), picture_path)); + image5 = new GuiImage(Resources::GetTexture(renderer->getTarget(), picture_path)); + if(!image){ + DEBUG_FUNCTION_LINE("Failed to add image"); + return; + } + if(!image2){ + DEBUG_FUNCTION_LINE("Failed to add image"); + return; + } + if(!image3){ + DEBUG_FUNCTION_LINE("Failed to add image"); + return; + } + if(!image4){ + DEBUG_FUNCTION_LINE("Failed to add image"); + return; + } + + if(!image5){ + DEBUG_FUNCTION_LINE("Failed to add image"); + return; + } + + button = new GuiButton(image5->getWidth(), image5->getHeight()); + + this->setAlignment(ALIGN_TOP_LEFT); + this->append(button); + this->append(image); + this->append(image2); + this->append(image3); + this->append(image4); + + image->setAlignment(ALIGN_TOP_CENTER); + image2->setAlignment(ALIGN_MIDDLE | ALIGN_LEFT); + image3->setAlignment(ALIGN_BOTTOM | ALIGN_CENTER); + image4->setAlignment(ALIGN_MIDDLE | ALIGN_RIGHT); + + button->setAlignment(ALIGN_CENTERED); + button->setImage(image5); + + sound = Resources::GetSound(renderer->getTarget(), music_click); + + touchTrigger = new GuiTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::TOUCHED); + buttonTrigger = new GuiTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_A, true); + button->setTrigger(touchTrigger); + button->setTrigger(buttonTrigger); + button->setEffectGrow(); + label->setAlignment(ALIGN_CENTERED); + button->setLabel(label); + label->setMaxWidth(button->getWidth()); + button->setSoundClick(sound); + + button->clicked.connect(this, &MainWindowDRC::test); +} + +void MainWindowDRC::process() { + GuiFrame::process(); + + if(!button){ + return; + } + // Rotate the button for fun. + auto res = button->getAngle() - 1.0f; + if(res > 360){ + res = 0; + } + button->setAngle(res); +} + +void MainWindowDRC::test(GuiButton *, const GuiController *, GuiTrigger *) { + DEBUG_FUNCTION_LINE("Hello, you have clicked the button"); +} diff --git a/src/menu/MainWindowDRC.h b/src/menu/MainWindowDRC.h new file mode 100644 index 0000000..6ed0377 --- /dev/null +++ b/src/menu/MainWindowDRC.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include "../gui/GuiFrame.h" +#include "../gui/GuiButton.h" +#include "../utils/logger.h" +#include "../gui/GuiImage.h" + +class MainWindowDRC : public GuiFrame, public sigslot::has_slots<> { +public: + void test(GuiButton *, const GuiController *, GuiTrigger *); + + ~MainWindowDRC() override; + + MainWindowDRC(int32_t w, int32_t h, Renderer *renderer); + + void process() override; + +private: + GuiText *label = nullptr; + GuiTrigger *touchTrigger = nullptr; + GuiTrigger *buttonTrigger = nullptr; + GuiSound *sound = nullptr; + GuiImage *image = nullptr; + GuiImage *image2 = nullptr; + GuiImage *image3 = nullptr; + GuiImage *image4 = nullptr; + GuiImage *image5 = nullptr; + GuiImage bgImage; + GuiButton *button = nullptr; +}; diff --git a/src/menu/MainWindowTV.cpp b/src/menu/MainWindowTV.cpp new file mode 100644 index 0000000..15fbae8 --- /dev/null +++ b/src/menu/MainWindowTV.cpp @@ -0,0 +1,124 @@ +#include "MainWindowTV.h" +#include "../resources/Resources.h" + +MainWindowTV::~MainWindowTV() { + delete label; + delete touchTrigger; + delete buttonTrigger; + delete sound; + delete image; + delete image2; + delete image3; + delete image4; + delete image5; + delete image; + delete label; + delete button; + delete bgMusic; +} + +MainWindowTV::MainWindowTV(int32_t w, int32_t h, Renderer* renderer) : GuiFrame(w, h), bgImage({100, 0, 0, 255}, w, h) { + auto picture_path = "button.png"; + auto font_path = "FreeSans.ttf"; + auto music_click = "button_click.mp3"; + + append(&bgImage); + + + TTF_Font *font; + + SDL_RWops *rw = SDL_RWFromMem((void *) Resources::GetFile(font_path), Resources::GetFileSize(font_path)); + + DEBUG_FUNCTION_LINE("load font %08X %d", Resources::GetFile(font_path), Resources::GetFileSize(font_path)); + + font = TTF_OpenFontRW(rw, 0, 28); + if(!font){ + DEBUG_FUNCTION_LINE("Failed to load the font %s", SDL_GetError()); + return; + } + + FC_Font* fc_font = FC_CreateFont(); + if(!fc_font){ + DEBUG_FUNCTION_LINE("Failed to create font"); + } + + auto res = FC_LoadFontFromTTF(fc_font, renderer->getRenderer(), font, {255, 255, 255, 255}); + DEBUG_FUNCTION_LINE("FontCache init %d", res); + + label = new GuiText("This is a test.", {255, 255, 0, 255}, fc_font); + + image = new GuiImage(Resources::GetTexture(renderer->getTarget(), picture_path)); + image2 = new GuiImage(Resources::GetTexture(renderer->getTarget(), picture_path)); + image3 = new GuiImage(Resources::GetTexture(renderer->getTarget(), picture_path)); + image4 = new GuiImage(Resources::GetTexture(renderer->getTarget(), picture_path)); + image5 = new GuiImage(Resources::GetTexture(renderer->getTarget(), picture_path)); + if(!image){ + DEBUG_FUNCTION_LINE("Failed to add image"); + return; + } + if(!image2){ + DEBUG_FUNCTION_LINE("Failed to add image"); + return; + } + if(!image3){ + DEBUG_FUNCTION_LINE("Failed to add image"); + return; + } + if(!image4){ + DEBUG_FUNCTION_LINE("Failed to add image"); + return; + } + + if(!image5){ + DEBUG_FUNCTION_LINE("Failed to add image"); + return; + } + + button = new GuiButton(image5->getWidth(), image5->getHeight()); + + this->setAlignment(ALIGN_TOP_LEFT); + this->append(button); + this->append(image); + this->append(image2); + this->append(image3); + this->append(image4); + + image->setAlignment(ALIGN_TOP_LEFT); + image2->setAlignment(ALIGN_TOP_RIGHT); + image3->setAlignment(ALIGN_BOTTOM | ALIGN_LEFT); + image4->setAlignment(ALIGN_BOTTOM | ALIGN_RIGHT); + + button->setAlignment(ALIGN_CENTERED); + button->setImage(image5); + + sound = Resources::GetSound(renderer->getTarget(), music_click); + + buttonTrigger = new GuiTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_A, true); + button->setTrigger(buttonTrigger); + button->setEffectGrow(); + label->setAlignment(ALIGN_CENTERED); + button->setLabel(label); + label->setMaxWidth(button->getWidth()); + button->setSoundClick(sound); + + + button->clicked.connect(this, &MainWindowTV::test); +} + +void MainWindowTV::process() { + GuiFrame::process(); + + if(!button){ + return; + } + // Rotate the button for fun. + auto res = button->getAngle() + 1.0f; + if(res > 360){ + res = 0; + } + button->setAngle(res); +} + +void MainWindowTV::test(GuiButton *, const GuiController *, GuiTrigger *) { + DEBUG_FUNCTION_LINE("Hello, you have clicked the button"); +} diff --git a/src/menu/MainWindowTV.h b/src/menu/MainWindowTV.h new file mode 100644 index 0000000..9af7765 --- /dev/null +++ b/src/menu/MainWindowTV.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include "../gui/GuiFrame.h" +#include "../gui/GuiButton.h" +#include "../utils/logger.h" +#include "../gui/GuiImage.h" + +class MainWindowTV : public GuiFrame, public sigslot::has_slots<> { +public: + void test(GuiButton *, const GuiController *, GuiTrigger *); + + ~MainWindowTV() override; + + MainWindowTV(int32_t w, int32_t h, Renderer* renderer); + void process() override; +private: + GuiText *label = nullptr; + GuiTrigger *touchTrigger = nullptr; + GuiTrigger *buttonTrigger = nullptr; + GuiSound *sound = nullptr; + GuiImage *image = nullptr; + GuiImage *image2 = nullptr; + GuiImage *image3 = nullptr; + GuiImage *image4 = nullptr; + GuiImage *image5 = nullptr; + GuiImage bgImage; + GuiButton *button = nullptr; + GuiSound *bgMusic = nullptr; +}; diff --git a/src/resources/Resources.cpp b/src/resources/Resources.cpp index b682bbd..c7d1ba8 100644 --- a/src/resources/Resources.cpp +++ b/src/resources/Resources.cpp @@ -11,7 +11,8 @@ #include "filelist.h" #include "../utils/logger.h" -Resources *Resources::instance = nullptr; + +std::map Resources::instances; void Resources::Clear() { for (int32_t i = 0; RecourceList[i].filename != nullptr; ++i) { @@ -19,15 +20,15 @@ void Resources::Clear() { free(RecourceList[i].CustomFile); RecourceList[i].CustomFile = nullptr; } - if (RecourceList[i].CustomFileSize != 0) { RecourceList[i].CustomFileSize = 0; } } - delete instance; - - instance = nullptr; + for (auto const&[target, instance] : instances) { + delete instance; + } + instances.clear(); } bool Resources::LoadFiles(const char *path) { @@ -78,11 +79,13 @@ uint32_t Resources::GetFileSize(const char *filename) { return 0; } -GuiTextureData *Resources::GetTexture(const char *filename) { - if (!instance) { - instance = new Resources; +GuiTextureData *Resources::GetTexture(Renderer::RendererTarget target, const char *filename) { + if (instances.count(target) == 0) { + instances[target] = new Resources(); } + Resources *instance = instances[target]; + auto itr = instance->textureDataMap.find(std::string(filename)); if (itr != instance->textureDataMap.end()) { itr->second.first++; @@ -109,7 +112,13 @@ GuiTextureData *Resources::GetTexture(const char *filename) { return nullptr; } -bool Resources::RemoveTexture(GuiTextureData *image) { +bool Resources::RemoveTexture(Renderer::RendererTarget target, GuiTextureData *image) { + if (instances.count(target) == 0) { + instances[target] = new Resources(); + } + + Resources *instance = instances[target]; + std::map >::iterator itr; for (itr = instance->textureDataMap.begin(); itr != instance->textureDataMap.end(); itr++) { @@ -128,11 +137,13 @@ bool Resources::RemoveTexture(GuiTextureData *image) { return false; } -GuiSound *Resources::GetSound(const char *filename) { - if (!instance) { - instance = new Resources; +GuiSound *Resources::GetSound(Renderer::RendererTarget target, const char *filename) { + if (instances.count(target) == 0) { + instances[target] = new Resources(); } + Resources *instance = instances[target]; + auto itr = instance->soundDataMap.find(std::string(filename)); if (itr != instance->soundDataMap.end()) { itr->second.first++; @@ -159,7 +170,13 @@ GuiSound *Resources::GetSound(const char *filename) { return nullptr; } -void Resources::RemoveSound(GuiSound *sound) { +void Resources::RemoveSound(Renderer::RendererTarget target, GuiSound *sound) { + if (instances.count(target) == 0) { + instances[target] = new Resources(); + } + + Resources *instance = instances[target]; + std::map >::iterator itr; for (itr = instance->soundDataMap.begin(); itr != instance->soundDataMap.end(); itr++) { diff --git a/src/resources/Resources.h b/src/resources/Resources.h index d8e82ef..bd88955 100644 --- a/src/resources/Resources.h +++ b/src/resources/Resources.h @@ -3,6 +3,7 @@ #include #include #include +#include "../system/video/Renderer.h" //! forward declaration class GuiTextureData; @@ -18,6 +19,8 @@ typedef struct RecourceFile unsigned int CustomFileSize; } RecourceFile; + + class Resources { public: static void Clear(); @@ -28,20 +31,20 @@ public: static uint32_t GetFileSize(const char *filename); - static GuiTextureData *GetTexture(const char *filename); + static GuiTextureData *GetTexture(Renderer::RendererTarget target, const char *filename); - static bool RemoveTexture(GuiTextureData *image); + static bool RemoveTexture(Renderer::RendererTarget target, GuiTextureData *image); - static GuiSound *GetSound(const char *filename); + static GuiSound *GetSound(Renderer::RendererTarget target, const char *filename); - static void RemoveSound(GuiSound *sound); + static void RemoveSound(Renderer::RendererTarget target, GuiSound *sound); private: - static Resources *instance; + Resources() = default; - Resources() {} + ~Resources() = default; - ~Resources() {} + static std::map instances; std::map > textureDataMap; std::map > soundDataMap; diff --git a/src/system/SDLSystem.cpp b/src/system/SDLSystem.cpp index 9a1bd53..221c56e 100644 --- a/src/system/SDLSystem.cpp +++ b/src/system/SDLSystem.cpp @@ -18,27 +18,61 @@ #include "../utils/logger.h" #include #include +#ifdef __WIIU__ +#include +#endif SDLSystem::SDLSystem() { SDL_Init(SDL_INIT_EVERYTHING); + int width = 1280; + int height = 720; + auto SDLFlags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC; +#ifdef __WIIU__ + window_tv = SDL_CreateWindow(nullptr, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_WIIU_TV_ONLY); +#else + window_tv = SDL_CreateWindow(nullptr, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, 0); +#endif + //Setup window - window = SDL_CreateWindow(nullptr, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, 0); - if (!window) { + if (!window_tv) { DEBUG_FUNCTION_LINE("Failed to create window"); return; } - auto sdl_renderer = SDL_CreateRenderer(window, -1, SDLFlags); - if (!sdl_renderer) { + auto sdl_renderer_tv = SDL_CreateRenderer(window_tv, -1, SDLFlags); + if (!sdl_renderer_tv) { DEBUG_FUNCTION_LINE("Failed to init sdl renderer"); return; } - SDL_SetRenderTarget(sdl_renderer, nullptr); - this->renderer = new Renderer(sdl_renderer, SDL_GetWindowPixelFormat(window)); - if (!renderer) { - DEBUG_FUNCTION_LINE("Failed to init renderer"); + SDL_SetRenderTarget(sdl_renderer_tv, nullptr); + this->renderer_tv = new Renderer(sdl_renderer_tv, SDL_GetWindowPixelFormat(window_tv), Renderer::TARGET_TV); + if (!renderer_tv) { + DEBUG_FUNCTION_LINE("Failed to init renderer_tv"); + return; + } + +#ifdef __WIIU__ + window_drc = SDL_CreateWindow(nullptr, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_WIIU_GAMEPAD_ONLY ); +#else + window_drc = SDL_CreateWindow(nullptr, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, 0); +#endif + + //Setup window + if (!window_drc) { + DEBUG_FUNCTION_LINE("Failed to create window"); + return; + } + auto sdl_renderer_drc = SDL_CreateRenderer(window_drc, -1, SDLFlags); + if (!sdl_renderer_drc) { + DEBUG_FUNCTION_LINE("Failed to init sdl renderer"); + return; + } + SDL_SetRenderTarget(sdl_renderer_drc, nullptr); + this->renderer_drc = new Renderer(sdl_renderer_drc, SDL_GetWindowPixelFormat(window_drc), Renderer::TARGET_DRC); + if (!renderer_drc) { + DEBUG_FUNCTION_LINE("Failed to init renderer_tv"); return; } @@ -59,23 +93,29 @@ SDLSystem::SDLSystem() { } SDLSystem::~SDLSystem() { - SDL_DestroyWindow(window); - delete renderer; + SDL_DestroyWindow(window_tv); + SDL_DestroyWindow(window_drc); + delete renderer_tv; + delete renderer_drc; SDL_Quit(); } float SDLSystem::getHeight() { int h = 0; - SDL_GetWindowSize(window, nullptr, &h); + SDL_GetWindowSize(window_tv, nullptr, &h); return h; } float SDLSystem::getWidth() { int w = 0; - SDL_GetWindowSize(window, &w, nullptr); + SDL_GetWindowSize(window_tv, &w, nullptr); return w; } -Renderer *SDLSystem::getRenderer() { - return renderer; +Renderer *SDLSystem::getRendererTV() { + return renderer_tv; +} + +Renderer *SDLSystem::getRendererDRC() { + return renderer_drc; } diff --git a/src/system/SDLSystem.h b/src/system/SDLSystem.h index 795920c..b7897b2 100644 --- a/src/system/SDLSystem.h +++ b/src/system/SDLSystem.h @@ -24,12 +24,15 @@ public: virtual ~SDLSystem(); - Renderer *getRenderer(); + Renderer *getRendererTV(); + Renderer *getRendererDRC(); float getHeight(); float getWidth(); private: - SDL_Window *window = NULL; - Renderer *renderer = NULL; + SDL_Window *window_tv = nullptr; + SDL_Window *window_drc = nullptr; + Renderer *renderer_tv = nullptr; + Renderer *renderer_drc = nullptr; }; \ No newline at end of file diff --git a/src/system/video/Renderer.h b/src/system/video/Renderer.h index 8b1d745..a573c07 100644 --- a/src/system/video/Renderer.h +++ b/src/system/video/Renderer.h @@ -4,7 +4,16 @@ class Renderer { public: - Renderer(SDL_Renderer *renderer, uint32_t pixelFormat) : sdl_renderer(renderer), pixelFormat(pixelFormat){ + enum RendererTarget { + TARGET_TV = 0x00, + TARGET_DRC = 0x01, + }; + + Renderer(SDL_Renderer *renderer, uint32_t pixelFormat, RendererTarget renderTarget) : + sdl_renderer(renderer), + pixelFormat(pixelFormat), + renderTarget(renderTarget) + { } @@ -22,7 +31,12 @@ public: return pixelFormat; } + RendererTarget getTarget(){ + return renderTarget; + } + private: SDL_Renderer *sdl_renderer = NULL; uint32_t pixelFormat = SDL_PIXELFORMAT_RGBA8888; + RendererTarget renderTarget = TARGET_TV; }; \ No newline at end of file diff --git a/src/system/video/SDL_FontCache.cpp b/src/system/video/SDL_FontCache.cpp index 65efc39..751f205 100644 --- a/src/system/video/SDL_FontCache.cpp +++ b/src/system/video/SDL_FontCache.cpp @@ -417,8 +417,6 @@ static FC_GlyphData* FC_MapFind(FC_Map* map, Uint32 codepoint) return NULL; } - - struct FC_Font { #ifndef FC_USE_SDL_GPU @@ -451,10 +449,10 @@ struct FC_Font FC_Image** glyph_cache; char* loading_string; - - std::recursive_mutex* mutex = nullptr; }; +std::recursive_mutex mutex; + // Private static FC_GlyphData* FC_PackGlyphData(FC_Font* font, Uint32 codepoint, Uint16 width, Uint16 maxWidth, Uint16 maxHeight); @@ -702,6 +700,7 @@ FC_Rect FC_DefaultRenderCallback(FC_Image* src, FC_Rect* srcrect, FC_Target* des SDL_Rect r = *srcrect; SDL_Rect dr = {(int)x, (int)y, (int)(xscale*r.w), (int)(yscale*r.h)}; + DEBUG_FUNCTION_LINE("Src. %08X",src); SDL_RenderCopyEx(dest, src, &r, &dr, 0, NULL, flip); } #endif @@ -890,8 +889,6 @@ static void FC_Init(FC_Font* font) font->glyph_cache_size = 3; font->glyph_cache_count = 0; - font->mutex = new std::recursive_mutex(); - font->glyph_cache = (FC_Image**)malloc(font->glyph_cache_size * sizeof(FC_Image*)); if (font->loading_string == NULL) @@ -1177,7 +1174,7 @@ Uint8 FC_LoadFontFromTTF(FC_Font* font, SDL_Renderer* renderer, TTF_Font* ttf, S #endif FC_ClearFont(font); - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); // Might as well check render target support here #ifdef FC_USE_SDL_GPU @@ -1431,9 +1428,6 @@ void FC_ClearFont(FC_Font* font) } free(font->glyph_cache); font->glyph_cache = NULL; - delete font->mutex; - - font->mutex = nullptr; // Reset font FC_Init(font); @@ -1769,7 +1763,7 @@ FC_Rect FC_Draw(FC_Font* font, FC_Target* dest, float x, float y, const char* fo if(formatted_text == NULL || font == NULL) return FC_MakeRect(x, y, 0, 0); - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); set_color_for_all_caches(font, font->default_color); @@ -2061,7 +2055,7 @@ FC_Rect FC_DrawBox(FC_Font* font, FC_Target* dest, FC_Rect box, const char* form if(formatted_text == NULL || font == NULL) return FC_MakeRect(box.x, box.y, 0, 0); - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2095,7 +2089,7 @@ FC_Rect FC_DrawBoxAlign(FC_Font* font, FC_Target* dest, FC_Rect box, FC_AlignEnu if(formatted_text == NULL || font == NULL) return FC_MakeRect(box.x, box.y, 0, 0); - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2128,7 +2122,7 @@ FC_Rect FC_DrawBoxScale(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Scale sc if(formatted_text == NULL || font == NULL) return FC_MakeRect(box.x, box.y, 0, 0); - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2161,7 +2155,7 @@ FC_Rect FC_DrawBoxColor(FC_Font* font, FC_Target* dest, FC_Rect box, SDL_Color c if(formatted_text == NULL || font == NULL) return FC_MakeRect(box.x, box.y, 0, 0); - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2194,7 +2188,7 @@ FC_Rect FC_DrawBoxEffect(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Effect if(formatted_text == NULL || font == NULL) return FC_MakeRect(box.x, box.y, 0, 0); - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2229,7 +2223,7 @@ FC_Rect FC_DrawColumn(FC_Font* font, FC_Target* dest, float x, float y, Uint16 w if(formatted_text == NULL || font == NULL) return FC_MakeRect(x, y, 0, 0); - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2244,7 +2238,7 @@ FC_Rect FC_DrawColumn(FC_Font* font, FC_Target* dest, float x, float y, Uint16 w FC_Rect FC_DrawColumnToTexture(FC_Font* font, SDL_Texture* target, float x, float y, Uint16 width, const char* text) { - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); // Draw the text onto it SDL_SetRenderTarget(font->renderer, target); @@ -2264,7 +2258,7 @@ FC_Rect FC_DrawColumnAlign(FC_Font* font, FC_Target* dest, float x, float y, Uin if(formatted_text == NULL || font == NULL) return FC_MakeRect(x, y, 0, 0); - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2297,7 +2291,7 @@ FC_Rect FC_DrawColumnScale(FC_Font* font, FC_Target* dest, float x, float y, Uin if(formatted_text == NULL || font == NULL) return FC_MakeRect(x, y, 0, 0); - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2320,7 +2314,7 @@ FC_Rect FC_DrawColumnColor(FC_Font* font, FC_Target* dest, float x, float y, Uin if(formatted_text == NULL || font == NULL) return FC_MakeRect(x, y, 0, 0); - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2343,7 +2337,7 @@ FC_Rect FC_DrawColumnEffect(FC_Font* font, FC_Target* dest, float x, float y, Ui if(formatted_text == NULL || font == NULL) return FC_MakeRect(x, y, 0, 0); - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2441,7 +2435,7 @@ FC_Rect FC_DrawScale(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale if(formatted_text == NULL || font == NULL) return FC_MakeRect(x, y, 0, 0); - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2459,7 +2453,7 @@ FC_Rect FC_DrawAlign(FC_Font* font, FC_Target* dest, float x, float y, FC_AlignE if(formatted_text == NULL || font == NULL) return FC_MakeRect(x, y, 0, 0); - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2492,7 +2486,7 @@ FC_Rect FC_DrawColor(FC_Font* font, FC_Target* dest, float x, float y, SDL_Color if(formatted_text == NULL || font == NULL) return FC_MakeRect(x, y, 0, 0); - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2511,7 +2505,7 @@ FC_Rect FC_DrawEffect(FC_Font* font, FC_Target* dest, float x, float y, FC_Effec if(formatted_text == NULL || font == NULL) return FC_MakeRect(x, y, 0, 0); - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2566,7 +2560,7 @@ Uint16 FC_GetHeight(FC_Font* font, const char* formatted_text, ...) if(formatted_text == NULL || font == NULL) return 0; - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2592,7 +2586,7 @@ Uint16 FC_GetWidth(FC_Font* font, const char* formatted_text, ...) if(formatted_text == NULL || font == NULL) return 0; - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2632,7 +2626,7 @@ FC_Rect FC_GetCharacterOffset(FC_Font* font, Uint16 position_index, int column_w if(formatted_text == NULL || column_width == 0 || position_index == 0 || font == NULL) return result; - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2691,7 +2685,7 @@ Uint16 FC_GetColumnHeight(FC_Font* font, Uint16 width, const char* formatted_tex if(formatted_text == NULL || width == 0) return font->height; - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2743,7 +2737,7 @@ int FC_GetAscent(FC_Font* font, const char* formatted_text, ...) if(formatted_text == NULL) return font->ascent; - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2779,7 +2773,7 @@ int FC_GetDescent(FC_Font* font, const char* formatted_text, ...) if(formatted_text == NULL) return font->descent; - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2898,7 +2892,7 @@ Uint16 FC_GetPositionFromOffset(FC_Font* font, float x, float y, int column_widt if(formatted_text == NULL || column_width == 0 || font == NULL) return 0; - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); @@ -2946,7 +2940,7 @@ int FC_GetWrappedText(FC_Font* font, char* result, int max_result_size, Uint16 w if(formatted_text == NULL || width == 0) return 0; - std::scoped_lock lock(*font->mutex); + std::scoped_lock lock(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);