diff --git a/CMakeLists.txt b/CMakeLists.txt index 5bfb342..12e56ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,38 +5,14 @@ set(CMAKE_CXX_STANDARD 20) add_executable(${PROJECT_NAME} src/main.cpp - src/gui/GuiElement.h - src/gui/GuiFrame.cpp - src/gui/GuiFrame.h - src/gui/sigslot.h - src/system/SDLSystem.cpp - src/system/SDLSystem.h - src/gui/GuiElement.cpp - src/gui/GuiText.cpp - src/gui/GuiText.h - src/gui/GuiImage.cpp - src/gui/GuiImage.h - src/gui/GuiSound.cpp - src/gui/GuiSound.h - src/gui/GuiTrigger.cpp - src/gui/GuiTrigger.h - src/gui/GuiController.h - src/gui/GuiButton.cpp - src/gui/GuiButton.h src/resources/Resources.cpp src/resources/Resources.h src/fs/CFile.cpp src/fs/CFile.hpp src/fs/FSUtils.cpp src/fs/FSUtils.h - src/input/SDLController.h src/menu/MainWindow.cpp src/menu/MainWindow.h src/input/SDLControllerJoystick.h src/input/SDLControllerMouse.h - src/input/SDLControllerWiiUGamepad.h - src/input/SDLControllerWiiUProContoller.h - src/gui/GuiTextureData.cpp src/gui/GuiTextureData.h - 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) + src/menu/MainWindow.cpp + src/menu/MainWindow.h ) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/sdl2) @@ -45,9 +21,27 @@ find_package(SDL2_image REQUIRED) find_package(SDL2_ttf REQUIRED) find_package(SDL2_mixer REQUIRED) -enable_language(ASM ) +enable_language(ASM) include(ExternalProject) +ExternalProject_Add(libgui-sdl_git + PREFIX vendor/ + GIT_REPOSITORY https://github.com/Maschell/libgui-sdl + GIT_TAG master + GIT_SUBMODULES + UPDATE_COMMAND "" + PATCH_COMMAND "" + BUILD_COMMAND "" + CMAKE_ARGS + INSTALL_COMMAND + "${CMAKE_COMMAND}") + +add_library (libgui-sdl STATIC IMPORTED GLOBAL) +set_target_properties (libgui-sdl PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/vendor/src/libgui-sdl_git-build/libgui-sdl.a + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR}/vendor/src/libgui-sdl_git/include/gui-sdl) +add_dependencies(libgui-sdl libgui-sdl_git) + ExternalProject_Add(bin2s_git PREFIX vendor/ GIT_REPOSITORY https://github.com/Maschell/bin2s @@ -92,7 +86,8 @@ function(add_binfile_library target_name) add_library(${target_name} ${_output_file}) endfunction() -add_binfile_library(resources data/fonts/FreeSans.ttf +add_binfile_library(resources + data/fonts/FreeSans.ttf data/sounds/bgMusic.ogg data/sounds/button_click.mp3 data/images/button.png @@ -100,4 +95,4 @@ add_binfile_library(resources data/fonts/FreeSans.ttf set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CMAKE_BUILD_") -target_link_libraries(${PROJECT_NAME} SDL2::Main SDL2::Image SDL2::TTF SDL2::Mixer resources) +target_link_libraries(${PROJECT_NAME} libgui-sdl SDL2::Main SDL2::Image SDL2::TTF SDL2::Mixer resources) diff --git a/Dockerfile.pc-win b/Dockerfile.pc-win deleted file mode 100644 index 38c3430..0000000 --- a/Dockerfile.pc-win +++ /dev/null @@ -1,22 +0,0 @@ -FROM dockcross/windows-shared-x64:latest - -RUN apt-get update && apt-get install -y gnupg -#Use http://mirror.mxe.cc/ -#First add the repository and install the static gcc compiler. This ensures that everything basic is setup. -RUN echo "deb http://pkg.mxe.cc/repos/apt xenial main" > \ - /etc/apt/sources.list.d/mxeapt.list && \ - apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 86B72ED9 && \ - apt-get update && \ - apt-get install -y mxe-i686-w64-mingw32.static-gcc \ - nsis \ - zip \ - libtool - -RUN apt-get update && wget -O - http://mirror.mxe.cc/repos/apt/dists/stretch/main/binary-amd64/Packages | grep Package | grep shared | grep sdl2 | awk '{print $2}' | xargs apt-get install -y - -ENV MINGW64_PREFIX=/usr/src/mxe/usr/bin/x86_64-w64-mingw32.shared- -ENV CONFIG_PREFIX=/usr/lib/mxe/usr/bin/x86_64-w64-mingw32.shared- -ENV EXTRA_CFLAGS=-I/usr/lib/mxe/usr/x86_64-w64-mingw32.shared/include -ENV EXTRA_LDFLAGS=-L/usr/lib/mxe/usr/x86_64-w64-mingw32.shared/lib - -WORKDIR /project \ No newline at end of file diff --git a/Dockerfile.wiiu b/Dockerfile.wiiu index dbcffdb..2428803 100644 --- a/Dockerfile.wiiu +++ b/Dockerfile.wiiu @@ -1,3 +1,5 @@ FROM wiiuenv/devkitppc-with-sdl2:20201002 +COPY --from=maschell/libgui-sdl:20201002 /artifacts $DEVKITPRO + WORKDIR project \ No newline at end of file diff --git a/Makefile.pc-win b/Makefile.pc-win deleted file mode 100644 index 6c5735b..0000000 --- a/Makefile.pc-win +++ /dev/null @@ -1,197 +0,0 @@ -#------------------------------------------------------------------------------- -.SUFFIXES: -#------------------------------------------------------------------------------- -ifeq ($(strip $(MINGW64_PREFIX)),) - $(error "Please set MINGW64_PREFIX in your environment. export MINGW64_PREFIX=/mingw64/bin/") -endif - -CXX := $(MINGW64_PREFIX)g++ -C := $(MINGW64_PREFIX)gcc -OBJCOPY := $(MINGW64_PREFIX)objcopy -LD := $(MINGW64_PREFIX)ld -PREFIX := $(MINGW64_PREFIX) - -ifeq ($(strip $(CONFIG_PREFIX)),) - PKG-CONFIG := $(PREFIX)pkg-config -else - PKG-CONFIG := $(CONFIG_PREFIX)pkg-config -endif - -#------------------------------------------------------------------------------- -# TARGET is the name of the output -# BUILD is the directory where object files & intermediate files will be placed -# SOURCES is a list of directories containing source code -# DATA is a list of directories containing data files -# INCLUDES is a list of directories containing header files -#------------------------------------------------------------------------------- -TARGET := SDL2_Playground -BUILD := build-pc-win -SOURCES := src \ - src/gui \ - src/fs \ - src/input \ - src/menu \ - src/resources \ - src/system \ - src/system/video \ - src/utils -DATA := data \ - data/images \ - data/sounds \ - data/fonts -INCLUDES := source - - -#------------------------------------------------------------------------------- -# options for code generation -#------------------------------------------------------------------------------- -CFLAGS := -g -Wall -O2 -ffunction-sections `$(PKG-CONFIG) --cflags SDL2_mixer SDL2_ttf SDL2_image` \ - $(MACHDEP) - -CFLAGS += $(INCLUDE) - - -ifeq ($(strip $(EXTRA_CFLAGS)),) -else - CFLAGS += $(EXTRA_CFLAGS) -endif - -CXXFLAGS := $(CFLAGS) -std=c++17 - -ASFLAGS := -g $(ARCH) -LDFLAGS = -g $(ARCH) - -LIBS := `$(PKG-CONFIG) --libs SDL2_mixer SDL2_ttf SDL2_image` - -ifeq ($(strip $(EXTRA_LDFLAGS)),) -else - LDFLAGS += $(EXTRA_LDFLAGS) -endif - -#------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level -# containing include and lib -#------------------------------------------------------------------------------- -LIBDIRS := - -#------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#------------------------------------------------------------------------------- -ifneq ($(BUILD),$(notdir $(CURDIR))) -#------------------------------------------------------------------------------- - -export OUTPUT := $(CURDIR)/$(TARGET) -export TOPDIR := $(CURDIR) - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) - -export DEPSDIR := $(CURDIR)/$(BUILD) - -FILELIST := $(shell bash ./filelist.sh) -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) - -#------------------------------------------------------------------------------- -# use CXX for linking C++ projects, CC for standard C -#------------------------------------------------------------------------------- -ifeq ($(strip $(CPPFILES)),) -#------------------------------------------------------------------------------- - export LD := $(CC) -#------------------------------------------------------------------------------- -else -#------------------------------------------------------------------------------- - export LD := $(CXX) -#------------------------------------------------------------------------------- -endif -#------------------------------------------------------------------------------- - -export OFILES_BIN := $(addsuffix .o,$(BINFILES)) -export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) -export OFILES := $(OFILES_BIN) $(OFILES_SRC) - -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) - -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) - -.PHONY: $(BUILD) clean all - -#------------------------------------------------------------------------------- -all: $(BUILD) - -$(BUILD): - @[ -d $@ ] || mkdir -p $@ - @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.pc-win - -#------------------------------------------------------------------------------- -clean: - @echo clean ... - @rm -fr $(BUILD) $(TARGET).exe - -#------------------------------------------------------------------------------- -else -.PHONY: all - -DEPENDS := $(OFILES:.o=.d) - -#------------------------------------------------------------------------------- -# main targets -#------------------------------------------------------------------------------- - -all : $(OUTPUT).exe - -$(OUTPUT).exe : $(OFILES) - -$(OFILES_SRC) : $(HFILES_BIN) - -$(OUTPUT).exe: - @echo linking ... $(notdir $@) - @$(CXX) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ $(ERROR_FILTER) - -%.o: %.cpp - @echo "$(notdir $<)" - @$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER) - -%.png.o %.png.h : %.png - @echo $(notdir $<) - @$(bin2o) - -%.jpg.o %.jpg.h : %.jpg - @echo $(notdir $<) - @$(bin2o) - -%.ogg.o %.ogg.h : %.ogg - @echo $(notdir $<) - @$(bin2o) - -%.mp3.o %.mp3.h : %.mp3 - @echo $(notdir $<) - @$(bin2o) - -%.ttf.o %.ttf.h : %.ttf - @echo $(notdir $<) - @$(bin2o) - -define bin2o - @$(LD) -r -b binary $< -o $( \n\ -#include \n\ -\n\ -extern const uint8_t `(echo $( `(echo $(. - ****************************************************************************/ -#include -#include "GuiButton.h" -#include "GuiController.h" - -/** - * Constructor for the GuiButton class. - */ - -GuiButton::GuiButton(float w, float h) { - width = w; - height = h; - image = nullptr; - imageOver = nullptr; - imageHold = nullptr; - imageClick = nullptr; - icon = nullptr; - iconOver = nullptr; - - for (int32_t i = 0; i < 4; i++) { - label[i] = nullptr; - labelOver[i] = nullptr; - labelHold[i] = nullptr; - labelClick[i] = nullptr; - } - for (auto &i : trigger) { - i = nullptr; - } - - soundOver = nullptr; - soundHold = nullptr; - soundClick = nullptr; - clickedTrigger = nullptr; - heldTrigger = nullptr; - selectable = true; - holdable = false; - clickable = true; -} - -/** - * Destructor for the GuiButton class. - */ -GuiButton::~GuiButton() = default; - -void GuiButton::setImage(GuiImage *img) { - image = img; - if (img) { img->setParent(this); } -} - -void GuiButton::setImageOver(GuiImage *img) { - imageOver = img; - if (img) { img->setParent(this); } -} - -void GuiButton::setImageHold(GuiImage *img) { - imageHold = img; - if (img) { img->setParent(this); } -} - -void GuiButton::setImageClick(GuiImage *img) { - imageClick = img; - if (img) { img->setParent(this); } -} - -void GuiButton::setIcon(GuiImage *img) { - icon = img; - if (img) { img->setParent(this); } -} - -void GuiButton::setIconOver(GuiImage *img) { - iconOver = img; - if (img) { img->setParent(this); } -} - -void GuiButton::setLabel(GuiText *txt, int32_t n) { - label[n] = txt; - if (txt) { txt->setParent(this); } -} - -void GuiButton::setLabelOver(GuiText *txt, int32_t n) { - labelOver[n] = txt; - if (txt) { txt->setParent(this); } -} - -void GuiButton::setLabelHold(GuiText *txt, int32_t n) { - labelHold[n] = txt; - if (txt) { txt->setParent(this); } -} - -void GuiButton::setLabelClick(GuiText *txt, int32_t n) { - labelClick[n] = txt; - if (txt) { txt->setParent(this); } -} - -void GuiButton::setSoundOver(GuiSound *snd) { - soundOver = snd; -} - -void GuiButton::setSoundHold(GuiSound *snd) { - soundHold = snd; -} - -void GuiButton::setSoundClick(GuiSound *snd) { - soundClick = snd; -} - -void GuiButton::setTrigger(GuiTrigger *t, int32_t idx) { - if (idx >= 0 && idx < iMaxGuiTriggers) { - trigger[idx] = t; - } else { - for (auto &i : trigger) { - if (!i) { - i = t; - break; - } - } - } -} - -void GuiButton::resetState() { - clickedTrigger = nullptr; - heldTrigger = nullptr; - GuiElement::resetState(); -} - -/** - * Draw the button on screen - */ -void GuiButton::draw(Renderer *v) { - if (!this->isVisible()) { - return; - } - - // draw image - if ((isDrawOverOnlyWhenSelected() && (isStateSet(STATE_SELECTED) && imageOver)) || - (!isDrawOverOnlyWhenSelected() && (isStateSet(STATE_OVER | STATE_SELECTED | STATE_CLICKED | STATE_HELD) && imageOver))) { - imageOver->draw(v); - } else if (image) { - image->draw(v); - } - - if ((isDrawOverOnlyWhenSelected() && (isStateSet(STATE_SELECTED) && iconOver)) || - (!isDrawOverOnlyWhenSelected() && (isStateSet(STATE_OVER | STATE_SELECTED | STATE_CLICKED | STATE_HELD) && iconOver))) { - iconOver->draw(v); - } else if (icon) { - icon->draw(v); - } - - // draw text - for (int32_t i = 0; i < 4; i++) { - if (isStateSet(STATE_OVER | STATE_SELECTED | STATE_CLICKED | STATE_HELD) && labelOver[i]) { - labelOver[i]->draw(v); - } else if (label[i]) { - label[i]->draw(v); - } - } -} - -void GuiButton::update(GuiController *c) { - if (!c || isStateSet(STATE_DISABLED | STATE_HIDDEN | STATE_DISABLE_INPUT, c->chanIdx)) { - return; - } else if (parentElement && (parentElement->isStateSet(STATE_DISABLED | STATE_HIDDEN | STATE_DISABLE_INPUT, c->chanIdx))) { - return; - } - - if (selectable) { - if (c->data.validPointer && this->isInside(c->data.x, c->data.y)) { - if (!isStateSet(STATE_OVER, c->chanIdx)) { - setState(STATE_OVER, c->chanIdx); - - //if(this->isRumbleActive()) - // this->rumble(t->chan); - - if (soundOver) { - soundOver->Play(); - } - - if (effectsOver && !effects) { - // initiate effects - effects = effectsOver; - effectAmount = effectAmountOver; - effectTarget = effectTargetOver; - } - - pointedOn(this, c); - } - } else if (isStateSet(STATE_OVER, c->chanIdx)) { - this->clearState(STATE_OVER, c->chanIdx); - pointedOff(this, c); - - if (effectTarget == effectTargetOver && effectAmount == effectAmountOver) { - // initiate effects (in reverse) - effects = effectsOver; - effectAmount = -effectAmountOver; - effectTarget = 100; - } - } - } - - for (auto & i : trigger) { - if (!i) { - continue; - } - - // button triggers - if (clickable) { - int32_t isClicked = i->clicked(c); - if (!clickedTrigger && (isClicked != GuiTrigger::CLICKED_NONE) - && (i->isClickEverywhere() || (isStateSet(STATE_SELECTED | STATE_OVER, c->chanIdx) && i->isSelectionClickEverywhere()) || this->isInside(c->data.x, c->data.y))) { - if (soundClick) { - soundClick->Play(); - } - - clickedTrigger = i; - - if (!isStateSet(STATE_CLICKED, c->chanIdx)) { - if (isClicked == GuiTrigger::CLICKED_TOUCH) { - setState(STATE_CLICKED_TOUCH, c->chanIdx); - } else { - setState(STATE_CLICKED, c->chanIdx); - } - } - - clicked(this, c, i); - } else if ((isStateSet(STATE_CLICKED, c->chanIdx) || isStateSet(STATE_CLICKED_TOUCH, c->chanIdx)) && (clickedTrigger == i) && !isStateSet(STATE_HELD, c->chanIdx) && !i->held(c) && - ((isClicked == GuiTrigger::CLICKED_NONE) || i->released(c))) { - if ((isStateSet(STATE_CLICKED_TOUCH, c->chanIdx) && this->isInside(c->data.x, c->data.y)) || (isStateSet(STATE_CLICKED, c->chanIdx))) { - clickedTrigger = nullptr; - clearState(STATE_CLICKED, c->chanIdx); - released(this, c, i); - } - } - } - - if (holdable) { - bool isHeld = i->held(c); - - if ((!heldTrigger || heldTrigger == i) && isHeld - && (i->isHoldEverywhere() || (isStateSet(STATE_SELECTED | STATE_OVER, c->chanIdx) && i->isSelectionClickEverywhere()) || this->isInside(c->data.x, c->data.y))) { - heldTrigger = i; - - if (!isStateSet(STATE_HELD, c->chanIdx)) { - setState(STATE_HELD, c->chanIdx); - } - - held(this, c, i); - } else if (isStateSet(STATE_HELD, c->chanIdx) && (heldTrigger == i) && (!isHeld || i->released(c))) { - //! click is removed at this point and converted to held - if (clickedTrigger == i) { - clickedTrigger = nullptr; - clearState(STATE_CLICKED, c->chanIdx); - } - heldTrigger = nullptr; - clearState(STATE_HELD, c->chanIdx); - released(this, c, i); - } - } - } -} - -void GuiButton::process() { - GuiElement::process(); - - if(image) { image->process(); } - if(imageOver) { imageOver->process(); } - if(imageHold) { imageHold->process(); } - if(imageClick) { imageClick->process(); } - if(icon) { icon->process(); } - if(iconOver) { iconOver->process(); } - if(soundOver) { soundOver->process(); } - if(soundHold) { soundHold->process(); } - if(soundClick) { soundClick->process(); } - - for(int i = 0;i<4;i++){ - if(label[i]) { label[i]->process(); } - if(labelOver[i]) { labelOver[i]->process(); } - if(labelHold[i]) { labelHold[i]->process(); } - if(labelClick[i]) { labelClick[i]->process(); } - } -} diff --git a/src/gui/GuiButton.h b/src/gui/GuiButton.h deleted file mode 100644 index 6a4390a..0000000 --- a/src/gui/GuiButton.h +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2015 Dimok - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ -#pragma once -#include "GuiElement.h" -#include "GuiImage.h" -#include "GuiText.h" -#include "GuiSound.h" -#include "GuiTrigger.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 { -public: - //!Constructor - //!\param w Width - //!\param h Height - GuiButton(float w, float h); - - //!Destructor - virtual ~GuiButton(); - - //!Sets the button's image - //!\param i Pointer to GuiImage object - void setImage(GuiImage *i); - - //!Sets the button's image on over - //!\param i Pointer to GuiImage object - void setImageOver(GuiImage *i); - - void setIcon(GuiImage *i); - - void setIconOver(GuiImage *i); - - //!Sets the button's image on hold - //!\param i Pointer to GuiImage object - void setImageHold(GuiImage *i); - - //!Sets the button's image on click - //!\param i Pointer to GuiImage object - void setImageClick(GuiImage *i); - - //!Sets the button's label - //!\param t Pointer to GuiText object - //!\param n Index of label to set (optional, default is 0) - void setLabel(GuiText *t, int32_t n = 0); - - //!Sets the button's label on over (eg: different colored text) - //!\param t Pointer to GuiText object - //!\param n Index of label to set (optional, default is 0) - void setLabelOver(GuiText *t, int32_t n = 0); - - //!Sets the button's label on hold - //!\param t Pointer to GuiText object - //!\param n Index of label to set (optional, default is 0) - void setLabelHold(GuiText *t, int32_t n = 0); - - //!Sets the button's label on click - //!\param t Pointer to GuiText object - //!\param n Index of label to set (optional, default is 0) - void setLabelClick(GuiText *t, int32_t n = 0); - - //!Sets the sound to play on over - //!\param s Pointer to GuiSound object - void setSoundOver(GuiSound *s); - - //!Sets the sound to play on hold - //!\param s Pointer to GuiSound object - void setSoundHold(GuiSound *s); - - //!Sets the sound to play on click - //!\param s Pointer to GuiSound object - void setSoundClick(GuiSound *s); - - //!Set a new GuiTrigger for the element - //!\param i Index of trigger array to set - //!\param t Pointer to GuiTrigger - void setTrigger(GuiTrigger *t, int32_t idx = -1); - - //! - void resetState(void) override; - - //!Constantly called to draw the GuiButton - 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 - void update(GuiController *c) override; - - void process() override; - - sigslot::signal2 selected; - sigslot::signal2 deSelected; - sigslot::signal2 pointedOn; - sigslot::signal2 pointedOff; - sigslot::signal3 clicked; - sigslot::signal3 held; - sigslot::signal3 released; -protected: - static const int32_t iMaxGuiTriggers = 10; - - GuiImage *image; //!< Button image (default) - GuiImage *imageOver; //!< Button image for STATE_SELECTED - GuiImage *imageHold; //!< Button image for STATE_HELD - GuiImage *imageClick; //!< Button image for STATE_CLICKED - GuiImage *icon; - GuiImage *iconOver; - GuiText *label[4]; //!< Label(s) to display (default) - GuiText *labelOver[4]; //!< Label(s) to display for STATE_SELECTED - GuiText *labelHold[4]; //!< Label(s) to display for STATE_HELD - GuiText *labelClick[4]; //!< Label(s) to display for STATE_CLICKED - GuiSound *soundOver; //!< Sound to play for STATE_SELECTED - GuiSound *soundHold; //!< Sound to play for STATE_HELD - GuiSound *soundClick; //!< Sound to play for STATE_CLICKED - GuiTrigger *trigger[iMaxGuiTriggers]; //!< GuiTriggers (input actions) that this element responds to - GuiTrigger *clickedTrigger; - GuiTrigger *heldTrigger; -}; diff --git a/src/gui/GuiController.h b/src/gui/GuiController.h deleted file mode 100644 index f506eb2..0000000 --- a/src/gui/GuiController.h +++ /dev/null @@ -1,68 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2015 Dimok - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ -#pragma once - -#include -#include "GuiTrigger.h" - -class GuiController { -public: - //!Constructor - GuiController(int32_t channel) - : chan(channel) { - memset(&lastData, 0, sizeof(lastData)); - memset(&data, 0, sizeof(data)); - - switch (chan) { - default: - case GuiTrigger::CHANNEL_1: - chanIdx = 0; - break; - case GuiTrigger::CHANNEL_2: - chanIdx = 1; - break; - case GuiTrigger::CHANNEL_3: - chanIdx = 2; - break; - case GuiTrigger::CHANNEL_4: - chanIdx = 3; - break; - case GuiTrigger::CHANNEL_5: - chanIdx = 4; - break; - } - } - - //!Destructor - virtual ~GuiController() {} - - typedef struct { - uint32_t buttons_h; - uint32_t buttons_d; - uint32_t buttons_r; - bool validPointer; - bool touched; - float pointerAngle; - int32_t x; - int32_t y; - } PadData; - - uint32_t chan; - int32_t chanIdx; - PadData data; - PadData lastData; -}; diff --git a/src/gui/GuiElement.cpp b/src/gui/GuiElement.cpp deleted file mode 100644 index cee2a97..0000000 --- a/src/gui/GuiElement.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2015 Dimok - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ -#include "GuiElement.h" - -//! TODO remove this! -static int32_t screenwidth = 1280; -static int32_t screenheight = 720; - -/** - * Constructor for the Object class. - */ -GuiElement::GuiElement() { - xoffset = 0.0f; - yoffset = 0.0f; - zoffset = 0.0f; - width = 0.0f; - height = 0.0f; - alpha = 1.0f; - scaleX = 1.0f; - scaleY = 1.0f; - scaleZ = 1.0f; - for (unsigned int & i : state) { - i = STATE_DEFAULT; - } - stateChan = -1; - parentElement = nullptr; - rumble = true; - selectable = false; - clickable = false; - holdable = false; - drawOverOnlyWhenSelected = false; - visible = true; - yoffsetDyn = 0; - xoffsetDyn = 0; - alphaDyn = -1; - scaleDyn = 1; - effects = EFFECT_NONE; - effectAmount = 0; - effectTarget = 0; - effectsOver = EFFECT_NONE; - effectAmountOver = 0; - effectTargetOver = 0; - angle = 0.0f; - - // default alignment - align to top left - alignment = (ALIGN_TOP_LEFT); -} - -/** - * Get the left position of the GuiElement. - * @see SetLeft() - * @return Left position in pixel. - */ -float GuiElement::getLeft() { - float pWidth = 0; - float pLeft = 0; - float pScaleX = 1.0f; - - if (parentElement) { - pWidth = parentElement->getWidth(); - pLeft = parentElement->getLeft(); - pScaleX = parentElement->getScaleX(); - } - - pLeft += xoffsetDyn; - - float x = pLeft; - - //! TODO: the conversion from int to float and back to int is bad for performance, change that - if (alignment & ALIGN_CENTER) { - x = pLeft + pWidth * 0.5f * pScaleX - width * 0.5f * getScaleX(); - } else if (alignment & ALIGN_RIGHT) { - x = pLeft + pWidth * pScaleX - width * getScaleX(); - } - - return x + xoffset; -} - -/** - * Get the top position of the GuiElement. - * @see SetTop() - * @return Top position in pixel. - */ -float GuiElement::getTop() { - float pHeight = 0; - float pTop = 0; - float pScaleY = 1.0f; - - if (parentElement) { - pHeight = parentElement->getHeight(); - pTop = parentElement->getTop(); - pScaleY = parentElement->getScaleY(); - } - - pTop += yoffsetDyn; - - float y = pTop; - - //! TODO: the conversion from int to float and back to int is bad for performance, change that - if (alignment & ALIGN_MIDDLE) { - y = pTop + pHeight * 0.5f * pScaleY - getHeight() * 0.5f * getScaleY(); - } else if (alignment & ALIGN_BOTTOM) { - y = pTop + pHeight * pScaleY - getHeight() * getScaleY(); - } - - return y + yoffset; -} - -void GuiElement::setEffect(uint32_t eff, int32_t amount, int32_t target) { - if (eff & EFFECT_SLIDE_IN) { - // these calculations overcompensate a little - if (eff & EFFECT_SLIDE_TOP) { - if (eff & EFFECT_SLIDE_FROM) { - yoffsetDyn = (int32_t) -getHeight() * scaleY; - } else { - yoffsetDyn = -screenheight; - } - } else if (eff & EFFECT_SLIDE_LEFT) { - if (eff & EFFECT_SLIDE_FROM) { - xoffsetDyn = (int32_t) -getWidth() * scaleX; - } else { - xoffsetDyn = -screenwidth; - } - } else if (eff & EFFECT_SLIDE_BOTTOM) { - if (eff & EFFECT_SLIDE_FROM) { - yoffsetDyn = (int32_t) getHeight() * scaleY; - } else { - yoffsetDyn = screenheight; - } - } else if (eff & EFFECT_SLIDE_RIGHT) { - if (eff & EFFECT_SLIDE_FROM) { - xoffsetDyn = (int32_t) getWidth() * scaleX; - } else { - xoffsetDyn = screenwidth; - } - } - } - if ((eff & EFFECT_FADE) && amount > 0) { - alphaDyn = 0; - } else if ((eff & EFFECT_FADE) && amount < 0) { - alphaDyn = alpha; - } - effects |= eff; - effectAmount = amount; - effectTarget = target; -} - -//!Sets an effect to be enabled on wiimote cursor over -//!\param e Effect to enable -//!\param a Amount of the effect (usage varies on effect) -//!\param t Target amount of the effect (usage varies on effect) -void GuiElement::setEffectOnOver(uint32_t e, int32_t a, int32_t t) { - effectsOver |= e; - effectAmountOver = a; - effectTargetOver = t; -} - -void GuiElement::resetEffects() { - yoffsetDyn = 0; - xoffsetDyn = 0; - alphaDyn = -1; - scaleDyn = 1; - effects = EFFECT_NONE; - effectAmount = 0; - effectTarget = 0; - effectsOver = EFFECT_NONE; - effectAmountOver = 0; - effectTargetOver = 0; -} - -void GuiElement::updateEffects() { - if (!this->isVisible() && parentElement) { - return; - } - - if (effects & (EFFECT_SLIDE_IN | EFFECT_SLIDE_OUT | EFFECT_SLIDE_FROM)) { - if (effects & EFFECT_SLIDE_IN) { - if (effects & EFFECT_SLIDE_LEFT) { - xoffsetDyn += effectAmount; - - if (xoffsetDyn >= 0) { - xoffsetDyn = 0; - effects = 0; - effectFinished(this); - } - } else if (effects & EFFECT_SLIDE_RIGHT) { - xoffsetDyn -= effectAmount; - - if (xoffsetDyn <= 0) { - xoffsetDyn = 0; - effects = 0; - effectFinished(this); - } - } else if (effects & EFFECT_SLIDE_TOP) { - yoffsetDyn += effectAmount; - - if (yoffsetDyn >= 0) { - yoffsetDyn = 0; - effects = 0; - effectFinished(this); - } - } else if (effects & EFFECT_SLIDE_BOTTOM) { - yoffsetDyn -= effectAmount; - - if (yoffsetDyn <= 0) { - yoffsetDyn = 0; - effects = 0; - effectFinished(this); - } - } - } else { - if (effects & EFFECT_SLIDE_LEFT) { - xoffsetDyn -= effectAmount; - - if (xoffsetDyn <= -screenwidth) { - effects = 0; // shut off effect - effectFinished(this); - } else if ((effects & EFFECT_SLIDE_FROM) && xoffsetDyn <= -getWidth()) { - effects = 0; // shut off effect - effectFinished(this); - } - } else if (effects & EFFECT_SLIDE_RIGHT) { - xoffsetDyn += effectAmount; - - if (xoffsetDyn >= screenwidth) { - effects = 0; // shut off effect - effectFinished(this); - } else if ((effects & EFFECT_SLIDE_FROM) && xoffsetDyn >= getWidth() * scaleX) { - effects = 0; // shut off effect - effectFinished(this); - } - } else if (effects & EFFECT_SLIDE_TOP) { - yoffsetDyn -= effectAmount; - - if (yoffsetDyn <= -screenheight) { - effects = 0; // shut off effect - effectFinished(this); - } else if ((effects & EFFECT_SLIDE_FROM) && yoffsetDyn <= -getHeight()) { - effects = 0; // shut off effect - effectFinished(this); - } - } else if (effects & EFFECT_SLIDE_BOTTOM) { - yoffsetDyn += effectAmount; - - if (yoffsetDyn >= screenheight) { - effects = 0; // shut off effect - effectFinished(this); - } else if ((effects & EFFECT_SLIDE_FROM) && yoffsetDyn >= getHeight()) { - effects = 0; // shut off effect - effectFinished(this); - } - } - } - } else if (effects & EFFECT_FADE) { - alphaDyn += effectAmount * (1.0f / 255.0f); - - if (effectAmount < 0 && alphaDyn <= 0) { - alphaDyn = 0; - effects = 0; // shut off effect - effectFinished(this); - } else if (effectAmount > 0 && alphaDyn >= alpha) { - alphaDyn = alpha; - effects = 0; // shut off effect - effectFinished(this); - } - } else if (effects & EFFECT_SCALE) { - scaleDyn += effectAmount * 0.01f; - - if ((effectAmount < 0 && scaleDyn <= (effectTarget * 0.01f)) - || (effectAmount > 0 && scaleDyn >= (effectTarget * 0.01f))) { - scaleDyn = effectTarget * 0.01f; - effects = 0; // shut off effect - effectFinished(this); - } - } -} diff --git a/src/gui/GuiElement.h b/src/gui/GuiElement.h deleted file mode 100644 index f331c2b..0000000 --- a/src/gui/GuiElement.h +++ /dev/null @@ -1,629 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2015 Dimok - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ -#pragma once - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include "sigslot.h" -#include "../system/video/Renderer.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -enum { - EFFECT_NONE = 0x00, - EFFECT_SLIDE_TOP = 0x01, - EFFECT_SLIDE_BOTTOM = 0x02, - EFFECT_SLIDE_RIGHT = 0x04, - EFFECT_SLIDE_LEFT = 0x08, - EFFECT_SLIDE_IN = 0x10, - EFFECT_SLIDE_OUT = 0x20, - EFFECT_SLIDE_FROM = 0x40, - EFFECT_FADE = 0x80, - EFFECT_SCALE = 0x100, - EFFECT_COLOR_TRANSITION = 0x200 -}; - -enum { - ALIGN_LEFT = 0x01, - ALIGN_CENTER = 0x02, - ALIGN_RIGHT = 0x04, - ALIGN_TOP = 0x10, - ALIGN_MIDDLE = 0x20, - ALIGN_BOTTOM = 0x40, - ALIGN_TOP_LEFT = ALIGN_LEFT | ALIGN_TOP, - ALIGN_TOP_CENTER = ALIGN_CENTER | ALIGN_TOP, - ALIGN_TOP_RIGHT = ALIGN_RIGHT | ALIGN_TOP, - ALIGN_CENTERED = ALIGN_CENTER | ALIGN_MIDDLE, -}; - -//!Forward declaration -class GuiController; - -class SDLSystem; - -//!Primary GUI class. Most other classes inherit from this class. -class GuiElement { -public: - //!Constructor - GuiElement(); - - //!Destructor - virtual ~GuiElement() = default; - - //!Set the element's parent - //!\param e Pointer to parent element - virtual void setParent(GuiElement *e) { - parentElement = e; - } - - //!Gets the element's parent - //!\return Pointer to parent element - virtual GuiElement *getParent() { - return parentElement; - } - - //!Gets the current leftmost coordinate of the element - //!Considers horizontal alignment, x offset, width, and parent element's GetLeft() / GetWidth() values - //!\return left coordinate - virtual float getLeft(); - - //!Gets the current topmost coordinate of the element - //!Considers vertical alignment, y offset, height, and parent element's GetTop() / GetHeight() values - //!\return top coordinate - virtual float getTop(); - - //!Gets the current Z coordinate of the element - //!\return Z coordinate - virtual float getDepth() { - float zParent = 0.0f; - - if (parentElement) { - zParent = parentElement->getDepth(); - } - - return zParent + zoffset; - } - - virtual float getCenterX() { - float pCenterX = 0.0f; - - if (parentElement) { - pCenterX = parentElement->getCenterX(); - } - - pCenterX += xoffset + xoffsetDyn; - - if (alignment & ALIGN_LEFT) { - float pWidth = 0.0f; - float pScale = 0.0f; - - if (parentElement) { - pWidth = parentElement->getWidth(); - pScale = parentElement->getScaleX(); - } - - pCenterX -= pWidth * 0.5f * pScale - width * 0.5f * getScaleX(); - } else if (alignment & ALIGN_RIGHT) { - float pWidth = 0.0f; - float pScale = 0.0f; - - if (parentElement) { - pWidth = parentElement->getWidth(); - pScale = parentElement->getScaleX(); - } - - pCenterX += pWidth * 0.5f * pScale - width * 0.5f * getScaleX(); - } - return pCenterX; - } - - virtual float getCenterY() { - float pCenterY = 0.0f; - - if (parentElement) { - pCenterY = parentElement->getCenterY(); - } - - pCenterY += yoffset + yoffsetDyn; - - if (alignment & ALIGN_TOP) { - float pHeight = 0.0f; - float pScale = 0.0f; - - if (parentElement) { - pHeight = parentElement->getHeight(); - pScale = parentElement->getScaleY(); - } - - pCenterY += pHeight * 0.5f * pScale + getHeight() * 0.5f * getScaleY(); - } else if (alignment & ALIGN_BOTTOM) { - float pHeight = 0.0f; - float pScale = 0.0f; - - if (parentElement) { - pHeight = parentElement->getHeight(); - pScale = parentElement->getScaleY(); - } - - pCenterY -= pHeight * 0.5f * pScale - getHeight() * 0.5f * getScaleY(); - } - return pCenterY; - } - - //!Gets elements xoffset - virtual float getOffsetX() { - return xoffset; - } - - //!Gets elements yoffset - virtual float getOffsetY() { - return yoffset; - } - - //!Gets the current width of the element. Does not currently consider the scale - //!\return width - virtual float getWidth() { - return width; - }; - - //!Gets the height of the element. Does not currently consider the scale - //!\return height - virtual float getHeight() { - return height; - } - - //!Sets the size (width/height) of the element - //!\param w Width of element - //!\param h Height of element - virtual void setSize(float w, float h) { - width = w; - height = h; - } - - //!Sets the element's visibility - //!\param v Visibility (true = visible) - virtual void setVisible(bool v) { - visible = v; - visibleChanged(this, v); - } - - //!Checks whether or not the element is visible - //!\return true if visible, false otherwise - virtual bool isVisible() const { - return !isStateSet(STATE_HIDDEN) && visible; - }; - - //!Checks whether or not the element is selectable - //!\return true if selectable, false otherwise - virtual bool isSelectable() { - return !isStateSet(STATE_DISABLED) && selectable; - } - - virtual bool isDrawOverOnlyWhenSelected() { - return drawOverOnlyWhenSelected; - } - - virtual void setdrawOverOnlyWhenSelected(bool s) { - drawOverOnlyWhenSelected = s; - } - - //!Checks whether or not the element is clickable - //!\return true if clickable, false otherwise - virtual bool isClickable() { - return !isStateSet(STATE_DISABLED) && clickable; - } - - //!Checks whether or not the element is holdable - //!\return true if holdable, false otherwise - virtual bool isHoldable() { - return !isStateSet(STATE_DISABLED) && holdable; - } - - //!Sets whether or not the element is selectable - //!\param s Selectable - virtual void setSelectable(bool s) { - selectable = s; - } - - //!Sets whether or not the element is clickable - //!\param c Clickable - virtual void setClickable(bool c) { - clickable = c; - } - - //!Sets whether or not the element is holdable - //!\param c Holdable - virtual void setHoldable(bool d) { - holdable = d; - } - - //!Sets the element's state - //!\param s State (STATE_DEFAULT, STATE_SELECTED, STATE_CLICKED, STATE_DISABLED) - //!\param c Controller channel (0-3, -1 = none) - virtual void setState(uint32_t s, int32_t c) { - if (c >= 0 && c < 5) { - state[c] |= s; - } else { - for (int32_t i = 0; i < 5; i++) { - state[i] |= s; - } - } - stateChan = c; - stateChanged(this, s, c); - } - - virtual void clearState(uint32_t s, int32_t c) { - if (c >= 0 && c < 5) { - state[c] &= ~s; - } else { - for (unsigned int & i : state) { - i &= ~s; - } - } - stateChan = c; - stateChanged(this, s, c); - } - - virtual bool isStateSet(uint32_t s, int32_t c = -1) const { - if (c >= 0 && c < 5) { - return (state[c] & s) != 0; - } else { - for (unsigned int i : state) { - if ((i & s) != 0) { - return true; - } - } - - return false; - } - } - - //!Gets the element's current state - //!\return state - virtual int32_t getState(int32_t c) { - return state[c]; - }; - - //!Gets the controller channel that last changed the element's state - //!\return Channel number (0-3, -1 = no channel) - virtual int32_t getStateChan() { - return stateChan; - }; - - //!Resets the element's state to STATE_DEFAULT - virtual void resetState() { - for (unsigned int & i : state) { - i = STATE_DEFAULT; - } - stateChan = -1; - } - - //!Sets the element's alpha value - //!\param a alpha value - virtual void setAlpha(float a) { - alpha = a; - } - - //!Gets the element's alpha value - //!Considers alpha, alphaDyn, and the parent element's getAlpha() value - //!\return alpha - virtual float getAlpha() { - float a; - - if (alphaDyn >= 0) { - a = alphaDyn; - } else { - a = alpha; - } - - if (parentElement) { - a = (a * parentElement->getAlpha()); - } - - return a; - } - - //!Sets the element's scale - //!\param s scale (1 is 100%) - virtual void setScale(float s) { - scaleX = s; - scaleY = s; - scaleZ = s; - } - - //!Sets the element's scale - //!\param s scale (1 is 100%) - virtual void setScaleX(float s) { - scaleX = s; - } - - //!Sets the element's scale - //!\param s scale (1 is 100%) - virtual void setScaleY(float s) { - scaleY = s; - } - - //!Sets the element's scale - //!\param s scale (1 is 100%) - virtual void setScaleZ(float s) { - scaleZ = s; - } - - //!Gets the element's current scale - //!Considers scale, scaleDyn, and the parent element's getScale() value - virtual float getScale() { - float s = 0.5f * (scaleX + scaleY) * scaleDyn; - - if (parentElement) { - s *= parentElement->getScale(); - } - - return s; - } - - //!Gets the element's current scale - //!Considers scale, scaleDyn, and the parent element's getScale() value - virtual float getScaleX() { - float s = scaleX * scaleDyn; - - if (parentElement) { - s *= parentElement->getScaleX(); - } - - return s; - } - - //!Gets the element's current scale - //!Considers scale, scaleDyn, and the parent element's getScale() value - virtual float getScaleY() { - float s = scaleY * scaleDyn; - - if (parentElement) { - s *= parentElement->getScaleY(); - } - - return s; - } - - //!Gets the element's current scale - //!Considers scale, scaleDyn, and the parent element's getScale() value - virtual float getScaleZ() { - float s = scaleZ; - - if (parentElement) { - s *= parentElement->getScaleZ(); - } - - return s; - } - - //!Checks whether rumble was requested by the element - //!\return true is rumble was requested, false otherwise - virtual bool isRumbleActive() { - return rumble; - } - - //!Sets whether or not the element is requesting a rumble event - //!\param r true if requesting rumble, false if not - virtual void setRumble(bool r) { - rumble = r; - } - - //!Set an effect for the element - //!\param e Effect to enable - //!\param a Amount of the effect (usage varies on effect) - //!\param t Target amount of the effect (usage varies on effect) - virtual void setEffect(uint32_t e, int32_t a, int32_t t); - - //!Sets an effect to be enabled on wiimote cursor over - //!\param e Effect to enable - //!\param a Amount of the effect (usage varies on effect) - //!\param t Target amount of the effect (usage varies on effect) - virtual void setEffectOnOver(uint32_t e, int32_t a, int32_t t); - - //!Shortcut to SetEffectOnOver(EFFECT_SCALE, 4, 110) - virtual void setEffectGrow() { - setEffectOnOver(EFFECT_SCALE, 4, 110); - } - - //!Reset all applied effects - virtual void resetEffects(); - - //!Gets the current element effects - //!\return element effects - virtual int32_t getEffect() const { - return effects; - } - - //!\return true if element animation is on going - virtual bool isAnimated() const { - return (parentElement != 0) && (getEffect() > 0); - } - - //!Checks whether the specified coordinates are within the element's boundaries - //!\param x X coordinate - //!\param y Y coordinate - //!\return true if contained within, false otherwise - virtual bool isInside(float x, float y) { - float rotatedX = x; - float rotatedY = y; - - if (getAngle() != 0.f) { - // translate input point - float tempX = x - getCenterX(); - float tempY = y - getCenterY(); - - // Conver to Rad - auto angleInRad = (float) ((getAngle() * -1.0f) * M_PI / 180.0f); - - // now apply rotation - rotatedX = tempX * cos((angleInRad)) - tempY * sin(angleInRad); - rotatedY = tempX * sin(angleInRad) + tempY * cos(angleInRad); - - // translate back - rotatedX = rotatedX + getCenterX(); - rotatedY = rotatedY + getCenterY(); - } - - return (rotatedX > (this->getCenterX() - getScaleX() * getWidth() * 0.5f) - && rotatedX < (this->getCenterX() + getScaleX() * getWidth() * 0.5f) - && rotatedY > (this->getCenterY() - getScaleY() * getHeight() * 0.5f) - && rotatedY < (this->getCenterY() + getScaleY() * getHeight() * 0.5f)); - } - - //!Sets the element's position - //!\param x X coordinate - //!\param y Y coordinate - virtual void setPosition(float x, float y) { - xoffset = x; - yoffset = y; - } - - //!Sets the element's position - //!\param x X coordinate - //!\param y Y coordinate - //!\param z Z coordinate - virtual void setPosition(float x, float y, float z) { - xoffset = x; - yoffset = y; - zoffset = z; - } - - //!Gets whether or not the element is in STATE_SELECTED - //!\return true if selected, false otherwise - virtual int32_t getSelected() { - return -1; - } - - //!Sets the element's alignment respective to its parent element - //!Bitwise ALIGN_LEFT | ALIGN_RIGHT | ALIGN_CENTRE, ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE) - //!\param align Alignment - virtual void setAlignment(int32_t a) { - alignment = a; - } - - //!Gets the element's alignment - virtual int32_t getAlignment() const { - return alignment; - } - - //!Angle of the object - virtual void setAngle(float a) { - angle = a; - } - - //!Angle of the object - virtual float getAngle() const { - float r_angle = angle; - if (parentElement) { r_angle += parentElement->getAngle(); } - return r_angle; - } - - //!Called constantly to allow the element to respond to the current input data - //!\param t Pointer to a GuiController, containing the current input data from PAD/WPAD/VPAD - virtual void update(GuiController *t) {} - - //!Called constantly to redraw the element - virtual void draw(Renderer * v) {} - - //!Called constantly to process stuff in the element - virtual void process() {} - - //!Updates the element's effects (dynamic values) - //!Called by Draw(), used for animation purposes - virtual void updateEffects(); - - typedef struct _POINT { - int32_t x; - int32_t y; - } POINT; - - enum { - STATE_DEFAULT = 0, - STATE_SELECTED = 0x01, - STATE_CLICKED = 0x02, - STATE_HELD = 0x04, - STATE_OVER = 0x08, - STATE_HIDDEN = 0x10, - STATE_DISABLE_INPUT = 0x20, - STATE_CLICKED_TOUCH = 0x40, - STATE_DISABLED = 0x80 - }; - - //! Switch pointer from control to screen position - POINT PtrToScreen(POINT p) { - //! TODO for 3D - //POINT r = { p.x + getLeft(), p.y + getTop() }; - return p; - } - - //! Switch pointer screen to control position - POINT PtrToControl(POINT p) { - //! TODO for 3D - //POINT r = { p.x - getLeft(), p.y - getTop() }; - return p; - } - - //! Signals - sigslot::signal2 visibleChanged; - sigslot::signal3 stateChanged; - sigslot::signal1 effectFinished; -protected: - bool rumble; //!< Wiimote rumble (on/off) - set to on when this element requests a rumble event - bool visible; //!< Visibility of the element. If false, Draw() is skipped - bool selectable; //!< Whether or not this element selectable (can change to SELECTED state) - bool clickable; //!< Whether or not this element is clickable (can change to CLICKED state) - bool holdable; //!< Whether or not this element is holdable (can change to HELD state) - bool drawOverOnlyWhenSelected; //!< Whether or not this element is holdable (can change to HELD state) - float width; //!< Element width - float height; //!< Element height - float xoffset; //!< Element X offset - float yoffset; //!< Element Y offset - float zoffset; //!< Element Z offset - float alpha; //!< Element alpha value (0-255) - float angle; //!< Angle of the object (0-360) - float scaleX; //!< Element scale (1 = 100%) - float scaleY; //!< Element scale (1 = 100%) - float scaleZ; //!< Element scale (1 = 100%) - uint32_t alignment; //!< Horizontal element alignment, respective to parent element - uint32_t state[5]{}; //!< Element state (DEFAULT, SELECTED, CLICKED, DISABLED) - int32_t stateChan; //!< Which controller channel is responsible for the last change in state - GuiElement *parentElement; //!< Parent element - - //! TODO: Move me to some Animator class - int32_t xoffsetDyn; //!< Element X offset, dynamic (added to xoffset value for animation effects) - int32_t yoffsetDyn; //!< Element Y offset, dynamic (added to yoffset value for animation effects) - float alphaDyn; //!< Element alpha, dynamic (multiplied by alpha value for blending/fading effects) - float scaleDyn; //!< Element scale, dynamic (multiplied by alpha value for blending/fading effects) - uint32_t effects; //!< Currently enabled effect(s). 0 when no effects are enabled - int32_t effectAmount; //!< Effect amount. Used by different effects for different purposes - int32_t effectTarget; //!< Effect target amount. Used by different effects for different purposes - uint32_t effectsOver; //!< Effects to enable when wiimote cursor is over this element. Copied to effects variable on over event - int32_t effectAmountOver; //!< EffectAmount to set when wiimote cursor is over this element - int32_t effectTargetOver; //!< EffectTarget to set when wiimote cursor is over this element -}; diff --git a/src/gui/GuiFrame.cpp b/src/gui/GuiFrame.cpp deleted file mode 100644 index accde1b..0000000 --- a/src/gui/GuiFrame.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2015 Dimok - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ -#include "GuiFrame.h" - -GuiFrame::GuiFrame(GuiFrame *p) { - parent = p; - width = 0; - height = 0; - dim = false; - - if (parent) { - parent->append(this); - } -} - -GuiFrame::GuiFrame(float w, float h, GuiFrame *p) { - parent = p; - width = w; - height = h; - dim = false; - - if (parent) { - parent->append(this); - } -} - -GuiFrame::~GuiFrame() { - closing(this); - - if (parent) { - parent->remove(this); - } -} - -void GuiFrame::append(GuiElement *e) { - if (e == nullptr) { - return; - } - - remove(e); - mutex.lock(); - elements.push_back(e); - e->setParent(this); - mutex.unlock(); -} - -void GuiFrame::insert(GuiElement *e, uint32_t index) { - if (e == nullptr || (index >= elements.size())) { - return; - } - - remove(e); - mutex.lock(); - elements.insert(elements.begin() + index, e); - e->setParent(this); - mutex.unlock(); -} - -void GuiFrame::remove(GuiElement *e) { - if (e == NULL) { - return; - } - - mutex.lock(); - for (uint32_t i = 0; i < elements.size(); ++i) { - if (e == elements[i]) { - elements.erase(elements.begin() + i); - break; - } - } - mutex.unlock(); -} - -void GuiFrame::removeAll() { - mutex.lock(); - elements.clear(); - mutex.unlock(); -} - -GuiElement *GuiFrame::getGuiElementAt(uint32_t index) const { - if (index >= elements.size()) { - return nullptr; - } - - return elements[index]; -} - -uint32_t GuiFrame::getSize() { - return elements.size(); -} - -void GuiFrame::resetState() { - GuiElement::resetState(); - - mutex.lock(); - for (auto & element : elements) { - element->resetState(); - } - mutex.unlock(); -} - -void GuiFrame::setState(uint32_t s, int32_t c) { - GuiElement::setState(s, c); - mutex.lock(); - for (uint32_t i = 0; i < elements.size(); ++i) { - elements[i]->setState(s, c); - } - mutex.unlock(); -} - -void GuiFrame::clearState(uint32_t s, int32_t c) { - GuiElement::clearState(s, c); - - mutex.lock(); - for (uint32_t i = 0; i < elements.size(); ++i) { - elements[i]->clearState(s, c); - } - mutex.unlock(); -} - -void GuiFrame::setVisible(bool v) { - visible = v; - - mutex.lock(); - for (auto & element : elements) { - element->setVisible(v); - } - mutex.unlock(); -} - -int32_t GuiFrame::getSelected() { - // find selected element - int32_t found = -1; - mutex.lock(); - for (uint32_t i = 0; i < elements.size(); ++i) { - if (elements[i]->isStateSet(STATE_SELECTED | STATE_OVER)) { - found = i; - break; - } - } - mutex.unlock(); - return found; -} - -void GuiFrame::draw(Renderer *v) { - if (!this->isVisible() && parentElement) { - return; - } - - if (parentElement && dim) { - //GXColor dimColor = (GXColor){0, 0, 0, 0x70}; - //Menu_DrawRectangle(0, 0, GetZPosition(), screenwidth,screenheight, &dimColor, false, true); - } - - mutex.lock(); - //! render appended items next frame but allow stop of render if size is reached - uint32_t size = elements.size(); - - for (uint32_t i = 0; i < size && i < elements.size(); ++i) { - elements[i]->draw(v); - } - mutex.unlock(); -} - -void GuiFrame::updateEffects() { - if (!this->isVisible() && parentElement) { - return; - } - - GuiElement::updateEffects(); - - mutex.lock(); - //! render appended items next frame but allow stop of render if size is reached - uint32_t size = elements.size(); - - for (uint32_t i = 0; i < size && i < elements.size(); ++i) { - elements[i]->updateEffects(); - } - mutex.unlock(); -} - -void GuiFrame::process() { - if (!this->isVisible() && parentElement) { - return; - } - - GuiElement::process(); - - mutex.lock(); - //! render appended items next frame but allow stop of render if size is reached - uint32_t size = elements.size(); - - for (uint32_t i = 0; i < size && i < elements.size(); ++i) { - elements[i]->process(); - } - mutex.unlock(); -} - -void GuiFrame::update(GuiController *c) { - if (isStateSet(STATE_DISABLED) && parentElement) { - return; - } - - mutex.lock(); - //! update appended items next frame - uint32_t size = elements.size(); - - for (uint32_t i = 0; i < size && i < elements.size(); ++i) { - elements[i]->update(c); - } - mutex.unlock(); -} diff --git a/src/gui/GuiFrame.h b/src/gui/GuiFrame.h deleted file mode 100644 index 0488239..0000000 --- a/src/gui/GuiFrame.h +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2015 Dimok - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ -#pragma once - -#include -#include -#include "GuiElement.h" -#include "sigslot.h" -#include "../system/video/Renderer.h" - -//!Allows GuiElements to be grouped together into a "window" -class GuiFrame : public GuiElement { -public: - //!Constructor - GuiFrame(GuiFrame *parent = 0); - - //!\overload - //!\param w Width of window - //!\param h Height of window - GuiFrame(float w, float h, GuiFrame *parent = 0); - - //!Destructor - ~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 - void append(GuiElement *e); - - //!Inserts a GuiElement into the GuiFrame at the specified index - //!\param e The GuiElement to insert. If it is already in the GuiFrame, it is removed first - //!\param i Index in which to insert the element - void insert(GuiElement *e, uint32_t i); - - //!Removes the specified GuiElement from the GuiFrame - //!\param e GuiElement to be removed - void remove(GuiElement *e); - - //!Removes all GuiElements - void removeAll(); - - //!Bring element to front of the window - void bringToFront(GuiElement *e) { - remove(e); - append(e); - } - - //!Returns the GuiElement at the specified index - //!\param index The index of the element - //!\return A pointer to the element at the index, NULL on error (eg: out of bounds) - GuiElement *getGuiElementAt(uint32_t index) const; - - //!Returns the size of the list of elements - //!\return The size of the current element list - uint32_t getSize(); - - //!Sets the visibility of the window - //!\param v visibility (true = visible) - void setVisible(bool v) override; - - //!Resets the window's state to STATE_DEFAULT - void resetState() override; - - //!Sets the window's state - //!\param s State - void setState(uint32_t s, int32_t c = -1) override; - - void clearState(uint32_t s, int32_t c = -1) override; - - //!Gets the index of the GuiElement inside the window that is currently selected - //!\return index of selected GuiElement - int32_t getSelected() override; - - //!Draws all the elements in this GuiFrame - 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 - //!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD - void update(GuiController *t) override; - - //!virtual updateEffects which is called by the main loop - void updateEffects() override; - - //!virtual process which is called by the main loop - void process() override; - - //! Signals - //! On Closing - sigslot::signal1 closing; -protected: - bool dim; //! Enable/disable dim of a window only - GuiFrame *parent; //!< Parent Window - std::vector elements; //!< Contains all elements within the GuiFrame - std::recursive_mutex mutex; -}; diff --git a/src/gui/GuiImage.cpp b/src/gui/GuiImage.cpp deleted file mode 100644 index 3026481..0000000 --- a/src/gui/GuiImage.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2015 Dimok - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ -#include -#include "GuiImage.h" -#include "../utils/logger.h" - -GuiImage::GuiImage(GuiTextureData *texture) { - setTexture(texture); -} - -GuiImage::GuiImage(SDL_Color color, float width, float height) { - this->color = color; - this->setSize(width, height); -} - -GuiImage::~GuiImage() { - if (this->texture && freeTextureData) { - delete this->texture; - } -} - -void GuiImage::draw(Renderer *renderer) { - if (!this->isVisible()) { - return; - } - - SDL_Rect rect; - rect.x = (int) getLeft(); - rect.y = (int) getTop(); - rect.w = (int) (getScaleX() * getWidth()); - rect.h = (int) (getScaleY() * getHeight()); - - if (texture) { - texture->draw(renderer, rect, getAngle()); - } else { - SDL_SetRenderDrawColor(renderer->getRenderer(), color.r, color.g, color.b, color.a); - SDL_RenderFillRect(renderer->getRenderer(), &rect); - if(getAngle() != 0.0f){ - DEBUG_FUNCTION_LINE("Drawing a rotated rect is not supported yet"); - } - } -} - -void GuiImage::setTexture(GuiTextureData *tex) { - if (tex) { - if(this->texture && freeTextureData){ - delete this->texture; - } - this->texture = tex; - this->setSize(tex->getWidth(), tex->getHeight()); - } -} diff --git a/src/gui/GuiImage.h b/src/gui/GuiImage.h deleted file mode 100644 index e5b80ed..0000000 --- a/src/gui/GuiImage.h +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2015 Dimok - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ -#pragma once - -#include -#include "GuiElement.h" -#include "GuiTextureData.h" - -//!Display, manage, and manipulate images in the GUI -class GuiImage : public GuiElement { -public: - - GuiImage() = default; - - //! Draws an image from an existing texture - //!\param texture Pointer to GuiTextureData element - explicit GuiImage(GuiTextureData *texture); - - //! Draws a colored rectangle - //!\param texture Pointer to GuiTextureData element - explicit GuiImage(SDL_Color color, float width, float height); - - //!Destructor - ~GuiImage() override; - - void draw(Renderer *r) override; - - void setTexture(GuiTextureData *tex); - -private: - GuiTextureData *texture = nullptr; - bool freeTextureData = false; - - // Color of the rect that's drawn if the picture has no texture. - SDL_Color color = {0, 0, 0, 0}; -}; diff --git a/src/gui/GuiSound.cpp b/src/gui/GuiSound.cpp deleted file mode 100644 index 1a633c7..0000000 --- a/src/gui/GuiSound.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2015 Dimok - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ -#include "GuiSound.h" - -GuiSound::GuiSound(void *buffer, uint32_t filesize, bool freeSrc) { - SDL_RWops *rw = SDL_RWFromMem(buffer, filesize); - music = Mix_LoadWAV_RW(rw, freeSrc); -} - -GuiSound::GuiSound(const char *filepath) { - Load(filepath); -} - -GuiSound::~GuiSound() { - if (music) { - Mix_FreeChunk(music); - music = nullptr; - } -} - -bool GuiSound::Load(const char *filepath) { - music = Mix_LoadWAV(filepath); - return music != nullptr; -} - -void GuiSound::Play() { - if (music) { - playedOn = Mix_PlayChannel(-1, music, loops); - } -} - -void GuiSound::Stop() const { - Pause(); -} - -void GuiSound::Pause() const { - if (playedOn != -1) { - Mix_HaltChannel(playedOn); - } -} - -void GuiSound::Resume() { - Play(); -} - -bool GuiSound::IsPlaying() const { - if (playedOn == -1) { - return false; - } - return Mix_Playing(playedOn); -} - -void GuiSound::SetVolume(uint32_t vol) const { - if (music) { Mix_VolumeChunk(music, vol); } -} - -void GuiSound::SetLoop(bool l) { - // < 0 == infinitive loop - loops = l ? -1 : 1; -} - -void GuiSound::Rewind() const { - // TODO: how to rewind? - Stop(); -} diff --git a/src/gui/GuiSound.h b/src/gui/GuiSound.h deleted file mode 100644 index cada45d..0000000 --- a/src/gui/GuiSound.h +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2015 Dimok - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ -#pragma once - -#include "GuiElement.h" -#include - -//!Sound conversion and playback. A wrapper for other sound libraries - ASND, libmad, ltremor, etc -class GuiSound : public GuiElement { -public: - explicit GuiSound(const char *filepath); - - //!Constructor - //!\param sound Pointer to the sound data - //!\param filesize Length of sound data - GuiSound(void *buffer, uint32_t filesize, bool freeSrc = false); - - //!Destructor - ~GuiSound() override; - - //!Load a file and replace the old one - bool Load(const char *filepath); - - //!Start sound playback - void Play(); - - //!Stop sound playback - void Stop() const; - - //!Pause sound playback - void Pause() const; - - //!Resume sound playback - void Resume(); - - //!Checks if the sound is currently playing - //!\return true if sound is playing, false otherwise - [[nodiscard]] bool IsPlaying() const; - - //!Rewind the music - void Rewind() const; - - //!Set sound volume - //!\param v Sound volume (0-100) - void SetVolume(uint32_t v) const; - - //!\param l Loop (true to loop) - void SetLoop(bool l); - - Mix_Chunk *music = nullptr; - int32_t loops = 0; - int32_t playedOn = -1; -}; \ No newline at end of file diff --git a/src/gui/GuiText.cpp b/src/gui/GuiText.cpp deleted file mode 100644 index 07960f8..0000000 --- a/src/gui/GuiText.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2015 Dimok - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ -#include -#include -#include "GuiText.h" - -/** - * Constructor for the GuiText class. - */ - -GuiText::GuiText(const std::string& text, SDL_Color c, FC_Font* gFont) { - this->text = text; - this->color = c; - this->fc_font = gFont; - this->doUpdateTexture = true; - this->texture.setParent(this); -} - -GuiText::~GuiText() { - delete textureData; -} - -void GuiText::draw(Renderer *renderer) { - if (!this->isVisible()) { - return; - } - - updateTexture(renderer); - - texture.draw(renderer); -} - -void GuiText::process() { - GuiElement::process(); -} - -void GuiText::setMaxWidth(float width) { - this->maxWidth = width; - - // Rebuild the texture cache on next draw - 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(doUpdateTexture) { - updateSize(); - int tex_width = tex_width = width == 0 ? 1 : (int) width; - int tex_height = tex_height = height == 0 ? 1 : (int)height; - - SDL_Texture *temp = SDL_CreateTexture(renderer->getRenderer(), renderer->getPixelFormat(), SDL_TEXTUREACCESS_TARGET, tex_width, tex_height); - if (temp) { - texture.setTexture(nullptr); - delete textureData; - textureData = new GuiTextureData(temp); - textureData->setBlendMode(SDL_BLENDMODE_BLEND); - texture.setTexture(textureData); - - // Set render target to texture - SDL_SetRenderTarget(renderer->getRenderer(), temp); - - // Clear texture. - SDL_SetRenderDrawColor(renderer->getRenderer(), 0, 0, 0, 0); - SDL_RenderClear(renderer->getRenderer()); - - // Draw text to texture - FC_DrawColumn(fc_font, renderer->getRenderer(), 0, 0, maxWidth, text.c_str()); - - // Restore render target - SDL_SetRenderTarget(renderer->getRenderer(), nullptr); - } else { - DEBUG_FUNCTION_LINE("Failed to create texture"); - } - doUpdateTexture = false; - } -} diff --git a/src/gui/GuiText.h b/src/gui/GuiText.h deleted file mode 100644 index 9fe139f..0000000 --- a/src/gui/GuiText.h +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2015 Dimok - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ -#pragma once - -#include "GuiElement.h" -#include "GuiTextureData.h" -#include "../system/video/SDL_FontCache.h" -#include "GuiImage.h" -#include -#include - -//!Display, manage, and manipulate text in the GUI -class GuiText : public GuiElement { -public: - - //!\param t Text - //!\param s Font size - //!\param c Font color - GuiText(const std::string &t, SDL_Color c, FC_Font *font); - ~GuiText() override; - - void draw(Renderer *pVideo) override; - - void process() override; - - void setMaxWidth(float width); - -protected: - GuiImage texture; - GuiTextureData* textureData = nullptr; - - std::string text; - SDL_Color color; - FC_Font *fc_font = nullptr; - bool doUpdateTexture = true; - - uint16_t maxWidth = 0xFFFF; - - void updateSize(); - - void updateTexture(Renderer *renderer); -}; diff --git a/src/gui/GuiTextureData.cpp b/src/gui/GuiTextureData.cpp deleted file mode 100644 index 52a4d94..0000000 --- a/src/gui/GuiTextureData.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include "GuiTextureData.h" -#include "../system/SDLSystem.h" -#include "../utils/logger.h" - -GuiTextureData::GuiTextureData(const std::string& path) { - SDL_Surface *surface = IMG_Load_RW(SDL_RWFromFile(path.c_str(), "rb"), 1); - loadSurface(surface); -} - -GuiTextureData::GuiTextureData(void *buffer, const uint32_t filesize, bool freesrc) { - SDL_RWops *rw = SDL_RWFromMem(buffer, filesize); - SDL_Surface *surface = IMG_Load_RW(rw, freesrc); - loadSurface(surface); -} - -GuiTextureData::GuiTextureData(SDL_Texture *texture) { - if (this->texture) { - SDL_DestroyTexture(this->texture); - this->texture = nullptr; - } - this->texture = texture; - int w, h; - SDL_QueryTexture(this->texture, nullptr, nullptr, &w, &h); - this->width = w; - this->height = h; -} - -void GuiTextureData::loadSurface(SDL_Surface *pSurface) { - if(!pSurface){ - return; - } - - cleanUp(); - - imgSurface = pSurface; - - this->width = imgSurface->w; - this->height = imgSurface->h; -} - -void GuiTextureData::cleanUp() { - if (imgSurface) { - SDL_FreeSurface(imgSurface); - imgSurface = nullptr; - } - if (texture) { - SDL_DestroyTexture(texture); - texture = nullptr; - } -} - -/** - * Destructor for the GuiImage class. - */ -GuiTextureData::~GuiTextureData() { - cleanUp(); -} - -void GuiTextureData::draw(Renderer *renderer, const SDL_Rect& dest, float angle) { - if (texture == nullptr && imgSurface) { - texture = SDL_CreateTextureFromSurface(renderer->getRenderer(), imgSurface); - } - if (!texture) { - DEBUG_FUNCTION_LINE("no texture!"); - return; - } - - // copy the texture to the rendering context - SDL_BlendMode mode; - SDL_GetRenderDrawBlendMode(renderer->getRenderer(), &mode); - - // adjust blend mode - if(blendMode != mode){ - SDL_SetRenderDrawBlendMode(renderer->getRenderer(), blendMode); - } - - if (angle == 0) { - SDL_RenderCopy(renderer->getRenderer(), texture, nullptr, &dest); - } else { - SDL_RenderCopyEx(renderer->getRenderer(), texture, nullptr, &dest, angle, nullptr, SDL_FLIP_NONE); - } - - if(blendMode != mode){ - SDL_SetRenderDrawBlendMode(renderer->getRenderer(), mode); - } -} - -int GuiTextureData::setBlendMode(SDL_BlendMode blendMode) { - this->blendMode = blendMode; - if(texture){ return SDL_SetTextureBlendMode(texture, blendMode); } - return SDL_BLENDMODE_INVALID; -} \ No newline at end of file diff --git a/src/gui/GuiTextureData.h b/src/gui/GuiTextureData.h deleted file mode 100644 index c081854..0000000 --- a/src/gui/GuiTextureData.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include -#include "GuiElement.h" - -class GuiTextureData { -public: - GuiTextureData(void *buffer, uint32_t filesize, bool freesrc = false); - - explicit GuiTextureData(SDL_Texture *texture); - - explicit GuiTextureData(const std::string &path); - - //!Destructor - ~GuiTextureData(); - - void draw(Renderer *pVideo, const SDL_Rect &rect, float angle); - - int setBlendMode(SDL_BlendMode blendMode); - - [[nodiscard]] int32_t getWidth() const { - return width; - } - - [[nodiscard]] int32_t getHeight() const { - return height; - } - - -protected: - void loadSurface(SDL_Surface *pSurface); - - SDL_Surface *imgSurface = nullptr; - - void cleanUp(); - - SDL_Texture *texture = nullptr; - int32_t width = 0; - int32_t height = 0; - SDL_BlendMode blendMode; -}; diff --git a/src/gui/GuiTrigger.cpp b/src/gui/GuiTrigger.cpp deleted file mode 100644 index 23f3ecd..0000000 --- a/src/gui/GuiTrigger.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2015 Dimok - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ -#include "GuiController.h" - -/** - * Constructor for the GuiTrigger class. - */ -GuiTrigger::GuiTrigger() - : chan(CHANNEL_ALL), btns(BUTTON_NONE), bClickEverywhere(false), bHoldEverywhere(false), bSelectionClickEverywhere(false), bLastTouched(false) { -} - -GuiTrigger::GuiTrigger(uint32_t ch, uint32_t btn, bool clickEverywhere, bool holdEverywhere, bool selectionClickEverywhere) - : chan(ch), btns(btn), bClickEverywhere(clickEverywhere), bHoldEverywhere(holdEverywhere), bSelectionClickEverywhere(selectionClickEverywhere), bLastTouched(false) { -} - -/** - * Destructor for the GuiTrigger class. - */ -GuiTrigger::~GuiTrigger() = default; - -/** - * Sets a simple trigger. Requires: - * - Element is selected - * - Trigger button is pressed - */ -void GuiTrigger::setTrigger(uint32_t ch, uint32_t btn) { - chan = ch; - btns = btn; -} - -bool GuiTrigger::left(const GuiController *controller) const { - if ((controller->chan & chan) == 0) { - return false; - } - if ((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_LEFT | STICK_L_LEFT)) { - return true; - } - return false; -} - -bool GuiTrigger::right(const GuiController *controller) const { - if ((controller->chan & chan) == 0) { - return false; - } - if ((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_RIGHT | STICK_L_RIGHT)) { - return true; - } - return false; -} - -bool GuiTrigger::up(const GuiController *controller) const { - if ((controller->chan & chan) == 0) { - return false; - } - if ((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_UP | STICK_L_UP)) { - return true; - } - return false; -} - -bool GuiTrigger::down(const GuiController *controller) const { - if ((controller->chan & chan) == 0) { - return false; - } - if ((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_DOWN | STICK_L_DOWN)) { - return true; - } - return false; -} - -int32_t GuiTrigger::clicked(const GuiController *controller) const { - if ((controller->chan & chan) == 0) { - return CLICKED_NONE; - } - - int32_t bResult = CLICKED_NONE; - - - if (controller->data.touched && controller->data.validPointer && (btns & TOUCHED) && !controller->lastData.touched) { - bResult = CLICKED_TOUCH; - } - - if (controller->data.buttons_d & btns) { - bResult = CLICKED_BUTTON; - } - return bResult; -} - -bool GuiTrigger::held(const GuiController *controller) const { - if ((controller->chan & chan) == 0) { - return false; - } - - bool bResult = false; - - if (controller->data.touched && (btns & TOUCHED) && controller->data.validPointer && controller->lastData.touched && controller->lastData.validPointer) { - bResult = true; - } - - if (controller->data.buttons_h & btns) { - bResult = true; - } - - return bResult; -} - -bool GuiTrigger::released(const GuiController *controller) const { - if ((controller->chan & chan) == 0) { - return false; - } - - if (clicked(controller) || held(controller)) { - return false; - } - - bool bResult = false; - - if (!controller->data.touched && (btns & TOUCHED) && controller->lastData.touched && controller->lastData.validPointer) { - bResult = true; - } - - if (controller->data.buttons_r & btns) { - bResult = true; - } - - return bResult; -} - diff --git a/src/gui/GuiTrigger.h b/src/gui/GuiTrigger.h deleted file mode 100644 index 6134d1d..0000000 --- a/src/gui/GuiTrigger.h +++ /dev/null @@ -1,132 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2015 Dimok - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ -#pragma once - -#include - -class GuiController; - -//!Menu input trigger management. Determine if action is necessary based on input data by comparing controller input data to a specific trigger element. -class GuiTrigger { -public: - enum eClicked { - CLICKED_NONE = 0x00, - CLICKED_TOUCH = 0x01, - CLICKED_BUTTON = 0x02, - }; - enum eChannels { - CHANNEL_1 = 0x01, - CHANNEL_2 = 0x02, - CHANNEL_3 = 0x04, - CHANNEL_4 = 0x08, - CHANNEL_5 = 0x10, - CHANNEL_ALL = 0xFF - }; - enum eButtons { - BUTTON_NONE = 0x0000, - TOUCHED = 0x80000000, - VPAD_TOUCH = TOUCHED, - BUTTON_Z = 0x20000, - BUTTON_C = 0x10000, - BUTTON_A = 0x8000, - BUTTON_B = 0x4000, - BUTTON_X = 0x2000, - BUTTON_Y = 0x1000, - BUTTON_1 = BUTTON_Y, - BUTTON_2 = BUTTON_X, - BUTTON_LEFT = 0x0800, - BUTTON_RIGHT = 0x0400, - BUTTON_UP = 0x0200, - BUTTON_DOWN = 0x0100, - BUTTON_ZL = 0x0080, - BUTTON_ZR = 0x0040, - BUTTON_L = 0x0020, - BUTTON_R = 0x0010, - BUTTON_PLUS = 0x0008, - BUTTON_MINUS = 0x0004, - BUTTON_HOME = 0x0002, - BUTTON_SYNC = 0x0001, - STICK_R_LEFT = 0x04000000, - STICK_R_RIGHT = 0x02000000, - STICK_R_UP = 0x01000000, - STICK_R_DOWN = 0x00800000, - STICK_L_LEFT = 0x40000000, - STICK_L_RIGHT = 0x20000000, - STICK_L_UP = 0x10000000, - STICK_L_DOWN = 0x08000000, - BUTTON_STICK_L = BUTTON_Z, - BUTTON_STICK_R = BUTTON_C, - }; - - //!Constructor - GuiTrigger(); - - //!Constructor - GuiTrigger(uint32_t ch, uint32_t btns, bool clickEverywhere = false, bool holdEverywhere = false, bool selectionClickEverywhere = false); - - //!Destructor - virtual ~GuiTrigger(); - - //!Sets a simple trigger. Requires: element is selected, and trigger button is pressed - void setTrigger(uint32_t ch, uint32_t btns); - - void setClickEverywhere(bool b) { - bClickEverywhere = b; - } - - void setHoldOnly(bool b) { - bHoldEverywhere = b; - } - - void setSelectionClickEverywhere(bool b) { - bSelectionClickEverywhere = b; - } - - [[nodiscard]] bool isClickEverywhere() const { - return bClickEverywhere; - } - - [[nodiscard]] bool isHoldEverywhere() const { - return bHoldEverywhere; - } - - [[nodiscard]] bool isSelectionClickEverywhere() const { - return bSelectionClickEverywhere; - } - - bool left(const GuiController *controller) const; - - bool right(const GuiController *controller) const; - - bool up(const GuiController *controller) const; - - bool down(const GuiController *controller) const; - - int32_t clicked(const GuiController *controller) const; - - bool held(const GuiController *controller) const; - - bool released(const GuiController *controller) const; - -private: - uint32_t chan; - uint32_t btns; - bool bClickEverywhere; - bool bHoldEverywhere; - bool bSelectionClickEverywhere; - bool bLastTouched; -}; diff --git a/src/gui/sigslot.h b/src/gui/sigslot.h deleted file mode 100644 index f578c47..0000000 --- a/src/gui/sigslot.h +++ /dev/null @@ -1,2433 +0,0 @@ -// sigslot.h: Signal/Slot classes -// -// Written by Sarah Thompson (sarah@telergy.com) 2002. -// -// License: Public domain. You are free to use this code however you like, with the proviso that -// the author takes on no responsibility or liability for any use. -// -// QUICK DOCUMENTATION -// -// (see also the full documentation at http://sigslot.sourceforge.net/) -// -// #define switches -// SIGSLOT_PURE_ISO - Define this to force ISO C++ compliance. This also disables -// all of the thread safety support on platforms where it is -// available. -// -// SIGSLOT_USE_POSIX_THREADS - Force use of Posix threads when using a C++ compiler other than -// gcc on a platform that supports Posix threads. (When using gcc, -// this is the default - use SIGSLOT_PURE_ISO to disable this if -// necessary) -// -// SIGSLOT_DEFAULT_MT_POLICY - Where thread support is enabled, this defaults to multi_threaded_global. -// Otherwise, the default is single_threaded. #define this yourself to -// override the default. In pure ISO mode, anything other than -// single_threaded will cause a compiler error. -// -// PLATFORM NOTES -// -// Win32 - On Win32, the WIN32 symbol must be #defined. Most mainstream -// compilers do this by default, but you may need to define it -// yourself if your build environment is less standard. This causes -// the Win32 thread support to be compiled in and used automatically. -// -// Unix/Linux/BSD, etc. - If you're using gcc, it is assumed that you have Posix threads -// available, so they are used automatically. You can override this -// (as under Windows) with the SIGSLOT_PURE_ISO switch. If you're using -// something other than gcc but still want to use Posix threads, you -// need to #define SIGSLOT_USE_POSIX_THREADS. -// -// ISO C++ - If none of the supported platforms are detected, or if -// SIGSLOT_PURE_ISO is defined, all multithreading support is turned off, -// along with any code that might cause a pure ISO C++ environment to -// complain. Before you ask, gcc -ansi -pedantic won't compile this -// library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of -// errors that aren't really there. If you feel like investigating this, -// please contact the author. -// -// -// THREADING MODES -// -// single_threaded - Your program is assumed to be single threaded from the point of view -// of signal/slot usage (i.e. all objects using signals and slots are -// created and destroyed from a single thread). Behaviour if objects are -// destroyed concurrently is undefined (i.e. you'll get the occasional -// segmentation fault/memory exception). -// -// multi_threaded_global - Your program is assumed to be multi threaded. Objects using signals and -// slots can be safely created and destroyed from any thread, even when -// connections exist. In multi_threaded_global mode, this is achieved by a -// single global mutex (actually a critical section on Windows because they -// are faster). This option uses less OS resources, but results in more -// opportunities for contention, possibly resulting in more context switches -// than are strictly necessary. -// -// multi_threaded_local - Behaviour in this mode is essentially the same as multi_threaded_global, -// except that each signal, and each object that inherits has_slots, all -// have their own mutex/critical section. In practice, this means that -// mutex collisions (and hence context switches) only happen if they are -// absolutely essential. However, on some platforms, creating a lot of -// mutexes can slow down the whole OS, so use this option with care. -// -// USING THE LIBRARY -// -// See the full documentation at http://sigslot.sourceforge.net/ -// -// -#ifndef SIGSLOT_H__ -#define SIGSLOT_H__ - -#include -#include - -#define _SIGSLOT_SINGLE_THREADED - -#ifndef SIGSLOT_DEFAULT_MT_POLICY -# ifdef _SIGSLOT_SINGLE_THREADED -# define SIGSLOT_DEFAULT_MT_POLICY single_threaded -# else -# define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local -# endif -#endif - - -namespace sigslot { - - class single_threaded { - public: - single_threaded() { - ; - } - - virtual ~single_threaded() { - ; - } - - virtual void lock() { - ; - } - - virtual void unlock() { - ; - } - }; - -#ifdef _SIGSLOT_HAS_WIN32_THREADS - // The multi threading policies only get compiled in if they are enabled. - class multi_threaded_global { - public: - multi_threaded_global() { - static bool isinitialised = false; - - if(!isinitialised) { - InitializeCriticalSection(get_critsec()); - isinitialised = true; - } - } - - multi_threaded_global(const multi_threaded_global&) { - ; - } - - virtual ~multi_threaded_global() { - ; - } - - virtual void lock() { - EnterCriticalSection(get_critsec()); - } - - virtual void unlock() { - LeaveCriticalSection(get_critsec()); - } - - private: - CRITICAL_SECTION* get_critsec() { - static CRITICAL_SECTION g_critsec; - return &g_critsec; - } - }; - - class multi_threaded_local { - public: - multi_threaded_local() { - InitializeCriticalSection(&m_critsec); - } - - multi_threaded_local(const multi_threaded_local&) { - InitializeCriticalSection(&m_critsec); - } - - virtual ~multi_threaded_local() { - DeleteCriticalSection(&m_critsec); - } - - virtual void lock() { - EnterCriticalSection(&m_critsec); - } - - virtual void unlock() { - LeaveCriticalSection(&m_critsec); - } - - private: - CRITICAL_SECTION m_critsec; - }; -#endif // _SIGSLOT_HAS_WIN32_THREADS - -#ifdef _SIGSLOT_HAS_POSIX_THREADS - // The multi threading policies only get compiled in if they are enabled. - class multi_threaded_global { - public: - multi_threaded_global() { - pthread_mutex_init(get_mutex(), NULL); - } - - multi_threaded_global(const multi_threaded_global&) { - ; - } - - virtual ~multi_threaded_global() { - ; - } - - virtual void lock() { - pthread_mutex_lock(get_mutex()); - } - - virtual void unlock() { - pthread_mutex_unlock(get_mutex()); - } - - private: - pthread_mutex_t* get_mutex() { - static pthread_mutex_t g_mutex; - return &g_mutex; - } - }; - - class multi_threaded_local { - public: - multi_threaded_local() { - pthread_mutex_init(&m_mutex, NULL); - } - - multi_threaded_local(const multi_threaded_local&) { - pthread_mutex_init(&m_mutex, NULL); - } - - virtual ~multi_threaded_local() { - pthread_mutex_destroy(&m_mutex); - } - - virtual void lock() { - pthread_mutex_lock(&m_mutex); - } - - virtual void unlock() { - pthread_mutex_unlock(&m_mutex); - } - - private: - pthread_mutex_t m_mutex; - }; -#endif // _SIGSLOT_HAS_POSIX_THREADS - -#ifdef _SIGSLOT_HAS_LWP_THREADS - - class multi_threaded_global { - public: - multi_threaded_global() { - ; - } - - multi_threaded_global(const multi_threaded_global&) { - ; - } - - virtual ~multi_threaded_global() { - ; - } - - virtual void lock() { - ; - } - - virtual void unlock() { - ; - } - }; - - class multi_threaded_local { - public: - multi_threaded_local() { - ; - } - - multi_threaded_local(const multi_threaded_local&) { - ; - } - - virtual ~multi_threaded_local() { - } - - virtual void lock() { - ; - } - - virtual void unlock() { - ; - } - }; - -#endif // _SIGSLOT_HAS_LWP_THREADS - - template - class lock_block { - public: - mt_policy *m_mutex; - - lock_block(mt_policy *mtx) - : m_mutex(mtx) { - m_mutex->lock(); - } - - ~lock_block() { - m_mutex->unlock(); - } - }; - - template - class has_slots; - - template - class _connection_base0 { - public: - virtual ~_connection_base0() { - ; - } - - virtual has_slots *getdest() const = 0; - - virtual void emit() = 0; - - virtual _connection_base0 *clone() = 0; - - virtual _connection_base0 *duplicate(has_slots *pnewdest) = 0; - }; - - template - class _connection_base1 { - public: - virtual ~_connection_base1() { - ; - } - - virtual has_slots *getdest() const = 0; - - virtual void emit(arg1_type) = 0; - - virtual _connection_base1 *clone() = 0; - - virtual _connection_base1 *duplicate(has_slots *pnewdest) = 0; - }; - - template - class _connection_base2 { - public: - virtual ~_connection_base2() { - ; - } - - virtual has_slots *getdest() const = 0; - - virtual void emit(arg1_type, arg2_type) = 0; - - virtual _connection_base2 *clone() = 0; - - virtual _connection_base2 *duplicate(has_slots *pnewdest) = 0; - }; - - template - class _connection_base3 { - public: - virtual ~_connection_base3() { - ; - } - - virtual has_slots *getdest() const = 0; - - virtual void emit(arg1_type, arg2_type, arg3_type) = 0; - - virtual _connection_base3 *clone() = 0; - - virtual _connection_base3 *duplicate(has_slots *pnewdest) = 0; - }; - - template - class _connection_base4 { - public: - virtual ~_connection_base4() { - ; - } - - virtual has_slots *getdest() const = 0; - - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type) = 0; - - virtual _connection_base4 *clone() = 0; - - virtual _connection_base4 *duplicate(has_slots *pnewdest) = 0; - }; - - template - class _connection_base5 { - public: - virtual ~_connection_base5() { - ; - } - - virtual has_slots *getdest() const = 0; - - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type) = 0; - - virtual _connection_base5 *clone() = 0; - - virtual _connection_base5 *duplicate(has_slots *pnewdest) = 0; - }; - - template - class _connection_base6 { - public: - virtual ~_connection_base6() { - ; - } - - virtual has_slots *getdest() const = 0; - - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, - arg6_type) = 0; - - virtual _connection_base6 *clone() = 0; - - virtual _connection_base6 *duplicate(has_slots *pnewdest) = 0; - }; - - template - class _connection_base7 { - public: - virtual ~_connection_base7() { - ; - } - - virtual has_slots *getdest() const = 0; - - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, - arg6_type, arg7_type) = 0; - - virtual _connection_base7 *clone() = 0; - - virtual _connection_base7 *duplicate(has_slots *pnewdest) = 0; - }; - - template - class _connection_base8 { - public: - virtual ~_connection_base8() { - ; - } - - virtual has_slots *getdest() const = 0; - - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, - arg6_type, arg7_type, arg8_type) = 0; - - virtual _connection_base8 *clone() = 0; - - virtual _connection_base8 *duplicate(has_slots *pnewdest) = 0; - }; - - template - class _signal_base : public mt_policy { - public: - virtual void slot_disconnect(has_slots *pslot) = 0; - - virtual void slot_duplicate(const has_slots *poldslot, has_slots *pnewslot) = 0; - }; - - template - class has_slots : public mt_policy { - private: - typedef typename std::set<_signal_base *> sender_set; - typedef typename sender_set::const_iterator const_iterator; - - public: - has_slots() { - ; - } - - has_slots(const has_slots &hs) - : mt_policy(hs) { - lock_block lock(this); - const_iterator it = hs.m_senders.begin(); - const_iterator itEnd = hs.m_senders.end(); - - while (it != itEnd) { - (*it)->slot_duplicate(&hs, this); - m_senders.insert(*it); - ++it; - } - } - - void signal_connect(_signal_base *sender) { - lock_block lock(this); - m_senders.insert(sender); - } - - void signal_disconnect(_signal_base *sender) { - lock_block lock(this); - m_senders.erase(sender); - } - - virtual ~has_slots() { - disconnect_all(); - } - - void disconnect_all() { - lock_block lock(this); - const_iterator it = m_senders.begin(); - const_iterator itEnd = m_senders.end(); - - while (it != itEnd) { - (*it)->slot_disconnect(this); - ++it; - } - - m_senders.erase(m_senders.begin(), m_senders.end()); - } - - private: - sender_set m_senders; - }; - - template - class _signal_base0 : public _signal_base { - public: - typedef typename std::list<_connection_base0 *> connections_list; - typedef typename connections_list::const_iterator const_iterator; - typedef typename connections_list::iterator iterator; - - _signal_base0() { - ; - } - - _signal_base0(const _signal_base0 &s) - : _signal_base(s) { - lock_block lock(this); - const_iterator it = s.m_connected_slots.begin(); - const_iterator itEnd = s.m_connected_slots.end(); - - while (it != itEnd) { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - ~_signal_base0() { - disconnect_all(); - } - - void disconnect_all() { - lock_block lock(this); - const_iterator it = m_connected_slots.begin(); - const_iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots *pclass) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - if ((*it)->getdest() == pclass) { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - bool connected() { - return m_connected_slots.size() != 0; - } - - void slot_disconnect(has_slots *pslot) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - iterator itNext = it; - ++itNext; - - if ((*it)->getdest() == pslot) { - delete *it; - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - void slot_duplicate(const has_slots *oldtarget, has_slots *newtarget) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - if ((*it)->getdest() == oldtarget) { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base1 : public _signal_base { - public: - typedef typename std::list<_connection_base1 *> connections_list; - typedef typename connections_list::const_iterator const_iterator; - typedef typename connections_list::iterator iterator; - - _signal_base1() { - ; - } - - _signal_base1(const _signal_base1 &s) - : _signal_base(s) { - lock_block lock(this); - const_iterator it = s.m_connected_slots.begin(); - const_iterator itEnd = s.m_connected_slots.end(); - - while (it != itEnd) { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots *oldtarget, has_slots *newtarget) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - if ((*it)->getdest() == oldtarget) { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base1() { - disconnect_all(); - } - - void disconnect_all() { - lock_block lock(this); - const_iterator it = m_connected_slots.begin(); - const_iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots *pclass) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - if ((*it)->getdest() == pclass) { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - bool connected() { - return m_connected_slots.size() != 0; - } - - void slot_disconnect(has_slots *pslot) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - iterator itNext = it; - ++itNext; - - if ((*it)->getdest() == pslot) { - delete *it; - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base2 : public _signal_base { - public: - typedef typename std::list<_connection_base2 *> - connections_list; - typedef typename connections_list::const_iterator const_iterator; - typedef typename connections_list::iterator iterator; - - _signal_base2() { - ; - } - - _signal_base2(const _signal_base2 &s) - : _signal_base(s) { - lock_block lock(this); - const_iterator it = s.m_connected_slots.begin(); - const_iterator itEnd = s.m_connected_slots.end(); - - while (it != itEnd) { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots *oldtarget, has_slots *newtarget) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - if ((*it)->getdest() == oldtarget) { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base2() { - disconnect_all(); - } - - void disconnect_all() { - lock_block lock(this); - const_iterator it = m_connected_slots.begin(); - const_iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots *pclass) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - if ((*it)->getdest() == pclass) { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - bool connected() { - return m_connected_slots.size() != 0; - } - - void slot_disconnect(has_slots *pslot) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - iterator itNext = it; - ++itNext; - - if ((*it)->getdest() == pslot) { - delete *it; - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base3 : public _signal_base { - public: - typedef std::list<_connection_base3 *> - connections_list; - - typedef typename connections_list::const_iterator const_iterator; - typedef typename connections_list::iterator iterator; - - _signal_base3() { - ; - } - - _signal_base3(const _signal_base3 &s) - : _signal_base(s) { - lock_block lock(this); - const_iterator it = s.m_connected_slots.begin(); - const_iterator itEnd = s.m_connected_slots.end(); - - while (it != itEnd) { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots *oldtarget, has_slots *newtarget) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - if ((*it)->getdest() == oldtarget) { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base3() { - disconnect_all(); - } - - void disconnect_all() { - lock_block lock(this); - const_iterator it = m_connected_slots.begin(); - const_iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots *pclass) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - if ((*it)->getdest() == pclass) { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - bool connected() { - return m_connected_slots.size() != 0; - } - - void slot_disconnect(has_slots *pslot) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - iterator itNext = it; - ++itNext; - - if ((*it)->getdest() == pslot) { - delete *it; - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base4 : public _signal_base { - public: - typedef std::list<_connection_base4 *> connections_list; - typedef typename connections_list::const_iterator const_iterator; - typedef typename connections_list::iterator iterator; - - _signal_base4() { - ; - } - - _signal_base4(const _signal_base4 &s) - : _signal_base(s) { - lock_block lock(this); - const_iterator it = s.m_connected_slots.begin(); - const_iterator itEnd = s.m_connected_slots.end(); - - while (it != itEnd) { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots *oldtarget, has_slots *newtarget) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - if ((*it)->getdest() == oldtarget) { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base4() { - disconnect_all(); - } - - void disconnect_all() { - lock_block lock(this); - const_iterator it = m_connected_slots.begin(); - const_iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots *pclass) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - if ((*it)->getdest() == pclass) { - delete *it; - this->m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - bool connected() { - return m_connected_slots.size() != 0; - } - - void slot_disconnect(has_slots *pslot) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - iterator itNext = it; - ++itNext; - - if ((*it)->getdest() == pslot) { - delete *it; - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base5 : public _signal_base { - public: - typedef std::list<_connection_base5 *> connections_list; - typedef typename connections_list::const_iterator const_iterator; - typedef typename connections_list::iterator iterator; - - _signal_base5() { - ; - } - - _signal_base5(const _signal_base5 &s) - : _signal_base(s) { - lock_block lock(this); - const_iterator it = s.m_connected_slots.begin(); - const_iterator itEnd = s.m_connected_slots.end(); - - while (it != itEnd) { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots *oldtarget, has_slots *newtarget) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - if ((*it)->getdest() == oldtarget) { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base5() { - disconnect_all(); - } - - void disconnect_all() { - lock_block lock(this); - const_iterator it = m_connected_slots.begin(); - const_iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots *pclass) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - if ((*it)->getdest() == pclass) { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - bool connected() { - return m_connected_slots.size() != 0; - } - - void slot_disconnect(has_slots *pslot) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - iterator itNext = it; - ++itNext; - - if ((*it)->getdest() == pslot) { - delete *it; - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base6 : public _signal_base { - public: - typedef std::list<_connection_base6 *> connections_list; - typedef typename connections_list::const_iterator const_iterator; - typedef typename connections_list::iterator iterator; - - _signal_base6() { - ; - } - - _signal_base6(const _signal_base6 &s) - : _signal_base(s) { - lock_block lock(this); - const_iterator it = s.m_connected_slots.begin(); - const_iterator itEnd = s.m_connected_slots.end(); - - while (it != itEnd) { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots *oldtarget, has_slots *newtarget) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - if ((*it)->getdest() == oldtarget) { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base6() { - disconnect_all(); - } - - void disconnect_all() { - lock_block lock(this); - const_iterator it = m_connected_slots.begin(); - const_iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots *pclass) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - if ((*it)->getdest() == pclass) { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - bool connected() { - return m_connected_slots.size() != 0; - } - - void slot_disconnect(has_slots *pslot) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - iterator itNext = it; - ++itNext; - - if ((*it)->getdest() == pslot) { - delete *it; - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base7 : public _signal_base { - public: - typedef std::list<_connection_base7 *> connections_list; - typedef typename connections_list::const_iterator const_iterator; - typedef typename connections_list::iterator iterator; - - _signal_base7() { - ; - } - - _signal_base7(const _signal_base7 &s) - : _signal_base(s) { - lock_block lock(this); - const_iterator it = s.m_connected_slots.begin(); - const_iterator itEnd = s.m_connected_slots.end(); - - while (it != itEnd) { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots *oldtarget, has_slots *newtarget) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - if ((*it)->getdest() == oldtarget) { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base7() { - disconnect_all(); - } - - void disconnect_all() { - lock_block lock(this); - const_iterator it = m_connected_slots.begin(); - const_iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots *pclass) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - if ((*it)->getdest() == pclass) { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - bool connected() { - return m_connected_slots.size() != 0; - } - - void slot_disconnect(has_slots *pslot) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - iterator itNext = it; - ++itNext; - - if ((*it)->getdest() == pslot) { - delete *it; - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base8 : public _signal_base { - public: - typedef std::list<_connection_base8 *> - connections_list; - typedef typename connections_list::const_iterator const_iterator; - typedef typename connections_list::iterator iterator; - - _signal_base8() { - ; - } - - _signal_base8(const _signal_base8 &s) - : _signal_base(s) { - lock_block lock(this); - const_iterator it = s.m_connected_slots.begin(); - const_iterator itEnd = s.m_connected_slots.end(); - - while (it != itEnd) { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots *oldtarget, has_slots *newtarget) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - if ((*it)->getdest() == oldtarget) { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base8() { - disconnect_all(); - } - - void disconnect_all() { - lock_block lock(this); - const_iterator it = m_connected_slots.begin(); - const_iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots *pclass) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - if ((*it)->getdest() == pclass) { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - bool connected() { - return m_connected_slots.size() != 0; - } - - void slot_disconnect(has_slots *pslot) { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while (it != itEnd) { - iterator itNext = it; - ++itNext; - - if ((*it)->getdest() == pslot) { - delete *it; - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - - template - class _connection0 : public _connection_base0 { - public: - _connection0() { - this->pobject = NULL; - this->pmemfun = NULL; - } - - _connection0(dest_type *pobject, void (dest_type::*pmemfun)()) { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection0() { - ; - } - - virtual _connection_base0 *clone() { - return new _connection0(*this); - } - - virtual _connection_base0 *duplicate(has_slots *pnewdest) { - return new _connection0((dest_type *) pnewdest, m_pmemfun); - } - - virtual void emit() { - (m_pobject->*m_pmemfun)(); - } - - virtual has_slots *getdest() const { - return m_pobject; - } - - private: - dest_type *m_pobject; - - void (dest_type::* m_pmemfun)(); - }; - - template - class _connection1 : public _connection_base1 { - public: - _connection1() { - this->pobject = NULL; - this->pmemfun = NULL; - } - - _connection1(dest_type *pobject, void (dest_type::*pmemfun)(arg1_type)) { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection1() { - ; - } - - virtual _connection_base1 *clone() { - return new _connection1(*this); - } - - virtual _connection_base1 *duplicate(has_slots *pnewdest) { - return new _connection1((dest_type *) pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1) { - (m_pobject->*m_pmemfun)(a1); - } - - virtual has_slots *getdest() const { - return m_pobject; - } - - private: - dest_type *m_pobject; - - void (dest_type::* m_pmemfun)(arg1_type); - }; - - template - class _connection2 : public _connection_base2 { - public: - _connection2() { - this->pobject = NULL; - this->pmemfun = NULL; - } - - _connection2(dest_type *pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type)) { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection2() { - ; - } - - - virtual _connection_base2 *clone() { - return new _connection2(*this); - } - - virtual _connection_base2 *duplicate(has_slots *pnewdest) { - return new _connection2((dest_type *) pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2) { - (m_pobject->*m_pmemfun)(a1, a2); - } - - virtual has_slots *getdest() const { - return m_pobject; - } - - private: - dest_type *m_pobject; - - void (dest_type::* m_pmemfun)(arg1_type, arg2_type); - }; - - template - class _connection3 : public _connection_base3 { - public: - _connection3() { - this->pobject = NULL; - this->pmemfun = NULL; - } - - _connection3(dest_type *pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type)) { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection3() { - ; - } - - - virtual _connection_base3 *clone() { - return new _connection3(*this); - } - - virtual _connection_base3 *duplicate(has_slots *pnewdest) { - return new _connection3((dest_type *) pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3) { - (m_pobject->*m_pmemfun)(a1, a2, a3); - } - - virtual has_slots *getdest() const { - return m_pobject; - } - - private: - dest_type *m_pobject; - - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type); - }; - - template - class _connection4 : public _connection_base4 { - public: - _connection4() { - this->pobject = NULL; - this->pmemfun = NULL; - } - - _connection4(dest_type *pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type)) { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection4() { - ; - } - - virtual _connection_base4 *clone() { - return new _connection4(*this); - } - - virtual _connection_base4 *duplicate(has_slots *pnewdest) { - return new _connection4((dest_type *) pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, - arg4_type a4) { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4); - } - - virtual has_slots *getdest() const { - return m_pobject; - } - - private: - dest_type *m_pobject; - - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, - arg4_type); - }; - - template - class _connection5 : public _connection_base5 { - public: - _connection5() { - this->pobject = NULL; - this->pmemfun = NULL; - } - - _connection5(dest_type *pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type)) { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection5() { - ; - } - - virtual _connection_base5 *clone() { - return new _connection5(*this); - } - - virtual _connection_base5 *duplicate(has_slots *pnewdest) { - return new _connection5((dest_type *) pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5) { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5); - } - - virtual has_slots *getdest() const { - return m_pobject; - } - - private: - dest_type *m_pobject; - - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type); - }; - - template - class _connection6 : public _connection_base6 { - public: - _connection6() { - this->pobject = NULL; - this->pmemfun = NULL; - } - - _connection6(dest_type *pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type)) { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection6() { - ; - } - - virtual _connection_base6 *clone() { - return new _connection6(*this); - } - - virtual _connection_base6 *duplicate(has_slots *pnewdest) { - return new _connection6((dest_type *) pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6) { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6); - } - - virtual has_slots *getdest() const { - return m_pobject; - } - - private: - dest_type *m_pobject; - - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type, arg6_type); - }; - - template - class _connection7 : public _connection_base7 { - public: - _connection7() { - this->pobject = NULL; - this->pmemfun = NULL; - } - - _connection7(dest_type *pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type)) { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection7() { - ; - } - - virtual _connection_base7 *clone() { - return new _connection7(*this); - } - - virtual _connection_base7 *duplicate(has_slots *pnewdest) { - return new _connection7((dest_type *) pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7) { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7); - } - - virtual has_slots *getdest() const { - return m_pobject; - } - - private: - dest_type *m_pobject; - - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type, arg6_type, arg7_type); - }; - - template - class _connection8 : public _connection_base8 { - public: - _connection8() { - this->pobject = NULL; - this->pmemfun = NULL; - } - - _connection8(dest_type *pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, - arg7_type, arg8_type)) { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection8() { - ; - } - - virtual _connection_base8 *clone() { - return new _connection8(*this); - } - - virtual _connection_base8 *duplicate(has_slots *pnewdest) { - return new _connection8((dest_type *) pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7, a8); - } - - virtual has_slots *getdest() const { - return m_pobject; - } - - private: - dest_type *m_pobject; - - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type, arg6_type, arg7_type, arg8_type); - }; - - template - class signal0 : public _signal_base0 { - public: - typedef typename _signal_base0::connections_list::const_iterator const_iterator; - - signal0() { - ; - } - - signal0(const signal0 &s) - : _signal_base0(s) { - ; - } - - virtual ~signal0() { - ; - } - - template - void connect(desttype *pclass, void (desttype::*pmemfun)()) { - lock_block lock(this); - _connection0 *conn = - new _connection0(pclass, pmemfun); - this->m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit() { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while (it != itEnd) { - itNext = it; - ++itNext; - - (*it)->emit(); - - it = itNext; - } - } - - void operator()() { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while (it != itEnd) { - itNext = it; - ++itNext; - - (*it)->emit(); - - it = itNext; - } - } - }; - - template - class signal1 : public _signal_base1 { - public: - typedef typename _signal_base1::connections_list::const_iterator const_iterator; - - signal1() { - ; - } - - signal1(const signal1 &s) - : _signal_base1(s) { - ; - } - - virtual ~signal1() { - ; - } - - template - void connect(desttype *pclass, void (desttype::*pmemfun)(arg1_type)) { - lock_block lock(this); - _connection1 *conn = - new _connection1(pclass, pmemfun); - this->m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1) { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while (it != itEnd) { - itNext = it; - ++itNext; - - (*it)->emit(a1); - - it = itNext; - } - } - - void operator()(arg1_type a1) { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while (it != itEnd) { - itNext = it; - ++itNext; - - (*it)->emit(a1); - - it = itNext; - } - } - }; - - template - class signal2 : public _signal_base2 { - public: - typedef typename _signal_base2::connections_list::const_iterator const_iterator; - - signal2() { - ; - } - - signal2(const signal2 &s) - : _signal_base2(s) { - ; - } - - virtual ~signal2() { - ; - } - - template - void connect(desttype *pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type)) { - lock_block lock(this); - _connection2 *conn = new - _connection2(pclass, pmemfun); - this->m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2) { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while (it != itEnd) { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2) { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while (it != itEnd) { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2); - - it = itNext; - } - } - }; - - template - class signal3 : public _signal_base3 { - public: - typedef typename _signal_base3::connections_list::const_iterator const_iterator; - - signal3() { - ; - } - - signal3(const signal3 &s) - : _signal_base3(s) { - ; - } - - virtual ~signal3() { - ; - } - - template - void connect(desttype *pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type)) { - lock_block lock(this); - _connection3 *conn = - new _connection3(pclass, - pmemfun); - this->m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3) { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while (it != itEnd) { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3) { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while (it != itEnd) { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3); - - it = itNext; - } - } - }; - - template - class signal4 : public _signal_base4 { - public: - typedef typename _signal_base4::connections_list::const_iterator const_iterator; - - signal4() { - ; - } - - signal4(const signal4 &s) - : _signal_base4(s) { - ; - } - - virtual ~signal4() { - ; - } - - template - void connect(desttype *pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type)) { - lock_block lock(this); - _connection4 * - conn = new _connection4(pclass, pmemfun); - this->m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while (it != itEnd) { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while (it != itEnd) { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4); - - it = itNext; - } - } - }; - - template - class signal5 : public _signal_base5 { - public: - typedef typename _signal_base5::connections_list::const_iterator const_iterator; - - signal5() { - ; - } - - signal5(const signal5 &s) - : _signal_base5(s) { - ; - } - - virtual ~signal5() { - ; - } - - template - void connect(desttype *pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type)) { - lock_block lock(this); - _connection5 *conn = new _connection5(pclass, pmemfun); - this->m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5) { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while (it != itEnd) { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5) { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while (it != itEnd) { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5); - - it = itNext; - } - } - }; - - - template - class signal6 : public _signal_base6 { - public: - typedef typename _signal_base6::connections_list::const_iterator const_iterator; - - signal6() { - ; - } - - signal6(const signal6 &s) - : _signal_base6(s) { - ; - } - - virtual ~signal6() { - ; - } - - template - void connect(desttype *pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type)) { - lock_block lock(this); - _connection6 *conn = - new _connection6(pclass, pmemfun); - this->m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6) { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while (it != itEnd) { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6) { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while (it != itEnd) { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6); - - it = itNext; - } - } - }; - - template - class signal7 : public _signal_base7 { - public: - typedef typename _signal_base7::connections_list::const_iterator const_iterator; - - signal7() { - ; - } - - signal7(const signal7 &s) - : _signal_base7(s) { - ; - } - - virtual ~signal7() { - ; - } - - template - void connect(desttype *pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, - arg7_type)) { - lock_block lock(this); - _connection7 *conn = - new _connection7(pclass, pmemfun); - this->m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7) { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while (it != itEnd) { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6, a7); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7) { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while (it != itEnd) { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6, a7); - - it = itNext; - } - } - }; - - template - class signal8 : public _signal_base8 { - public: - typedef typename _signal_base8::connections_list::const_iterator const_iterator; - - signal8() { - ; - } - - signal8(const signal8 &s) - : _signal_base8(s) { - ; - } - - virtual ~signal8() { - ; - } - - template - void connect(desttype *pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, - arg7_type, arg8_type)) { - lock_block lock(this); - _connection8 *conn = - new _connection8(pclass, pmemfun); - this->m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while (it != itEnd) { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while (it != itEnd) { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8); - - it = itNext; - } - } - }; - -}; // namespace sigslot - -#endif // SIGSLOT_H__ diff --git a/src/input/ControllerManager.cpp b/src/input/ControllerManager.cpp deleted file mode 100644 index a6f21af..0000000 --- a/src/input/ControllerManager.cpp +++ /dev/null @@ -1,104 +0,0 @@ -#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 - || std::string(SDL_JoystickName(joystick)).find("X-Box") != 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.count(static_cast(channel)) > 0) { - 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 deleted file mode 100644 index 53b5b2e..0000000 --- a/src/input/ControllerManager.h +++ /dev/null @@ -1,37 +0,0 @@ -#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/input/SDLController.h b/src/input/SDLController.h deleted file mode 100644 index 81283e0..0000000 --- a/src/input/SDLController.h +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once - -#include -#include -#include -#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) - -class SDLController : public GuiController { -public: - explicit SDLController(int32_t channel) : GuiController(channel) { - - } - - virtual bool update(SDL_Event *e, int32_t screenWidth, int32_t screenHeight) = 0; - - - virtual void before() { - lastData = data; - - data.buttons_d = 0; - data.buttons_r = 0; - } - - virtual void after() { - data.buttons_d |= (data.buttons_h & (~(lastData.buttons_h))); - data.buttons_r |= ((lastData.buttons_h) & (~data.buttons_h)); - if (data.buttons_h != 0 || data.buttons_d != 0 || data.buttons_r != 0) { - // DEBUG_FUNCTION_LINE("Controller #%d: h %08X d %08X r %08X", chanIdx, data.buttons_h, data.buttons_d, data.buttons_r); - - printButton(chanIdx, GuiTrigger::BUTTON_A); - printButton(chanIdx, GuiTrigger::BUTTON_B); - printButton(chanIdx, GuiTrigger::BUTTON_X); - printButton(chanIdx, GuiTrigger::BUTTON_Y); - printButton(chanIdx, GuiTrigger::BUTTON_STICK_L); - printButton(chanIdx, GuiTrigger::BUTTON_STICK_R); - printButton(chanIdx, GuiTrigger::BUTTON_L); - printButton(chanIdx, GuiTrigger::BUTTON_R); - printButton(chanIdx, GuiTrigger::BUTTON_ZL); - printButton(chanIdx, GuiTrigger::BUTTON_ZR); - printButton(chanIdx, GuiTrigger::BUTTON_PLUS); - printButton(chanIdx, GuiTrigger::BUTTON_MINUS); - printButton(chanIdx, GuiTrigger::BUTTON_LEFT); - printButton(chanIdx, GuiTrigger::BUTTON_UP); - printButton(chanIdx, GuiTrigger::BUTTON_RIGHT); - printButton(chanIdx, GuiTrigger::BUTTON_DOWN); - printButton(chanIdx, GuiTrigger::STICK_L_LEFT); - printButton(chanIdx, GuiTrigger::STICK_L_UP); - printButton(chanIdx, GuiTrigger::STICK_L_RIGHT); - printButton(chanIdx, GuiTrigger::STICK_L_DOWN); - printButton(chanIdx, GuiTrigger::STICK_R_LEFT); - printButton(chanIdx, GuiTrigger::STICK_R_UP); - printButton(chanIdx, GuiTrigger::STICK_R_RIGHT); - printButton(chanIdx, GuiTrigger::STICK_R_DOWN); - printButton(chanIdx, GuiTrigger::TOUCHED); - } - } -}; diff --git a/src/input/SDLControllerJoystick.h b/src/input/SDLControllerJoystick.h deleted file mode 100644 index 419171b..0000000 --- a/src/input/SDLControllerJoystick.h +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once - -class SDLControllerJoystick : public SDLController { -public: - SDLControllerJoystick(int32_t channel, SDL_JoystickID joystickId) : SDLController(channel) { - - } - - bool update(SDL_Event *e, int32_t screenWidth, int32_t screenHeight) override { - if (e->type == SDL_JOYBUTTONDOWN) { - data.buttons_h |= (1 << e->jbutton.button); - } else if (e->type == SDL_JOYBUTTONUP) { - data.buttons_h &= ~(1 << 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 value. - 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) { - // - } - return true; - } -}; - diff --git a/src/input/SDLControllerMouse.h b/src/input/SDLControllerMouse.h deleted file mode 100644 index 80cea96..0000000 --- a/src/input/SDLControllerMouse.h +++ /dev/null @@ -1,30 +0,0 @@ - -#pragma once - -class SDLControllerMouse: public SDLController { -public: - explicit SDLControllerMouse(int32_t channel) : SDLController(channel) { - - } - - void before() override{ - SDLController::before(); - data.validPointer = true; - } - - 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; - } else if (e->type == SDL_MOUSEBUTTONDOWN && e->button.button == SDL_BUTTON_LEFT) { - data.touched = true; - } else if (e->type == SDL_MOUSEBUTTONUP && e->button.button == SDL_BUTTON_LEFT) { - data.touched = false; - }else{ - DEBUG_FUNCTION_LINE("Unknown event"); - return false; - } - return true; - } -}; - diff --git a/src/input/SDLControllerWiiUGamepad.h b/src/input/SDLControllerWiiUGamepad.h deleted file mode 100644 index 352bf44..0000000 --- a/src/input/SDLControllerWiiUGamepad.h +++ /dev/null @@ -1,53 +0,0 @@ -#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 || e->type == SDL_FINGERUP || e->type == SDL_FINGERDOWN) { - data.y = e->tfinger.y * screenHeight; - data.x = e->tfinger.x * screenWidth; - if (e->type == SDL_FINGERUP) { - data.touched = false; - } else if (e->type == SDL_FINGERDOWN) { - data.touched = true; - } - } 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; - } - - void after() override { - data.validPointer = data.touched; - SDLController::after(); - } -}; - diff --git a/src/input/SDLControllerWiiUProContoller.h b/src/input/SDLControllerWiiUProContoller.h deleted file mode 100644 index 1fa5451..0000000 --- a/src/input/SDLControllerWiiUProContoller.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "SDLControllerWiiUGamepad.h" - -class SDLControllerWiiUProContoller : public SDLControllerWiiUGamepad { -public: - explicit SDLControllerWiiUProContoller(int32_t channel) : SDLControllerWiiUGamepad(channel){ - - } -}; - diff --git a/src/input/SDLControllerXboxOne.h b/src/input/SDLControllerXboxOne.h deleted file mode 100644 index 222732a..0000000 --- a/src/input/SDLControllerXboxOne.h +++ /dev/null @@ -1,106 +0,0 @@ -#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 f5f87bd..d239ae4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,12 +1,12 @@ #include -#include "system/SDLSystem.h" -#include "gui/GuiFrame.h" -#include "gui/GuiButton.h" -#include "gui/GuiController.h" +#include +#include +#include +#include #include "menu/MainWindow.h" -#include "input/SDLController.h" -#include "input/SDLControllerMouse.h" -#include "input/ControllerManager.h" +#include +#include +#include #include #include diff --git a/src/menu/MainWindow.h b/src/menu/MainWindow.h index fbfdeab..c645be7 100644 --- a/src/menu/MainWindow.h +++ b/src/menu/MainWindow.h @@ -1,10 +1,10 @@ #pragma once #include -#include "../gui/GuiFrame.h" -#include "../gui/GuiButton.h" +#include +#include #include "../utils/logger.h" -#include "../gui/GuiImage.h" +#include class MainWindow : public GuiFrame, public sigslot::has_slots<> { public: diff --git a/src/resources/Resources.cpp b/src/resources/Resources.cpp index b682bbd..48a34ed 100644 --- a/src/resources/Resources.cpp +++ b/src/resources/Resources.cpp @@ -1,10 +1,9 @@ #include -#include #include #include "Resources.h" #include "../fs/FSUtils.h" -#include "../gui/GuiSound.h" -#include "../gui/GuiTextureData.h" +#include +#include #include diff --git a/src/system/SDLSystem.cpp b/src/system/SDLSystem.cpp deleted file mode 100644 index c669e79..0000000 --- a/src/system/SDLSystem.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2015 Dimok - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ -#include "SDLSystem.h" -#include "../utils/logger.h" -#include -#include -#include - -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) { - 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()); - return; - } - - int flags = 0; - int result = 0; - if (flags != (result = Mix_Init(flags))) { - DEBUG_FUNCTION_LINE("Could not initialize mixer (result: %d).\n", result); - DEBUG_FUNCTION_LINE("Mix_Init: %s\n", Mix_GetError()); - } - - auto dev = Mix_OpenAudio(22050, AUDIO_S16SYS, 2, 640); - SDL_PauseAudioDevice(dev, 0); - - TTF_Init(); -} - -SDLSystem::~SDLSystem() { - SDL_DestroyWindow(window); - delete renderer; - SDL_Quit(); -} - -float SDLSystem::getHeight() { - int h = 0; - SDL_GetWindowSize(window, nullptr, &h); - return h; -} - -float SDLSystem::getWidth() { - int w = 0; - SDL_GetWindowSize(window, &w, nullptr); - return w; -} - -Renderer *SDLSystem::getRenderer() { - return renderer; -} diff --git a/src/system/SDLSystem.h b/src/system/SDLSystem.h deleted file mode 100644 index 795920c..0000000 --- a/src/system/SDLSystem.h +++ /dev/null @@ -1,35 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2015 Dimok - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ -#pragma once -#include -#include "video/Renderer.h" - -class SDLSystem { -public: - SDLSystem(); - - virtual ~SDLSystem(); - - Renderer *getRenderer(); - - float getHeight(); - float getWidth(); - -private: - SDL_Window *window = NULL; - Renderer *renderer = NULL; -}; \ No newline at end of file diff --git a/src/system/video/Renderer.h b/src/system/video/Renderer.h deleted file mode 100644 index 8b1d745..0000000 --- a/src/system/video/Renderer.h +++ /dev/null @@ -1,28 +0,0 @@ -#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/system/video/SDL_FontCache.cpp b/src/system/video/SDL_FontCache.cpp deleted file mode 100644 index 65efc39..0000000 --- a/src/system/video/SDL_FontCache.cpp +++ /dev/null @@ -1,3033 +0,0 @@ -/* -SDL_FontCache: A font cache for SDL and SDL_ttf -by Jonathan Dearborn - -See SDL_FontCache.h for license info. -*/ - -#include "SDL_FontCache.h" - -#include -#include -#include -#include - -// Visual C does not support static inline -#ifndef static_inline - #ifdef _MSC_VER - #define static_inline static - #else - #define static_inline static inline - #endif -#endif - -#if SDL_VERSION_ATLEAST(2,0,0) - #define FC_GET_ALPHA(sdl_color) ((sdl_color).a) -#else - #define FC_GET_ALPHA(sdl_color) ((sdl_color).unused) -#endif - -// Need SDL_RenderIsClipEnabled() for proper clipping support -#if SDL_VERSION_ATLEAST(2,0,4) - #define ENABLE_SDL_CLIPPING -#endif - -#define FC_MIN(a,b) ((a) < (b)? (a) : (b)) -#define FC_MAX(a,b) ((a) > (b)? (a) : (b)) - - -// vsnprintf replacement from Valentin Milea: -// http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 -#if defined(_MSC_VER) && _MSC_VER < 1900 - -#define snprintf c99_snprintf -#define vsnprintf c99_vsnprintf - -__inline int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) -{ - int count = -1; - - if (size != 0) - count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); - if (count == -1) - count = _vscprintf(format, ap); - - return count; -} - -__inline int c99_snprintf(char *outBuf, size_t size, const char *format, ...) -{ - int count; - va_list ap; - - va_start(ap, format); - count = c99_vsnprintf(outBuf, size, format, ap); - va_end(ap); - - return count; -} - -#endif - - -#define FC_EXTRACT_VARARGS(buffer, start_args) \ -{ \ - va_list lst; \ - va_start(lst, start_args); \ - vsnprintf(buffer, fc_buffer_size, start_args, lst); \ - va_end(lst); \ -} - -// Extra pixels of padding around each glyph to avoid linear filtering artifacts -#define FC_CACHE_PADDING 1 - - -static Uint8 has_clip(FC_Target* dest) -{ - #ifdef FC_USE_SDL_GPU - return dest->use_clip_rect; - #elif defined(ENABLE_SDL_CLIPPING) - return SDL_RenderIsClipEnabled(dest); - #else - return 0; - #endif -} - -static FC_Rect get_clip(FC_Target* dest) -{ - #ifdef FC_USE_SDL_GPU - return dest->clip_rect; - #elif defined(ENABLE_SDL_CLIPPING) - SDL_Rect r; - SDL_RenderGetClipRect(dest, &r); - return r; - #else - SDL_Rect r = {0, 0, 0, 0}; - return r; - #endif -} - -static void set_clip(FC_Target* dest, FC_Rect* rect) -{ - #ifdef FC_USE_SDL_GPU - if(rect != NULL) - GPU_SetClipRect(dest, *rect); - else - GPU_UnsetClip(dest); - #elif defined(ENABLE_SDL_CLIPPING) - SDL_RenderSetClipRect(dest, rect); - #endif -} - -static void set_color(FC_Image* src, Uint8 r, Uint8 g, Uint8 b, Uint8 a) -{ - #ifdef FC_USE_SDL_GPU - GPU_SetRGBA(src, r, g, b, a); - #else - SDL_SetTextureColorMod(src, r, g, b); - SDL_SetTextureAlphaMod(src, a); - #endif -} - - - -static char* new_concat(const char* a, const char* b) -{ - // Create new buffer - unsigned int size = strlen(a) + strlen(b); - char* new_string = (char*)malloc(size+1); - - // Concatenate strings in the new buffer - strcpy(new_string, a); - strcat(new_string, b); - - return new_string; -} - -static char* replace_concat(char** a, const char* b) -{ - char* new_string = new_concat(*a, b); - free(*a); - *a = new_string; - return *a; -} - - -// Width of a tab in units of the space width (sorry, no tab alignment!) -static unsigned int fc_tab_width = 4; - -// Shared buffer for variadic text -static char* fc_buffer = NULL; -static unsigned int fc_buffer_size = 1024; - -static Uint8 fc_has_render_target_support = 0; - -// The number of fonts that has been created but not freed -static int NUM_EXISTING_FONTS = 0; - -// Globals for GetString functions -static char* ASCII_STRING = NULL; -static char* LATIN_1_STRING = NULL; -static char* ASCII_LATIN_1_STRING = NULL; - -char* FC_GetStringASCII(void) -{ - if(ASCII_STRING == NULL) - { - int i; - char c; - ASCII_STRING = (char*)malloc(512); - memset(ASCII_STRING, 0, 512); - i = 0; - c = 32; - while(1) - { - ASCII_STRING[i] = c; - if(c == 126) - break; - ++i; - ++c; - } - } - return U8_strdup(ASCII_STRING); -} - -char* FC_GetStringLatin1(void) -{ - if(LATIN_1_STRING == NULL) - { - int i; - unsigned char c; - LATIN_1_STRING = (char*)malloc(512); - memset(LATIN_1_STRING, 0, 512); - i = 0; - c = 0xA0; - while(1) - { - LATIN_1_STRING[i] = 0xC2; - LATIN_1_STRING[i+1] = c; - if(c == 0xBF) - break; - i += 2; - ++c; - } - i += 2; - c = 0x80; - while(1) - { - LATIN_1_STRING[i] = 0xC3; - LATIN_1_STRING[i+1] = c; - if(c == 0xBF) - break; - i += 2; - ++c; - } - } - return U8_strdup(LATIN_1_STRING); -} - -char* FC_GetStringASCII_Latin1(void) -{ - if(ASCII_LATIN_1_STRING == NULL) - ASCII_LATIN_1_STRING = new_concat(FC_GetStringASCII(), FC_GetStringLatin1()); - - return U8_strdup(ASCII_LATIN_1_STRING); -} - -FC_Rect FC_MakeRect(float x, float y, float w, float h) -{ - FC_Rect r = {(int) x, (int) y, (int) w, (int) h}; - return r; -} - -FC_Scale FC_MakeScale(float x, float y) -{ - FC_Scale s = {x, y}; - - return s; -} - -SDL_Color FC_MakeColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a) -{ - SDL_Color c = {r, g, b, a}; - - return c; -} - -FC_Effect FC_MakeEffect(FC_AlignEnum alignment, FC_Scale scale, SDL_Color color) -{ - FC_Effect e; - - e.alignment = alignment; - e.scale = scale; - e.color = color; - - return e; -} - -FC_GlyphData FC_MakeGlyphData(int cache_level, Sint16 x, Sint16 y, Uint16 w, Uint16 h) -{ - FC_GlyphData gd; - - gd.rect.x = x; - gd.rect.y = y; - gd.rect.w = w; - gd.rect.h = h; - gd.cache_level = cache_level; - - return gd; -} - -// Enough to hold all of the ascii characters and some. -#define FC_DEFAULT_NUM_BUCKETS 300 - -typedef struct FC_MapNode -{ - Uint32 key; - FC_GlyphData value; - struct FC_MapNode* next; - -} FC_MapNode; - -typedef struct FC_Map -{ - int num_buckets; - FC_MapNode** buckets; -} FC_Map; - - - -static FC_Map* FC_MapCreate(int num_buckets) -{ - int i; - FC_Map* map = (FC_Map*)malloc(sizeof(FC_Map)); - - map->num_buckets = num_buckets; - map->buckets = (FC_MapNode**)malloc(num_buckets * sizeof(FC_MapNode*)); - - for(i = 0; i < num_buckets; ++i) - { - map->buckets[i] = NULL; - } - - return map; -} - -/*static void FC_MapClear(FC_Map* map) -{ - int i; - if(map == NULL) - return; - - // Go through each bucket - for(i = 0; i < map->num_buckets; ++i) - { - // Delete the nodes in order - FC_MapNode* node = map->buckets[i]; - while(node != NULL) - { - FC_MapNode* last = node; - node = node->next; - free(last); - } - // Set the bucket to empty - map->buckets[i] = NULL; - } -}*/ - -static void FC_MapFree(FC_Map* map) -{ - int i; - if(map == NULL) - return; - - // Go through each bucket - for(i = 0; i < map->num_buckets; ++i) - { - // Delete the nodes in order - FC_MapNode* node = map->buckets[i]; - while(node != NULL) - { - FC_MapNode* last = node; - node = node->next; - free(last); - } - } - - free(map->buckets); - free(map); -} - -// Note: Does not handle duplicates in any special way. -static FC_GlyphData* FC_MapInsert(FC_Map* map, Uint32 codepoint, FC_GlyphData glyph) -{ - Uint32 index; - FC_MapNode* node; - if(map == NULL) - return NULL; - - // Get index for bucket - index = codepoint % map->num_buckets; - - // If this bucket is empty, create a node and return its value - if(map->buckets[index] == NULL) - { - node = map->buckets[index] = (FC_MapNode*)malloc(sizeof(FC_MapNode)); - node->key = codepoint; - node->value = glyph; - node->next = NULL; - return &node->value; - } - - for(node = map->buckets[index]; node != NULL; node = node->next) - { - // Find empty node and add a new one on. - if(node->next == NULL) - { - node->next = (FC_MapNode*)malloc(sizeof(FC_MapNode)); - node = node->next; - - node->key = codepoint; - node->value = glyph; - node->next = NULL; - return &node->value; - } - } - - return NULL; -} - -static FC_GlyphData* FC_MapFind(FC_Map* map, Uint32 codepoint) -{ - Uint32 index; - FC_MapNode* node; - if(map == NULL) - return NULL; - - // Get index for bucket - index = codepoint % map->num_buckets; - - // Go through list until we find a match - for(node = map->buckets[index]; node != NULL; node = node->next) - { - if(node->key == codepoint) - return &node->value; - } - - return NULL; -} - - - -struct FC_Font -{ - #ifndef FC_USE_SDL_GPU - SDL_Renderer* renderer; - #endif - - TTF_Font* ttf_source; // TTF_Font source of characters - Uint8 owns_ttf_source; // Can we delete the TTF_Font ourselves? - - FC_FilterEnum filter; - - SDL_Color default_color; - Uint16 height; - - Uint16 maxWidth; - Uint16 baseline; - int ascent; - int descent; - - int lineSpacing; - int letterSpacing; - - // Uses 32-bit (4-byte) Unicode codepoints to refer to each glyph - // Codepoints are little endian (reversed from UTF-8) so that something like 0x00000005 is ASCII 5 and the map can be indexed by ASCII values - FC_Map* glyphs; - - FC_GlyphData last_glyph; // Texture packing cursor - int glyph_cache_size; - int glyph_cache_count; - FC_Image** glyph_cache; - - char* loading_string; - - std::recursive_mutex* mutex = nullptr; -}; - -// Private -static FC_GlyphData* FC_PackGlyphData(FC_Font* font, Uint32 codepoint, Uint16 width, Uint16 maxWidth, Uint16 maxHeight); - - -static FC_Rect FC_RenderLeft(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); -static FC_Rect FC_RenderRight(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* text); - - -static_inline SDL_Surface* FC_CreateSurface32(Uint32 width, Uint32 height) -{ - #if SDL_BYTEORDER == SDL_BIG_ENDIAN - return SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); - #else - return SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); - #endif -} - - -char* U8_alloc(unsigned int size) -{ - char* result; - if(size == 0) - return NULL; - - result = (char*)malloc(size); - result[0] = '\0'; - - return result; -} - -void U8_free(char* string) -{ - free(string); -} - -char* U8_strdup(const char* string) -{ - char* result; - if(string == NULL) - return NULL; - - result = (char*)malloc(strlen(string)+1); - strcpy(result, string); - - return result; -} - -int U8_strlen(const char* string) -{ - int length = 0; - if(string == NULL) - return 0; - - while(*string != '\0') - { - string = U8_next(string); - ++length; - } - - return length; -} - -int U8_charsize(const char* character) -{ - if(character == NULL) - return 0; - - if((unsigned char)*character <= 0x7F) - return 1; - else if((unsigned char)*character < 0xE0) - return 2; - else if((unsigned char)*character < 0xF0) - return 3; - else - return 4; - return 1; -} - -int U8_charcpy(char* buffer, const char* source, int buffer_size) -{ - int charsize; - if(buffer == NULL || source == NULL || buffer_size < 1) - return 0; - - charsize = U8_charsize(source); - if(charsize > buffer_size) - return 0; - - memcpy(buffer, source, charsize); - return charsize; -} - -const char* U8_next(const char* string) -{ - return string + U8_charsize(string); -} - -int U8_strinsert(char* string, int position, const char* source, int max_bytes) -{ - int pos_u8char; - int len; - int add_len; - int ulen; - const char* string_start = string; - - if(string == NULL || source == NULL) - return 0; - - len = strlen(string); - add_len = strlen(source); - ulen = U8_strlen(string); - - if(position == -1) - position = ulen; - - if(position < 0 || position > ulen || len + add_len + 1 > max_bytes) - return 0; - - // Move string pointer to the proper position - pos_u8char = 0; - while(*string != '\0' && pos_u8char < position) - { - string = (char*)U8_next(string); - ++pos_u8char; - } - - // Move the rest of the string out of the way - memmove(string + add_len, string, len - (string - string_start) + 1); - - // Copy in the new characters - memcpy(string, source, add_len); - - return 1; -} - -void U8_strdel(char* string, int position) -{ - if(string == NULL || position < 0) - return; - - while(*string != '\0') - { - if(position == 0) - { - int chars_to_erase = U8_charsize(string); - int remaining_bytes = strlen(string) + 1; - memmove(string, string + chars_to_erase, remaining_bytes); - break; - } - - string = (char*)U8_next(string); - --position; - } -} - - - - - -static_inline FC_Rect FC_RectUnion(FC_Rect A, FC_Rect B) -{ - float x,x2,y,y2; - x = FC_MIN(A.x, B.x); - y = FC_MIN(A.y, B.y); - 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 = {(int) x, (int) y, (int) FC_MAX(0, x2 - x), (int) FC_MAX(0, y2 - y)}; - return result; - } -} - -// Adapted from SDL_IntersectRect -static_inline FC_Rect FC_RectIntersect(FC_Rect A, FC_Rect B) -{ - FC_Rect result; - float Amin, Amax, Bmin, Bmax; - - // Horizontal intersection - Amin = A.x; - Amax = Amin + A.w; - Bmin = B.x; - Bmax = Bmin + B.w; - if(Bmin > Amin) - Amin = Bmin; - result.x = Amin; - if(Bmax < Amax) - Amax = Bmax; - result.w = Amax - Amin > 0 ? Amax - Amin : 0; - - // Vertical intersection - Amin = A.y; - Amax = Amin + A.h; - Bmin = B.y; - Bmax = Bmin + B.h; - if(Bmin > Amin) - Amin = Bmin; - result.y = Amin; - if(Bmax < Amax) - Amax = Bmax; - result.h = Amax - Amin > 0 ? Amax - Amin : 0; - - return result; -} - - - - - - - - - - - - - - -FC_Rect FC_DefaultRenderCallback(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale) -{ - float w = srcrect->w * xscale; - float h = srcrect->h * yscale; - FC_Rect result; - - // FIXME: Why does the scaled offset look so wrong? - #ifdef FC_USE_SDL_GPU - { - GPU_Rect r = *srcrect; - GPU_BlitScale(src, &r, dest, x + xscale*r.w/2.0f, y + r.h/2.0f, xscale, yscale); - } - #else - { - SDL_RendererFlip flip = SDL_FLIP_NONE; - if(xscale < 0) - { - xscale = -xscale; - flip = (SDL_RendererFlip) ((int)flip | (int)SDL_FLIP_HORIZONTAL); - } - if(yscale < 0) - { - yscale = -yscale; - flip = (SDL_RendererFlip) ((int)flip | (int)SDL_FLIP_VERTICAL); - } - - SDL_Rect r = *srcrect; - SDL_Rect dr = {(int)x, (int)y, (int)(xscale*r.w), (int)(yscale*r.h)}; - SDL_RenderCopyEx(dest, src, &r, &dr, 0, NULL, flip); - } - #endif - - result.x = x; - result.y = y; - result.w = w; - result.h = h; - return result; -} - -static FC_Rect (*fc_render_callback)(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale) = &FC_DefaultRenderCallback; - -void FC_SetRenderCallback(FC_Rect (*callback)(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale)) -{ - if(callback == NULL) - fc_render_callback = &FC_DefaultRenderCallback; - else - fc_render_callback = callback; -} - -void FC_GetUTF8FromCodepoint(char* result, Uint32 codepoint) -{ - char a, b, c, d; - - if(result == NULL) - return; - - a = (codepoint >> 24) & 0xFF; - b = (codepoint >> 16) & 0xFF; - c = (codepoint >> 8) & 0xFF; - d = codepoint & 0xFF; - - if(a == 0) - { - if(b == 0) - { - if(c == 0) - { - result[0] = d; - result[1] = '\0'; - } - else - { - result[0] = c; - result[1] = d; - result[2] = '\0'; - } - } - else - { - result[0] = b; - result[1] = c; - result[2] = d; - result[3] = '\0'; - } - } - else - { - result[0] = a; - result[1] = b; - result[2] = c; - result[3] = d; - result[4] = '\0'; - } -} - -Uint32 FC_GetCodepointFromUTF8(const char** c, Uint8 advance_pointer) -{ - Uint32 result = 0; - const char* str; - if(c == NULL || *c == NULL) - return 0; - - str = *c; - if((unsigned char)*str <= 0x7F) - result = *str; - else if((unsigned char)*str < 0xE0) - { - result |= (unsigned char)(*str) << 8; - result |= (unsigned char)(*(str+1)); - if(advance_pointer) - *c += 1; - } - else if((unsigned char)*str < 0xF0) - { - result |= (unsigned char)(*str) << 16; - result |= (unsigned char)(*(str+1)) << 8; - result |= (unsigned char)(*(str+2)); - if(advance_pointer) - *c += 2; - } - else - { - result |= (unsigned char)(*str) << 24; - result |= (unsigned char)(*(str+1)) << 16; - result |= (unsigned char)(*(str+2)) << 8; - result |= (unsigned char)(*(str+3)); - if(advance_pointer) - *c += 3; - } - return result; -} - - -void FC_SetLoadingString(FC_Font* font, const char* string) -{ - if(font == NULL) - return; - - free(font->loading_string); - font->loading_string = U8_strdup(string); -} - - -unsigned int FC_GetBufferSize(void) -{ - return fc_buffer_size; -} - -void FC_SetBufferSize(unsigned int size) -{ - free(fc_buffer); - if(size > 0) - { - fc_buffer_size = size; - fc_buffer = (char*)malloc(fc_buffer_size); - } - else - fc_buffer = (char*)malloc(fc_buffer_size); -} - - -unsigned int FC_GetTabWidth(void) -{ - return fc_tab_width; -} - -void FC_SetTabWidth(unsigned int width_in_spaces) -{ - fc_tab_width = width_in_spaces; -} - -// Constructors -static void FC_Init(FC_Font* font) -{ - if(font == NULL) - return; - - #ifndef FC_USE_SDL_GPU - font->renderer = NULL; - #endif - - font->ttf_source = NULL; - font->owns_ttf_source = 0; - - font->filter = FC_FILTER_NEAREST; - - font->default_color.r = 0; - font->default_color.g = 0; - font->default_color.b = 0; - FC_GET_ALPHA(font->default_color) = 255; - - font->height = 0; // ascent+descent - - font->maxWidth = 0; - font->baseline = 0; - font->ascent = 0; - font->descent = 0; - - font->lineSpacing = 0; - font->letterSpacing = 0; - - // Give a little offset for when filtering/mipmaps are used. Depending on mipmap level, this will still not be enough. - font->last_glyph.rect.x = FC_CACHE_PADDING; - font->last_glyph.rect.y = FC_CACHE_PADDING; - font->last_glyph.rect.w = 0; - font->last_glyph.rect.h = 0; - font->last_glyph.cache_level = 0; - - if(font->glyphs != NULL) - FC_MapFree(font->glyphs); - - font->glyphs = FC_MapCreate(FC_DEFAULT_NUM_BUCKETS); - - font->glyph_cache_size = 3; - font->glyph_cache_count = 0; - - font->mutex = new std::recursive_mutex(); - - font->glyph_cache = (FC_Image**)malloc(font->glyph_cache_size * sizeof(FC_Image*)); - - if (font->loading_string == NULL) - font->loading_string = FC_GetStringASCII(); - - if(fc_buffer == NULL) - fc_buffer = (char*)malloc(fc_buffer_size); -} - -static Uint8 FC_GrowGlyphCache(FC_Font* font) -{ - if(font == NULL) - return 0; - #ifdef FC_USE_SDL_GPU - GPU_Image* new_level = GPU_CreateImage(font->height * 12, font->height * 12, GPU_FORMAT_RGBA); - GPU_SetAnchor(new_level, 0.5f, 0.5f); // Just in case the default is different - #else - SDL_Texture* new_level = SDL_CreateTexture(font->renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, font->height * 12, font->height * 12); - #endif - if(new_level == NULL || !FC_SetGlyphCacheLevel(font, font->glyph_cache_count, new_level)) - { - FC_Log("Error: SDL_FontCache ran out of packing space and could not add another cache level.\n"); - #ifdef FC_USE_SDL_GPU - GPU_FreeImage(new_level); - #else - SDL_DestroyTexture(new_level); - #endif - return 0; - } - // bug: we do not have the correct color here, this might be the wrong color! - // , most functions use set_color_for_all_caches() - // - for evading this bug, you must use FC_SetDefaultColor(), before using any draw functions - set_color(new_level, font->default_color.r, font->default_color.g, font->default_color.b, FC_GET_ALPHA(font->default_color)); -#ifndef FC_USE_SDL_GPU - { - Uint8 r, g, b, a; - SDL_Texture* prev_target = SDL_GetRenderTarget(font->renderer); - SDL_Rect prev_clip, prev_viewport; - int prev_logicalw, prev_logicalh; - Uint8 prev_clip_enabled; - float prev_scalex, prev_scaley; - // only backup if previous target existed (SDL will preserve them for the default target) - if (prev_target) { - prev_clip_enabled = has_clip(font->renderer); - if (prev_clip_enabled) - prev_clip = get_clip(font->renderer); - SDL_RenderGetViewport(font->renderer, &prev_viewport); - SDL_RenderGetScale(font->renderer, &prev_scalex, &prev_scaley); - SDL_RenderGetLogicalSize(font->renderer, &prev_logicalw, &prev_logicalh); - } - SDL_SetTextureBlendMode(new_level, SDL_BLENDMODE_BLEND); - SDL_SetRenderTarget(font->renderer, new_level); - SDL_GetRenderDrawColor(font->renderer, &r, &g, &b, &a); - SDL_SetRenderDrawColor(font->renderer, 0, 0, 0, 0); - SDL_RenderClear(font->renderer); - SDL_SetRenderDrawColor(font->renderer, r, g, b, a); - SDL_SetRenderTarget(font->renderer, prev_target); - if (prev_target) { - if (prev_clip_enabled) - set_clip(font->renderer, &prev_clip); - if (prev_logicalw && prev_logicalh) - SDL_RenderSetLogicalSize(font->renderer, prev_logicalw, prev_logicalh); - else { - SDL_RenderSetViewport(font->renderer, &prev_viewport); - SDL_RenderSetScale(font->renderer, prev_scalex, prev_scaley); - } - } - } -#endif - return 1; -} - -Uint8 FC_UploadGlyphCache(FC_Font* font, int cache_level, SDL_Surface* data_surface) -{ - if(font == NULL || data_surface == NULL) - return 0; - #ifdef FC_USE_SDL_GPU - GPU_Image* new_level = GPU_CopyImageFromSurface(data_surface); - GPU_SetAnchor(new_level, 0.5f, 0.5f); // Just in case the default is different - if(FC_GetFilterMode(font) == FC_FILTER_LINEAR) - GPU_SetImageFilter(new_level, GPU_FILTER_LINEAR); - else - GPU_SetImageFilter(new_level, GPU_FILTER_NEAREST); - #else - SDL_Texture* new_level; - if(!fc_has_render_target_support) - new_level = SDL_CreateTextureFromSurface(font->renderer, data_surface); - else - { - // Must upload with render target enabled so we can put more glyphs on later - SDL_Renderer* renderer = font->renderer; - - // Set filter mode for new texture - char old_filter_mode[16]; // Save it so we can change the hint value in the meantime - const char* old_filter_hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY); - if(!old_filter_hint) - old_filter_hint = "nearest"; - snprintf(old_filter_mode, 16, "%s", old_filter_hint); - - if(FC_GetFilterMode(font) == FC_FILTER_LINEAR) - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"); - else - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); - - new_level = SDL_CreateTexture(renderer, data_surface->format->format, SDL_TEXTUREACCESS_TARGET, data_surface->w, data_surface->h); - SDL_SetTextureBlendMode(new_level, SDL_BLENDMODE_BLEND); - - // Reset filter mode for the temp texture - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); - - { - Uint8 r, g, b, a; - SDL_Texture* temp = SDL_CreateTextureFromSurface(renderer, data_surface); - SDL_Texture* prev_target = SDL_GetRenderTarget(renderer); - SDL_Rect prev_clip, prev_viewport; - int prev_logicalw, prev_logicalh; - Uint8 prev_clip_enabled; - float prev_scalex, prev_scaley; - // only backup if previous target existed (SDL will preserve them for the default target) - if (prev_target) { - prev_clip_enabled = has_clip(renderer); - if (prev_clip_enabled) - prev_clip = get_clip(renderer); - SDL_RenderGetViewport(renderer, &prev_viewport); - SDL_RenderGetScale(renderer, &prev_scalex, &prev_scaley); - SDL_RenderGetLogicalSize(renderer, &prev_logicalw, &prev_logicalh); - } - SDL_SetTextureBlendMode(temp, SDL_BLENDMODE_NONE); - SDL_SetRenderTarget(renderer, new_level); - - SDL_GetRenderDrawColor(renderer, &r, &g, &b, &a); - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); - SDL_RenderClear(renderer); - SDL_SetRenderDrawColor(renderer, r, g, b, a); - - SDL_RenderCopy(renderer, temp, NULL, NULL); - SDL_SetRenderTarget(renderer, prev_target); - if (prev_target) { - if (prev_clip_enabled) - set_clip(renderer, &prev_clip); - if (prev_logicalw && prev_logicalh) - SDL_RenderSetLogicalSize(renderer, prev_logicalw, prev_logicalh); - else { - SDL_RenderSetViewport(renderer, &prev_viewport); - SDL_RenderSetScale(renderer, prev_scalex, prev_scaley); - } - } - - SDL_DestroyTexture(temp); - } - - // Reset to the old filter value - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, old_filter_mode); - - } - #endif - if(new_level == NULL || !FC_SetGlyphCacheLevel(font, cache_level, new_level)) - { - FC_Log("Error: SDL_FontCache ran out of packing space and could not add another cache level.\n"); - #ifdef FC_USE_SDL_GPU - GPU_FreeImage(new_level); - #else - SDL_DestroyTexture(new_level); - #endif - return 0; - } - return 1; -} - -static FC_GlyphData* FC_PackGlyphData(FC_Font* font, Uint32 codepoint, Uint16 width, Uint16 maxWidth, Uint16 maxHeight) -{ - FC_Map* glyphs = font->glyphs; - FC_GlyphData* last_glyph = &font->last_glyph; - Uint16 height = font->height + FC_CACHE_PADDING; - - // TAB is special! - if(codepoint == '\t') - { - FC_GlyphData spaceGlyph; - FC_GetGlyphData(font, &spaceGlyph, ' '); - width = fc_tab_width * spaceGlyph.rect.w; - } - - if(last_glyph->rect.x + last_glyph->rect.w + width >= maxWidth - FC_CACHE_PADDING) - { - if(last_glyph->rect.y + height + height >= maxHeight - FC_CACHE_PADDING) - { - // Get ready to pack on the next cache level when it is ready - last_glyph->cache_level = font->glyph_cache_count; - last_glyph->rect.x = FC_CACHE_PADDING; - last_glyph->rect.y = FC_CACHE_PADDING; - last_glyph->rect.w = 0; - return NULL; - } - else - { - // Go to next row - last_glyph->rect.x = FC_CACHE_PADDING; - last_glyph->rect.y += height; - last_glyph->rect.w = 0; - } - } - - // Move to next space - last_glyph->rect.x += last_glyph->rect.w + 1 + FC_CACHE_PADDING; - last_glyph->rect.w = width; - - return FC_MapInsert(glyphs, codepoint, FC_MakeGlyphData(last_glyph->cache_level, last_glyph->rect.x, last_glyph->rect.y, last_glyph->rect.w, last_glyph->rect.h)); -} - - -FC_Image* FC_GetGlyphCacheLevel(FC_Font* font, int cache_level) -{ - if(font == NULL || cache_level < 0 || cache_level > font->glyph_cache_count) - return NULL; - - return font->glyph_cache[cache_level]; -} - -Uint8 FC_SetGlyphCacheLevel(FC_Font* font, int cache_level, FC_Image* cache_texture) -{ - if(font == NULL || cache_level < 0) - return 0; - - // Must be sequentially added - if(cache_level > font->glyph_cache_count + 1) - return 0; - - if(cache_level == font->glyph_cache_count) - { - font->glyph_cache_count++; - - // Grow cache? - if(font->glyph_cache_count > font->glyph_cache_size) - { - // Copy old cache to new one - int i; - FC_Image** new_cache; - new_cache = (FC_Image**)malloc(font->glyph_cache_count * sizeof(FC_Image*)); - for(i = 0; i < font->glyph_cache_size; ++i) - new_cache[i] = font->glyph_cache[i]; - - // Save new cache - free(font->glyph_cache); - font->glyph_cache_size = font->glyph_cache_count; - font->glyph_cache = new_cache; - } - } - - font->glyph_cache[cache_level] = cache_texture; - return 1; -} - - -FC_Font* FC_CreateFont(void) -{ - FC_Font* font; - - font = (FC_Font*)malloc(sizeof(FC_Font)); - memset(font, 0, sizeof(FC_Font)); - - FC_Init(font); - ++NUM_EXISTING_FONTS; - - return font; -} - - -// Assume this many will be enough... -#define FC_LOAD_MAX_SURFACES 10 - -#ifdef FC_USE_SDL_GPU -Uint8 FC_LoadFontFromTTF(FC_Font* font, TTF_Font* ttf, SDL_Color color) -#else -Uint8 FC_LoadFontFromTTF(FC_Font* font, SDL_Renderer* renderer, TTF_Font* ttf, SDL_Color color) -#endif -{ - if(font == NULL || ttf == NULL) - return 0; - #ifndef FC_USE_SDL_GPU - if(renderer == NULL) - return 0; - #endif - - FC_ClearFont(font); - std::scoped_lock lock(*font->mutex); - - // Might as well check render target support here - #ifdef FC_USE_SDL_GPU - fc_has_render_target_support = GPU_IsFeatureEnabled(GPU_FEATURE_RENDER_TARGETS); - #else - SDL_RendererInfo info; - SDL_GetRendererInfo(renderer, &info); - fc_has_render_target_support = (info.flags & SDL_RENDERER_TARGETTEXTURE); - - font->renderer = renderer; - #endif - - font->ttf_source = ttf; - - //font->line_height = TTF_FontLineSkip(ttf); - font->height = TTF_FontHeight(ttf); - font->ascent = TTF_FontAscent(ttf); - font->descent = -TTF_FontDescent(ttf); - - // Some bug for certain fonts can result in an incorrect height. - if(font->height < font->ascent - font->descent) - font->height = font->ascent - font->descent; - - font->baseline = font->height - font->descent; - - font->default_color = color; - - { - SDL_Color white = {255, 255, 255, 255}; - SDL_Surface* glyph_surf; - char buff[5]; - const char* buff_ptr = buff; - const char* source_string; - Uint8 packed = 0; - - // Copy glyphs from the surface to the font texture and store the position data - // Pack row by row into a square texture - // Try figuring out dimensions that make sense for the font size. - unsigned int w = font->height*12; - unsigned int h = font->height*12; - SDL_Surface* surfaces[FC_LOAD_MAX_SURFACES]; - int num_surfaces = 1; - surfaces[0] = FC_CreateSurface32(w, h); - font->last_glyph.rect.x = FC_CACHE_PADDING; - font->last_glyph.rect.y = FC_CACHE_PADDING; - font->last_glyph.rect.w = 0; - font->last_glyph.rect.h = font->height; - - source_string = font->loading_string; - for(; *source_string != '\0'; source_string = U8_next(source_string)) - { - memset(buff, 0, 5); - if(!U8_charcpy(buff, source_string, 5)) - continue; - glyph_surf = TTF_RenderUTF8_Blended(ttf, buff, white); - if(glyph_surf == NULL) - continue; - - // Try packing. If it fails, create a new surface for the next cache level. - packed = (FC_PackGlyphData(font, FC_GetCodepointFromUTF8(&buff_ptr, 0), glyph_surf->w, surfaces[num_surfaces-1]->w, surfaces[num_surfaces-1]->h) != NULL); - if(!packed) - { - int i = num_surfaces-1; - if(num_surfaces >= FC_LOAD_MAX_SURFACES) - { - // Can't do any more! - FC_Log("SDL_FontCache error: Could not create enough cache surfaces to fit all of the loading string!\n"); - SDL_FreeSurface(glyph_surf); - break; - } - - // Upload the current surface to the glyph cache now so we can keep the cache level packing cursor up to date as we go. - FC_UploadGlyphCache(font, i, surfaces[i]); - SDL_FreeSurface(surfaces[i]); - #ifndef FC_USE_SDL_GPU - SDL_SetTextureBlendMode(font->glyph_cache[i], SDL_BLENDMODE_BLEND); - #endif - // Update the glyph cursor to the new cache level. We need to do this here because the actual cache lags behind our use of the packing above. - font->last_glyph.cache_level = num_surfaces; - - - surfaces[num_surfaces] = FC_CreateSurface32(w, h); - num_surfaces++; - } - - // Try packing for the new surface, then blit onto it. - if(packed || FC_PackGlyphData(font, FC_GetCodepointFromUTF8(&buff_ptr, 0), glyph_surf->w, surfaces[num_surfaces-1]->w, surfaces[num_surfaces-1]->h) != NULL) - { - SDL_SetSurfaceBlendMode(glyph_surf, SDL_BLENDMODE_NONE); - SDL_Rect srcRect = {0, 0, glyph_surf->w, glyph_surf->h}; - SDL_Rect destrect = font->last_glyph.rect; - SDL_BlitSurface(glyph_surf, &srcRect, surfaces[num_surfaces-1], &destrect); - } - - SDL_FreeSurface(glyph_surf); - } - - { - int i = num_surfaces-1; - FC_UploadGlyphCache(font, i, surfaces[i]); - SDL_FreeSurface(surfaces[i]); - #ifndef FC_USE_SDL_GPU - SDL_SetTextureBlendMode(font->glyph_cache[i], SDL_BLENDMODE_BLEND); - #endif - } - } - - - - return 1; -} - - -#ifdef FC_USE_SDL_GPU -Uint8 FC_LoadFont(FC_Font* font, const char* filename_ttf, Uint32 pointSize, SDL_Color color, int style) -#else -Uint8 FC_LoadFont(FC_Font* font, FC_Target* renderer, const char* filename_ttf, Uint32 pointSize, SDL_Color color, int style) -#endif -{ - SDL_RWops* rwops; - - if(font == NULL) - return 0; - - rwops = SDL_RWFromFile(filename_ttf, "rb"); - - if(rwops == NULL) - { - FC_Log("Unable to open file for reading: %s \n", SDL_GetError()); - return 0; - } - - #ifdef FC_USE_SDL_GPU - return FC_LoadFont_RW(font, rwops, 1, pointSize, color, style); - #else - return FC_LoadFont_RW(font, renderer, rwops, 1, pointSize, color, style); - #endif -} - -#ifdef FC_USE_SDL_GPU -Uint8 FC_LoadFont_RW(FC_Font* font, SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, SDL_Color color, int style) -#else -Uint8 FC_LoadFont_RW(FC_Font* font, FC_Target* renderer, SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, SDL_Color color, int style) -#endif -{ - Uint8 result; - TTF_Font* ttf; - Uint8 outline; - - if(font == NULL) - return 0; - - if(!TTF_WasInit() && TTF_Init() < 0) - { - FC_Log("Unable to initialize SDL_ttf: %s \n", TTF_GetError()); - if(own_rwops) - SDL_RWclose(file_rwops_ttf); - return 0; - } - - ttf = TTF_OpenFontRW(file_rwops_ttf, own_rwops, pointSize); - - if(ttf == NULL) - { - FC_Log("Unable to load TrueType font: %s \n", TTF_GetError()); - if(own_rwops) - SDL_RWclose(file_rwops_ttf); - return 0; - } - - outline = (style & TTF_STYLE_OUTLINE); - if(outline) - { - style &= ~TTF_STYLE_OUTLINE; - TTF_SetFontOutline(ttf, 1); - } - TTF_SetFontStyle(ttf, style); - - #ifdef FC_USE_SDL_GPU - result = FC_LoadFontFromTTF(font, ttf, color); - #else - result = FC_LoadFontFromTTF(font, renderer, ttf, color); - #endif - - // Can only load new (uncached) glyphs if we can keep the SDL_RWops open. - font->owns_ttf_source = own_rwops; - if(!own_rwops) - { - TTF_CloseFont(font->ttf_source); - font->ttf_source = NULL; - } - - return result; -} - - -#ifndef FC_USE_SDL_GPU -void FC_ResetFontFromRendererReset(FC_Font* font, SDL_Renderer* renderer, Uint32 evType) -{ - TTF_Font* ttf; - SDL_Color col; - Uint8 owns_ttf; - if (font == NULL) - return; - - // Destroy glyph cache - if (evType == SDL_RENDER_TARGETS_RESET) { - int i; - for (i = 0; i < font->glyph_cache_count; ++i) - SDL_DestroyTexture(font->glyph_cache[i]); - } - free(font->glyph_cache); - - ttf = font->ttf_source; - col = font->default_color; - owns_ttf = font->owns_ttf_source; - FC_Init(font); - - // Can only reload glyphs if we own the SDL_RWops. - if (owns_ttf) - FC_LoadFontFromTTF(font, renderer, ttf, col); - font->owns_ttf_source = owns_ttf; -} -#endif - -void FC_ClearFont(FC_Font* font) -{ - int i; - if(font == NULL) - return; - - // Release resources - if(font->owns_ttf_source) - TTF_CloseFont(font->ttf_source); - - font->owns_ttf_source = 0; - font->ttf_source = NULL; - - // Delete glyph map - FC_MapFree(font->glyphs); - font->glyphs = NULL; - - // Delete glyph cache - for(i = 0; i < font->glyph_cache_count; ++i) - { - #ifdef FC_USE_SDL_GPU - GPU_FreeImage(font->glyph_cache[i]); - #else - SDL_DestroyTexture(font->glyph_cache[i]); - #endif - } - free(font->glyph_cache); - font->glyph_cache = NULL; - delete font->mutex; - - font->mutex = nullptr; - - // Reset font - FC_Init(font); -} - - -void FC_FreeFont(FC_Font* font) -{ - int i; - if(font == NULL) - return; - - // Release resources - if(font->owns_ttf_source) - TTF_CloseFont(font->ttf_source); - - // Delete glyph map - FC_MapFree(font->glyphs); - - // Delete glyph cache - for(i = 0; i < font->glyph_cache_count; ++i) - { - #ifdef FC_USE_SDL_GPU - GPU_FreeImage(font->glyph_cache[i]); - #else - SDL_DestroyTexture(font->glyph_cache[i]); - #endif - } - free(font->glyph_cache); - - free(font->loading_string); - - free(font); - - // If the last font has been freed; assume shutdown and free the global variables - if (--NUM_EXISTING_FONTS <= 0) - { - free(ASCII_STRING); - ASCII_STRING = NULL; - - free(LATIN_1_STRING); - LATIN_1_STRING = NULL; - - free(ASCII_LATIN_1_STRING); - ASCII_LATIN_1_STRING = NULL; - - free(fc_buffer); - fc_buffer = NULL; - } -} - -int FC_GetNumCacheLevels(FC_Font* font) -{ - return font->glyph_cache_count; -} - -Uint8 FC_AddGlyphToCache(FC_Font* font, SDL_Surface* glyph_surface) -{ - if(font == NULL || glyph_surface == NULL) - return 0; - - SDL_SetSurfaceBlendMode(glyph_surface, SDL_BLENDMODE_NONE); - FC_Image* dest = FC_GetGlyphCacheLevel(font, font->last_glyph.cache_level); - if(dest == NULL) - return 0; - - #ifdef FC_USE_SDL_GPU - { - GPU_Target* target = GPU_LoadTarget(dest); - if(target == NULL) - return 0; - GPU_Image* img = GPU_CopyImageFromSurface(glyph_surface); - GPU_SetAnchor(img, 0.5f, 0.5f); // Just in case the default is different - GPU_SetImageFilter(img, GPU_FILTER_NEAREST); - GPU_SetBlendMode(img, GPU_BLEND_SET); - - SDL_Rect destrect = font->last_glyph.rect; - GPU_Blit(img, NULL, target, destrect.x + destrect.w/2, destrect.y + destrect.h/2); - - GPU_FreeImage(img); - GPU_FreeTarget(target); - } - #else - { - SDL_Renderer* renderer = font->renderer; - SDL_Texture* img; - SDL_Rect destrect; - SDL_Texture* prev_target = SDL_GetRenderTarget(renderer); - SDL_Rect prev_clip, prev_viewport; - int prev_logicalw, prev_logicalh; - Uint8 prev_clip_enabled; - float prev_scalex, prev_scaley; - // only backup if previous target existed (SDL will preserve them for the default target) - if (prev_target) { - prev_clip_enabled = has_clip(renderer); - if (prev_clip_enabled) - prev_clip = get_clip(renderer); - SDL_RenderGetViewport(renderer, &prev_viewport); - SDL_RenderGetScale(renderer, &prev_scalex, &prev_scaley); - SDL_RenderGetLogicalSize(renderer, &prev_logicalw, &prev_logicalh); - } - - img = SDL_CreateTextureFromSurface(renderer, glyph_surface); - - destrect = font->last_glyph.rect; - SDL_SetRenderTarget(renderer, dest); - SDL_RenderCopy(renderer, img, NULL, &destrect); - SDL_SetRenderTarget(renderer, prev_target); - if (prev_target) { - if (prev_clip_enabled) - set_clip(renderer, &prev_clip); - if (prev_logicalw && prev_logicalh) - SDL_RenderSetLogicalSize(renderer, prev_logicalw, prev_logicalh); - else { - SDL_RenderSetViewport(renderer, &prev_viewport); - SDL_RenderSetScale(renderer, prev_scalex, prev_scaley); - } - } - - SDL_DestroyTexture(img); - } - #endif - - return 1; -} - - -unsigned int FC_GetNumCodepoints(FC_Font* font) -{ - FC_Map* glyphs; - int i; - unsigned int result = 0; - if(font == NULL || font->glyphs == NULL) - return 0; - - glyphs = font->glyphs; - - for(i = 0; i < glyphs->num_buckets; ++i) - { - FC_MapNode* node; - for(node = glyphs->buckets[i]; node != NULL; node = node->next) - { - result++; - } - } - - return result; -} - -void FC_GetCodepoints(FC_Font* font, Uint32* result) -{ - FC_Map* glyphs; - int i; - unsigned int count = 0; - if(font == NULL || font->glyphs == NULL) - return; - - glyphs = font->glyphs; - - for(i = 0; i < glyphs->num_buckets; ++i) - { - FC_MapNode* node; - for(node = glyphs->buckets[i]; node != NULL; node = node->next) - { - result[count] = node->key; - count++; - } - } -} - -Uint8 FC_GetGlyphData(FC_Font* font, FC_GlyphData* result, Uint32 codepoint) -{ - FC_GlyphData* e = FC_MapFind(font->glyphs, codepoint); - if(e == NULL) - { - char buff[5]; - int w, h; - SDL_Color white = {255, 255, 255, 255}; - SDL_Surface* surf; - FC_Image* cache_image; - - if(font->ttf_source == NULL) - return 0; - - FC_GetUTF8FromCodepoint(buff, codepoint); - - cache_image = FC_GetGlyphCacheLevel(font, font->last_glyph.cache_level); - if(cache_image == NULL) - { - FC_Log("SDL_FontCache: Failed to load cache image, so cannot add new glyphs!\n"); - return 0; - } - - #ifdef FC_USE_SDL_GPU - w = cache_image->w; - h = cache_image->h; - #else - SDL_QueryTexture(cache_image, NULL, NULL, &w, &h); - #endif - - surf = TTF_RenderUTF8_Blended(font->ttf_source, buff, white); - if(surf == NULL) - { - return 0; - } - - e = FC_PackGlyphData(font, codepoint, surf->w, w, h); - if(e == NULL) - { - // Grow the cache - FC_GrowGlyphCache(font); - - // Try packing again - e = FC_PackGlyphData(font, codepoint, surf->w, w, h); - if(e == NULL) - { - SDL_FreeSurface(surf); - return 0; - } - } - - // Render onto the cache texture - FC_AddGlyphToCache(font, surf); - - SDL_FreeSurface(surf); - } - - if(result != NULL && e != NULL) - *result = *e; - - return 1; -} - - -FC_GlyphData* FC_SetGlyphData(FC_Font* font, Uint32 codepoint, FC_GlyphData glyph_data) -{ - return FC_MapInsert(font->glyphs, codepoint, glyph_data); -} - - - -// Drawing -static FC_Rect FC_RenderLeft(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* text) -{ - const char* c = text; - FC_Rect srcRect; - FC_Rect dstRect; - FC_Rect dirtyRect = FC_MakeRect(x, y, 0, 0); - - FC_GlyphData glyph; - Uint32 codepoint; - - float destX = x; - float destY = y; - float destH; - float destLineSpacing; - float destLetterSpacing; - - if(font == NULL) - return dirtyRect; - - destH = font->height * scale.y; - destLineSpacing = font->lineSpacing*scale.y; - destLetterSpacing = font->letterSpacing*scale.x; - - if(c == NULL || font->glyph_cache_count == 0 || dest == NULL) - return dirtyRect; - - int newlineX = x; - - for(; *c != '\0'; c++) - { - if(*c == '\n') - { - destX = newlineX; - destY += destH + destLineSpacing; - continue; - } - - codepoint = FC_GetCodepointFromUTF8(&c, 1); // Increments 'c' to skip the extra UTF-8 bytes - if(!FC_GetGlyphData(font, &glyph, codepoint)) - { - codepoint = ' '; - if(!FC_GetGlyphData(font, &glyph, codepoint)) - continue; // Skip bad characters - } - - if (codepoint == ' ') - { - destX += glyph.rect.w*scale.x + destLetterSpacing; - continue; - } - /*if(destX >= dest->w) - continue; - if(destY >= dest->h) - continue;*/ - - #ifdef FC_USE_SDL_GPU - srcRect.x = glyph.rect.x; - srcRect.y = glyph.rect.y; - srcRect.w = glyph.rect.w; - srcRect.h = glyph.rect.h; - #else - srcRect = glyph.rect; - #endif - dstRect = fc_render_callback(FC_GetGlyphCacheLevel(font, glyph.cache_level), &srcRect, dest, destX, destY, scale.x, scale.y); - if(dirtyRect.w == 0 || dirtyRect.h == 0) - dirtyRect = dstRect; - else - dirtyRect = FC_RectUnion(dirtyRect, dstRect); - - destX += glyph.rect.w*scale.x + destLetterSpacing; - } - - return dirtyRect; -} - -static void set_color_for_all_caches(FC_Font* font, SDL_Color color) -{ - // TODO: How can I predict which glyph caches are to be used? - FC_Image* img; - int i; - int num_levels = FC_GetNumCacheLevels(font); - for(i = 0; i < num_levels; ++i) - { - img = FC_GetGlyphCacheLevel(font, i); - set_color(img, color.r, color.g, color.b, FC_GET_ALPHA(color)); - } -} - -FC_Rect FC_Draw(FC_Font* font, FC_Target* dest, float x, float y, const char* formatted_text, ...) -{ - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(x, y, 0, 0); - - std::scoped_lock lock(*font->mutex); - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - set_color_for_all_caches(font, font->default_color); - - auto res = FC_RenderLeft(font, dest, x, y, FC_MakeScale(1,1), fc_buffer); - - return res; -} - -typedef struct FC_StringList -{ - char* value; - struct FC_StringList* next; -} FC_StringList; - -void FC_StringListFree(FC_StringList* node) -{ - // Delete the nodes in order - while(node != NULL) - { - FC_StringList* last = node; - node = node->next; - - free(last->value); - free(last); - } -} - -FC_StringList** FC_StringListPushBack(FC_StringList** node, char* value, Uint8 copy) -{ - if(node == NULL) - { - return NULL; - } - - // Get to the last node - while(*node != NULL) - { - node = &(*node)->next; - } - - *node = (FC_StringList*)malloc(sizeof(FC_StringList)); - - (*node)->value = (copy? U8_strdup(value) : value); - (*node)->next = NULL; - - return node; -} - -FC_StringList** FC_StringListPushBackBytes(FC_StringList** node, const char* data, int num_bytes) -{ - if(node == NULL) - { - return node; - } - - // Get to the last node - while(*node != NULL) - { - node = &(*node)->next; - } - - *node = (FC_StringList*)malloc(sizeof(FC_StringList)); - - (*node)->value = (char*)malloc(num_bytes + 1); - memcpy((*node)->value, data, num_bytes); - (*node)->value[num_bytes] = '\0'; - (*node)->next = NULL; - - return node; -} - -static FC_StringList* FC_Explode(const char* text, char delimiter) -{ - FC_StringList* head; - FC_StringList* new_node; - FC_StringList** node; - const char* start; - const char* end; - unsigned int size; - if(text == NULL) - return NULL; - - head = NULL; - node = &head; - - // Doesn't technically support UTF-8, but it's probably fine, right? - size = 0; - start = end = text; - while(1) - { - if(*end == delimiter || *end == '\0') - { - *node = (FC_StringList*)malloc(sizeof(FC_StringList)); - new_node = *node; - - new_node->value = (char*)malloc(size + 1); - memcpy(new_node->value, start, size); - new_node->value[size] = '\0'; - - new_node->next = NULL; - - if(*end == '\0') - break; - - node = &((*node)->next); - start = end+1; - size = 0; - } - else - ++size; - - ++end; - } - - return head; -} - -static FC_StringList* FC_ExplodeBreakingSpace(const char* text, FC_StringList** spaces) -{ - FC_StringList* head; - FC_StringList** node; - const char* start; - const char* end; - unsigned int size; - if(text == NULL) - return NULL; - - head = NULL; - node = &head; - - // Warning: spaces must not be initialized before this function - *spaces = NULL; - - // Doesn't technically support UTF-8, but it's probably fine, right? - size = 0; - start = end = text; - while(1) - { - // Add any characters here that should make separate words (except for \n?) - if(*end == ' ' || *end == '\t' || *end == '\0') - { - FC_StringListPushBackBytes(node, start, size); - FC_StringListPushBackBytes(spaces, end, 1); - - if(*end == '\0') - break; - - node = &((*node)->next); - start = end+1; - size = 0; - } - else - ++size; - - ++end; - } - - return head; -} - -static FC_StringList* FC_ExplodeAndKeep(const char* text, char delimiter) -{ - FC_StringList* head; - FC_StringList** node; - const char* start; - const char* end; - unsigned int size; - if(text == NULL) - return NULL; - - head = NULL; - node = &head; - - // Doesn't technically support UTF-8, but it's probably fine, right? - size = 0; - start = end = text; - while(1) - { - if(*end == delimiter || *end == '\0') - { - FC_StringListPushBackBytes(node, start, size); - - if(*end == '\0') - break; - - node = &((*node)->next); - start = end; - size = 1; - } - else - ++size; - - ++end; - } - - return head; -} - -static void FC_RenderAlign(FC_Font* font, FC_Target* dest, float x, float y, int width, FC_Scale scale, FC_AlignEnum align, const char* text) -{ - switch(align) - { - case FC_ALIGN_LEFT: - FC_RenderLeft(font, dest, x, y, scale, text); - break; - case FC_ALIGN_CENTER: - FC_RenderCenter(font, dest, x + width/2, y, scale, text); - break; - case FC_ALIGN_RIGHT: - FC_RenderRight(font, dest, x + width, y, scale, text); - break; - } -} - -static FC_StringList* FC_GetBufferFitToColumn(FC_Font* font, int width, FC_Scale scale, Uint8 keep_newlines) -{ - FC_StringList* result = NULL; - FC_StringList** current = &result; - - FC_StringList *ls, *iter; - - ls = (keep_newlines? FC_ExplodeAndKeep(fc_buffer, '\n') : FC_Explode(fc_buffer, '\n')); - for(iter = ls; iter != NULL; iter = iter->next) - { - char* line = iter->value; - - // If line is too long, then add words one at a time until we go over. - if(width > 0 && FC_GetWidth(font, "%s", line) > width) - { - FC_StringList *words, *word_iter, *spaces, *spaces_iter; - - words = FC_ExplodeBreakingSpace(line, &spaces); - // Skip the first word for the iterator, so there will always be at least one word per line - line = new_concat(words->value, spaces->value); - for(word_iter = words->next, spaces_iter = spaces->next; word_iter != NULL && spaces_iter != NULL; word_iter = word_iter->next, spaces_iter = spaces_iter->next) - { - char* line_plus_word = new_concat(line, word_iter->value); - char* word_plus_space = new_concat(word_iter->value, spaces_iter->value); - if(FC_GetWidth(font, "%s", line_plus_word) > width) - { - current = FC_StringListPushBack(current, line, 0); - - line = word_plus_space; - } - else - { - replace_concat(&line, word_plus_space); - free(word_plus_space); - } - free(line_plus_word); - } - current = FC_StringListPushBack(current, line, 0); - FC_StringListFree(words); - FC_StringListFree(spaces); - } - else - { - current = FC_StringListPushBack(current, line, 0); - iter->value = NULL; - } - } - FC_StringListFree(ls); - - return result; -} - -static void FC_DrawColumnFromBuffer(FC_Font* font, FC_Target* dest, FC_Rect box, int* total_height, FC_Scale scale, FC_AlignEnum align) -{ - int y = box.y; - FC_StringList *ls, *iter; - - ls = FC_GetBufferFitToColumn(font, box.w, scale, 0); - int8_t onFirst = 1; - for(iter = ls; iter != NULL; iter = iter->next) - { - FC_RenderAlign(font, dest, box.x, y, box.w, scale, onFirst ? FC_ALIGN_LEFT : align, iter->value); - y += FC_GetLineHeight(font); - onFirst = 0; - } - FC_StringListFree(ls); - - if(total_height != NULL) - *total_height = y - box.y; -} - -FC_Rect FC_DrawBox(FC_Font* font, FC_Target* dest, FC_Rect box, const char* formatted_text, ...) -{ - Uint8 useClip; - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(box.x, box.y, 0, 0); - - std::scoped_lock lock(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - useClip = has_clip(dest); - FC_Rect oldclip, newclip; - if(useClip) - { - oldclip = get_clip(dest); - newclip = FC_RectIntersect(oldclip, box); - } - else - newclip = box; - - set_clip(dest, &newclip); - - set_color_for_all_caches(font, font->default_color); - - FC_DrawColumnFromBuffer(font, dest, box, NULL, FC_MakeScale(1,1), FC_ALIGN_LEFT); - - if(useClip) - set_clip(dest, &oldclip); - else - set_clip(dest, NULL); - - return box; -} - -FC_Rect FC_DrawBoxAlign(FC_Font* font, FC_Target* dest, FC_Rect box, FC_AlignEnum align, const char* formatted_text, ...) -{ - Uint8 useClip; - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(box.x, box.y, 0, 0); - - std::scoped_lock lock(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - useClip = has_clip(dest); - FC_Rect oldclip, newclip; - if(useClip) - { - oldclip = get_clip(dest); - newclip = FC_RectIntersect(oldclip, box); - } - else - newclip = box; - set_clip(dest, &newclip); - - set_color_for_all_caches(font, font->default_color); - - FC_DrawColumnFromBuffer(font, dest, box, NULL, FC_MakeScale(1,1), align); - - if(useClip) - set_clip(dest, &oldclip); - else - set_clip(dest, NULL); - - return box; -} - -FC_Rect FC_DrawBoxScale(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Scale scale, const char* formatted_text, ...) -{ - Uint8 useClip; - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(box.x, box.y, 0, 0); - - std::scoped_lock lock(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - useClip = has_clip(dest); - FC_Rect oldclip, newclip; - if(useClip) - { - oldclip = get_clip(dest); - newclip = FC_RectIntersect(oldclip, box); - } - else - newclip = box; - set_clip(dest, &newclip); - - set_color_for_all_caches(font, font->default_color); - - FC_DrawColumnFromBuffer(font, dest, box, NULL, scale, FC_ALIGN_LEFT); - - if(useClip) - set_clip(dest, &oldclip); - else - set_clip(dest, NULL); - - return box; -} - -FC_Rect FC_DrawBoxColor(FC_Font* font, FC_Target* dest, FC_Rect box, SDL_Color color, const char* formatted_text, ...) -{ - Uint8 useClip; - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(box.x, box.y, 0, 0); - - std::scoped_lock lock(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - useClip = has_clip(dest); - FC_Rect oldclip, newclip; - if(useClip) - { - oldclip = get_clip(dest); - newclip = FC_RectIntersect(oldclip, box); - } - else - newclip = box; - set_clip(dest, &newclip); - - set_color_for_all_caches(font, color); - - FC_DrawColumnFromBuffer(font, dest, box, NULL, FC_MakeScale(1,1), FC_ALIGN_LEFT); - - if(useClip) - set_clip(dest, &oldclip); - else - set_clip(dest, NULL); - - return box; -} - -FC_Rect FC_DrawBoxEffect(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Effect effect, const char* formatted_text, ...) -{ - Uint8 useClip; - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(box.x, box.y, 0, 0); - - std::scoped_lock lock(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - useClip = has_clip(dest); - FC_Rect oldclip, newclip; - if(useClip) - { - oldclip = get_clip(dest); - newclip = FC_RectIntersect(oldclip, box); - } - else - newclip = box; - set_clip(dest, &newclip); - - set_color_for_all_caches(font, effect.color); - - FC_DrawColumnFromBuffer(font, dest, box, NULL, effect.scale, effect.alignment); - - if(useClip) - set_clip(dest, &oldclip); - else - set_clip(dest, NULL); - - return box; -} - -FC_Rect FC_DrawColumn(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, const char* formatted_text, ...) -{ - 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(*font->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); - - 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(*font->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 = {(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(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - set_color_for_all_caches(font, font->default_color); - - switch(align) - { - case FC_ALIGN_CENTER: - box.x -= width/2; - break; - case FC_ALIGN_RIGHT: - box.x -= width; - break; - default: - break; - } - - FC_DrawColumnFromBuffer(font, dest, box, &total_height, FC_MakeScale(1,1), align); - - 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 = {(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(*font->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); - - 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 = {(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(*font->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); - - 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 = {(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(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - set_color_for_all_caches(font, effect.color); - - switch(effect.alignment) - { - case FC_ALIGN_CENTER: - box.x -= width/2; - break; - case FC_ALIGN_RIGHT: - box.x -= width; - break; - default: - break; - } - - FC_DrawColumnFromBuffer(font, dest, box, &total_height, effect.scale, effect.alignment); - - 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 = {(int) x, (int) y, (int) 0, (int) 0}; - if(text == NULL || font == NULL) - return result; - - char* str = U8_strdup(text); - char* del = str; - char* c; - - // Go through str, when you find a \n, replace it with \0 and print it - // then move down, back, and continue. - for(c = str; *c != '\0';) - { - if(*c == '\n') - { - *c = '\0'; - result = FC_RectUnion(FC_RenderLeft(font, dest, x - scale.x*FC_GetWidth(font, "%s", str)/2.0f, y, scale, str), result); - *c = '\n'; - c++; - str = c; - y += scale.y*font->height; - } - else - c++; - } - - result = FC_RectUnion(FC_RenderLeft(font, dest, x - scale.x*FC_GetWidth(font, "%s", str)/2.0f, y, scale, str), result); - - free(del); - return result; -} - -static FC_Rect FC_RenderRight(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* text) -{ - FC_Rect result = {(int) x, (int) y, (int) 0, (int) 0}; - if(text == NULL || font == NULL) - return result; - - char* str = U8_strdup(text); - char* del = str; - char* c; - - for(c = str; *c != '\0';) - { - if(*c == '\n') - { - *c = '\0'; - result = FC_RectUnion(FC_RenderLeft(font, dest, x - scale.x*FC_GetWidth(font, "%s", str), y, scale, str), result); - *c = '\n'; - c++; - str = c; - y += scale.y*font->height; - } - else - c++; - } - - result = FC_RectUnion(FC_RenderLeft(font, dest, x - scale.x*FC_GetWidth(font, "%s", str), y, scale, str), result); - - free(del); - return result; -} - - - -FC_Rect FC_DrawScale(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* formatted_text, ...) -{ - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(x, y, 0, 0); - - std::scoped_lock lock(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - set_color_for_all_caches(font, font->default_color); - - 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, ...) -{ - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(x, y, 0, 0); - - std::scoped_lock lock(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - set_color_for_all_caches(font, font->default_color); - - FC_Rect result; - switch(align) - { - case FC_ALIGN_LEFT: - result = FC_RenderLeft(font, dest, x, y, FC_MakeScale(1,1), fc_buffer); - break; - case FC_ALIGN_CENTER: - result = FC_RenderCenter(font, dest, x, y, FC_MakeScale(1,1), fc_buffer); - break; - case FC_ALIGN_RIGHT: - result = FC_RenderRight(font, dest, x, y, FC_MakeScale(1,1), fc_buffer); - break; - default: - result = FC_MakeRect(x, y, 0, 0); - break; - } - - - - return result; -} - -FC_Rect FC_DrawColor(FC_Font* font, FC_Target* dest, float x, float y, SDL_Color color, const char* formatted_text, ...) -{ - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(x, y, 0, 0); - - std::scoped_lock lock(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - set_color_for_all_caches(font, color); - - auto res = FC_RenderLeft(font, dest, x, y, FC_MakeScale(1,1), fc_buffer); - - - - return res; -} - - -FC_Rect FC_DrawEffect(FC_Font* font, FC_Target* dest, float x, float y, FC_Effect effect, const char* formatted_text, ...) -{ - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(x, y, 0, 0); - - std::scoped_lock lock(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - set_color_for_all_caches(font, effect.color); - - FC_Rect result; - switch(effect.alignment) - { - case FC_ALIGN_LEFT: - result = FC_RenderLeft(font, dest, x, y, effect.scale, fc_buffer); - break; - case FC_ALIGN_CENTER: - result = FC_RenderCenter(font, dest, x, y, effect.scale, fc_buffer); - break; - case FC_ALIGN_RIGHT: - result = FC_RenderRight(font, dest, x, y, effect.scale, fc_buffer); - break; - default: - result = FC_MakeRect(x, y, 0, 0); - break; - } - - - - return result; -} - - - - -// Getters - - -FC_FilterEnum FC_GetFilterMode(FC_Font* font) -{ - if(font == NULL) - return FC_FILTER_NEAREST; - - return font->filter; -} - -Uint16 FC_GetLineHeight(FC_Font* font) -{ - if(font == NULL) - return 0; - - return font->height; -} - -Uint16 FC_GetHeight(FC_Font* font, const char* formatted_text, ...) -{ - if(formatted_text == NULL || font == NULL) - return 0; - - std::scoped_lock lock(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - Uint16 numLines = 1; - const char* c; - - for (c = fc_buffer; *c != '\0'; c++) - { - if(*c == '\n') - numLines++; - } - - // Actual height of letter region + line spacing - auto res = font->height*numLines + font->lineSpacing*(numLines - 1); //height*numLines; - - - - return res; -} - -Uint16 FC_GetWidth(FC_Font* font, const char* formatted_text, ...) -{ - if(formatted_text == NULL || font == NULL) - return 0; - - std::scoped_lock lock(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - const char* c; - Uint16 width = 0; - Uint16 bigWidth = 0; // Allows for multi-line strings - - for (c = fc_buffer; *c != '\0'; c++) - { - if(*c == '\n') - { - bigWidth = bigWidth >= width? bigWidth : width; - width = 0; - continue; - } - - FC_GlyphData glyph; - Uint32 codepoint = FC_GetCodepointFromUTF8(&c, 1); - if(FC_GetGlyphData(font, &glyph, codepoint) || FC_GetGlyphData(font, &glyph, ' ')) - width += glyph.rect.w; - } - bigWidth = bigWidth >= width? bigWidth : width; - - - - return bigWidth; -} - -// If width == -1, use no width limit -FC_Rect FC_GetCharacterOffset(FC_Font* font, Uint16 position_index, int column_width, const char* formatted_text, ...) -{ - FC_Rect result = {0, 0, 1, FC_GetLineHeight(font)}; - FC_StringList *ls, *iter; - int num_lines = 0; - Uint8 done = 0; - - if(formatted_text == NULL || column_width == 0 || position_index == 0 || font == NULL) - return result; - - std::scoped_lock lock(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - ls = FC_GetBufferFitToColumn(font, column_width, FC_MakeScale(1,1), 1); - for(iter = ls; iter != NULL;) - { - char* line; - int i = 0; - FC_StringList* next_iter = iter->next; - - ++num_lines; - for(line = iter->value; line != NULL && *line != '\0'; line = (char*)U8_next(line)) - { - ++i; - --position_index; - if(position_index == 0) - { - // FIXME: Doesn't handle box-wrapped newlines correctly - line = (char*)U8_next(line); - line[0] = '\0'; - result.x = FC_GetWidth(font, "%s", iter->value); - done = 1; - break; - } - } - if(done) - break; - - // Prevent line wrapping if there are no more lines - if(next_iter == NULL && !done) - result.x = FC_GetWidth(font, "%s", iter->value); - iter = next_iter; - } - FC_StringListFree(ls); - - if(num_lines > 1) - { - result.y = (num_lines - 1) * FC_GetLineHeight(font); - } - - - - return result; -} - - -Uint16 FC_GetColumnHeight(FC_Font* font, Uint16 width, const char* formatted_text, ...) -{ - int y = 0; - - FC_StringList *ls, *iter; - - if(font == NULL) - return 0; - - if(formatted_text == NULL || width == 0) - return font->height; - - std::scoped_lock lock(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - ls = FC_GetBufferFitToColumn(font, width, FC_MakeScale(1,1), 0); - for(iter = ls; iter != NULL; iter = iter->next) - { - y += FC_GetLineHeight(font); - } - FC_StringListFree(ls); - - - - return y; -} - -static int FC_GetAscentFromCodepoint(FC_Font* font, Uint32 codepoint) -{ - FC_GlyphData glyph; - - if(font == NULL) - return 0; - - // FIXME: Store ascent so we can return it here - FC_GetGlyphData(font, &glyph, codepoint); - return glyph.rect.h; -} - -static int FC_GetDescentFromCodepoint(FC_Font* font, Uint32 codepoint) -{ - FC_GlyphData glyph; - - if(font == NULL) - return 0; - - // FIXME: Store descent so we can return it here - FC_GetGlyphData(font, &glyph, codepoint); - return glyph.rect.h; -} - -int FC_GetAscent(FC_Font* font, const char* formatted_text, ...) -{ - Uint32 codepoint; - int max, ascent; - const char* c; - - if(font == NULL) - return 0; - - if(formatted_text == NULL) - return font->ascent; - - std::scoped_lock lock(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - max = 0; - c = fc_buffer; - - while(*c != '\0') - { - codepoint = FC_GetCodepointFromUTF8(&c, 1); - if(codepoint != 0) - { - ascent = FC_GetAscentFromCodepoint(font, codepoint); - if(ascent > max) - max = ascent; - } - ++c; - } - - - - return max; -} - -int FC_GetDescent(FC_Font* font, const char* formatted_text, ...) -{ - Uint32 codepoint; - int max, descent; - const char* c; - - if(font == NULL) - return 0; - - if(formatted_text == NULL) - return font->descent; - - std::scoped_lock lock(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - max = 0; - c = fc_buffer; - - while(*c != '\0') - { - codepoint = FC_GetCodepointFromUTF8(&c, 1); - if(codepoint != 0) - { - descent = FC_GetDescentFromCodepoint(font, codepoint); - if(descent > max) - max = descent; - } - ++c; - } - - - - return max; -} - -int FC_GetBaseline(FC_Font* font) -{ - if(font == NULL) - return 0; - - return font->baseline; -} - -int FC_GetSpacing(FC_Font* font) -{ - if(font == NULL) - return 0; - - return font->letterSpacing; -} - -int FC_GetLineSpacing(FC_Font* font) -{ - if(font == NULL) - return 0; - - return font->lineSpacing; -} - -Uint16 FC_GetMaxWidth(FC_Font* font) -{ - if(font == NULL) - return 0; - - return font->maxWidth; -} - -SDL_Color FC_GetDefaultColor(FC_Font* font) -{ - if(font == NULL) - { - SDL_Color c = {0,0,0,255}; - return c; - } - - return font->default_color; -} - -FC_Rect FC_GetBounds(FC_Font* font, float x, float y, FC_AlignEnum align, FC_Scale scale, const char* formatted_text, ...) -{ - FC_Rect result = {(int) x, (int) y, (int) 0, (int) 0}; - - if(formatted_text == NULL) - return result; - - // Create a temp buffer while GetWidth and GetHeight use fc_buffer. - char* temp = (char*)malloc(fc_buffer_size); - FC_EXTRACT_VARARGS(temp, formatted_text); - - result.w = FC_GetWidth(font, "%s", temp) * scale.x; - result.h = FC_GetHeight(font, "%s", temp) * scale.y; - - switch(align) - { - case FC_ALIGN_LEFT: - break; - case FC_ALIGN_CENTER: - result.x -= result.w/2; - break; - case FC_ALIGN_RIGHT: - result.x -= result.w; - break; - default: - break; - } - - free(temp); - - return result; -} - -Uint8 FC_InRect(float x, float y, FC_Rect input_rect) -{ - return (input_rect.x <= x && x <= input_rect.x + input_rect.w && input_rect.y <= y && y <= input_rect.y + input_rect.h); -} - -// TODO: Make it work with alignment -Uint16 FC_GetPositionFromOffset(FC_Font* font, float x, float y, int column_width, FC_AlignEnum align, const char* formatted_text, ...) -{ - FC_StringList *ls, *iter; - Uint8 done = 0; - int height = FC_GetLineHeight(font); - Uint16 position = 0; - int current_x = 0; - int current_y = 0; - FC_GlyphData glyph_data; - - if(formatted_text == NULL || column_width == 0 || font == NULL) - return 0; - - std::scoped_lock lock(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - ls = FC_GetBufferFitToColumn(font, column_width, FC_MakeScale(1,1), 1); - for(iter = ls; iter != NULL; iter = iter->next) - { - char* line; - - for(line = iter->value; line != NULL && *line != '\0'; line = (char*)U8_next(line)) - { - if(FC_GetGlyphData(font, &glyph_data, FC_GetCodepointFromUTF8((const char**)&line, 0))) - { - if(FC_InRect(x, y, FC_MakeRect(current_x, current_y, glyph_data.rect.w, glyph_data.rect.h))) - { - done = 1; - break; - } - - current_x += glyph_data.rect.w; - } - position++; - } - if(done) - break; - - current_x = 0; - current_y += height; - if(y < current_y) - break; - } - FC_StringListFree(ls); - - - - return position; -} - -int FC_GetWrappedText(FC_Font* font, char* result, int max_result_size, Uint16 width, const char* formatted_text, ...) -{ - FC_StringList *ls, *iter; - - if(font == NULL) - return 0; - - if(formatted_text == NULL || width == 0) - return 0; - - std::scoped_lock lock(*font->mutex); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - ls = FC_GetBufferFitToColumn(font, width, FC_MakeScale(1,1), 0); - int size_so_far = 0; - int size_remaining = max_result_size-1; // reserve for \0 - for(iter = ls; iter != NULL && size_remaining > 0; iter = iter->next) - { - // Copy as much of this line as we can - int len = strlen(iter->value); - int num_bytes = FC_MIN(len, size_remaining); - memcpy(&result[size_so_far], iter->value, num_bytes); - size_so_far += num_bytes; - - // If there's another line, add newline character - if(size_remaining > 0 && iter->next != NULL) - { - --size_remaining; - result[size_so_far] = '\n'; - ++size_so_far; - } - } - FC_StringListFree(ls); - - result[size_so_far] = '\0'; - - - - return size_so_far; -} - - - -// Setters -void FC_SetFilterMode(FC_Font* font, FC_FilterEnum filter) -{ - if(font == NULL) - return; - - if(font->filter != filter) - { - font->filter = filter; - - #ifdef FC_USE_SDL_GPU - // Update each texture to use this filter mode - { - int i; - GPU_FilterEnum gpu_filter = GPU_FILTER_NEAREST; - if(FC_GetFilterMode(font) == FC_FILTER_LINEAR) - gpu_filter = GPU_FILTER_LINEAR; - - for(i = 0; i < font->glyph_cache_count; ++i) - { - GPU_SetImageFilter(font->glyph_cache[i], gpu_filter); - } - } - #endif - } -} - - -void FC_SetSpacing(FC_Font* font, int LetterSpacing) -{ - if(font == NULL) - return; - - font->letterSpacing = LetterSpacing; -} - -void FC_SetLineSpacing(FC_Font* font, int LineSpacing) -{ - if(font == NULL) - return; - - font->lineSpacing = LineSpacing; -} - -void FC_SetDefaultColor(FC_Font* font, SDL_Color color) -{ - if(font == NULL) - return; - - font->default_color = color; -} diff --git a/src/system/video/SDL_FontCache.h b/src/system/video/SDL_FontCache.h deleted file mode 100644 index 9d3895a..0000000 --- a/src/system/video/SDL_FontCache.h +++ /dev/null @@ -1,320 +0,0 @@ -/* -SDL_FontCache v0.10.0: A font cache for SDL and SDL_ttf -by Jonathan Dearborn -Dedicated to the memory of Florian Hufsky - -License: - The short: - Use it however you'd like, but keep the copyright and license notice - whenever these files or parts of them are distributed in uncompiled form. - - The long: -Copyright (c) 2019 Jonathan Dearborn - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef _SDL_FONTCACHE_H__ -#define _SDL_FONTCACHE_H__ - -#include -#include -#include -#include "../../utils/logger.h" - -#ifdef FC_USE_SDL_GPU - #include "SDL_gpu.h" -#endif - - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -// Let's pretend this exists... -#define TTF_STYLE_OUTLINE 16 - - - -// Differences between SDL_Renderer and SDL_gpu -#ifdef FC_USE_SDL_GPU -#define FC_Rect GPU_Rect -#define FC_Target GPU_Target -#define FC_Image GPU_Image -#define FC_Log GPU_LogError -#else -#define FC_Rect SDL_Rect -#define FC_Target SDL_Renderer -#define FC_Image SDL_Texture -#define FC_Log DEBUG_FUNCTION_LINE -#endif - - -// SDL_FontCache types - -typedef enum -{ - FC_ALIGN_LEFT, - FC_ALIGN_CENTER, - FC_ALIGN_RIGHT -} FC_AlignEnum; - -typedef enum -{ - FC_FILTER_NEAREST, - FC_FILTER_LINEAR -} FC_FilterEnum; - -typedef struct FC_Scale -{ - float x; - float y; - -} FC_Scale; - -typedef struct FC_Effect -{ - FC_AlignEnum alignment; - FC_Scale scale; - SDL_Color color; - -} FC_Effect; - -// Opaque type -typedef struct FC_Font FC_Font; - - -typedef struct FC_GlyphData -{ - SDL_Rect rect; - int cache_level; - -} FC_GlyphData; - -// Object creation -FC_Rect FC_MakeRect(float x, float y, float w, float h); - -FC_Scale FC_MakeScale(float x, float y); - -SDL_Color FC_MakeColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a); - -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); - -#ifdef FC_USE_SDL_GPU -Uint8 FC_LoadFont(FC_Font* font, const char* filename_ttf, Uint32 pointSize, SDL_Color color, int style); - -Uint8 FC_LoadFontFromTTF(FC_Font* font, TTF_Font* ttf, SDL_Color color); - -Uint8 FC_LoadFont_RW(FC_Font* font, SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, SDL_Color color, int style); -#else -Uint8 FC_LoadFont(FC_Font* font, SDL_Renderer* renderer, const char* filename_ttf, Uint32 pointSize, SDL_Color color, int style); - -Uint8 FC_LoadFontFromTTF(FC_Font* font, SDL_Renderer* renderer, TTF_Font* ttf, SDL_Color color); - -Uint8 FC_LoadFont_RW(FC_Font* font, SDL_Renderer* renderer, SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, SDL_Color color, int style); -#endif - -#ifndef FC_USE_SDL_GPU -// note: handle SDL event types SDL_RENDER_TARGETS_RESET(>= SDL 2.0.2) and SDL_RENDER_DEVICE_RESET(>= SDL 2.0.4) -void FC_ResetFontFromRendererReset(FC_Font* font, SDL_Renderer* renderer, Uint32 evType); -#endif - -void FC_ClearFont(FC_Font* font); - -void FC_FreeFont(FC_Font* font); - - - -// Built-in loading strings - -char* FC_GetStringASCII(void); - -char* FC_GetStringLatin1(void); - -char* FC_GetStringASCII_Latin1(void); - - -// UTF-8 to SDL_FontCache codepoint conversion - -/*! -Returns the Uint32 codepoint (not UTF-32) parsed from the given UTF-8 string. -\param c A pointer to a string of proper UTF-8 character values. -\param advance_pointer If true, the source pointer will be incremented to skip the extra bytes from multibyte codepoints. -*/ -Uint32 FC_GetCodepointFromUTF8(const char** c, Uint8 advance_pointer); - -/*! -Parses the given codepoint and stores the UTF-8 bytes in 'result'. The result is NULL terminated. -\param result A memory buffer for the UTF-8 values. Must be at least 5 bytes long. -\param codepoint The Uint32 codepoint to parse (not UTF-32). -*/ -void FC_GetUTF8FromCodepoint(char* result, Uint32 codepoint); - - -// UTF-8 string operations - -/*! Allocates a new string of 'size' bytes that is already NULL-terminated. The NULL byte counts toward the size limit, as usual. Returns NULL if size is 0. */ -char* U8_alloc(unsigned int size); - -/*! Deallocates the given string. */ -void U8_free(char* string); - -/*! Allocates a copy of the given string. */ -char* U8_strdup(const char* string); - -/*! Returns the number of UTF-8 characters in the given string. */ -int U8_strlen(const char* string); - -/*! Returns the number of bytes in the UTF-8 multibyte character pointed at by 'character'. */ -int U8_charsize(const char* character); - -/*! Copies the source multibyte character into the given buffer without overrunning it. Returns 0 on failure. */ -int U8_charcpy(char* buffer, const char* source, int buffer_size); - -/*! Returns a pointer to the next UTF-8 character. */ -const char* U8_next(const char* string); - -/*! Inserts a UTF-8 string into 'string' at the given position. Use a position of -1 to append. Returns 0 when unable to insert the string. */ -int U8_strinsert(char* string, int position, const char* source, int max_bytes); - -/*! Erases the UTF-8 character at the given position, moving the subsequent characters down. */ -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); - -/*! Returns the size of the internal buffer which is used for unpacking variadic text data. This buffer is shared by all FC_Fonts. */ -unsigned int FC_GetBufferSize(void); - -/*! Changes the size of the internal buffer which is used for unpacking variadic text data. This buffer is shared by all FC_Fonts. */ -void FC_SetBufferSize(unsigned int size); - -/*! Returns the width of a single horizontal tab in multiples of the width of a space (default: 4) */ -unsigned int FC_GetTabWidth(void); - -/*! Changes the width of a horizontal tab in multiples of the width of a space (default: 4) */ -void FC_SetTabWidth(unsigned int width_in_spaces); - -void FC_SetRenderCallback(FC_Rect (*callback)(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale)); - -FC_Rect FC_DefaultRenderCallback(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale); - - -// Custom caching - -/*! Returns the number of cache levels that are active. */ -int FC_GetNumCacheLevels(FC_Font* font); - -/*! Returns the cache source texture at the given cache level. */ -FC_Image* FC_GetGlyphCacheLevel(FC_Font* font, int cache_level); - -// TODO: Specify ownership of the texture (should be shareable) -/*! Sets a cache source texture for rendering. New cache levels must be sequential. */ -Uint8 FC_SetGlyphCacheLevel(FC_Font* font, int cache_level, FC_Image* cache_texture); - -/*! 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); - -/*! Copies the stored codepoints into the given array. */ -void FC_GetCodepoints(FC_Font* font, Uint32* result); - -/*! Stores the glyph data for the given codepoint in 'result'. Returns 0 if the codepoint was not found in the cache. */ -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, ...); -FC_Rect FC_DrawColor(FC_Font* font, FC_Target* dest, float x, float y, SDL_Color color, const char* formatted_text, ...); -FC_Rect FC_DrawEffect(FC_Font* font, FC_Target* dest, float x, float y, FC_Effect effect, const char* formatted_text, ...); - -FC_Rect FC_DrawBox(FC_Font* font, FC_Target* dest, FC_Rect box, const char* formatted_text, ...); -FC_Rect FC_DrawBoxAlign(FC_Font* font, FC_Target* dest, FC_Rect box, FC_AlignEnum align, const char* formatted_text, ...); -FC_Rect FC_DrawBoxScale(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Scale scale, const char* formatted_text, ...); -FC_Rect FC_DrawBoxColor(FC_Font* font, FC_Target* dest, FC_Rect box, SDL_Color color, 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_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, ...); -FC_Rect FC_DrawColumnEffect(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_Effect effect, const char* formatted_text, ...); - - -// Getters - -FC_FilterEnum FC_GetFilterMode(FC_Font* font); -Uint16 FC_GetLineHeight(FC_Font* font); -Uint16 FC_GetHeight(FC_Font* font, const char* formatted_text, ...); -Uint16 FC_GetWidth(FC_Font* font, const char* formatted_text, ...); - -// Returns a 1-pixel wide box in front of the character in the given position (index) -FC_Rect FC_GetCharacterOffset(FC_Font* font, Uint16 position_index, int column_width, const char* formatted_text, ...); -Uint16 FC_GetColumnHeight(FC_Font* font, Uint16 width, const char* formatted_text, ...); - -int FC_GetAscent(FC_Font* font, const char* formatted_text, ...); -int FC_GetDescent(FC_Font* font, const char* formatted_text, ...); -int FC_GetBaseline(FC_Font* font); -int FC_GetSpacing(FC_Font* font); -int FC_GetLineSpacing(FC_Font* font); -Uint16 FC_GetMaxWidth(FC_Font* font); -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, ...); - -Uint8 FC_InRect(float x, float y, FC_Rect input_rect); -// Given an offset (x,y) from the text draw position (the upper-left corner), returns the character position (UTF-8 index) -Uint16 FC_GetPositionFromOffset(FC_Font* font, float x, float y, int column_width, FC_AlignEnum align, const char* formatted_text, ...); - -// Returns the number of characters in the new wrapped text written into `result`. -int FC_GetWrappedText(FC_Font* font, char* result, int max_result_size, Uint16 width, const char* formatted_text, ...); - -// Setters - -void FC_SetFilterMode(FC_Font* font, FC_FilterEnum filter); -void FC_SetSpacing(FC_Font* font, int LetterSpacing); -void FC_SetLineSpacing(FC_Font* font, int LineSpacing); -void FC_SetDefaultColor(FC_Font* font, SDL_Color color); - - -#ifdef __cplusplus -} -#endif - - - -#endif