diff --git a/.github/workflows/pc-win.yml b/.github/workflows/pc-win.yml new file mode 100644 index 0000000..841319b --- /dev/null +++ b/.github/workflows/pc-win.yml @@ -0,0 +1,18 @@ +name: Windows building. +on: + push: + branches: + - master +jobs: + build-binary: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - name: build binary + run: | + docker build . -f .\Dockerfile.pc-win -t sdl2_playground-builder-pc-win + docker run --rm -v ${PWD}:/project sdl2_playground-builder-pc-win make -f .\Makefile.pc-win + - uses: actions/upload-artifact@master + with: + name: binary + path: "*.exe" \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 7250130..3b9673f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,8 +11,8 @@ add_executable(${PROJECT_NAME} src/gui/GuiImage.cpp src/gui/GuiImage.h src/gui/sigslot.h - src/CVideo.cpp - src/CVideo.h + src/system/SDLSystem.cpp + src/system/SDLSystem.h src/gui/GuiElement.cpp src/gui/GuiText.cpp src/gui/GuiText.h @@ -25,13 +25,14 @@ add_executable(${PROJECT_NAME} src/gui/GuiButton.h - src/gui/SDLController.h src/MainWindow.cpp src/MainWindow.h src/gui/SDLControllerJoystick.h src/gui/SDLControllerMouse.h - src/gui/SDLControllerWiiUGamepad.h - src/gui/SDLControllerWiiUProContoller.h + src/input/SDLController.h src/menu/MainWindow.cpp src/menu/MainWindow.h src/input/SDLControllerJoystick.h src/input/SDLControllerMouse.h + src/input/SDLControllerWiiUGamepad.h + src/input/SDLControllerWiiUProContoller.h src/gui/GuiTexture.cpp src/gui/GuiTexture.h - src/gui/SDL_FontCache.h src/gui/SDL_FontCache.c + src/system/video/SDL_FontCache.h + src/system/video/SDL_FontCache.cpp - ) + src/system/video/Renderer.h src/input/ControllerManager.cpp src/input/ControllerManager.h) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/sdl2) diff --git a/Makefile.pc-win b/Makefile.pc-win index 3062acc..64944a1 100644 --- a/Makefile.pc-win +++ b/Makefile.pc-win @@ -28,7 +28,12 @@ endif TARGET := SDL2_Playground BUILD := build-pc-win SOURCES := src \ - src/gui + src/gui \ + src/input \ + src/menu \ + src/system \ + src/system/video \ + src/utils DATA := data INCLUDES := source diff --git a/Makefile.wiiu b/Makefile.wiiu index 2c70735..a5e2d3c 100644 --- a/Makefile.wiiu +++ b/Makefile.wiiu @@ -21,7 +21,12 @@ WUMS_ROOT := $(DEVKITPRO)/wums TARGET := SDL2_Playground BUILD := build SOURCES := src \ - src/gui + src/gui \ + src/input \ + src/menu \ + src/system \ + src/system/video \ + src/utils DATA := data INCLUDES := source diff --git a/src/gui/GuiButton.cpp b/src/gui/GuiButton.cpp index d3af71f..dd79357 100644 --- a/src/gui/GuiButton.cpp +++ b/src/gui/GuiButton.cpp @@ -133,7 +133,7 @@ void GuiButton::setTrigger(GuiTrigger *t, int32_t idx) { } } -void GuiButton::resetState(void) { +void GuiButton::resetState() { clickedTrigger = NULL; heldTrigger = NULL; GuiElement::resetState(); @@ -142,7 +142,7 @@ void GuiButton::resetState(void) { /** * Draw the button on screen */ -void GuiButton::draw(CVideo *v) { +void GuiButton::draw(Renderer *v) { if (!this->isVisible()) { return; } diff --git a/src/gui/GuiButton.h b/src/gui/GuiButton.h index 2bcbd73..6a4390a 100644 --- a/src/gui/GuiButton.h +++ b/src/gui/GuiButton.h @@ -20,7 +20,7 @@ #include "GuiText.h" #include "GuiSound.h" #include "GuiTrigger.h" -#include "../CVideo.h" +#include "../system/SDLSystem.h" //!Display, manage, and manipulate buttons in the GUI. Buttons can have images, icons, text, and sound set (all of which are optional) class GuiButton : public GuiElement { @@ -94,7 +94,7 @@ public: void resetState(void) override; //!Constantly called to draw the GuiButton - void draw(CVideo *video) override; + void draw(Renderer *video) override; //!Constantly called to allow the GuiButton to respond to updated input data //!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD diff --git a/src/gui/GuiElement.h b/src/gui/GuiElement.h index 8d95e97..e258679 100644 --- a/src/gui/GuiElement.h +++ b/src/gui/GuiElement.h @@ -20,14 +20,15 @@ #include #include -#include -#include -#include +#include +#include +#include #include -#include -#include +#include +#include #include #include "sigslot.h" +#include "../system/video/Renderer.h" enum { EFFECT_NONE = 0x00, @@ -59,7 +60,7 @@ enum { //!Forward declaration class GuiController; -class CVideo; +class SDLSystem; //!Primary GUI class. Most other classes inherit from this class. class GuiElement { @@ -524,7 +525,7 @@ public: virtual void update(GuiController *t) {} //!Called constantly to redraw the element - virtual void draw(CVideo *v) {} + virtual void draw(Renderer * v) {} //!Called constantly to process stuff in the element virtual void process() {} diff --git a/src/gui/GuiFrame.cpp b/src/gui/GuiFrame.cpp index 7b259eb..e699946 100644 --- a/src/gui/GuiFrame.cpp +++ b/src/gui/GuiFrame.cpp @@ -15,6 +15,7 @@ * along with this program. If not, see . ****************************************************************************/ #include "GuiFrame.h" +#include "../system/video/Renderer.h" GuiFrame::GuiFrame(GuiFrame *p) { parent = p; @@ -156,12 +157,12 @@ int32_t GuiFrame::getSelected() { return found; } -void GuiFrame::draw(CVideo *v) { +void GuiFrame::draw(Renderer *v) { if (!this->isVisible() && parentElement) { return; } - if (parentElement && dim == true) { + if (parentElement && dim) { //GXColor dimColor = (GXColor){0, 0, 0, 0x70}; //Menu_DrawRectangle(0, 0, GetZPosition(), screenwidth,screenheight, &dimColor, false, true); } diff --git a/src/gui/GuiFrame.h b/src/gui/GuiFrame.h index ef97816..6297660 100644 --- a/src/gui/GuiFrame.h +++ b/src/gui/GuiFrame.h @@ -20,6 +20,7 @@ #include #include "GuiElement.h" #include "sigslot.h" +#include "../system/video/Renderer.h" //!Allows GuiElements to be grouped together into a "window" class GuiFrame : public GuiElement { @@ -33,7 +34,7 @@ public: GuiFrame(float w, float h, GuiFrame *parent = 0); //!Destructor - virtual ~GuiFrame(); + ~GuiFrame() override; //!Appends a GuiElement to the GuiFrame //!\param e The GuiElement to append. If it is already in the GuiFrame, it is removed first @@ -84,7 +85,7 @@ public: int32_t getSelected() override; //!Draws all the elements in this GuiFrame - void draw(CVideo *v) override; + void draw(Renderer *v) override; //!Updates the window and all elements contains within //!Allows the GuiFrame and all elements to respond to the input data specified diff --git a/src/gui/GuiImage.cpp b/src/gui/GuiImage.cpp index 038a30e..36ff4ff 100644 --- a/src/gui/GuiImage.cpp +++ b/src/gui/GuiImage.cpp @@ -17,7 +17,7 @@ #include #include #include "GuiImage.h" -#include "../CVideo.h" +#include "../system/SDLSystem.h" GuiImage::GuiImage(const std::string& path) : GuiTexture(path){ } diff --git a/src/gui/GuiSound.cpp b/src/gui/GuiSound.cpp index db3323b..3419333 100644 --- a/src/gui/GuiSound.cpp +++ b/src/gui/GuiSound.cpp @@ -15,7 +15,7 @@ * along with this program. If not, see . ****************************************************************************/ #include "GuiSound.h" -#include "../logger.h" +#include "../utils/logger.h" GuiSound::GuiSound(const char *filepath) { Load(filepath); diff --git a/src/gui/GuiText.cpp b/src/gui/GuiText.cpp index aa2d483..b712189 100644 --- a/src/gui/GuiText.cpp +++ b/src/gui/GuiText.cpp @@ -17,23 +17,17 @@ #include #include #include "GuiText.h" -#include "../CVideo.h" -#include "../logger.h" -#include "SDL_FontCache.h" - /** * Constructor for the GuiText class. */ -GuiText::GuiText(const std::string& text, int32_t s, SDL_Color c, TTF_Font* gFont) { +GuiText::GuiText(const std::string& text, SDL_Color c, FC_Font* gFont) { this->text = text; - this->size = s; this->color = c; - this->ttf_font = gFont; - this->invalid = true; - this->updateText = true; - this->maxWidth = 200; + this->fc_font = gFont; + updateSize(); + this->doUpdateTexture = true; } GuiText::~GuiText(){ @@ -44,61 +38,51 @@ GuiText::~GuiText(){ delete texture; } -void GuiText::draw(CVideo *pVideo) { +void GuiText::draw(Renderer *renderer) { if (!this->isVisible()) { return; } - if(invalid){ - if(fc_font){ - FC_FreeFont(fc_font); - fc_font = nullptr; - } - fc_font = FC_CreateFont(); - invalid = !FC_LoadFontFromTTF(fc_font, pVideo->getRenderer(), this->ttf_font, color); - DEBUG_FUNCTION_LINE("FC_CACHE init done"); - } - if(updateText || !texture){ - delete texture; - // Create the intermediate texture target - SDL_Texture* temp = SDL_CreateTexture(pVideo->getRenderer(), pVideo->getPixelFormat(), SDL_TEXTUREACCESS_TARGET, width, height); - if(temp){ - texture = new GuiTexture(temp); - texture->setParent(this); - texture->setBlendMode(SDL_BLENDMODE_BLEND); - - // Draw the text onto it - SDL_SetRenderTarget(pVideo->getRenderer(), temp); - // make sure the texture is clean. - SDL_RenderClear(pVideo->getRenderer()); - FC_DrawColumn(fc_font, pVideo->getRenderer(), 0, 0, maxWidth, text.c_str()); - SDL_SetRenderTarget(pVideo->getRenderer(), NULL); - - updateText = false; - }else{ - DEBUG_FUNCTION_LINE("Failed to create texture"); - } - - } + updateTexture(renderer); if(texture){ - texture->draw(pVideo); + texture->draw(renderer); } } void GuiText::process() { GuiElement::process(); - - if(updateText && fc_font){ - auto height = FC_GetColumnHeight(fc_font, maxWidth, text.c_str()); - auto width = FC_GetWidth(fc_font, text.c_str()); - width = width > maxWidth ? maxWidth : width; - this->setSize(width, height); - } } void GuiText::setMaxWidth(float width) { this->maxWidth = width; + // Rebuild the texture cache. - updateText = true; + doUpdateTexture = true; +} + +void GuiText::updateSize() { + auto height = FC_GetColumnHeight(fc_font, maxWidth, text.c_str()); + auto width = FC_GetWidth(fc_font, text.c_str()); + width = width > maxWidth ? maxWidth : width; + this->setSize(width, height); +} + +void GuiText::updateTexture(Renderer *renderer) { + if(!texture || doUpdateTexture) { + updateSize(); + + SDL_Texture *temp = SDL_CreateTexture(renderer->getRenderer(), renderer->getPixelFormat(), SDL_TEXTUREACCESS_TARGET, (int) width, (int) height); + if (temp) { + delete texture; + texture = new GuiTexture(temp); + texture->setParent(this); + texture->setBlendMode(SDL_BLENDMODE_BLEND); + + FC_DrawColumnToTexture(fc_font, temp, 0, 0, maxWidth, text.c_str()); + doUpdateTexture = false; + } else { + DEBUG_FUNCTION_LINE("Failed to create texture"); + } + } } diff --git a/src/gui/GuiText.h b/src/gui/GuiText.h index 9e7b40b..83a292b 100644 --- a/src/gui/GuiText.h +++ b/src/gui/GuiText.h @@ -17,12 +17,11 @@ #pragma once #include "GuiElement.h" -#include "SDL_FontCache.h" #include "GuiTexture.h" +#include "../system/video/SDL_FontCache.h" #include #include - //!Display, manage, and manipulate text in the GUI class GuiText : public GuiElement { public: @@ -30,10 +29,10 @@ public: //!\param t Text //!\param s Font size //!\param c Font color - GuiText(const std::string &t, int32_t s, SDL_Color c, TTF_Font *gFont); + GuiText(const std::string &t, SDL_Color c, FC_Font *font); ~GuiText() override; - void draw(CVideo *pVideo) override; + void draw(Renderer *pVideo) override; void process() override; @@ -42,12 +41,13 @@ public: protected: GuiTexture* texture = nullptr; std::string text; - int32_t size; SDL_Color color; - TTF_Font *ttf_font = nullptr; FC_Font *fc_font = nullptr; - bool invalid = true; - bool updateText = true; + bool doUpdateTexture = true; uint16_t maxWidth = 0xFFFF; + + void updateSize(); + + void updateTexture(Renderer *renderer); }; diff --git a/src/gui/GuiTexture.cpp b/src/gui/GuiTexture.cpp index 52cc8da..db2061e 100644 --- a/src/gui/GuiTexture.cpp +++ b/src/gui/GuiTexture.cpp @@ -1,7 +1,7 @@ #include #include "GuiTexture.h" -#include "../CVideo.h" -#include "../logger.h" +#include "../system/SDLSystem.h" +#include "../utils/logger.h" GuiTexture::GuiTexture(const std::string& path) { imgSurface = IMG_Load( path.c_str() ); @@ -49,20 +49,20 @@ GuiTexture::~GuiTexture() { } } -void GuiTexture::draw(CVideo *pVideo) { +void GuiTexture::draw(Renderer *renderer) { if (!this->isVisible()) { DEBUG_FUNCTION_LINE("not visible!"); return; } if (texture == NULL && imgSurface) { - SDL_Surface *optimizedSurface = SDL_ConvertSurfaceFormat(imgSurface, pVideo->getPixelFormat(), 0); + SDL_Surface *optimizedSurface = SDL_ConvertSurfaceFormat(imgSurface, renderer->getPixelFormat(), 0); if (optimizedSurface != NULL) { SDL_FreeSurface(imgSurface); imgSurface = optimizedSurface; DEBUG_FUNCTION_LINE("Optimized surface"); } - texture = SDL_CreateTextureFromSurface(pVideo->getRenderer(), imgSurface); + texture = SDL_CreateTextureFromSurface(renderer->getRenderer(), imgSurface); } if (!texture) { DEBUG_FUNCTION_LINE("no texture!"); @@ -79,9 +79,9 @@ void GuiTexture::draw(CVideo *pVideo) { rect.h = currScaleY * getHeight(); if (getAngle() == 0) { - SDL_RenderCopy(pVideo->getRenderer(), texture, nullptr, &rect); + SDL_RenderCopy(renderer->getRenderer(), texture, nullptr, &rect); } else { - SDL_RenderCopyEx(pVideo->getRenderer(), texture, nullptr, &rect, getAngle(), nullptr, SDL_FLIP_NONE); + SDL_RenderCopyEx(renderer->getRenderer(), texture, nullptr, &rect, getAngle(), nullptr, SDL_FLIP_NONE); } } diff --git a/src/gui/GuiTexture.h b/src/gui/GuiTexture.h index 027dcce..36b1d9c 100644 --- a/src/gui/GuiTexture.h +++ b/src/gui/GuiTexture.h @@ -12,7 +12,7 @@ public: ~GuiTexture() override; //!Constantly called to draw the image - void draw(CVideo *pVideo) override; + void draw(Renderer *pVideo) override; int setBlendMode(SDL_BlendMode blendMode); diff --git a/src/input/ControllerManager.cpp b/src/input/ControllerManager.cpp new file mode 100644 index 0000000..46fa852 --- /dev/null +++ b/src/input/ControllerManager.cpp @@ -0,0 +1,103 @@ +#include +#include "ControllerManager.h" +#include "SDLControllerWiiUGamepad.h" +#include "SDLControllerXboxOne.h" +#include "SDLControllerWiiUProContoller.h" +#include "SDLControllerJoystick.h" + +GuiTrigger::eChannels ControllerManager::increaseChannel(GuiTrigger::eChannels channel) { + switch (channel) { + case GuiTrigger::CHANNEL_1: + return GuiTrigger::CHANNEL_2; + case GuiTrigger::CHANNEL_2: + return GuiTrigger::CHANNEL_3; + case GuiTrigger::CHANNEL_3: + return GuiTrigger::CHANNEL_4; + case GuiTrigger::CHANNEL_4: + return GuiTrigger::CHANNEL_5; + case GuiTrigger::CHANNEL_5: + case GuiTrigger::CHANNEL_ALL: + return GuiTrigger::CHANNEL_ALL; + } + return GuiTrigger::CHANNEL_ALL; +} + +void ControllerManager::attachController(GuiTrigger::eChannels channel, SDLController *controller) { + controllerList[channel] = controller; +} + +void ControllerManager::prepare() { + //! Read out inputs + for (auto const&[channel, controller] : controllerList) { + controller->before(); + } +} + +bool ControllerManager::attachJoystick(int32_t deviceId) { + auto joystick = SDL_JoystickOpen(deviceId); + if (joystick == nullptr) { + DEBUG_FUNCTION_LINE("SDL_JoystickOpen failed: %s\n", SDL_GetError()); + return false; + } + auto instanceId = SDL_JoystickInstanceID(joystick); + if (std::string("WiiU Gamepad") == SDL_JoystickName(joystick)) { + controllerList[GuiTrigger::CHANNEL_1] = new SDLControllerWiiUGamepad(GuiTrigger::CHANNEL_1); + joystickToChannel[instanceId] = GuiTrigger::CHANNEL_1; + } else { + bool successfully_added = false; + auto channel = GuiTrigger::CHANNEL_2; + while (channel != GuiTrigger::CHANNEL_ALL) { + if (controllerList.find(channel) == controllerList.end()) { + if (std::string(SDL_JoystickName(joystick)).find("Xbox") != std::string::npos) { + controllerList[channel] = new SDLControllerXboxOne(channel); + } else if (std::string(SDL_JoystickName(joystick)).find("WiiU Pro Controller") != std::string::npos) { + controllerList[channel] = new SDLControllerWiiUProContoller(channel); + } else { + controllerList[channel] = new SDLControllerJoystick(channel, instanceId); + } + joystickToChannel[instanceId] = channel; + successfully_added = true; + break; + } + channel = increaseChannel(channel); + } + if (!successfully_added) { + DEBUG_FUNCTION_LINE("Failed to add joystick. Closing it now"); + SDL_JoystickClose(joystick); + return false; + } + } + DEBUG_FUNCTION_LINE("Added joystick %s", SDL_JoystickName(joystick)); + return true; +} + +void ControllerManager::detachJoystick(int32_t instanceId) { + auto channel = joystickToChannel[instanceId]; + delete controllerList[channel]; + controllerList.erase(channel); + joystickToChannel.erase(instanceId); + DEBUG_FUNCTION_LINE("Removed joystick: %d", instanceId); +} + +void ControllerManager::processEvent(SDL_JoystickID joystickId, int32_t channel, SDL_Event *e) { + if (joystickId != -1) { + if (joystickToChannel.find(joystickId) != joystickToChannel.end()) { + channel = joystickToChannel[joystickId]; + } + } + if (channel != -1) { + controllerList[static_cast(channel)]->update(e, screenWidth, screenHeight); + } +} + +void ControllerManager::finish() { + for (auto const&[joypad, controller] : controllerList) { + controller->after(); + } +} + +void ControllerManager::callPerController(std::function func) { + for (auto const&[joypad, controller] : controllerList) { + func(controller); + } +} diff --git a/src/input/ControllerManager.h b/src/input/ControllerManager.h new file mode 100644 index 0000000..53b5b2e --- /dev/null +++ b/src/input/ControllerManager.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include "../gui/GuiTrigger.h" +#include "SDLController.h" +#include "SDLControllerMouse.h" + +class ControllerManager { +public: + ControllerManager(int32_t screenWidth, int32_t screenHeight) : screenWidth(screenWidth), screenHeight(screenHeight){ + + } + + void attachController(GuiTrigger::eChannels channels, SDLController *controller); + + void prepare(); + + bool attachJoystick(int32_t deviceId); + + void detachJoystick(int32_t deviceId); + + void processEvent(SDL_JoystickID joystickId, int32_t channel, SDL_Event *event); + + void finish(); + + + void callPerController(std::function func); + +private: + GuiTrigger::eChannels increaseChannel(GuiTrigger::eChannels channel); + + std::map controllerList; + std::map joystickToChannel; + int32_t screenWidth; + int32_t screenHeight; +}; diff --git a/src/gui/SDLController.h b/src/input/SDLController.h similarity index 97% rename from src/gui/SDLController.h rename to src/input/SDLController.h index d0a0b35..81283e0 100644 --- a/src/gui/SDLController.h +++ b/src/input/SDLController.h @@ -3,8 +3,8 @@ #include #include #include -#include "GuiController.h" -#include "../logger.h" +#include "../gui/GuiController.h" +#include "../utils/logger.h" #define printButton(chan, x) if(data.buttons_d & x) DEBUG_FUNCTION_LINE("Controller #%d %s", chan, #x) diff --git a/src/gui/SDLControllerJoystick.h b/src/input/SDLControllerJoystick.h similarity index 100% rename from src/gui/SDLControllerJoystick.h rename to src/input/SDLControllerJoystick.h diff --git a/src/gui/SDLControllerMouse.h b/src/input/SDLControllerMouse.h similarity index 96% rename from src/gui/SDLControllerMouse.h rename to src/input/SDLControllerMouse.h index 8a9d9cb..e3d1a43 100644 --- a/src/gui/SDLControllerMouse.h +++ b/src/input/SDLControllerMouse.h @@ -1,26 +1,26 @@ - -#pragma once - -class SDLControllerMouse: public SDLController { -public: - explicit SDLControllerMouse(int32_t channel) : SDLController(channel) { - - } - - virtual bool update(SDL_Event *e, int32_t screenWidth, int32_t screenHeight) override { - if (e->type == SDL_MOUSEMOTION) { - data.y = e->motion.y; - data.x = e->motion.x; - data.validPointer = true; - } else if (e->type == SDL_MOUSEBUTTONDOWN && e->button.button == SDL_BUTTON_LEFT) { - data.buttons_h |= GuiTrigger::TOUCHED; - } else if (e->type == SDL_MOUSEBUTTONUP && e->button.button == SDL_BUTTON_LEFT) { - data.buttons_h &= ~GuiTrigger::TOUCHED; - }else{ - DEBUG_FUNCTION_LINE("Unknown event"); - return false; - } - return true; - } -}; - + +#pragma once + +class SDLControllerMouse: public SDLController { +public: + explicit SDLControllerMouse(int32_t channel) : SDLController(channel) { + + } + + virtual bool update(SDL_Event *e, int32_t screenWidth, int32_t screenHeight) override { + if (e->type == SDL_MOUSEMOTION) { + data.y = e->motion.y; + data.x = e->motion.x; + data.validPointer = true; + } else if (e->type == SDL_MOUSEBUTTONDOWN && e->button.button == SDL_BUTTON_LEFT) { + data.buttons_h |= GuiTrigger::TOUCHED; + } else if (e->type == SDL_MOUSEBUTTONUP && e->button.button == SDL_BUTTON_LEFT) { + data.buttons_h &= ~GuiTrigger::TOUCHED; + }else{ + DEBUG_FUNCTION_LINE("Unknown event"); + return false; + } + return true; + } +}; + diff --git a/src/gui/SDLControllerWiiUGamepad.h b/src/input/SDLControllerWiiUGamepad.h similarity index 97% rename from src/gui/SDLControllerWiiUGamepad.h rename to src/input/SDLControllerWiiUGamepad.h index 2063539..d2972e3 100644 --- a/src/gui/SDLControllerWiiUGamepad.h +++ b/src/input/SDLControllerWiiUGamepad.h @@ -1,50 +1,50 @@ -#pragma once - - -#pragma once - -#include "SDLController.h" - -static GuiTrigger::eButtons vpad_button_map[] = { - GuiTrigger::BUTTON_A, - GuiTrigger::BUTTON_B, - GuiTrigger::BUTTON_X, - GuiTrigger::BUTTON_Y, - GuiTrigger::BUTTON_STICK_L, GuiTrigger::BUTTON_STICK_R, - GuiTrigger::BUTTON_L, GuiTrigger::BUTTON_R, - GuiTrigger::BUTTON_ZL, GuiTrigger::BUTTON_ZR, - GuiTrigger::BUTTON_PLUS, GuiTrigger::BUTTON_MINUS, - GuiTrigger::BUTTON_LEFT, GuiTrigger::BUTTON_UP, GuiTrigger::BUTTON_RIGHT, GuiTrigger::BUTTON_DOWN, - GuiTrigger::STICK_L_LEFT, GuiTrigger::STICK_L_UP, GuiTrigger::STICK_L_RIGHT, GuiTrigger::STICK_L_DOWN, - GuiTrigger::STICK_R_LEFT, GuiTrigger::STICK_R_UP, GuiTrigger::STICK_R_RIGHT, GuiTrigger::STICK_R_DOWN, -}; - -class SDLControllerWiiUGamepad : public SDLController { -public: - explicit SDLControllerWiiUGamepad(int32_t channel) : SDLController(channel) { - - } - - bool update(SDL_Event *e, int32_t screenWidth, int32_t screenHeight) override { - if (e->type == SDL_FINGERMOTION) { - data.y = e->tfinger.y * screenHeight; - data.x = e->tfinger.x * screenWidth;; - data.validPointer = true; - } else if (e->type == SDL_FINGERUP) { - data.validPointer = false; - data.buttons_h &= ~GuiTrigger::TOUCHED; - } else if (e->type == SDL_FINGERDOWN) { - data.validPointer = true; - data.buttons_h |= GuiTrigger::TOUCHED; - } else if (e->type == SDL_JOYBUTTONDOWN) { - data.buttons_h |= vpad_button_map[e->jbutton.button]; - } else if (e->type == SDL_JOYBUTTONUP) { - data.buttons_h &= ~vpad_button_map[e->jbutton.button]; - } else { - DEBUG_FUNCTION_LINE("Unknown event"); - return false; - } - return true; - } -}; - +#pragma once + + +#pragma once + +#include "SDLController.h" + +static GuiTrigger::eButtons vpad_button_map[] = { + GuiTrigger::BUTTON_A, + GuiTrigger::BUTTON_B, + GuiTrigger::BUTTON_X, + GuiTrigger::BUTTON_Y, + GuiTrigger::BUTTON_STICK_L, GuiTrigger::BUTTON_STICK_R, + GuiTrigger::BUTTON_L, GuiTrigger::BUTTON_R, + GuiTrigger::BUTTON_ZL, GuiTrigger::BUTTON_ZR, + GuiTrigger::BUTTON_PLUS, GuiTrigger::BUTTON_MINUS, + GuiTrigger::BUTTON_LEFT, GuiTrigger::BUTTON_UP, GuiTrigger::BUTTON_RIGHT, GuiTrigger::BUTTON_DOWN, + GuiTrigger::STICK_L_LEFT, GuiTrigger::STICK_L_UP, GuiTrigger::STICK_L_RIGHT, GuiTrigger::STICK_L_DOWN, + GuiTrigger::STICK_R_LEFT, GuiTrigger::STICK_R_UP, GuiTrigger::STICK_R_RIGHT, GuiTrigger::STICK_R_DOWN, +}; + +class SDLControllerWiiUGamepad : public SDLController { +public: + explicit SDLControllerWiiUGamepad(int32_t channel) : SDLController(channel) { + + } + + bool update(SDL_Event *e, int32_t screenWidth, int32_t screenHeight) override { + if (e->type == SDL_FINGERMOTION) { + data.y = e->tfinger.y * screenHeight; + data.x = e->tfinger.x * screenWidth;; + data.validPointer = true; + } else if (e->type == SDL_FINGERUP) { + data.validPointer = false; + data.buttons_h &= ~GuiTrigger::TOUCHED; + } else if (e->type == SDL_FINGERDOWN) { + data.validPointer = true; + data.buttons_h |= GuiTrigger::TOUCHED; + } else if (e->type == SDL_JOYBUTTONDOWN) { + data.buttons_h |= vpad_button_map[e->jbutton.button]; + } else if (e->type == SDL_JOYBUTTONUP) { + data.buttons_h &= ~vpad_button_map[e->jbutton.button]; + } else { + DEBUG_FUNCTION_LINE("Unknown event"); + return false; + } + return true; + } +}; + diff --git a/src/gui/SDLControllerWiiUProContoller.h b/src/input/SDLControllerWiiUProContoller.h similarity index 95% rename from src/gui/SDLControllerWiiUProContoller.h rename to src/input/SDLControllerWiiUProContoller.h index 98684ee..1fa5451 100644 --- a/src/gui/SDLControllerWiiUProContoller.h +++ b/src/input/SDLControllerWiiUProContoller.h @@ -1,11 +1,11 @@ -#pragma once - -#include "SDLControllerWiiUGamepad.h" - -class SDLControllerWiiUProContoller : public SDLControllerWiiUGamepad { -public: - explicit SDLControllerWiiUProContoller(int32_t channel) : SDLControllerWiiUGamepad(channel){ - - } -}; - +#pragma once + +#include "SDLControllerWiiUGamepad.h" + +class SDLControllerWiiUProContoller : public SDLControllerWiiUGamepad { +public: + explicit SDLControllerWiiUProContoller(int32_t channel) : SDLControllerWiiUGamepad(channel){ + + } +}; + diff --git a/src/gui/SDLControllerXboxOne.h b/src/input/SDLControllerXboxOne.h similarity index 97% rename from src/gui/SDLControllerXboxOne.h rename to src/input/SDLControllerXboxOne.h index c3cca45..222732a 100644 --- a/src/gui/SDLControllerXboxOne.h +++ b/src/input/SDLControllerXboxOne.h @@ -1,106 +1,106 @@ -#pragma once - -#include "SDLController.h" - -static GuiTrigger::eButtons xbox_button_map[] = - { - GuiTrigger::BUTTON_A, - GuiTrigger::BUTTON_B, - GuiTrigger::BUTTON_X, - GuiTrigger::BUTTON_Y, - GuiTrigger::BUTTON_L, - GuiTrigger::BUTTON_R, - GuiTrigger::BUTTON_MINUS, - GuiTrigger::BUTTON_PLUS, - GuiTrigger::BUTTON_STICK_L, - GuiTrigger::BUTTON_STICK_R, - }; - -#define getDigitalAxis(axis, targetAxis, value, hold, first, second) \ -if(axis == targetAxis){ \ - if (value < 0x4000 && value > -0x4000){ \ - hold &= ~first; \ - hold &= ~second; \ - }else if(value < -0x4000){ \ - hold |= first; \ - hold &= ~second; \ - }else if(value > 0x4000){ \ - hold |= second; \ - hold &= ~first; \ - } \ -} \ - -#define getDigitalTrigger(axis, targetAxis, value, hold, first) \ -if(axis == targetAxis){ \ - if(value > 0){ \ - hold |= first; \ - }else{ \ - hold &= ~first; \ - } \ -} \ - - -class SDLControllerXboxOne : public SDLController { -public: - explicit SDLControllerXboxOne(int32_t channel) : SDLController(channel) { - - } - - bool update(SDL_Event *e, int32_t screenWidth, int32_t screenHeight) override { - if (e->type == SDL_JOYBUTTONDOWN) { - data.buttons_h |= xbox_button_map[e->jbutton.button]; - } else if (e->type == SDL_JOYBUTTONUP) { - data.buttons_h &= ~xbox_button_map[e->jbutton.button]; - } else if (e->type == SDL_JOYHATMOTION) { - auto val = e->jhat.value; - - auto hatMask = (GuiTrigger::BUTTON_LEFT | GuiTrigger::BUTTON_UP | GuiTrigger::BUTTON_DOWN | GuiTrigger::BUTTON_RIGHT); - - // Remove hat values so we can add the new values. - data.buttons_h &= ~hatMask; - - switch (val) { - case SDL_HAT_LEFTUP: - data.buttons_h |= GuiTrigger::BUTTON_LEFT; - data.buttons_h |= GuiTrigger::BUTTON_UP; - break; - case SDL_HAT_LEFT: - data.buttons_h |= GuiTrigger::BUTTON_LEFT; - break; - case SDL_HAT_LEFTDOWN: - data.buttons_h |= GuiTrigger::BUTTON_LEFT; - data.buttons_h |= GuiTrigger::BUTTON_DOWN; - break; - case SDL_HAT_UP: - data.buttons_h |= GuiTrigger::BUTTON_UP; - break; - case SDL_HAT_DOWN: - data.buttons_h |= GuiTrigger::BUTTON_DOWN; - break; - case SDL_HAT_RIGHTUP: - data.buttons_h |= GuiTrigger::BUTTON_RIGHT; - data.buttons_h |= GuiTrigger::BUTTON_UP; - break; - case SDL_HAT_RIGHT: - data.buttons_h |= GuiTrigger::BUTTON_RIGHT; - break; - case SDL_HAT_RIGHTDOWN: - data.buttons_h |= GuiTrigger::BUTTON_RIGHT; - data.buttons_h |= GuiTrigger::BUTTON_DOWN; - break; - } - } else if (e->type == SDL_JOYAXISMOTION) { - getDigitalTrigger(e->jaxis.axis, 2, e->jaxis.value, data.buttons_h, GuiTrigger::BUTTON_ZL); - getDigitalTrigger(e->jaxis.axis, 5, e->jaxis.value, data.buttons_h, GuiTrigger::BUTTON_ZR); - getDigitalAxis(e->jaxis.axis, 0, e->jaxis.value, data.buttons_h, GuiTrigger::STICK_L_LEFT, GuiTrigger::STICK_L_RIGHT); - getDigitalAxis(e->jaxis.axis, 1, e->jaxis.value, data.buttons_h, GuiTrigger::STICK_L_UP, GuiTrigger::STICK_L_DOWN); - getDigitalAxis(e->jaxis.axis, 3, e->jaxis.value, data.buttons_h, GuiTrigger::STICK_R_LEFT, GuiTrigger::STICK_R_RIGHT); - getDigitalAxis(e->jaxis.axis, 4, e->jaxis.value, data.buttons_h, GuiTrigger::STICK_R_UP, GuiTrigger::STICK_R_DOWN); - } else { - DEBUG_FUNCTION_LINE("Unknown event"); - return false; - } - return true; - } -}; - +#pragma once + +#include "SDLController.h" + +static GuiTrigger::eButtons xbox_button_map[] = + { + GuiTrigger::BUTTON_A, + GuiTrigger::BUTTON_B, + GuiTrigger::BUTTON_X, + GuiTrigger::BUTTON_Y, + GuiTrigger::BUTTON_L, + GuiTrigger::BUTTON_R, + GuiTrigger::BUTTON_MINUS, + GuiTrigger::BUTTON_PLUS, + GuiTrigger::BUTTON_STICK_L, + GuiTrigger::BUTTON_STICK_R, + }; + +#define getDigitalAxis(axis, targetAxis, value, hold, first, second) \ +if(axis == targetAxis){ \ + if (value < 0x4000 && value > -0x4000){ \ + hold &= ~first; \ + hold &= ~second; \ + }else if(value < -0x4000){ \ + hold |= first; \ + hold &= ~second; \ + }else if(value > 0x4000){ \ + hold |= second; \ + hold &= ~first; \ + } \ +} \ + +#define getDigitalTrigger(axis, targetAxis, value, hold, first) \ +if(axis == targetAxis){ \ + if(value > 0){ \ + hold |= first; \ + }else{ \ + hold &= ~first; \ + } \ +} \ + + +class SDLControllerXboxOne : public SDLController { +public: + explicit SDLControllerXboxOne(int32_t channel) : SDLController(channel) { + + } + + bool update(SDL_Event *e, int32_t screenWidth, int32_t screenHeight) override { + if (e->type == SDL_JOYBUTTONDOWN) { + data.buttons_h |= xbox_button_map[e->jbutton.button]; + } else if (e->type == SDL_JOYBUTTONUP) { + data.buttons_h &= ~xbox_button_map[e->jbutton.button]; + } else if (e->type == SDL_JOYHATMOTION) { + auto val = e->jhat.value; + + auto hatMask = (GuiTrigger::BUTTON_LEFT | GuiTrigger::BUTTON_UP | GuiTrigger::BUTTON_DOWN | GuiTrigger::BUTTON_RIGHT); + + // Remove hat values so we can add the new values. + data.buttons_h &= ~hatMask; + + switch (val) { + case SDL_HAT_LEFTUP: + data.buttons_h |= GuiTrigger::BUTTON_LEFT; + data.buttons_h |= GuiTrigger::BUTTON_UP; + break; + case SDL_HAT_LEFT: + data.buttons_h |= GuiTrigger::BUTTON_LEFT; + break; + case SDL_HAT_LEFTDOWN: + data.buttons_h |= GuiTrigger::BUTTON_LEFT; + data.buttons_h |= GuiTrigger::BUTTON_DOWN; + break; + case SDL_HAT_UP: + data.buttons_h |= GuiTrigger::BUTTON_UP; + break; + case SDL_HAT_DOWN: + data.buttons_h |= GuiTrigger::BUTTON_DOWN; + break; + case SDL_HAT_RIGHTUP: + data.buttons_h |= GuiTrigger::BUTTON_RIGHT; + data.buttons_h |= GuiTrigger::BUTTON_UP; + break; + case SDL_HAT_RIGHT: + data.buttons_h |= GuiTrigger::BUTTON_RIGHT; + break; + case SDL_HAT_RIGHTDOWN: + data.buttons_h |= GuiTrigger::BUTTON_RIGHT; + data.buttons_h |= GuiTrigger::BUTTON_DOWN; + break; + } + } else if (e->type == SDL_JOYAXISMOTION) { + getDigitalTrigger(e->jaxis.axis, 2, e->jaxis.value, data.buttons_h, GuiTrigger::BUTTON_ZL); + getDigitalTrigger(e->jaxis.axis, 5, e->jaxis.value, data.buttons_h, GuiTrigger::BUTTON_ZR); + getDigitalAxis(e->jaxis.axis, 0, e->jaxis.value, data.buttons_h, GuiTrigger::STICK_L_LEFT, GuiTrigger::STICK_L_RIGHT); + getDigitalAxis(e->jaxis.axis, 1, e->jaxis.value, data.buttons_h, GuiTrigger::STICK_L_UP, GuiTrigger::STICK_L_DOWN); + getDigitalAxis(e->jaxis.axis, 3, e->jaxis.value, data.buttons_h, GuiTrigger::STICK_R_LEFT, GuiTrigger::STICK_R_RIGHT); + getDigitalAxis(e->jaxis.axis, 4, e->jaxis.value, data.buttons_h, GuiTrigger::STICK_R_UP, GuiTrigger::STICK_R_DOWN); + } else { + DEBUG_FUNCTION_LINE("Unknown event"); + return false; + } + return true; + } +}; + diff --git a/src/main.cpp b/src/main.cpp index 3e0ff33..d5ae0a2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,17 +1,18 @@ #include -#include "CVideo.h" +#include "system/SDLSystem.h" #include "gui/GuiFrame.h" #include "gui/GuiImage.h" #include "gui/GuiButton.h" #include "gui/GuiController.h" -#include "gui/SDLController.h" -#include "MainWindow.h" -#include "logger.h" -#include "gui/SDLControllerJoystick.h" -#include "gui/SDLControllerMouse.h" -#include "gui/SDLControllerWiiUGamepad.h" -#include "gui/SDLControllerXboxOne.h" -#include "gui/SDLControllerWiiUProContoller.h" +#include "menu/MainWindow.h" +#include "utils/logger.h" +#include "input/SDLController.h" +#include "input/SDLControllerMouse.h" +#include "input/SDLControllerWiiUGamepad.h" +#include "input/SDLControllerXboxOne.h" +#include "input/SDLControllerWiiUProContoller.h" +#include "input/SDLControllerJoystick.h" +#include "input/ControllerManager.h" #include #include @@ -51,14 +52,9 @@ bool CheckRunning(){ } #endif -bool addJoystick(int deviceId, std::map &controllerList, std::map& joystickToChannel); - -GuiTrigger::eChannels increaseChannel(GuiTrigger::eChannels channel); - -void removeJoystick(int32_t instanceId, std::map &controllerList, std::map& joystickToChannel); int main(int argc, char *args[]) { - auto *video = new CVideo(); + auto *system = new SDLSystem(); #if defined _WIN32 // Create the Console @@ -82,14 +78,14 @@ int main(int argc, char *args[]) { WHBLogUdpInit(); #endif - GuiFrame *frame = new MainWindow(video->getWidth(), video->getHeight()); + auto * frame = new MainWindow(system->getWidth(), system->getHeight(), system->getRenderer()); + + auto * controllerM = new ControllerManager(system->getWidth(), system->getHeight()); - std::map controllerList; - std::map joystickToChannel; #if defined _WIN32 - controllerList[GuiTrigger::CHANNEL_1] = new SDLControllerMouse(GuiTrigger::CHANNEL_1); - DEBUG_FUNCTION_LINE("Add mouse"); + controllerM->attachController(GuiTrigger::CHANNEL_1, new SDLControllerMouse(GuiTrigger::CHANNEL_1)); + DEBUG_FUNCTION_LINE("Added mouse"); #endif while (true) { @@ -99,11 +95,8 @@ int main(int argc, char *args[]) { break; } #endif - - //! Read out inputs - for( auto const& [channel, controller] : controllerList ){ - controller->before(); - } + // Prepare to process new events. + controllerM->prepare(); bool quit = false; SDL_Event e; @@ -111,12 +104,12 @@ int main(int argc, char *args[]) { int32_t channel = -1; SDL_JoystickID jId = -1; if(e.type == SDL_JOYDEVICEADDED) { - addJoystick(e.jdevice.which, controllerList, joystickToChannel); + controllerM->attachJoystick(e.jdevice.which); continue; }else if(e.type == SDL_JOYDEVICEREMOVED) { auto j = SDL_JoystickFromInstanceID(e.jdevice.which); if (j) { - removeJoystick(e.jdevice.which, controllerList, joystickToChannel); + controllerM->detachJoystick(e.jdevice.which); SDL_JoystickClose(j); continue; } @@ -133,105 +126,32 @@ int main(int argc, char *args[]) { quit = true; break; } - - if(jId != -1){ - if(joystickToChannel.find(jId) != joystickToChannel.end()){ - channel = joystickToChannel[jId]; - } - } - if(channel != -1){ - controllerList[static_cast(channel)]->update(&e, video->getWidth(), video->getHeight()); - } - } - if(quit){ - break; + controllerM->processEvent(jId, channel, &e); } - for( auto const& [joypad, controller] : controllerList ){ - controller->after(); + if(quit){ break; } - frame->update(controller); - } + // Finish controller inputs + controllerM->finish(); + + // Update gui elements based on controller inputs + controllerM->callPerController([frame](GuiController* controller) { frame->update(controller);}); frame->process(); // clear the screen - SDL_RenderClear(video->getRenderer()); + SDL_RenderClear(system->getRenderer()->getRenderer()); - frame->draw(video); + frame->draw(system->getRenderer()); frame->updateEffects(); // flip the backbuffer // this means that everything that we prepared behind the screens is actually shown - SDL_RenderPresent(video->getRenderer()); - + SDL_RenderPresent(system->getRenderer()->getRenderer()); } delete frame; return 0; } - -void removeJoystick(int32_t instanceId, std::map &controllerList, std::map& joystickToChannel) { - auto channel = joystickToChannel[instanceId]; - delete controllerList[channel]; - controllerList.erase(channel); - joystickToChannel.erase(instanceId); - DEBUG_FUNCTION_LINE("Removed joystick: %d", instanceId); -} - -bool addJoystick(int deviceId, std::map &controllerList, std::map& joystickToChannel) { - auto joystick = SDL_JoystickOpen(deviceId); - if (joystick == NULL){ - DEBUG_FUNCTION_LINE("SDL_JoystickOpen failed: %s\n", SDL_GetError()); - return false; - } - auto instanceId = SDL_JoystickInstanceID(joystick); - if(std::string("WiiU Gamepad").compare(SDL_JoystickName(joystick)) == 0){ - controllerList[GuiTrigger::CHANNEL_1] = new SDLControllerWiiUGamepad(GuiTrigger::CHANNEL_1); - joystickToChannel[instanceId] = GuiTrigger::CHANNEL_1; - }else { - bool successfully_added = false; - auto channel = GuiTrigger::CHANNEL_2; - while(channel != GuiTrigger::CHANNEL_ALL){ - if(controllerList.find(channel) == controllerList.end()) { - if (std::string(SDL_JoystickName(joystick)).find("Xbox") != std::string::npos){ - controllerList[channel] = new SDLControllerXboxOne(channel); - }else if(std::string(SDL_JoystickName(joystick)).find("WiiU Pro Controller") != std::string::npos) { - controllerList[channel] = new SDLControllerWiiUProContoller(channel); - }else{ - controllerList[channel] = new SDLControllerJoystick(channel, instanceId); - } - joystickToChannel[instanceId] = channel; - successfully_added = true; - break; - } - channel = increaseChannel(channel); - } - if(!successfully_added){ - DEBUG_FUNCTION_LINE("Failed to add joystick. Closing it now"); - SDL_JoystickClose(joystick); - return false; - } - } - DEBUG_FUNCTION_LINE("Added joystick %s", SDL_JoystickName(joystick)); - return true; -} - -GuiTrigger::eChannels increaseChannel(GuiTrigger::eChannels channel) { - switch(channel){ - case GuiTrigger::CHANNEL_1: - return GuiTrigger::CHANNEL_2; - case GuiTrigger::CHANNEL_2: - return GuiTrigger::CHANNEL_3; - case GuiTrigger::CHANNEL_3: - return GuiTrigger::CHANNEL_4; - case GuiTrigger::CHANNEL_4: - return GuiTrigger::CHANNEL_5; - case GuiTrigger::CHANNEL_5: - case GuiTrigger::CHANNEL_ALL: - return GuiTrigger::CHANNEL_ALL; - } - return GuiTrigger::CHANNEL_ALL; -} \ No newline at end of file diff --git a/src/MainWindow.cpp b/src/menu/MainWindow.cpp similarity index 81% rename from src/MainWindow.cpp rename to src/menu/MainWindow.cpp index e1ec0ea..65ffe61 100644 --- a/src/MainWindow.cpp +++ b/src/menu/MainWindow.cpp @@ -1,89 +1,99 @@ -#include "MainWindow.h" -#include "gui/SDL_FontCache.h" - -MainWindow::~MainWindow() { - delete label;; - delete touchTrigger;; - delete sound;; - delete image;; - delete image2;; - delete image3;; - delete image4;; - delete image5;; - delete image;; - delete label;; - delete button;; - delete bgMusic;; -} - -MainWindow::MainWindow(int32_t w, int32_t h) : GuiFrame(w, h) { -#if defined _WIN32 - auto picture_path = "test.png"; - auto font_path = "FreeSans.ttf"; - auto bgMusic_path = "bgMusic.ogg"; - auto music_click = "button_click.mp3"; -#else - auto picture_path = "fs:/vol/external01/test.png"; - auto font_path = "fs:/vol/external01/FreeSans.ttf"; - auto bgMusic_path = "fs:/vol/external01/bgMusic.ogg"; - auto music_click = "fs:/vol/external01/button_click.mp3"; -#endif - - TTF_Init(); - TTF_Font *font; - - font = TTF_OpenFont(font_path, 28); - - label = new GuiText("This is a test.This is a test. This is a test.This is a test.This is a test.This is a test.", 25, {255, 255, 0, 255}, font); - - bgMusic = new GuiSound(bgMusic_path); - bgMusic->SetLoop(true); - bgMusic->Play(); - - image = new GuiImage(picture_path); - image2 = new GuiImage(picture_path); - image3 = new GuiImage(picture_path); - image4 = new GuiImage(picture_path); - image5 = new GuiImage(picture_path); - - 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 = new GuiSound(music_click); - - touchTrigger = new GuiTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::TOUCHED); - touchTrigger = new GuiTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::TOUCHED); - button->setTrigger(touchTrigger); - button->setEffectGrow(); - label->setAlignment(ALIGN_CENTERED); - button->setLabel(label); - label->setMaxWidth(button->getWidth()); - button->setSoundClick(sound); - - button->clicked.connect(this, &MainWindow::test); -} - -void MainWindow::process() { - GuiFrame::process(); - - // Rotate the button for fun. - auto res = button->getAngle() + 1; - if(res > 360){ - res = 0; - } - button->setAngle(res); -} +#include "MainWindow.h" + +MainWindow::~MainWindow() { + delete label;; + delete touchTrigger;; + delete sound;; + delete image;; + delete image2;; + delete image3;; + delete image4;; + delete image5;; + delete image;; + delete label;; + delete button;; + delete bgMusic;; +} + +MainWindow::MainWindow(int32_t w, int32_t h, Renderer* renderer) : GuiFrame(w, h) { +#if defined _WIN32 + auto picture_path = "test.png"; + auto font_path = "FreeSans.ttf"; + auto bgMusic_path = "bgMusic.ogg"; + auto music_click = "button_click.mp3"; +#else + auto picture_path = "fs:/vol/external01/test.png"; + auto font_path = "fs:/vol/external01/FreeSans.ttf"; + auto bgMusic_path = "fs:/vol/external01/bgMusic.ogg"; + auto music_click = "fs:/vol/external01/button_click.mp3"; +#endif + + TTF_Init(); + TTF_Font *font; + + font = TTF_OpenFont(font_path, 28); + + FC_Font* fc_font = FC_CreateFont(); + if(!fc_font){ + DEBUG_FUNCTION_LINE("Failed to create font"); + } + + FC_LoadFontFromTTF(fc_font, renderer->getRenderer(), font, {255, 255, 255, 255}); + + label = new GuiText("This is a test.This is a test. This is a test.This is a test.This is a test.This is a test.", {255, 255, 0, 255}, fc_font); + + bgMusic = new GuiSound(bgMusic_path); + bgMusic->SetLoop(true); + bgMusic->Play(); + + image = new GuiImage(picture_path); + image2 = new GuiImage(picture_path); + image3 = new GuiImage(picture_path); + image4 = new GuiImage(picture_path); + image5 = new GuiImage(picture_path); + + 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 = new GuiSound(music_click); + + touchTrigger = new GuiTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::TOUCHED); + touchTrigger = new GuiTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::TOUCHED); + button->setTrigger(touchTrigger); + button->setEffectGrow(); + label->setAlignment(ALIGN_CENTERED); + button->setLabel(label); + label->setMaxWidth(button->getWidth()); + button->setSoundClick(sound); + + button->clicked.connect(this, &MainWindow::test); +} + +void MainWindow::process() { + GuiFrame::process(); + + // Rotate the button for fun. + auto res = button->getAngle() + 1; + if(res > 360){ + res = 0; + } + button->setAngle(res); +} + +void MainWindow::test(GuiButton *, const GuiController *, GuiTrigger *) { + DEBUG_FUNCTION_LINE("Hello, you have clicked the button"); +} diff --git a/src/MainWindow.h b/src/menu/MainWindow.h similarity index 61% rename from src/MainWindow.h rename to src/menu/MainWindow.h index 36cd390..fcc9df7 100644 --- a/src/MainWindow.h +++ b/src/menu/MainWindow.h @@ -1,29 +1,27 @@ -#pragma once - -#include -#include "gui/GuiFrame.h" -#include "gui/GuiButton.h" -#include "logger.h" - -class MainWindow : public GuiFrame, public sigslot::has_slots<> { -public: - void test(GuiButton *, const GuiController *, GuiTrigger *) { - DEBUG_FUNCTION_LINE("Hello, you have clicked the button"); - } - - ~MainWindow(); - - MainWindow(int32_t w, int32_t h); - void process() override; -private: - GuiText *label = nullptr; - GuiTrigger *touchTrigger = 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; -}; +#pragma once + +#include +#include "../gui/GuiFrame.h" +#include "../gui/GuiButton.h" +#include "../utils/logger.h" + +class MainWindow : public GuiFrame, public sigslot::has_slots<> { +public: + void test(GuiButton *, const GuiController *, GuiTrigger *); + + ~MainWindow() override; + + MainWindow(int32_t w, int32_t h, Renderer* renderer); + void process() override; +private: + GuiText *label = nullptr; + GuiTrigger *touchTrigger = 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; +}; diff --git a/src/CVideo.cpp b/src/system/SDLSystem.cpp similarity index 68% rename from src/CVideo.cpp rename to src/system/SDLSystem.cpp index f2647d1..9a1bd53 100644 --- a/src/CVideo.cpp +++ b/src/system/SDLSystem.cpp @@ -14,22 +14,33 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . ****************************************************************************/ -#include "CVideo.h" -#include "logger.h" +#include "SDLSystem.h" +#include "../utils/logger.h" #include #include -CVideo::CVideo() { +SDLSystem::SDLSystem() { SDL_Init(SDL_INIT_EVERYTHING); auto SDLFlags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC; //Setup window window = SDL_CreateWindow(nullptr, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, 0); - if (!window) { return; } - renderer = SDL_CreateRenderer(window, -1, SDLFlags); - if (!renderer) { return; } - SDL_SetRenderTarget(renderer, NULL); + if (!window) { + DEBUG_FUNCTION_LINE("Failed to create window"); + return; + } + auto sdl_renderer = SDL_CreateRenderer(window, -1, SDLFlags); + if (!sdl_renderer) { + 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"); + return; + } if (SDL_Init(SDL_INIT_AUDIO) != 0) { DEBUG_FUNCTION_LINE("SDL init error: %s\n", SDL_GetError()); @@ -47,28 +58,24 @@ CVideo::CVideo() { SDL_PauseAudioDevice(dev, 0); } -CVideo::~CVideo() { - SDL_DestroyRenderer(renderer); +SDLSystem::~SDLSystem() { SDL_DestroyWindow(window); + delete renderer; SDL_Quit(); } -SDL_Renderer *CVideo::getRenderer() { - return renderer; -} - -float CVideo::getHeight() { +float SDLSystem::getHeight() { int h = 0; - SDL_GetWindowSize(window, NULL, &h); + SDL_GetWindowSize(window, nullptr, &h); return h; } -float CVideo::getWidth() { +float SDLSystem::getWidth() { int w = 0; - SDL_GetWindowSize(window, &w, NULL); + SDL_GetWindowSize(window, &w, nullptr); return w; } -unsigned int CVideo::getPixelFormat() { - return SDL_GetWindowPixelFormat(window); +Renderer *SDLSystem::getRenderer() { + return renderer; } diff --git a/src/CVideo.h b/src/system/SDLSystem.h similarity index 86% rename from src/CVideo.h rename to src/system/SDLSystem.h index 0dbf068..795920c 100644 --- a/src/CVideo.h +++ b/src/system/SDLSystem.h @@ -16,21 +16,20 @@ ****************************************************************************/ #pragma once #include +#include "video/Renderer.h" -class CVideo { +class SDLSystem { public: - CVideo(); + SDLSystem(); - virtual ~CVideo(); + virtual ~SDLSystem(); - SDL_Renderer *getRenderer(); + Renderer *getRenderer(); float getHeight(); float getWidth(); - unsigned int getPixelFormat(); - private: SDL_Window *window = NULL; - SDL_Renderer *renderer = NULL; + Renderer *renderer = NULL; }; \ No newline at end of file diff --git a/src/system/video/Renderer.h b/src/system/video/Renderer.h new file mode 100644 index 0000000..8b1d745 --- /dev/null +++ b/src/system/video/Renderer.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +class Renderer { +public: + Renderer(SDL_Renderer *renderer, uint32_t pixelFormat) : sdl_renderer(renderer), pixelFormat(pixelFormat){ + + } + + virtual ~Renderer() { + if(sdl_renderer){ + SDL_DestroyRenderer(sdl_renderer); + } + } + + SDL_Renderer *getRenderer(){ + return sdl_renderer; + } + + uint32_t getPixelFormat(){ + return pixelFormat; + } + +private: + SDL_Renderer *sdl_renderer = NULL; + uint32_t pixelFormat = SDL_PIXELFORMAT_RGBA8888; +}; \ No newline at end of file diff --git a/src/gui/SDL_FontCache.c b/src/system/video/SDL_FontCache.cpp similarity index 96% rename from src/gui/SDL_FontCache.c rename to src/system/video/SDL_FontCache.cpp index 9ca8d55..66d41d2 100644 --- a/src/gui/SDL_FontCache.c +++ b/src/system/video/SDL_FontCache.cpp @@ -10,6 +10,7 @@ See SDL_FontCache.h for license info. #include #include #include +#include // Visual C does not support static inline #ifndef static_inline @@ -81,7 +82,6 @@ __inline int c99_snprintf(char *outBuf, size_t size, const char *format, ...) #define FC_CACHE_PADDING 1 - static Uint8 has_clip(FC_Target* dest) { #ifdef FC_USE_SDL_GPU @@ -236,7 +236,7 @@ char* FC_GetStringASCII_Latin1(void) FC_Rect FC_MakeRect(float x, float y, float w, float h) { - FC_Rect r = {x, y, w, h}; + FC_Rect r = {(int) x, (int) y, (int) w, (int) h}; return r; } @@ -451,9 +451,10 @@ struct FC_Font FC_Image** glyph_cache; char* loading_string; - }; +std::recursive_mutex mutex; + // Private static FC_GlyphData* FC_PackGlyphData(FC_Font* font, Uint32 codepoint, Uint16 width, Uint16 maxWidth, Uint16 maxHeight); @@ -622,7 +623,7 @@ static_inline FC_Rect FC_RectUnion(FC_Rect A, FC_Rect B) x2 = FC_MAX(A.x+A.w, B.x+B.w); y2 = FC_MAX(A.y+A.h, B.y+B.h); { - FC_Rect result = {x, y, FC_MAX(0, x2 - x), FC_MAX(0, y2 - y)}; + FC_Rect result = {(int) x, (int) y, (int) FC_MAX(0, x2 - x), (int) FC_MAX(0, y2 - y)}; return result; } } @@ -1180,7 +1181,7 @@ Uint8 FC_LoadFontFromTTF(FC_Font* font, SDL_Renderer* renderer, TTF_Font* ttf, S #endif FC_ClearFont(font); - + std::scoped_lock lock(mutex); // Might as well check render target support here #ifdef FC_USE_SDL_GPU @@ -1288,6 +1289,8 @@ Uint8 FC_LoadFontFromTTF(FC_Font* font, SDL_Renderer* renderer, TTF_Font* ttf, S } } + + return 1; } @@ -1767,15 +1770,15 @@ 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(mutex); FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - set_color_for_all_caches(font, font->default_color); - return FC_RenderLeft(font, dest, x, y, FC_MakeScale(1,1), fc_buffer); + auto res = FC_RenderLeft(font, dest, x, y, FC_MakeScale(1,1), fc_buffer); + + return res; } - - typedef struct FC_StringList { char* value; @@ -2059,6 +2062,8 @@ 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(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); useClip = has_clip(dest); @@ -2091,6 +2096,8 @@ 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(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); useClip = has_clip(dest); @@ -2122,6 +2129,8 @@ 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(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); useClip = has_clip(dest); @@ -2153,6 +2162,8 @@ 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(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); useClip = has_clip(dest); @@ -2184,6 +2195,8 @@ 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(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); useClip = has_clip(dest); @@ -2211,29 +2224,49 @@ FC_Rect FC_DrawBoxEffect(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Effect FC_Rect FC_DrawColumn(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, const char* formatted_text, ...) { - FC_Rect box = {x, y, width, 0}; + FC_Rect box = {(int) x, (int) y, (int) width, (int) 0}; int total_height; if(formatted_text == NULL || font == NULL) return FC_MakeRect(x, y, 0, 0); + std::scoped_lock lock(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); set_color_for_all_caches(font, font->default_color); FC_DrawColumnFromBuffer(font, dest, box, &total_height, FC_MakeScale(1,1), FC_ALIGN_LEFT); - return FC_MakeRect(box.x, box.y, width, total_height); + auto res = FC_MakeRect(box.x, box.y, width, total_height); + + return res; +} + +FC_Rect FC_DrawColumnToTexture(FC_Font* font, SDL_Texture* target, float x, float y, Uint16 width, const char* text) +{ + std::scoped_lock lock(mutex); + + // Draw the text onto it + SDL_SetRenderTarget(font->renderer, target); + // make sure the texture is clean. + SDL_RenderClear(font->renderer); + FC_Rect res = FC_DrawColumn(font, font->renderer, x, y, width, text); + SDL_SetRenderTarget(font->renderer, NULL); + + return res; } FC_Rect FC_DrawColumnAlign(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_AlignEnum align, const char* formatted_text, ...) { - FC_Rect box = {x, y, width, 0}; + FC_Rect box = {(int) x, (int) y, (int) width, (int) 0}; int total_height; if(formatted_text == NULL || font == NULL) return FC_MakeRect(x, y, 0, 0); + std::scoped_lock lock(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); set_color_for_all_caches(font, font->default_color); @@ -2252,51 +2285,67 @@ FC_Rect FC_DrawColumnAlign(FC_Font* font, FC_Target* dest, float x, float y, Uin FC_DrawColumnFromBuffer(font, dest, box, &total_height, FC_MakeScale(1,1), align); - return FC_MakeRect(box.x, box.y, width, total_height); + auto res = FC_MakeRect(box.x, box.y, width, total_height); + + return res; } FC_Rect FC_DrawColumnScale(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_Scale scale, const char* formatted_text, ...) { - FC_Rect box = {x, y, width, 0}; + FC_Rect box = {(int) x, (int) y, (int) width, (int) 0}; int total_height; if(formatted_text == NULL || font == NULL) return FC_MakeRect(x, y, 0, 0); + std::scoped_lock lock(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); set_color_for_all_caches(font, font->default_color); FC_DrawColumnFromBuffer(font, dest, box, &total_height, scale, FC_ALIGN_CENTER); - return FC_MakeRect(box.x, box.y, width, total_height); + auto res = FC_MakeRect(box.x, box.y, width, total_height); + + + + return res; } FC_Rect FC_DrawColumnColor(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, SDL_Color color, const char* formatted_text, ...) { - FC_Rect box = {x, y, width, 0}; + FC_Rect box = {(int) x, (int) y, (int) width, (int) 0}; int total_height; if(formatted_text == NULL || font == NULL) return FC_MakeRect(x, y, 0, 0); + std::scoped_lock lock(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); set_color_for_all_caches(font, color); FC_DrawColumnFromBuffer(font, dest, box, &total_height, FC_MakeScale(1,1), FC_ALIGN_LEFT); - return FC_MakeRect(box.x, box.y, width, total_height); + auto res = FC_MakeRect(box.x, box.y, width, total_height); + + + + return res; } FC_Rect FC_DrawColumnEffect(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_Effect effect, const char* formatted_text, ...) { - FC_Rect box = {x, y, width, 0}; + FC_Rect box = {(int) x, (int) y, (int) width, (int) 0}; int total_height; if(formatted_text == NULL || font == NULL) return FC_MakeRect(x, y, 0, 0); + std::scoped_lock lock(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); set_color_for_all_caches(font, effect.color); @@ -2315,12 +2364,16 @@ FC_Rect FC_DrawColumnEffect(FC_Font* font, FC_Target* dest, float x, float y, Ui FC_DrawColumnFromBuffer(font, dest, box, &total_height, effect.scale, effect.alignment); - return FC_MakeRect(box.x, box.y, width, total_height); + auto res = FC_MakeRect(box.x, box.y, width, total_height); + + + + return res; } static FC_Rect FC_RenderCenter(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* text) { - FC_Rect result = {x, y, 0, 0}; + FC_Rect result = {(int) x, (int) y, (int) 0, (int) 0}; if(text == NULL || font == NULL) return result; @@ -2353,7 +2406,7 @@ static FC_Rect FC_RenderCenter(FC_Font* font, FC_Target* dest, float x, float y, static FC_Rect FC_RenderRight(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* text) { - FC_Rect result = {x, y, 0, 0}; + FC_Rect result = {(int) x, (int) y, (int) 0, (int) 0}; if(text == NULL || font == NULL) return result; @@ -2389,11 +2442,17 @@ 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(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); set_color_for_all_caches(font, font->default_color); - return FC_RenderLeft(font, dest, x, y, scale, fc_buffer); + auto res = FC_RenderLeft(font, dest, x, y, scale, fc_buffer); + + + + return res; } FC_Rect FC_DrawAlign(FC_Font* font, FC_Target* dest, float x, float y, FC_AlignEnum align, const char* formatted_text, ...) @@ -2401,6 +2460,8 @@ 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(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); set_color_for_all_caches(font, font->default_color); @@ -2422,6 +2483,8 @@ FC_Rect FC_DrawAlign(FC_Font* font, FC_Target* dest, float x, float y, FC_AlignE break; } + + return result; } @@ -2430,11 +2493,17 @@ 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(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); set_color_for_all_caches(font, color); - return FC_RenderLeft(font, dest, x, y, FC_MakeScale(1,1), fc_buffer); + auto res = FC_RenderLeft(font, dest, x, y, FC_MakeScale(1,1), fc_buffer); + + + + return res; } @@ -2443,6 +2512,8 @@ 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(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); set_color_for_all_caches(font, effect.color); @@ -2464,6 +2535,8 @@ FC_Rect FC_DrawEffect(FC_Font* font, FC_Target* dest, float x, float y, FC_Effec break; } + + return result; } @@ -2494,6 +2567,8 @@ Uint16 FC_GetHeight(FC_Font* font, const char* formatted_text, ...) if(formatted_text == NULL || font == NULL) return 0; + std::scoped_lock lock(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); Uint16 numLines = 1; @@ -2506,7 +2581,11 @@ Uint16 FC_GetHeight(FC_Font* font, const char* formatted_text, ...) } // Actual height of letter region + line spacing - return font->height*numLines + font->lineSpacing*(numLines - 1); //height*numLines; + auto res = font->height*numLines + font->lineSpacing*(numLines - 1); //height*numLines; + + + + return res; } Uint16 FC_GetWidth(FC_Font* font, const char* formatted_text, ...) @@ -2514,6 +2593,8 @@ Uint16 FC_GetWidth(FC_Font* font, const char* formatted_text, ...) if(formatted_text == NULL || font == NULL) return 0; + std::scoped_lock lock(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); const char* c; @@ -2536,6 +2617,8 @@ Uint16 FC_GetWidth(FC_Font* font, const char* formatted_text, ...) } bigWidth = bigWidth >= width? bigWidth : width; + + return bigWidth; } @@ -2550,6 +2633,8 @@ 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(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); ls = FC_GetBufferFitToColumn(font, column_width, FC_MakeScale(1,1), 1); @@ -2589,6 +2674,8 @@ FC_Rect FC_GetCharacterOffset(FC_Font* font, Uint16 position_index, int column_w result.y = (num_lines - 1) * FC_GetLineHeight(font); } + + return result; } @@ -2605,6 +2692,8 @@ 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(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); ls = FC_GetBufferFitToColumn(font, width, FC_MakeScale(1,1), 0); @@ -2614,6 +2703,8 @@ Uint16 FC_GetColumnHeight(FC_Font* font, Uint16 width, const char* formatted_tex } FC_StringListFree(ls); + + return y; } @@ -2653,6 +2744,8 @@ int FC_GetAscent(FC_Font* font, const char* formatted_text, ...) if(formatted_text == NULL) return font->ascent; + std::scoped_lock lock(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); max = 0; @@ -2669,6 +2762,9 @@ int FC_GetAscent(FC_Font* font, const char* formatted_text, ...) } ++c; } + + + return max; } @@ -2684,6 +2780,8 @@ int FC_GetDescent(FC_Font* font, const char* formatted_text, ...) if(formatted_text == NULL) return font->descent; + std::scoped_lock lock(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); max = 0; @@ -2700,6 +2798,9 @@ int FC_GetDescent(FC_Font* font, const char* formatted_text, ...) } ++c; } + + + return max; } @@ -2748,7 +2849,7 @@ SDL_Color FC_GetDefaultColor(FC_Font* font) FC_Rect FC_GetBounds(FC_Font* font, float x, float y, FC_AlignEnum align, FC_Scale scale, const char* formatted_text, ...) { - FC_Rect result = {x, y, 0, 0}; + FC_Rect result = {(int) x, (int) y, (int) 0, (int) 0}; if(formatted_text == NULL) return result; @@ -2798,6 +2899,8 @@ 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(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); ls = FC_GetBufferFitToColumn(font, column_width, FC_MakeScale(1,1), 1); @@ -2829,6 +2932,8 @@ Uint16 FC_GetPositionFromOffset(FC_Font* font, float x, float y, int column_widt } FC_StringListFree(ls); + + return position; } @@ -2842,6 +2947,8 @@ 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(mutex); + FC_EXTRACT_VARARGS(fc_buffer, formatted_text); ls = FC_GetBufferFitToColumn(font, width, FC_MakeScale(1,1), 0); @@ -2867,14 +2974,14 @@ int FC_GetWrappedText(FC_Font* font, char* result, int max_result_size, Uint16 w result[size_so_far] = '\0'; + + return size_so_far; } // Setters - - void FC_SetFilterMode(FC_Font* font, FC_FilterEnum filter) { if(font == NULL) diff --git a/src/gui/SDL_FontCache.h b/src/system/video/SDL_FontCache.h similarity index 98% rename from src/gui/SDL_FontCache.h rename to src/system/video/SDL_FontCache.h index a8cdfa1..9d3895a 100644 --- a/src/gui/SDL_FontCache.h +++ b/src/system/video/SDL_FontCache.h @@ -35,7 +35,8 @@ THE SOFTWARE. #include #include -#include "../logger.h" +#include +#include "../../utils/logger.h" #ifdef FC_USE_SDL_GPU #include "SDL_gpu.h" @@ -109,11 +110,7 @@ typedef struct FC_GlyphData } FC_GlyphData; - - - // Object creation - FC_Rect FC_MakeRect(float x, float y, float w, float h); FC_Scale FC_MakeScale(float x, float y); @@ -124,8 +121,6 @@ FC_Effect FC_MakeEffect(FC_AlignEnum alignment, FC_Scale scale, SDL_Color color) FC_GlyphData FC_MakeGlyphData(int cache_level, Sint16 x, Sint16 y, Uint16 w, Uint16 h); - - // Font object FC_Font* FC_CreateFont(void); @@ -212,7 +207,6 @@ void U8_strdel(char* string, int position); // Internal settings - /*! Sets the string from which to load the initial glyphs. Use this if you need upfront loading for any reason (such as lack of render-target support). */ void FC_SetLoadingString(FC_Font* font, const char* string); @@ -248,7 +242,6 @@ Uint8 FC_SetGlyphCacheLevel(FC_Font* font, int cache_level, FC_Image* cache_text /*! Copies the given surface to the given cache level as a texture. New cache levels must be sequential. */ Uint8 FC_UploadGlyphCache(FC_Font* font, int cache_level, SDL_Surface* data_surface); - /*! Returns the number of codepoints that are stored in the font's glyph data map. */ unsigned int FC_GetNumCodepoints(FC_Font* font); @@ -261,9 +254,7 @@ Uint8 FC_GetGlyphData(FC_Font* font, FC_GlyphData* result, Uint32 codepoint); /*! Sets the glyph data for the given codepoint. Duplicates are not checked. Returns a pointer to the stored data. */ FC_GlyphData* FC_SetGlyphData(FC_Font* font, Uint32 codepoint, FC_GlyphData glyph_data); - // Rendering - FC_Rect FC_Draw(FC_Font* font, FC_Target* dest, float x, float y, const char* formatted_text, ...); FC_Rect FC_DrawAlign(FC_Font* font, FC_Target* dest, float x, float y, FC_AlignEnum align, const char* formatted_text, ...); FC_Rect FC_DrawScale(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* formatted_text, ...); @@ -277,6 +268,7 @@ FC_Rect FC_DrawBoxColor(FC_Font* font, FC_Target* dest, FC_Rect box, SDL_Color c FC_Rect FC_DrawBoxEffect(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Effect effect, const char* formatted_text, ...); FC_Rect FC_DrawColumn(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, const char* formatted_text, ...); +FC_Rect FC_DrawColumnToTexture(FC_Font* font, SDL_Texture* target, float x, float y, Uint16 width, const char* text); FC_Rect FC_DrawColumnAlign(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_AlignEnum align, const char* formatted_text, ...); FC_Rect FC_DrawColumnScale(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_Scale scale, const char* formatted_text, ...); FC_Rect FC_DrawColumnColor(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, SDL_Color color, const char* formatted_text, ...); diff --git a/src/logger.h b/src/utils/logger.h similarity index 96% rename from src/logger.h rename to src/utils/logger.h index 3dce1e5..153c928 100644 --- a/src/logger.h +++ b/src/utils/logger.h @@ -1,32 +1,32 @@ -#pragma once - -#ifdef __WIIU__ -#include -#include -#include - -#include - -#endif -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define __FILENAME_X__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) -#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILENAME_X__) - -#ifdef __WIIU__ - #define DEBUG_FUNCTION_LINE(FMT, ARGS...)do { \ - WHBLogPrintf("[%23s]%30s@L%04d: " FMT "",__FILENAME__,__FUNCTION__, __LINE__, ## ARGS); \ - } while (0) -#else - #define DEBUG_FUNCTION_LINE(FMT, ARGS...)do { \ - printf("[%23s]%30s@L%04d: " FMT "\n",__FILENAME__,__FUNCTION__, __LINE__, ## ARGS); \ - } while (0) -#endif -#ifdef __cplusplus -} -#endif - +#pragma once + +#ifdef __WIIU__ +#include +#include +#include + +#include + +#endif +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define __FILENAME_X__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) +#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILENAME_X__) + +#ifdef __WIIU__ + #define DEBUG_FUNCTION_LINE(FMT, ARGS...)do { \ + WHBLogPrintf("[%23s]%30s@L%04d: " FMT "",__FILENAME__,__FUNCTION__, __LINE__, ## ARGS); \ + } while (0) +#else + #define DEBUG_FUNCTION_LINE(FMT, ARGS...)do { \ + printf("[%23s]%30s@L%04d: " FMT "\n",__FILENAME__,__FUNCTION__, __LINE__, ## ARGS); \ + } while (0) +#endif +#ifdef __cplusplus +} +#endif +