Big refactoring, add github ci file

This commit is contained in:
Maschell 2020-09-01 16:59:15 +02:00
parent 16862f2a88
commit e29ebece97
32 changed files with 829 additions and 612 deletions

18
.github/workflows/pc-win.yml vendored Normal file
View File

@ -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"

View File

@ -11,8 +11,8 @@ add_executable(${PROJECT_NAME}
src/gui/GuiImage.cpp src/gui/GuiImage.cpp
src/gui/GuiImage.h src/gui/GuiImage.h
src/gui/sigslot.h src/gui/sigslot.h
src/CVideo.cpp src/system/SDLSystem.cpp
src/CVideo.h src/system/SDLSystem.h
src/gui/GuiElement.cpp src/gui/GuiElement.cpp
src/gui/GuiText.cpp src/gui/GuiText.cpp
src/gui/GuiText.h src/gui/GuiText.h
@ -25,13 +25,14 @@ add_executable(${PROJECT_NAME}
src/gui/GuiButton.h src/gui/GuiButton.h
src/gui/SDLController.h src/MainWindow.cpp src/MainWindow.h src/gui/SDLControllerJoystick.h src/gui/SDLControllerMouse.h src/input/SDLController.h src/menu/MainWindow.cpp src/menu/MainWindow.h src/input/SDLControllerJoystick.h src/input/SDLControllerMouse.h
src/gui/SDLControllerWiiUGamepad.h src/input/SDLControllerWiiUGamepad.h
src/gui/SDLControllerWiiUProContoller.h src/input/SDLControllerWiiUProContoller.h
src/gui/GuiTexture.cpp src/gui/GuiTexture.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) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/sdl2)

View File

@ -28,7 +28,12 @@ endif
TARGET := SDL2_Playground TARGET := SDL2_Playground
BUILD := build-pc-win BUILD := build-pc-win
SOURCES := src \ SOURCES := src \
src/gui src/gui \
src/input \
src/menu \
src/system \
src/system/video \
src/utils
DATA := data DATA := data
INCLUDES := source INCLUDES := source

View File

@ -21,7 +21,12 @@ WUMS_ROOT := $(DEVKITPRO)/wums
TARGET := SDL2_Playground TARGET := SDL2_Playground
BUILD := build BUILD := build
SOURCES := src \ SOURCES := src \
src/gui src/gui \
src/input \
src/menu \
src/system \
src/system/video \
src/utils
DATA := data DATA := data
INCLUDES := source INCLUDES := source

View File

@ -133,7 +133,7 @@ void GuiButton::setTrigger(GuiTrigger *t, int32_t idx) {
} }
} }
void GuiButton::resetState(void) { void GuiButton::resetState() {
clickedTrigger = NULL; clickedTrigger = NULL;
heldTrigger = NULL; heldTrigger = NULL;
GuiElement::resetState(); GuiElement::resetState();
@ -142,7 +142,7 @@ void GuiButton::resetState(void) {
/** /**
* Draw the button on screen * Draw the button on screen
*/ */
void GuiButton::draw(CVideo *v) { void GuiButton::draw(Renderer *v) {
if (!this->isVisible()) { if (!this->isVisible()) {
return; return;
} }

View File

@ -20,7 +20,7 @@
#include "GuiText.h" #include "GuiText.h"
#include "GuiSound.h" #include "GuiSound.h"
#include "GuiTrigger.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) //!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 { class GuiButton : public GuiElement {
@ -94,7 +94,7 @@ public:
void resetState(void) override; void resetState(void) override;
//!Constantly called to draw the GuiButton //!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 //!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 //!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD

View File

@ -20,14 +20,15 @@
#include <vector> #include <vector>
#include <malloc.h> #include <malloc.h>
#include <stdio.h> #include <cstdio>
#include <stdlib.h> #include <cstdlib>
#include <string.h> #include <cstring>
#include <unistd.h> #include <unistd.h>
#include <wchar.h> #include <cwchar>
#include <math.h> #include <cmath>
#include <iostream> #include <iostream>
#include "sigslot.h" #include "sigslot.h"
#include "../system/video/Renderer.h"
enum { enum {
EFFECT_NONE = 0x00, EFFECT_NONE = 0x00,
@ -59,7 +60,7 @@ enum {
//!Forward declaration //!Forward declaration
class GuiController; class GuiController;
class CVideo; class SDLSystem;
//!Primary GUI class. Most other classes inherit from this class. //!Primary GUI class. Most other classes inherit from this class.
class GuiElement { class GuiElement {
@ -524,7 +525,7 @@ public:
virtual void update(GuiController *t) {} virtual void update(GuiController *t) {}
//!Called constantly to redraw the element //!Called constantly to redraw the element
virtual void draw(CVideo *v) {} virtual void draw(Renderer * v) {}
//!Called constantly to process stuff in the element //!Called constantly to process stuff in the element
virtual void process() {} virtual void process() {}

View File

@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/ ****************************************************************************/
#include "GuiFrame.h" #include "GuiFrame.h"
#include "../system/video/Renderer.h"
GuiFrame::GuiFrame(GuiFrame *p) { GuiFrame::GuiFrame(GuiFrame *p) {
parent = p; parent = p;
@ -156,12 +157,12 @@ int32_t GuiFrame::getSelected() {
return found; return found;
} }
void GuiFrame::draw(CVideo *v) { void GuiFrame::draw(Renderer *v) {
if (!this->isVisible() && parentElement) { if (!this->isVisible() && parentElement) {
return; return;
} }
if (parentElement && dim == true) { if (parentElement && dim) {
//GXColor dimColor = (GXColor){0, 0, 0, 0x70}; //GXColor dimColor = (GXColor){0, 0, 0, 0x70};
//Menu_DrawRectangle(0, 0, GetZPosition(), screenwidth,screenheight, &dimColor, false, true); //Menu_DrawRectangle(0, 0, GetZPosition(), screenwidth,screenheight, &dimColor, false, true);
} }

View File

@ -20,6 +20,7 @@
#include <mutex> #include <mutex>
#include "GuiElement.h" #include "GuiElement.h"
#include "sigslot.h" #include "sigslot.h"
#include "../system/video/Renderer.h"
//!Allows GuiElements to be grouped together into a "window" //!Allows GuiElements to be grouped together into a "window"
class GuiFrame : public GuiElement { class GuiFrame : public GuiElement {
@ -33,7 +34,7 @@ public:
GuiFrame(float w, float h, GuiFrame *parent = 0); GuiFrame(float w, float h, GuiFrame *parent = 0);
//!Destructor //!Destructor
virtual ~GuiFrame(); ~GuiFrame() override;
//!Appends a GuiElement to the GuiFrame //!Appends a GuiElement to the GuiFrame
//!\param e The GuiElement to append. If it is already in the GuiFrame, it is removed first //!\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; int32_t getSelected() override;
//!Draws all the elements in this GuiFrame //!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 //!Updates the window and all elements contains within
//!Allows the GuiFrame and all elements to respond to the input data specified //!Allows the GuiFrame and all elements to respond to the input data specified

View File

@ -17,7 +17,7 @@
#include <SDL2/SDL_image.h> #include <SDL2/SDL_image.h>
#include <iostream> #include <iostream>
#include "GuiImage.h" #include "GuiImage.h"
#include "../CVideo.h" #include "../system/SDLSystem.h"
GuiImage::GuiImage(const std::string& path) : GuiTexture(path){ GuiImage::GuiImage(const std::string& path) : GuiTexture(path){
} }

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/ ****************************************************************************/
#include "GuiSound.h" #include "GuiSound.h"
#include "../logger.h" #include "../utils/logger.h"
GuiSound::GuiSound(const char *filepath) { GuiSound::GuiSound(const char *filepath) {
Load(filepath); Load(filepath);

View File

@ -17,23 +17,17 @@
#include <cstdarg> #include <cstdarg>
#include <SDL2/SDL_surface.h> #include <SDL2/SDL_surface.h>
#include "GuiText.h" #include "GuiText.h"
#include "../CVideo.h"
#include "../logger.h"
#include "SDL_FontCache.h"
/** /**
* Constructor for the GuiText class. * 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->text = text;
this->size = s;
this->color = c; this->color = c;
this->ttf_font = gFont; this->fc_font = gFont;
this->invalid = true; updateSize();
this->updateText = true; this->doUpdateTexture = true;
this->maxWidth = 200;
} }
GuiText::~GuiText(){ GuiText::~GuiText(){
@ -44,61 +38,51 @@ GuiText::~GuiText(){
delete texture; delete texture;
} }
void GuiText::draw(CVideo *pVideo) { void GuiText::draw(Renderer *renderer) {
if (!this->isVisible()) { if (!this->isVisible()) {
return; 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){ updateTexture(renderer);
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");
}
}
if(texture){ if(texture){
texture->draw(pVideo); texture->draw(renderer);
} }
} }
void GuiText::process() { void GuiText::process() {
GuiElement::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) { void GuiText::setMaxWidth(float width) {
this->maxWidth = width; this->maxWidth = width;
// Rebuild the texture cache. // 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");
}
}
} }

View File

@ -17,12 +17,11 @@
#pragma once #pragma once
#include "GuiElement.h" #include "GuiElement.h"
#include "SDL_FontCache.h"
#include "GuiTexture.h" #include "GuiTexture.h"
#include "../system/video/SDL_FontCache.h"
#include <mutex> #include <mutex>
#include <SDL2/SDL_ttf.h> #include <SDL2/SDL_ttf.h>
//!Display, manage, and manipulate text in the GUI //!Display, manage, and manipulate text in the GUI
class GuiText : public GuiElement { class GuiText : public GuiElement {
public: public:
@ -30,10 +29,10 @@ public:
//!\param t Text //!\param t Text
//!\param s Font size //!\param s Font size
//!\param c Font color //!\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; ~GuiText() override;
void draw(CVideo *pVideo) override; void draw(Renderer *pVideo) override;
void process() override; void process() override;
@ -42,12 +41,13 @@ public:
protected: protected:
GuiTexture* texture = nullptr; GuiTexture* texture = nullptr;
std::string text; std::string text;
int32_t size;
SDL_Color color; SDL_Color color;
TTF_Font *ttf_font = nullptr;
FC_Font *fc_font = nullptr; FC_Font *fc_font = nullptr;
bool invalid = true; bool doUpdateTexture = true;
bool updateText = true;
uint16_t maxWidth = 0xFFFF; uint16_t maxWidth = 0xFFFF;
void updateSize();
void updateTexture(Renderer *renderer);
}; };

View File

@ -1,7 +1,7 @@
#include <SDL2/SDL_image.h> #include <SDL2/SDL_image.h>
#include "GuiTexture.h" #include "GuiTexture.h"
#include "../CVideo.h" #include "../system/SDLSystem.h"
#include "../logger.h" #include "../utils/logger.h"
GuiTexture::GuiTexture(const std::string& path) { GuiTexture::GuiTexture(const std::string& path) {
imgSurface = IMG_Load( path.c_str() ); 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()) { if (!this->isVisible()) {
DEBUG_FUNCTION_LINE("not visible!"); DEBUG_FUNCTION_LINE("not visible!");
return; return;
} }
if (texture == NULL && imgSurface) { 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) { if (optimizedSurface != NULL) {
SDL_FreeSurface(imgSurface); SDL_FreeSurface(imgSurface);
imgSurface = optimizedSurface; imgSurface = optimizedSurface;
DEBUG_FUNCTION_LINE("Optimized surface"); DEBUG_FUNCTION_LINE("Optimized surface");
} }
texture = SDL_CreateTextureFromSurface(pVideo->getRenderer(), imgSurface); texture = SDL_CreateTextureFromSurface(renderer->getRenderer(), imgSurface);
} }
if (!texture) { if (!texture) {
DEBUG_FUNCTION_LINE("no texture!"); DEBUG_FUNCTION_LINE("no texture!");
@ -79,9 +79,9 @@ void GuiTexture::draw(CVideo *pVideo) {
rect.h = currScaleY * getHeight(); rect.h = currScaleY * getHeight();
if (getAngle() == 0) { if (getAngle() == 0) {
SDL_RenderCopy(pVideo->getRenderer(), texture, nullptr, &rect); SDL_RenderCopy(renderer->getRenderer(), texture, nullptr, &rect);
} else { } 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);
} }
} }

View File

@ -12,7 +12,7 @@ public:
~GuiTexture() override; ~GuiTexture() override;
//!Constantly called to draw the image //!Constantly called to draw the image
void draw(CVideo *pVideo) override; void draw(Renderer *pVideo) override;
int setBlendMode(SDL_BlendMode blendMode); int setBlendMode(SDL_BlendMode blendMode);

View File

@ -0,0 +1,103 @@
#include <functional>
#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<GuiTrigger::eChannels>(channel)]->update(e, screenWidth, screenHeight);
}
}
void ControllerManager::finish() {
for (auto const&[joypad, controller] : controllerList) {
controller->after();
}
}
void ControllerManager::callPerController(std::function<void(GuiController*)> func) {
for (auto const&[joypad, controller] : controllerList) {
func(controller);
}
}

View File

@ -0,0 +1,37 @@
#pragma once
#include <map>
#include <functional>
#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<void(GuiController*)> func);
private:
GuiTrigger::eChannels increaseChannel(GuiTrigger::eChannels channel);
std::map<GuiTrigger::eChannels, SDLController *> controllerList;
std::map<int32_t, GuiTrigger::eChannels> joystickToChannel;
int32_t screenWidth;
int32_t screenHeight;
};

View File

@ -3,8 +3,8 @@
#include <SDL2/SDL_mouse.h> #include <SDL2/SDL_mouse.h>
#include <iostream> #include <iostream>
#include <SDL2/SDL_events.h> #include <SDL2/SDL_events.h>
#include "GuiController.h" #include "../gui/GuiController.h"
#include "../logger.h" #include "../utils/logger.h"
#define printButton(chan, x) if(data.buttons_d & x) DEBUG_FUNCTION_LINE("Controller #%d %s", chan, #x) #define printButton(chan, x) if(data.buttons_d & x) DEBUG_FUNCTION_LINE("Controller #%d %s", chan, #x)

View File

@ -1,17 +1,18 @@
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include "CVideo.h" #include "system/SDLSystem.h"
#include "gui/GuiFrame.h" #include "gui/GuiFrame.h"
#include "gui/GuiImage.h" #include "gui/GuiImage.h"
#include "gui/GuiButton.h" #include "gui/GuiButton.h"
#include "gui/GuiController.h" #include "gui/GuiController.h"
#include "gui/SDLController.h" #include "menu/MainWindow.h"
#include "MainWindow.h" #include "utils/logger.h"
#include "logger.h" #include "input/SDLController.h"
#include "gui/SDLControllerJoystick.h" #include "input/SDLControllerMouse.h"
#include "gui/SDLControllerMouse.h" #include "input/SDLControllerWiiUGamepad.h"
#include "gui/SDLControllerWiiUGamepad.h" #include "input/SDLControllerXboxOne.h"
#include "gui/SDLControllerXboxOne.h" #include "input/SDLControllerWiiUProContoller.h"
#include "gui/SDLControllerWiiUProContoller.h" #include "input/SDLControllerJoystick.h"
#include "input/ControllerManager.h"
#include <cstdio> #include <cstdio>
#include <fcntl.h> #include <fcntl.h>
@ -51,14 +52,9 @@ bool CheckRunning(){
} }
#endif #endif
bool addJoystick(int deviceId, std::map<GuiTrigger::eChannels, SDLController *> &controllerList, std::map<int32_t, GuiTrigger::eChannels>& joystickToChannel);
GuiTrigger::eChannels increaseChannel(GuiTrigger::eChannels channel);
void removeJoystick(int32_t instanceId, std::map<GuiTrigger::eChannels, SDLController *> &controllerList, std::map<int32_t, GuiTrigger::eChannels>& joystickToChannel);
int main(int argc, char *args[]) { int main(int argc, char *args[]) {
auto *video = new CVideo(); auto *system = new SDLSystem();
#if defined _WIN32 #if defined _WIN32
// Create the Console // Create the Console
@ -82,14 +78,14 @@ int main(int argc, char *args[]) {
WHBLogUdpInit(); WHBLogUdpInit();
#endif #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<GuiTrigger::eChannels, SDLController*> controllerList;
std::map<int32_t , GuiTrigger::eChannels> joystickToChannel;
#if defined _WIN32 #if defined _WIN32
controllerList[GuiTrigger::CHANNEL_1] = new SDLControllerMouse(GuiTrigger::CHANNEL_1); controllerM->attachController(GuiTrigger::CHANNEL_1, new SDLControllerMouse(GuiTrigger::CHANNEL_1));
DEBUG_FUNCTION_LINE("Add mouse"); DEBUG_FUNCTION_LINE("Added mouse");
#endif #endif
while (true) { while (true) {
@ -99,11 +95,8 @@ int main(int argc, char *args[]) {
break; break;
} }
#endif #endif
// Prepare to process new events.
//! Read out inputs controllerM->prepare();
for( auto const& [channel, controller] : controllerList ){
controller->before();
}
bool quit = false; bool quit = false;
SDL_Event e; SDL_Event e;
@ -111,12 +104,12 @@ int main(int argc, char *args[]) {
int32_t channel = -1; int32_t channel = -1;
SDL_JoystickID jId = -1; SDL_JoystickID jId = -1;
if(e.type == SDL_JOYDEVICEADDED) { if(e.type == SDL_JOYDEVICEADDED) {
addJoystick(e.jdevice.which, controllerList, joystickToChannel); controllerM->attachJoystick(e.jdevice.which);
continue; continue;
}else if(e.type == SDL_JOYDEVICEREMOVED) { }else if(e.type == SDL_JOYDEVICEREMOVED) {
auto j = SDL_JoystickFromInstanceID(e.jdevice.which); auto j = SDL_JoystickFromInstanceID(e.jdevice.which);
if (j) { if (j) {
removeJoystick(e.jdevice.which, controllerList, joystickToChannel); controllerM->detachJoystick(e.jdevice.which);
SDL_JoystickClose(j); SDL_JoystickClose(j);
continue; continue;
} }
@ -133,105 +126,32 @@ int main(int argc, char *args[]) {
quit = true; quit = true;
break; break;
} }
controllerM->processEvent(jId, channel, &e);
if(jId != -1){
if(joystickToChannel.find(jId) != joystickToChannel.end()){
channel = joystickToChannel[jId];
}
}
if(channel != -1){
controllerList[static_cast<GuiTrigger::eChannels>(channel)]->update(&e, video->getWidth(), video->getHeight());
}
}
if(quit){
break;
} }
for( auto const& [joypad, controller] : controllerList ){ if(quit){ break; }
controller->after();
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(); frame->process();
// clear the screen // clear the screen
SDL_RenderClear(video->getRenderer()); SDL_RenderClear(system->getRenderer()->getRenderer());
frame->draw(video); frame->draw(system->getRenderer());
frame->updateEffects(); frame->updateEffects();
// flip the backbuffer // flip the backbuffer
// this means that everything that we prepared behind the screens is actually shown // this means that everything that we prepared behind the screens is actually shown
SDL_RenderPresent(video->getRenderer()); SDL_RenderPresent(system->getRenderer()->getRenderer());
} }
delete frame; delete frame;
return 0; return 0;
} }
void removeJoystick(int32_t instanceId, std::map<GuiTrigger::eChannels, SDLController *> &controllerList, std::map<int32_t, GuiTrigger::eChannels>& 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<GuiTrigger::eChannels, SDLController *> &controllerList, std::map<int32_t, GuiTrigger::eChannels>& 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;
}

View File

@ -1,5 +1,4 @@
#include "MainWindow.h" #include "MainWindow.h"
#include "gui/SDL_FontCache.h"
MainWindow::~MainWindow() { MainWindow::~MainWindow() {
delete label;; delete label;;
@ -16,7 +15,7 @@ MainWindow::~MainWindow() {
delete bgMusic;; delete bgMusic;;
} }
MainWindow::MainWindow(int32_t w, int32_t h) : GuiFrame(w, h) { MainWindow::MainWindow(int32_t w, int32_t h, Renderer* renderer) : GuiFrame(w, h) {
#if defined _WIN32 #if defined _WIN32
auto picture_path = "test.png"; auto picture_path = "test.png";
auto font_path = "FreeSans.ttf"; auto font_path = "FreeSans.ttf";
@ -34,7 +33,14 @@ MainWindow::MainWindow(int32_t w, int32_t h) : GuiFrame(w, h) {
font = TTF_OpenFont(font_path, 28); 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); 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 = new GuiSound(bgMusic_path);
bgMusic->SetLoop(true); bgMusic->SetLoop(true);
@ -87,3 +93,7 @@ void MainWindow::process() {
} }
button->setAngle(res); button->setAngle(res);
} }
void MainWindow::test(GuiButton *, const GuiController *, GuiTrigger *) {
DEBUG_FUNCTION_LINE("Hello, you have clicked the button");
}

View File

@ -1,19 +1,17 @@
#pragma once #pragma once
#include <iostream> #include <iostream>
#include "gui/GuiFrame.h" #include "../gui/GuiFrame.h"
#include "gui/GuiButton.h" #include "../gui/GuiButton.h"
#include "logger.h" #include "../utils/logger.h"
class MainWindow : public GuiFrame, public sigslot::has_slots<> { class MainWindow : public GuiFrame, public sigslot::has_slots<> {
public: public:
void test(GuiButton *, const GuiController *, GuiTrigger *) { void test(GuiButton *, const GuiController *, GuiTrigger *);
DEBUG_FUNCTION_LINE("Hello, you have clicked the button");
}
~MainWindow(); ~MainWindow() override;
MainWindow(int32_t w, int32_t h); MainWindow(int32_t w, int32_t h, Renderer* renderer);
void process() override; void process() override;
private: private:
GuiText *label = nullptr; GuiText *label = nullptr;

View File

@ -14,22 +14,33 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/ ****************************************************************************/
#include "CVideo.h" #include "SDLSystem.h"
#include "logger.h" #include "../utils/logger.h"
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <SDL2/SDL_mixer.h> #include <SDL2/SDL_mixer.h>
CVideo::CVideo() { SDLSystem::SDLSystem() {
SDL_Init(SDL_INIT_EVERYTHING); SDL_Init(SDL_INIT_EVERYTHING);
auto SDLFlags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC; auto SDLFlags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC;
//Setup window //Setup window
window = SDL_CreateWindow(nullptr, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, 0); window = SDL_CreateWindow(nullptr, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, 0);
if (!window) { return; } if (!window) {
renderer = SDL_CreateRenderer(window, -1, SDLFlags); DEBUG_FUNCTION_LINE("Failed to create window");
if (!renderer) { return; } return;
SDL_SetRenderTarget(renderer, NULL); }
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) { if (SDL_Init(SDL_INIT_AUDIO) != 0) {
DEBUG_FUNCTION_LINE("SDL init error: %s\n", SDL_GetError()); DEBUG_FUNCTION_LINE("SDL init error: %s\n", SDL_GetError());
@ -47,28 +58,24 @@ CVideo::CVideo() {
SDL_PauseAudioDevice(dev, 0); SDL_PauseAudioDevice(dev, 0);
} }
CVideo::~CVideo() { SDLSystem::~SDLSystem() {
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
delete renderer;
SDL_Quit(); SDL_Quit();
} }
SDL_Renderer *CVideo::getRenderer() { float SDLSystem::getHeight() {
return renderer;
}
float CVideo::getHeight() {
int h = 0; int h = 0;
SDL_GetWindowSize(window, NULL, &h); SDL_GetWindowSize(window, nullptr, &h);
return h; return h;
} }
float CVideo::getWidth() { float SDLSystem::getWidth() {
int w = 0; int w = 0;
SDL_GetWindowSize(window, &w, NULL); SDL_GetWindowSize(window, &w, nullptr);
return w; return w;
} }
unsigned int CVideo::getPixelFormat() { Renderer *SDLSystem::getRenderer() {
return SDL_GetWindowPixelFormat(window); return renderer;
} }

View File

@ -16,21 +16,20 @@
****************************************************************************/ ****************************************************************************/
#pragma once #pragma once
#include <SDL2/SDL_render.h> #include <SDL2/SDL_render.h>
#include "video/Renderer.h"
class CVideo { class SDLSystem {
public: public:
CVideo(); SDLSystem();
virtual ~CVideo(); virtual ~SDLSystem();
SDL_Renderer *getRenderer(); Renderer *getRenderer();
float getHeight(); float getHeight();
float getWidth(); float getWidth();
unsigned int getPixelFormat();
private: private:
SDL_Window *window = NULL; SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL; Renderer *renderer = NULL;
}; };

View File

@ -0,0 +1,28 @@
#pragma once
#include <SDL2/SDL_render.h>
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;
};

View File

@ -10,6 +10,7 @@ See SDL_FontCache.h for license info.
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <mutex>
// Visual C does not support static inline // Visual C does not support static inline
#ifndef 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 #define FC_CACHE_PADDING 1
static Uint8 has_clip(FC_Target* dest) static Uint8 has_clip(FC_Target* dest)
{ {
#ifdef FC_USE_SDL_GPU #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 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; return r;
} }
@ -451,9 +451,10 @@ struct FC_Font
FC_Image** glyph_cache; FC_Image** glyph_cache;
char* loading_string; char* loading_string;
}; };
std::recursive_mutex mutex;
// Private // Private
static FC_GlyphData* FC_PackGlyphData(FC_Font* font, Uint32 codepoint, Uint16 width, Uint16 maxWidth, Uint16 maxHeight); 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); x2 = FC_MAX(A.x+A.w, B.x+B.w);
y2 = FC_MAX(A.y+A.h, B.y+B.h); 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; return result;
} }
} }
@ -1180,7 +1181,7 @@ Uint8 FC_LoadFontFromTTF(FC_Font* font, SDL_Renderer* renderer, TTF_Font* ttf, S
#endif #endif
FC_ClearFont(font); FC_ClearFont(font);
std::scoped_lock lock(mutex);
// Might as well check render target support here // Might as well check render target support here
#ifdef FC_USE_SDL_GPU #ifdef FC_USE_SDL_GPU
@ -1288,6 +1289,8 @@ Uint8 FC_LoadFontFromTTF(FC_Font* font, SDL_Renderer* renderer, TTF_Font* ttf, S
} }
} }
return 1; 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) if(formatted_text == NULL || font == NULL)
return FC_MakeRect(x, y, 0, 0); return FC_MakeRect(x, y, 0, 0);
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
set_color_for_all_caches(font, font->default_color); 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 typedef struct FC_StringList
{ {
char* value; 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) if(formatted_text == NULL || font == NULL)
return FC_MakeRect(box.x, box.y, 0, 0); return FC_MakeRect(box.x, box.y, 0, 0);
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
useClip = has_clip(dest); 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) if(formatted_text == NULL || font == NULL)
return FC_MakeRect(box.x, box.y, 0, 0); return FC_MakeRect(box.x, box.y, 0, 0);
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
useClip = has_clip(dest); 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) if(formatted_text == NULL || font == NULL)
return FC_MakeRect(box.x, box.y, 0, 0); return FC_MakeRect(box.x, box.y, 0, 0);
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
useClip = has_clip(dest); 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) if(formatted_text == NULL || font == NULL)
return FC_MakeRect(box.x, box.y, 0, 0); return FC_MakeRect(box.x, box.y, 0, 0);
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
useClip = has_clip(dest); 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) if(formatted_text == NULL || font == NULL)
return FC_MakeRect(box.x, box.y, 0, 0); return FC_MakeRect(box.x, box.y, 0, 0);
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
useClip = has_clip(dest); 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 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; int total_height;
if(formatted_text == NULL || font == NULL) if(formatted_text == NULL || font == NULL)
return FC_MakeRect(x, y, 0, 0); return FC_MakeRect(x, y, 0, 0);
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
set_color_for_all_caches(font, font->default_color); set_color_for_all_caches(font, font->default_color);
FC_DrawColumnFromBuffer(font, dest, box, &total_height, FC_MakeScale(1,1), FC_ALIGN_LEFT); 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 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; int total_height;
if(formatted_text == NULL || font == NULL) if(formatted_text == NULL || font == NULL)
return FC_MakeRect(x, y, 0, 0); return FC_MakeRect(x, y, 0, 0);
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
set_color_for_all_caches(font, font->default_color); 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); 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 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; int total_height;
if(formatted_text == NULL || font == NULL) if(formatted_text == NULL || font == NULL)
return FC_MakeRect(x, y, 0, 0); return FC_MakeRect(x, y, 0, 0);
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
set_color_for_all_caches(font, font->default_color); set_color_for_all_caches(font, font->default_color);
FC_DrawColumnFromBuffer(font, dest, box, &total_height, scale, FC_ALIGN_CENTER); 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 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; int total_height;
if(formatted_text == NULL || font == NULL) if(formatted_text == NULL || font == NULL)
return FC_MakeRect(x, y, 0, 0); return FC_MakeRect(x, y, 0, 0);
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
set_color_for_all_caches(font, color); set_color_for_all_caches(font, color);
FC_DrawColumnFromBuffer(font, dest, box, &total_height, FC_MakeScale(1,1), FC_ALIGN_LEFT); 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 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; int total_height;
if(formatted_text == NULL || font == NULL) if(formatted_text == NULL || font == NULL)
return FC_MakeRect(x, y, 0, 0); return FC_MakeRect(x, y, 0, 0);
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
set_color_for_all_caches(font, effect.color); 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); 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) 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) if(text == NULL || font == NULL)
return result; 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) 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) if(text == NULL || font == NULL)
return result; 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) if(formatted_text == NULL || font == NULL)
return FC_MakeRect(x, y, 0, 0); return FC_MakeRect(x, y, 0, 0);
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
set_color_for_all_caches(font, font->default_color); 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, ...) 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) if(formatted_text == NULL || font == NULL)
return FC_MakeRect(x, y, 0, 0); return FC_MakeRect(x, y, 0, 0);
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
set_color_for_all_caches(font, font->default_color); 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; break;
} }
return result; 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) if(formatted_text == NULL || font == NULL)
return FC_MakeRect(x, y, 0, 0); return FC_MakeRect(x, y, 0, 0);
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
set_color_for_all_caches(font, color); 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) if(formatted_text == NULL || font == NULL)
return FC_MakeRect(x, y, 0, 0); return FC_MakeRect(x, y, 0, 0);
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
set_color_for_all_caches(font, effect.color); 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; break;
} }
return result; return result;
} }
@ -2494,6 +2567,8 @@ Uint16 FC_GetHeight(FC_Font* font, const char* formatted_text, ...)
if(formatted_text == NULL || font == NULL) if(formatted_text == NULL || font == NULL)
return 0; return 0;
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
Uint16 numLines = 1; Uint16 numLines = 1;
@ -2506,7 +2581,11 @@ Uint16 FC_GetHeight(FC_Font* font, const char* formatted_text, ...)
} }
// Actual height of letter region + line spacing // 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, ...) 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) if(formatted_text == NULL || font == NULL)
return 0; return 0;
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
const char* c; const char* c;
@ -2536,6 +2617,8 @@ Uint16 FC_GetWidth(FC_Font* font, const char* formatted_text, ...)
} }
bigWidth = bigWidth >= width? bigWidth : width; bigWidth = bigWidth >= width? bigWidth : width;
return bigWidth; 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) if(formatted_text == NULL || column_width == 0 || position_index == 0 || font == NULL)
return result; return result;
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
ls = FC_GetBufferFitToColumn(font, column_width, FC_MakeScale(1,1), 1); 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); result.y = (num_lines - 1) * FC_GetLineHeight(font);
} }
return result; return result;
} }
@ -2605,6 +2692,8 @@ Uint16 FC_GetColumnHeight(FC_Font* font, Uint16 width, const char* formatted_tex
if(formatted_text == NULL || width == 0) if(formatted_text == NULL || width == 0)
return font->height; return font->height;
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
ls = FC_GetBufferFitToColumn(font, width, FC_MakeScale(1,1), 0); 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); FC_StringListFree(ls);
return y; return y;
} }
@ -2653,6 +2744,8 @@ int FC_GetAscent(FC_Font* font, const char* formatted_text, ...)
if(formatted_text == NULL) if(formatted_text == NULL)
return font->ascent; return font->ascent;
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
max = 0; max = 0;
@ -2669,6 +2762,9 @@ int FC_GetAscent(FC_Font* font, const char* formatted_text, ...)
} }
++c; ++c;
} }
return max; return max;
} }
@ -2684,6 +2780,8 @@ int FC_GetDescent(FC_Font* font, const char* formatted_text, ...)
if(formatted_text == NULL) if(formatted_text == NULL)
return font->descent; return font->descent;
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
max = 0; max = 0;
@ -2700,6 +2798,9 @@ int FC_GetDescent(FC_Font* font, const char* formatted_text, ...)
} }
++c; ++c;
} }
return max; 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 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) if(formatted_text == NULL)
return result; 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) if(formatted_text == NULL || column_width == 0 || font == NULL)
return 0; return 0;
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
ls = FC_GetBufferFitToColumn(font, column_width, FC_MakeScale(1,1), 1); 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); FC_StringListFree(ls);
return position; 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) if(formatted_text == NULL || width == 0)
return 0; return 0;
std::scoped_lock lock(mutex);
FC_EXTRACT_VARARGS(fc_buffer, formatted_text); FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
ls = FC_GetBufferFitToColumn(font, width, FC_MakeScale(1,1), 0); 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'; result[size_so_far] = '\0';
return size_so_far; return size_so_far;
} }
// Setters // Setters
void FC_SetFilterMode(FC_Font* font, FC_FilterEnum filter) void FC_SetFilterMode(FC_Font* font, FC_FilterEnum filter)
{ {
if(font == NULL) if(font == NULL)

View File

@ -35,7 +35,8 @@ THE SOFTWARE.
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h> #include <SDL2/SDL_ttf.h>
#include "../logger.h" #include <SDL2/SDL_pixels.h>
#include "../../utils/logger.h"
#ifdef FC_USE_SDL_GPU #ifdef FC_USE_SDL_GPU
#include "SDL_gpu.h" #include "SDL_gpu.h"
@ -109,11 +110,7 @@ typedef struct FC_GlyphData
} FC_GlyphData; } FC_GlyphData;
// Object creation // Object creation
FC_Rect FC_MakeRect(float x, float y, float w, float h); FC_Rect FC_MakeRect(float x, float y, float w, float h);
FC_Scale FC_MakeScale(float x, float y); 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); FC_GlyphData FC_MakeGlyphData(int cache_level, Sint16 x, Sint16 y, Uint16 w, Uint16 h);
// Font object // Font object
FC_Font* FC_CreateFont(void); FC_Font* FC_CreateFont(void);
@ -212,7 +207,6 @@ void U8_strdel(char* string, int position);
// Internal settings // 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). */ /*! 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); 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. */ /*! 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); 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. */ /*! Returns the number of codepoints that are stored in the font's glyph data map. */
unsigned int FC_GetNumCodepoints(FC_Font* font); 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. */ /*! 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); FC_GlyphData* FC_SetGlyphData(FC_Font* font, Uint32 codepoint, FC_GlyphData glyph_data);
// Rendering // Rendering
FC_Rect FC_Draw(FC_Font* font, FC_Target* dest, float x, float y, const char* formatted_text, ...); 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_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, ...); 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_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_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_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_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, ...); FC_Rect FC_DrawColumnColor(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, SDL_Color color, const char* formatted_text, ...);