mirror of
https://github.com/Maschell/SDL2_Playground.git
synced 2024-12-26 05:11:48 +01:00
first commit
This commit is contained in:
commit
9c189354cb
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.idea/
|
||||||
|
build/
|
||||||
|
cmake-build-debug/
|
||||||
|
cmake/
|
||||||
|
*.elf
|
||||||
|
*.rpx
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "cmake/sdl2"]
|
||||||
|
path = cmake/sdl2
|
||||||
|
url = https://github.com/aminosbh/sdl2-cmake-modules
|
40
CMakeLists.txt
Normal file
40
CMakeLists.txt
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.17)
|
||||||
|
project(SDL2_Playground)
|
||||||
|
|
||||||
|
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/GuiImage.cpp
|
||||||
|
src/gui/GuiImage.h
|
||||||
|
src/gui/sigslot.h
|
||||||
|
src/CVideo.cpp
|
||||||
|
src/CVideo.h
|
||||||
|
src/gui/GuiElement.cpp
|
||||||
|
src/gui/GuiText.cpp
|
||||||
|
src/gui/GuiText.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/gui/SDLController.h src/MainWindow.cpp src/MainWindow.h src/gui/SDLControllerJoystick.h src/gui/SDLControllerMouse.h
|
||||||
|
src/gui/SDLControllerWiiUGamepad.h
|
||||||
|
src/gui/SDLControllerWiiUProContoller.h
|
||||||
|
)
|
||||||
|
|
||||||
|
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/sdl2)
|
||||||
|
|
||||||
|
find_package(SDL2 REQUIRED)
|
||||||
|
find_package(SDL2_image REQUIRED)
|
||||||
|
find_package(SDL2_ttf REQUIRED)
|
||||||
|
find_package(SDL2_mixer REQUIRED)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME} SDL2::Main SDL2::Image SDL2::TTF SDL2::Mixer)
|
144
Makefile.wiiu
Normal file
144
Makefile.wiiu
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ifeq ($(strip $(DEVKITPRO)),)
|
||||||
|
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
|
||||||
|
endif
|
||||||
|
|
||||||
|
TOPDIR ?= $(CURDIR)
|
||||||
|
|
||||||
|
include $(DEVKITPRO)/wut/share/wut_rules
|
||||||
|
|
||||||
|
WUMS_ROOT := $(DEVKITPRO)/wums
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# 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
|
||||||
|
SOURCES := src \
|
||||||
|
src/gui
|
||||||
|
DATA := data
|
||||||
|
INCLUDES := source
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# options for code generation
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
CFLAGS := -g -Wall -O2 -ffunction-sections \
|
||||||
|
$(MACHDEP)
|
||||||
|
|
||||||
|
CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__
|
||||||
|
|
||||||
|
CXXFLAGS := $(CFLAGS) -std=c++14
|
||||||
|
|
||||||
|
ASFLAGS := -g $(ARCH)
|
||||||
|
LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map)
|
||||||
|
|
||||||
|
LIBS := -lSDL2_mixer -lSDL2 -lSDL2_image -ljpeg -lvorbisidec -logg -lmodplug -lmpg123 -lSDL2_ttf -lfreetype -lpng -lz -lbz2 -lwut
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# list of directories containing libraries, this must be the top level
|
||||||
|
# containing include and lib
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
LIBDIRS := $(PORTLIBS) $(WUT_ROOT) $(WUMS_ROOT)
|
||||||
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
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 HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||||
|
|
||||||
|
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.wiiu
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr $(BUILD) $(TARGET).rpx $(TARGET).elf
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
.PHONY: all
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
all : $(OUTPUT).rpx
|
||||||
|
|
||||||
|
|
||||||
|
$(OUTPUT).rpx : $(OUTPUT).elf
|
||||||
|
$(OUTPUT).elf : $(OFILES)
|
||||||
|
|
||||||
|
$(OFILES_SRC) : $(HFILES_BIN)
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# you need a rule like this for each extension you use as binary data
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
%.bin.o %_bin.h : %.bin
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(bin2o)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
%.o: %.s
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ $(ERROR_FILTER)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#-------------------------------------------------------------------------------
|
20
README.md
Normal file
20
README.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Building
|
||||||
|
|
||||||
|
## Windows with devkitPros version of msys2
|
||||||
|
Setup mingw:
|
||||||
|
1. Add the mingw64 repository to `/etc/pacman.conf`.
|
||||||
|
```
|
||||||
|
[mingw64]
|
||||||
|
Server = https://repo.msys2.org/mingw/x86_64
|
||||||
|
```
|
||||||
|
2. Install packages (List taken from [here](https://gist.github.com/thales17/fb2e4cff60890a51d9dddd4c6e832ad2))
|
||||||
|
```
|
||||||
|
pacman -Syu
|
||||||
|
pacman -S git mingw-w64-x86_64-toolchain mingw64/mingw-w64-x86_64-SDL2 mingw64/mingw-w64-x86_64-SDL2_mixer mingw64/mingw-w64-x86_64-SDL2_image mingw64/mingw-w64-x86_64-SDL2_ttf mingw64/mingw-w64-x86_64-SDL2_net mingw64/mingw-w64-x86_64-cmake mingw-w64-x86_64-glm make
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir build && cd build
|
||||||
|
C:\devkitPro\msys2\mingw64\bin\cmake.exe -DSDL2_PATH=C:/devkitPro/msys2/mingw64 -Wno-dev -G "Unix Makefiles" -DCMAKE_CXX_COMPILER=C:/devkitPro/msys2/mingw64/bin/g++.exe DCMAKE_C_COMPILER=C:/devkitPro/msys2/mingw64/bin/gcc.exe ../
|
||||||
|
make
|
||||||
|
```
|
1
cmake/sdl2
Submodule
1
cmake/sdl2
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit ad006a3daae65a612ed87415037e32188b81071e
|
74
src/CVideo.cpp
Normal file
74
src/CVideo.cpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include "CVideo.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_mixer.h>
|
||||||
|
|
||||||
|
CVideo::CVideo() {
|
||||||
|
SDL_Init(SDL_INIT_EVERYTHING);
|
||||||
|
|
||||||
|
auto SDLFlags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC;
|
||||||
|
|
||||||
|
//Setup window
|
||||||
|
window = SDL_CreateWindow(nullptr, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, 0);
|
||||||
|
if (!window) { return; }
|
||||||
|
renderer = SDL_CreateRenderer(window, -1, SDLFlags);
|
||||||
|
if (!renderer) { return; }
|
||||||
|
SDL_SetRenderTarget(renderer, NULL);
|
||||||
|
|
||||||
|
if (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);
|
||||||
|
}
|
||||||
|
|
||||||
|
CVideo::~CVideo() {
|
||||||
|
SDL_DestroyRenderer(renderer);
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
SDL_Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Renderer *CVideo::getRenderer() {
|
||||||
|
return renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
float CVideo::getHeight() {
|
||||||
|
int h = 0;
|
||||||
|
SDL_GetWindowSize(window, NULL, &h);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
float CVideo::getWidth() {
|
||||||
|
int w = 0;
|
||||||
|
SDL_GetWindowSize(window, &w, NULL);
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CVideo::getPixelFormat() {
|
||||||
|
return SDL_GetWindowPixelFormat(window);
|
||||||
|
}
|
36
src/CVideo.h
Normal file
36
src/CVideo.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
#include <SDL2/SDL_render.h>
|
||||||
|
|
||||||
|
class CVideo {
|
||||||
|
public:
|
||||||
|
CVideo();
|
||||||
|
|
||||||
|
virtual ~CVideo();
|
||||||
|
|
||||||
|
SDL_Renderer *getRenderer();
|
||||||
|
|
||||||
|
float getHeight();
|
||||||
|
float getWidth();
|
||||||
|
|
||||||
|
unsigned int getPixelFormat();
|
||||||
|
|
||||||
|
private:
|
||||||
|
SDL_Window *window = NULL;
|
||||||
|
SDL_Renderer *renderer = NULL;
|
||||||
|
};
|
75
src/MainWindow.cpp
Normal file
75
src/MainWindow.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#include "MainWindow.h"
|
||||||
|
|
||||||
|
MainWindow::~MainWindow() {
|
||||||
|
delete label;;
|
||||||
|
delete touchTrigger;;
|
||||||
|
delete sound;;
|
||||||
|
delete image;;
|
||||||
|
delete image2;;
|
||||||
|
delete image3;;
|
||||||
|
delete image4;;
|
||||||
|
delete image5;;
|
||||||
|
delete image;;
|
||||||
|
delete label;;
|
||||||
|
delete button;;
|
||||||
|
delete bgMusic;;
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::MainWindow(int32_t w, int32_t h) : GuiFrame(w, h) {
|
||||||
|
#if defined _WIN32
|
||||||
|
auto picture_path = "test.png";
|
||||||
|
auto font_path = "FreeSans.ttf";
|
||||||
|
auto bgMusic_path = "bgMusic.ogg";
|
||||||
|
auto music_click = "button_click.mp3";
|
||||||
|
#else
|
||||||
|
auto picture_path = "fs:/vol/external01/test.png";
|
||||||
|
auto font_path = "fs:/vol/external01/FreeSans.ttf";
|
||||||
|
auto bgMusic_path = "fs:/vol/external01/bgMusic.ogg";
|
||||||
|
auto music_click = "fs:/vol/external01/button_click.mp3";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TTF_Init();
|
||||||
|
TTF_Font *font;
|
||||||
|
font = TTF_OpenFont(font_path, 35);
|
||||||
|
|
||||||
|
label = new GuiText("This is a test AVAVAVVAVA", 25, {255, 255, 0, 255}, font);
|
||||||
|
|
||||||
|
bgMusic = new GuiSound(bgMusic_path);
|
||||||
|
bgMusic->SetLoop(true);
|
||||||
|
bgMusic->Play();
|
||||||
|
|
||||||
|
image = new GuiImage(picture_path);
|
||||||
|
image2 = new GuiImage(picture_path);
|
||||||
|
image3 = new GuiImage(picture_path);
|
||||||
|
image4 = new GuiImage(picture_path);
|
||||||
|
image5 = new GuiImage(picture_path);
|
||||||
|
|
||||||
|
button = new GuiButton(image5->getWidth(), image5->getHeight());
|
||||||
|
|
||||||
|
this->setAlignment(ALIGN_TOP_LEFT);
|
||||||
|
this->append(button);
|
||||||
|
this->append(image);
|
||||||
|
this->append(image2);
|
||||||
|
this->append(image3);
|
||||||
|
this->append(image4);
|
||||||
|
|
||||||
|
image->setAlignment(ALIGN_TOP_LEFT);
|
||||||
|
image2->setAlignment(ALIGN_TOP_RIGHT);
|
||||||
|
image3->setAlignment(ALIGN_BOTTOM | ALIGN_LEFT);
|
||||||
|
image4->setAlignment(ALIGN_BOTTOM | ALIGN_RIGHT);
|
||||||
|
|
||||||
|
button->setAlignment(ALIGN_CENTERED);
|
||||||
|
button->setImage(image5);
|
||||||
|
|
||||||
|
sound = new GuiSound(music_click);
|
||||||
|
|
||||||
|
touchTrigger = new GuiTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::TOUCHED);
|
||||||
|
touchTrigger = new GuiTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::TOUCHED);
|
||||||
|
button->setTrigger(touchTrigger);
|
||||||
|
button->setEffectGrow();
|
||||||
|
label->setAlignment(ALIGN_CENTERED);
|
||||||
|
button->setLabel(label);
|
||||||
|
button->setSoundClick(sound);
|
||||||
|
|
||||||
|
button->clicked.connect(this, &MainWindow::test);
|
||||||
|
}
|
29
src/MainWindow.h
Normal file
29
src/MainWindow.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "gui/GuiFrame.h"
|
||||||
|
#include "gui/GuiButton.h"
|
||||||
|
#include "logger.h"
|
||||||
|
|
||||||
|
class MainWindow : public GuiFrame, public sigslot::has_slots<> {
|
||||||
|
public:
|
||||||
|
void test(GuiButton *, const GuiController *, GuiTrigger *) {
|
||||||
|
DEBUG_FUNCTION_LINE("Hello, you have clicked the button");
|
||||||
|
}
|
||||||
|
|
||||||
|
~MainWindow();
|
||||||
|
|
||||||
|
MainWindow(int32_t w, int32_t h);
|
||||||
|
|
||||||
|
private:
|
||||||
|
GuiText *label = nullptr;
|
||||||
|
GuiTrigger *touchTrigger = nullptr;
|
||||||
|
GuiSound *sound = nullptr;
|
||||||
|
GuiImage *image = nullptr;
|
||||||
|
GuiImage *image2 = nullptr;
|
||||||
|
GuiImage *image3 = nullptr;
|
||||||
|
GuiImage *image4 = nullptr;
|
||||||
|
GuiImage *image5 = nullptr;
|
||||||
|
GuiButton *button = nullptr;
|
||||||
|
GuiSound *bgMusic = nullptr;
|
||||||
|
};
|
275
src/gui/GuiButton.cpp
Normal file
275
src/gui/GuiButton.cpp
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include <iostream>
|
||||||
|
#include "GuiButton.h"
|
||||||
|
#include "GuiController.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the GuiButton class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GuiButton::GuiButton(float w, float h) {
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
|
image = NULL;
|
||||||
|
imageOver = NULL;
|
||||||
|
imageHold = NULL;
|
||||||
|
imageClick = NULL;
|
||||||
|
icon = NULL;
|
||||||
|
iconOver = NULL;
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < 4; i++) {
|
||||||
|
label[i] = NULL;
|
||||||
|
labelOver[i] = NULL;
|
||||||
|
labelHold[i] = NULL;
|
||||||
|
labelClick[i] = NULL;
|
||||||
|
}
|
||||||
|
for (int32_t i = 0; i < iMaxGuiTriggers; i++) {
|
||||||
|
trigger[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
soundOver = NULL;
|
||||||
|
soundHold = NULL;
|
||||||
|
soundClick = NULL;
|
||||||
|
clickedTrigger = NULL;
|
||||||
|
heldTrigger = NULL;
|
||||||
|
selectable = true;
|
||||||
|
holdable = false;
|
||||||
|
clickable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor for the GuiButton class.
|
||||||
|
*/
|
||||||
|
GuiButton::~GuiButton() {
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (int32_t i = 0; i < iMaxGuiTriggers; i++) {
|
||||||
|
if (!trigger[i]) {
|
||||||
|
trigger[i] = t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiButton::resetState(void) {
|
||||||
|
clickedTrigger = NULL;
|
||||||
|
heldTrigger = NULL;
|
||||||
|
GuiElement::resetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw the button on screen
|
||||||
|
*/
|
||||||
|
void GuiButton::draw(CVideo *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 (int32_t i = 0; i < iMaxGuiTriggers; i++) {
|
||||||
|
if (!trigger[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// button triggers
|
||||||
|
if (clickable) {
|
||||||
|
int32_t isClicked = trigger[i]->clicked(c);
|
||||||
|
if (!clickedTrigger && (isClicked != GuiTrigger::CLICKED_NONE)
|
||||||
|
&& (trigger[i]->isClickEverywhere() || (isStateSet(STATE_SELECTED | STATE_OVER, c->chanIdx) && trigger[i]->isSelectionClickEverywhere()) || this->isInside(c->data.x, c->data.y))) {
|
||||||
|
if (soundClick) {
|
||||||
|
soundClick->Play();
|
||||||
|
}
|
||||||
|
|
||||||
|
clickedTrigger = trigger[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, trigger[i]);
|
||||||
|
} else if ((isStateSet(STATE_CLICKED, c->chanIdx) || isStateSet(STATE_CLICKED_TOUCH, c->chanIdx)) && (clickedTrigger == trigger[i]) && !isStateSet(STATE_HELD, c->chanIdx) && !trigger[i]->held(c) &&
|
||||||
|
((isClicked == GuiTrigger::CLICKED_NONE) || trigger[i]->released(c))) {
|
||||||
|
if ((isStateSet(STATE_CLICKED_TOUCH, c->chanIdx) && this->isInside(c->data.x, c->data.y)) || (isStateSet(STATE_CLICKED, c->chanIdx))) {
|
||||||
|
clickedTrigger = NULL;
|
||||||
|
clearState(STATE_CLICKED, c->chanIdx);
|
||||||
|
released(this, c, trigger[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (holdable) {
|
||||||
|
bool isHeld = trigger[i]->held(c);
|
||||||
|
|
||||||
|
if ((!heldTrigger || heldTrigger == trigger[i]) && isHeld
|
||||||
|
&& (trigger[i]->isHoldEverywhere() || (isStateSet(STATE_SELECTED | STATE_OVER, c->chanIdx) && trigger[i]->isSelectionClickEverywhere()) || this->isInside(c->data.x, c->data.y))) {
|
||||||
|
heldTrigger = trigger[i];
|
||||||
|
|
||||||
|
if (!isStateSet(STATE_HELD, c->chanIdx)) {
|
||||||
|
setState(STATE_HELD, c->chanIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
held(this, c, trigger[i]);
|
||||||
|
} else if (isStateSet(STATE_HELD, c->chanIdx) && (heldTrigger == trigger[i]) && (!isHeld || trigger[i]->released(c))) {
|
||||||
|
//! click is removed at this point and converted to held
|
||||||
|
if (clickedTrigger == trigger[i]) {
|
||||||
|
clickedTrigger = NULL;
|
||||||
|
clearState(STATE_CLICKED, c->chanIdx);
|
||||||
|
}
|
||||||
|
heldTrigger = NULL;
|
||||||
|
clearState(STATE_HELD, c->chanIdx);
|
||||||
|
released(this, c, trigger[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
129
src/gui/GuiButton.h
Normal file
129
src/gui/GuiButton.h
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
#include "GuiElement.h"
|
||||||
|
#include "GuiImage.h"
|
||||||
|
#include "GuiText.h"
|
||||||
|
#include "GuiSound.h"
|
||||||
|
#include "GuiTrigger.h"
|
||||||
|
#include "../CVideo.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);
|
||||||
|
|
||||||
|
//!Constantly called to draw the GuiButton
|
||||||
|
void draw(CVideo *video);
|
||||||
|
|
||||||
|
//!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);
|
||||||
|
|
||||||
|
sigslot::signal2<GuiButton *, const GuiController *> selected;
|
||||||
|
sigslot::signal2<GuiButton *, const GuiController *> deSelected;
|
||||||
|
sigslot::signal2<GuiButton *, const GuiController *> pointedOn;
|
||||||
|
sigslot::signal2<GuiButton *, const GuiController *> pointedOff;
|
||||||
|
sigslot::signal3<GuiButton *, const GuiController *, GuiTrigger *> clicked;
|
||||||
|
sigslot::signal3<GuiButton *, const GuiController *, GuiTrigger *> held;
|
||||||
|
sigslot::signal3<GuiButton *, const GuiController *, GuiTrigger *> 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;
|
||||||
|
};
|
68
src/gui/GuiController.h
Normal file
68
src/gui/GuiController.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
|
||||||
|
int32_t chan;
|
||||||
|
int32_t chanIdx;
|
||||||
|
PadData data;
|
||||||
|
PadData lastData;
|
||||||
|
};
|
290
src/gui/GuiElement.cpp
Normal file
290
src/gui/GuiElement.cpp
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#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 (int32_t i = 0; i < 5; i++) {
|
||||||
|
state[i] = STATE_DEFAULT;
|
||||||
|
}
|
||||||
|
stateChan = -1;
|
||||||
|
parentElement = NULL;
|
||||||
|
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(int32_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(int32_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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
604
src/gui/GuiElement.h
Normal file
604
src/gui/GuiElement.h
Normal file
@ -0,0 +1,604 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include "sigslot.h"
|
||||||
|
|
||||||
|
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 CVideo;
|
||||||
|
|
||||||
|
//!Primary GUI class. Most other classes inherit from this class.
|
||||||
|
class GuiElement {
|
||||||
|
public:
|
||||||
|
//!Constructor
|
||||||
|
GuiElement();
|
||||||
|
|
||||||
|
//!Destructor
|
||||||
|
virtual ~GuiElement() {}
|
||||||
|
|
||||||
|
//!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(void) {
|
||||||
|
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(void) {
|
||||||
|
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(int32_t s, int32_t c = -1) {
|
||||||
|
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(int32_t s, int32_t c = -1) {
|
||||||
|
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 bool isStateSet(int32_t s, int32_t c = -1) const {
|
||||||
|
if (c >= 0 && c < 5) {
|
||||||
|
return (state[c] & s) != 0;
|
||||||
|
} else {
|
||||||
|
for (int32_t i = 0; i < 5; i++) {
|
||||||
|
if ((state[i] & s) != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//!Gets the element's current state
|
||||||
|
//!\return state
|
||||||
|
virtual int32_t getState(int32_t c = 0) {
|
||||||
|
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 (int32_t i = 0; i < 5; 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(int32_t e, int32_t a, int32_t t = 0);
|
||||||
|
|
||||||
|
//!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(int32_t e, int32_t a, int32_t t = 0);
|
||||||
|
|
||||||
|
//!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) {
|
||||||
|
return (x > (this->getCenterX() - getScaleX() * getWidth() * 0.5f)
|
||||||
|
&& x < (this->getCenterX() + getScaleX() * getWidth() * 0.5f)
|
||||||
|
&& y > (this->getCenterY() - getScaleY() * getHeight() * 0.5f)
|
||||||
|
&& y < (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(CVideo *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<GuiElement *, bool> visibleChanged;
|
||||||
|
sigslot::signal3<GuiElement *, int32_t, int32_t> stateChanged;
|
||||||
|
sigslot::signal1<GuiElement *> 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%)
|
||||||
|
int32_t alignment; //!< Horizontal element alignment, respective to parent element
|
||||||
|
int32_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)
|
||||||
|
int32_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
|
||||||
|
int32_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
|
||||||
|
};
|
234
src/gui/GuiFrame.cpp
Normal file
234
src/gui/GuiFrame.cpp
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#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 == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(e);
|
||||||
|
mutex.lock();
|
||||||
|
elements.push_back(e);
|
||||||
|
e->setParent(this);
|
||||||
|
mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::insert(GuiElement *e, uint32_t index) {
|
||||||
|
if (e == NULL || (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();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::close() {
|
||||||
|
//Application::instance()->pushForDelete(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::dimBackground(bool d) {
|
||||||
|
dim = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiElement *GuiFrame::getGuiElementAt(uint32_t index) const {
|
||||||
|
if (index >= elements.size()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return elements[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t GuiFrame::getSize() {
|
||||||
|
return elements.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::resetState() {
|
||||||
|
GuiElement::resetState();
|
||||||
|
|
||||||
|
mutex.lock();
|
||||||
|
for (uint32_t i = 0; i < elements.size(); ++i) {
|
||||||
|
elements[i]->resetState();
|
||||||
|
}
|
||||||
|
mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::setState(int32_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(int32_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 (uint32_t i = 0; i < elements.size(); ++i) {
|
||||||
|
elements[i]->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(CVideo *v) {
|
||||||
|
if (!this->isVisible() && parentElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parentElement && dim == true) {
|
||||||
|
//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();
|
||||||
|
}
|
123
src/gui/GuiFrame.h
Normal file
123
src/gui/GuiFrame.h
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <mutex>
|
||||||
|
#include "GuiElement.h"
|
||||||
|
#include "sigslot.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
|
||||||
|
virtual ~GuiFrame();
|
||||||
|
|
||||||
|
//!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);
|
||||||
|
|
||||||
|
//!Resets the window's state to STATE_DEFAULT
|
||||||
|
void resetState();
|
||||||
|
|
||||||
|
//!Sets the window's state
|
||||||
|
//!\param s State
|
||||||
|
void setState(int32_t s, int32_t c = -1);
|
||||||
|
|
||||||
|
void clearState(int32_t s, int32_t c = -1);
|
||||||
|
|
||||||
|
//!Gets the index of the GuiElement inside the window that is currently selected
|
||||||
|
//!\return index of selected GuiElement
|
||||||
|
int32_t getSelected();
|
||||||
|
|
||||||
|
//!Dim the Window's background
|
||||||
|
void dimBackground(bool d);
|
||||||
|
|
||||||
|
//!Draws all the elements in this GuiFrame
|
||||||
|
void draw(CVideo *v);
|
||||||
|
|
||||||
|
//!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);
|
||||||
|
|
||||||
|
//!virtual Close Window - this will put the object on the delete queue in MainWindow
|
||||||
|
virtual void close();
|
||||||
|
|
||||||
|
//!virtual show window function
|
||||||
|
virtual void show() {}
|
||||||
|
|
||||||
|
//!virtual hide window function
|
||||||
|
virtual void hide() {}
|
||||||
|
|
||||||
|
//!virtual enter main loop function (blocking)
|
||||||
|
virtual void exec() {}
|
||||||
|
|
||||||
|
//!virtual updateEffects which is called by the main loop
|
||||||
|
virtual void updateEffects();
|
||||||
|
|
||||||
|
//!virtual process which is called by the main loop
|
||||||
|
virtual void process();
|
||||||
|
|
||||||
|
//! Signals
|
||||||
|
//! On Closing
|
||||||
|
sigslot::signal1<GuiFrame *> closing;
|
||||||
|
protected:
|
||||||
|
bool dim; //! Enable/disable dim of a window only
|
||||||
|
GuiFrame *parent; //!< Parent Window
|
||||||
|
std::vector<GuiElement *> elements; //!< Contains all elements within the GuiFrame
|
||||||
|
std::recursive_mutex mutex;
|
||||||
|
};
|
87
src/gui/GuiImage.cpp
Normal file
87
src/gui/GuiImage.cpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include <SDL2/SDL_image.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include "GuiImage.h"
|
||||||
|
#include "../CVideo.h"
|
||||||
|
#include "../logger.h"
|
||||||
|
|
||||||
|
GuiImage::GuiImage(const std::string& path) {
|
||||||
|
imgSurface = IMG_Load( path.c_str() );
|
||||||
|
|
||||||
|
this->width = imgSurface->w;
|
||||||
|
this->height = imgSurface->h;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor for the GuiImage class.
|
||||||
|
*/
|
||||||
|
GuiImage::~GuiImage() {
|
||||||
|
if(imgSurface){
|
||||||
|
SDL_FreeSurface(imgSurface);
|
||||||
|
imgSurface = NULL;
|
||||||
|
}
|
||||||
|
if(texture){
|
||||||
|
SDL_DestroyTexture(texture);
|
||||||
|
texture = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImage::process(){
|
||||||
|
auto res = this->getAngle() + 1;
|
||||||
|
if(res > 360){
|
||||||
|
res =0;
|
||||||
|
}
|
||||||
|
|
||||||
|
setAngle(res);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImage::draw(CVideo *pVideo) {
|
||||||
|
if (!this->isVisible()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(texture == NULL){
|
||||||
|
SDL_Surface * optimizedSurface = SDL_ConvertSurfaceFormat( imgSurface, pVideo->getPixelFormat(), 0 );
|
||||||
|
if(optimizedSurface != NULL){
|
||||||
|
SDL_FreeSurface(imgSurface);
|
||||||
|
imgSurface = optimizedSurface;
|
||||||
|
DEBUG_FUNCTION_LINE("Optimized surface");
|
||||||
|
}
|
||||||
|
texture = SDL_CreateTextureFromSurface(pVideo->getRenderer(), imgSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
float currScaleX = getScaleX();
|
||||||
|
float currScaleY = getScaleY();
|
||||||
|
|
||||||
|
SDL_Rect rect;
|
||||||
|
rect.x = getLeft();
|
||||||
|
rect.y = getTop();
|
||||||
|
rect.w = currScaleX * getWidth();
|
||||||
|
rect.h = currScaleY * getHeight();
|
||||||
|
|
||||||
|
|
||||||
|
// copy the texture to the rendering context
|
||||||
|
if(getAngle() == 0){
|
||||||
|
SDL_RenderCopy(pVideo->getRenderer(), texture, NULL, &rect);
|
||||||
|
}else{
|
||||||
|
SDL_RenderCopyEx(pVideo->getRenderer(), texture, NULL, &rect, getAngle(), NULL, SDL_FLIP_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
42
src/gui/GuiImage.h
Normal file
42
src/gui/GuiImage.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL2/SDL_render.h>
|
||||||
|
#include "GuiElement.h"
|
||||||
|
#include "glm/glm.hpp"
|
||||||
|
|
||||||
|
//!Display, manage, and manipulate images in the GUI
|
||||||
|
class GuiImage : public GuiElement {
|
||||||
|
public:
|
||||||
|
//!\overload
|
||||||
|
//!\param img Pointer to GuiImageData element
|
||||||
|
GuiImage(const std::string &path);
|
||||||
|
|
||||||
|
//!Destructor
|
||||||
|
virtual ~GuiImage();
|
||||||
|
|
||||||
|
//!Constantly called to draw the image
|
||||||
|
void draw(CVideo *pVideo);
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SDL_Surface *imgSurface = nullptr;
|
||||||
|
SDL_Texture *texture = nullptr;
|
||||||
|
|
||||||
|
virtual void process();
|
||||||
|
};
|
78
src/gui/GuiSound.cpp
Normal file
78
src/gui/GuiSound.cpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include "GuiSound.h"
|
||||||
|
#include "../logger.h"
|
||||||
|
|
||||||
|
GuiSound::GuiSound(const char *filepath) {
|
||||||
|
Load(filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiSound::~GuiSound() {
|
||||||
|
if(music){
|
||||||
|
Mix_FreeChunk(music);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool GuiSound::Load(const char *filepath) {
|
||||||
|
music = Mix_LoadWAV(filepath);
|
||||||
|
DEBUG_FUNCTION_LINE("load %s %d", filepath, music);
|
||||||
|
return music != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void GuiSound::Play() {
|
||||||
|
playedOn = Mix_PlayChannel(-1,music, loops);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSound::Stop() {
|
||||||
|
Pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSound::Pause() {
|
||||||
|
Mix_HaltChannel(playedOn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSound::Resume() {
|
||||||
|
Play();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GuiSound::IsPlaying() {
|
||||||
|
if(playedOn == -1){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Mix_Playing(playedOn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSound::SetVolume(uint32_t vol) {
|
||||||
|
if(music != nullptr){
|
||||||
|
Mix_VolumeChunk(music, vol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSound::SetLoop(bool l) {
|
||||||
|
if(l){
|
||||||
|
loops = -1;
|
||||||
|
}else{
|
||||||
|
loops = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSound::Rewind() {
|
||||||
|
Stop();
|
||||||
|
}
|
65
src/gui/GuiSound.h
Normal file
65
src/gui/GuiSound.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "GuiElement.h"
|
||||||
|
#include <SDL2/SDL_mixer.h>
|
||||||
|
|
||||||
|
//!Sound conversion and playback. A wrapper for other sound libraries - ASND, libmad, ltremor, etc
|
||||||
|
class GuiSound : public GuiElement {
|
||||||
|
public:
|
||||||
|
//!Constructor
|
||||||
|
//!\param sound Pointer to the sound data
|
||||||
|
//!\param filesize Length of sound data
|
||||||
|
GuiSound(const char *filepath);
|
||||||
|
|
||||||
|
//!Destructor
|
||||||
|
virtual ~GuiSound();
|
||||||
|
|
||||||
|
//!Load a file and replace the old one
|
||||||
|
bool Load(const char *filepath);
|
||||||
|
|
||||||
|
//!Start sound playback
|
||||||
|
void Play();
|
||||||
|
|
||||||
|
//!Stop sound playback
|
||||||
|
void Stop();
|
||||||
|
|
||||||
|
//!Pause sound playback
|
||||||
|
void Pause();
|
||||||
|
|
||||||
|
//!Resume sound playback
|
||||||
|
void Resume();
|
||||||
|
|
||||||
|
//!Checks if the sound is currently playing
|
||||||
|
//!\return true if sound is playing, false otherwise
|
||||||
|
bool IsPlaying();
|
||||||
|
|
||||||
|
//!Rewind the music
|
||||||
|
void Rewind();
|
||||||
|
|
||||||
|
//!Set sound volume
|
||||||
|
//!\param v Sound volume (0-100)
|
||||||
|
void SetVolume(uint32_t v);
|
||||||
|
|
||||||
|
//!\param l Loop (true to loop)
|
||||||
|
void SetLoop(bool l);
|
||||||
|
|
||||||
|
Mix_Chunk *music;
|
||||||
|
int32_t loops = 0;
|
||||||
|
int32_t playedOn = -1;
|
||||||
|
};
|
90
src/gui/GuiText.cpp
Normal file
90
src/gui/GuiText.cpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <SDl2/SDL_surface.h>
|
||||||
|
#include "GuiText.h"
|
||||||
|
#include "../CVideo.h"
|
||||||
|
#include "../logger.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the GuiText class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GuiText::GuiText(const std::string& text, int32_t s, SDL_Color c, TTF_Font* gFont) {
|
||||||
|
//Render text surface
|
||||||
|
textSurface = TTF_RenderText_Solid( gFont, text.c_str(), c );
|
||||||
|
if( textSurface == NULL ) {
|
||||||
|
DEBUG_FUNCTION_LINE( "Unable to render text surface! SDL_ttf Error: %s\n", TTF_GetError() );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiText::~GuiText(){
|
||||||
|
if(textSurface){
|
||||||
|
SDL_FreeSurface( textSurface );
|
||||||
|
textSurface = nullptr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(textTexture){
|
||||||
|
SDL_DestroyTexture( textTexture );
|
||||||
|
textTexture = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw the text on screen
|
||||||
|
*/
|
||||||
|
void GuiText::draw(CVideo *pVideo) {
|
||||||
|
if (!this->isVisible()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(textTexture == NULL){
|
||||||
|
//Create texture from surface pixels
|
||||||
|
textTexture = SDL_CreateTextureFromSurface( pVideo->getRenderer(), textSurface );
|
||||||
|
if( textTexture == NULL ) {
|
||||||
|
DEBUG_FUNCTION_LINE( "Unable to create texture from rendered text! SDL Error: %s\n", SDL_GetError() );
|
||||||
|
}else{
|
||||||
|
width = textSurface->w;
|
||||||
|
height = textSurface->h;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(textSurface){
|
||||||
|
SDL_FreeSurface( textSurface );
|
||||||
|
textSurface = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!textTexture){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Rect rect;
|
||||||
|
rect.x = getLeft();
|
||||||
|
rect.y = getTop();
|
||||||
|
rect.w = getScaleX() * getWidth();
|
||||||
|
rect.h = getScaleY() * getHeight();
|
||||||
|
|
||||||
|
// copy the texture to the rendering context
|
||||||
|
if(getAngle() == 0){
|
||||||
|
SDL_RenderCopy(pVideo->getRenderer(), textTexture, NULL, &rect);
|
||||||
|
}else{
|
||||||
|
SDL_RenderCopyEx(pVideo->getRenderer(), textTexture, NULL, &rect, getAngle(), NULL, SDL_FLIP_NONE);
|
||||||
|
}
|
||||||
|
}
|
40
src/gui/GuiText.h
Normal file
40
src/gui/GuiText.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "GuiElement.h"
|
||||||
|
#include <mutex>
|
||||||
|
#include <glm/vec4.hpp>
|
||||||
|
#include <SDL2/SDL_ttf.h>
|
||||||
|
|
||||||
|
|
||||||
|
//!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, int32_t s, SDL_Color c, TTF_Font *gFont);
|
||||||
|
virtual ~GuiText();
|
||||||
|
|
||||||
|
virtual void draw(CVideo *pVideo);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SDL_Surface *textSurface = nullptr;
|
||||||
|
SDL_Texture *textTexture = nullptr;
|
||||||
|
};
|
145
src/gui/GuiTrigger.cpp
Normal file
145
src/gui/GuiTrigger.cpp
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include <iostream>
|
||||||
|
#include "GuiElement.h"
|
||||||
|
#include "GuiController.h"
|
||||||
|
#include "GuiTrigger.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() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
132
src/gui/GuiTrigger.h
Normal file
132
src/gui/GuiTrigger.h
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
class GuiController;
|
||||||
|
|
||||||
|
//!Menu input trigger management. Determine if action is neccessary 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isClickEverywhere() const {
|
||||||
|
return bClickEverywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isHoldEverywhere() const {
|
||||||
|
return bHoldEverywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
60
src/gui/SDLController.h
Normal file
60
src/gui/SDLController.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL2/SDL_mouse.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <SDL2/SDL_events.h>
|
||||||
|
#include "GuiController.h"
|
||||||
|
#include "../logger.h"
|
||||||
|
|
||||||
|
#define printButton(chan, x) if(data.buttons_d & x) DEBUG_FUNCTION_LINE("Controller #%d %s", chan, #x)
|
||||||
|
|
||||||
|
class SDLController : public GuiController {
|
||||||
|
public:
|
||||||
|
SDLController(int32_t channel) : GuiController(channel) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool update(SDL_Event *e) = 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
58
src/gui/SDLControllerJoystick.h
Normal file
58
src/gui/SDLControllerJoystick.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class SDLControllerJoystick : public SDLController {
|
||||||
|
public:
|
||||||
|
SDLControllerJoystick(int32_t channel, SDL_JoystickID joystickId) : SDLController(channel) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool update(SDL_Event *e) 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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
26
src/gui/SDLControllerMouse.h
Normal file
26
src/gui/SDLControllerMouse.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class SDLControllerMouse: public SDLController {
|
||||||
|
public:
|
||||||
|
SDLControllerMouse(int32_t channel) : SDLController(channel) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool update(SDL_Event *e) override {
|
||||||
|
if (e->type == SDL_MOUSEMOTION) {
|
||||||
|
data.y = e->motion.y;
|
||||||
|
data.x = e->motion.x;
|
||||||
|
data.validPointer = true;
|
||||||
|
} else if (e->type == SDL_MOUSEBUTTONDOWN && e->button.button == SDL_BUTTON_LEFT) {
|
||||||
|
data.buttons_h |= GuiTrigger::TOUCHED;
|
||||||
|
} else if (e->type == SDL_MOUSEBUTTONUP && e->button.button == SDL_BUTTON_LEFT) {
|
||||||
|
data.buttons_h &= ~GuiTrigger::TOUCHED;
|
||||||
|
}else{
|
||||||
|
DEBUG_FUNCTION_LINE("Unknown event");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
51
src/gui/SDLControllerWiiUGamepad.h
Normal file
51
src/gui/SDLControllerWiiUGamepad.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#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:
|
||||||
|
SDLControllerWiiUGamepad(int32_t channel) : SDLController(channel) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool update(SDL_Event *e) override {
|
||||||
|
if (e->type == SDL_FINGERMOTION) {
|
||||||
|
data.y = e->tfinger.y * 720;
|
||||||
|
data.x = e->tfinger.x * 1280;;
|
||||||
|
data.validPointer = true;
|
||||||
|
} else if (e->type == SDL_FINGERUP) {
|
||||||
|
data.validPointer = false;
|
||||||
|
data.buttons_h &= ~GuiTrigger::TOUCHED;
|
||||||
|
} else if (e->type == SDL_FINGERDOWN) {
|
||||||
|
data.validPointer = true;
|
||||||
|
data.buttons_h |= GuiTrigger::TOUCHED;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
11
src/gui/SDLControllerWiiUProContoller.h
Normal file
11
src/gui/SDLControllerWiiUProContoller.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SDLControllerWiiUGamepad.h"
|
||||||
|
|
||||||
|
class SDLControllerWiiUProContoller : public SDLControllerWiiUGamepad {
|
||||||
|
public:
|
||||||
|
SDLControllerWiiUProContoller(int32_t channel) : SDLControllerWiiUGamepad(channel){
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
106
src/gui/SDLControllerXboxOne.h
Normal file
106
src/gui/SDLControllerXboxOne.h
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SDLController.h"
|
||||||
|
|
||||||
|
static GuiTrigger::eButtons xbox_button_map[] =
|
||||||
|
{
|
||||||
|
GuiTrigger::BUTTON_A,
|
||||||
|
GuiTrigger::BUTTON_B,
|
||||||
|
GuiTrigger::BUTTON_X,
|
||||||
|
GuiTrigger::BUTTON_Y,
|
||||||
|
GuiTrigger::BUTTON_L,
|
||||||
|
GuiTrigger::BUTTON_R,
|
||||||
|
GuiTrigger::BUTTON_MINUS,
|
||||||
|
GuiTrigger::BUTTON_PLUS,
|
||||||
|
GuiTrigger::BUTTON_STICK_L,
|
||||||
|
GuiTrigger::BUTTON_STICK_R,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define getDigitalAxis(axis, targetAxis, value, hold, first, second) \
|
||||||
|
if(axis == targetAxis){ \
|
||||||
|
if (value < 0x4000 && value > -0x4000){ \
|
||||||
|
hold &= ~first; \
|
||||||
|
hold &= ~second; \
|
||||||
|
}else if(value < -0x4000){ \
|
||||||
|
hold |= first; \
|
||||||
|
hold &= ~second; \
|
||||||
|
}else if(value > 0x4000){ \
|
||||||
|
hold |= second; \
|
||||||
|
hold &= ~first; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define getDigitalTrigger(axis, targetAxis, value, hold, first) \
|
||||||
|
if(axis == targetAxis){ \
|
||||||
|
if(value > 0){ \
|
||||||
|
hold |= first; \
|
||||||
|
}else{ \
|
||||||
|
hold &= ~first; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
|
||||||
|
|
||||||
|
class SDLControllerXboxOne : public SDLController {
|
||||||
|
public:
|
||||||
|
SDLControllerXboxOne(int32_t channel) : SDLController(channel) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool update(SDL_Event *e) 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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
2433
src/gui/sigslot.h
Normal file
2433
src/gui/sigslot.h
Normal file
File diff suppressed because it is too large
Load Diff
32
src/logger.h
Normal file
32
src/logger.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __WIIU__
|
||||||
|
#include <whb/log.h>
|
||||||
|
#include <whb/log_cafe.h>
|
||||||
|
#include <whb/log_udp.h>
|
||||||
|
|
||||||
|
#include <whb/log.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __FILENAME_X__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
|
||||||
|
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILENAME_X__)
|
||||||
|
|
||||||
|
#ifdef __WIIU__
|
||||||
|
#define DEBUG_FUNCTION_LINE(FMT, ARGS...)do { \
|
||||||
|
WHBLogPrintf("[%23s]%30s@L%04d: " FMT "",__FILENAME__,__FUNCTION__, __LINE__, ## ARGS); \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define DEBUG_FUNCTION_LINE(FMT, ARGS...)do { \
|
||||||
|
printf("[%23s]%30s@L%04d: " FMT "\n",__FILENAME__,__FUNCTION__, __LINE__, ## ARGS); \
|
||||||
|
} while (0)
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
237
src/main.cpp
Normal file
237
src/main.cpp
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include "CVideo.h"
|
||||||
|
#include "gui/GuiFrame.h"
|
||||||
|
#include "gui/GuiImage.h"
|
||||||
|
#include "gui/GuiButton.h"
|
||||||
|
#include "gui/GuiController.h"
|
||||||
|
#include "gui/SDLController.h"
|
||||||
|
#include "MainWindow.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "gui/SDLControllerJoystick.h"
|
||||||
|
#include "gui/SDLControllerMouse.h"
|
||||||
|
#include "gui/SDLControllerWiiUGamepad.h"
|
||||||
|
#include "gui/SDLControllerXboxOne.h"
|
||||||
|
#include "gui/SDLControllerWiiUProContoller.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#if defined _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __WIIU__
|
||||||
|
#include <whb/log.h>
|
||||||
|
#include <whb/log_cafe.h>
|
||||||
|
#include <whb/log_udp.h>
|
||||||
|
#include <proc_ui/procui.h>
|
||||||
|
bool CheckRunning(){
|
||||||
|
switch(ProcUIProcessMessages(true))
|
||||||
|
{
|
||||||
|
case PROCUI_STATUS_EXITING:
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case PROCUI_STATUS_RELEASE_FOREGROUND:
|
||||||
|
{
|
||||||
|
ProcUIDrawDoneRelease();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PROCUI_STATUS_IN_FOREGROUND:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PROCUI_STATUS_IN_BACKGROUND:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void proccessEvents();
|
||||||
|
|
||||||
|
bool addJoystick(int deviceId, std::map<GuiTrigger::eChannels, SDLController *> &controllerList, std::map<int32_t, GuiTrigger::eChannels>& map);
|
||||||
|
|
||||||
|
GuiTrigger::eChannels increaseChannel(GuiTrigger::eChannels channel);
|
||||||
|
|
||||||
|
void removeJoystick(int32_t which, std::map<GuiTrigger::eChannels, SDLController *> &controllerList, std::map<int32_t, GuiTrigger::eChannels>& joystickToChannel);
|
||||||
|
|
||||||
|
int main(int argc, char *args[]) {
|
||||||
|
CVideo *video = new CVideo();
|
||||||
|
|
||||||
|
#if defined _WIN32
|
||||||
|
// Create the Console
|
||||||
|
AllocConsole();
|
||||||
|
|
||||||
|
// Create Console Output Handle
|
||||||
|
HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
int hCrt = _open_osfhandle((intptr_t) handle_out, _O_TEXT);
|
||||||
|
FILE *hf_out = _fdopen(hCrt, "w");
|
||||||
|
setvbuf(hf_out, NULL, _IONBF, 1);
|
||||||
|
*stdout = *hf_out;
|
||||||
|
|
||||||
|
// Create Console Input Handle
|
||||||
|
HANDLE handle_in = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
hCrt = _open_osfhandle((intptr_t) handle_in, _O_TEXT);
|
||||||
|
FILE *hf_in = _fdopen(hCrt, "r");
|
||||||
|
setvbuf(hf_in, NULL, _IONBF, 128);
|
||||||
|
|
||||||
|
*stdin = *hf_in;
|
||||||
|
#elif __WIIU__
|
||||||
|
WHBLogUdpInit();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GuiFrame *frame = new MainWindow(video->getWidth(), video->getHeight());
|
||||||
|
|
||||||
|
std::map<GuiTrigger::eChannels, SDLController*> controllerList;
|
||||||
|
std::map<int32_t , GuiTrigger::eChannels> joystickToChannel;
|
||||||
|
|
||||||
|
#if defined _WIN32
|
||||||
|
controllerList[GuiTrigger::CHANNEL_1] = new SDLControllerMouse(GuiTrigger::CHANNEL_1);
|
||||||
|
DEBUG_FUNCTION_LINE("Add mouse");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
#ifdef __WIIU__
|
||||||
|
if(!CheckRunning()){
|
||||||
|
exit(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//! Read out inputs
|
||||||
|
for( auto const& [channel, controller] : controllerList ){
|
||||||
|
controller->before();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool quit = false;
|
||||||
|
SDL_Event e;
|
||||||
|
while (SDL_PollEvent(&e)) {
|
||||||
|
SDL_JoystickID jId = -1;
|
||||||
|
if(e.type == SDL_JOYDEVICEADDED) {
|
||||||
|
addJoystick(e.jdevice.which, controllerList, joystickToChannel);
|
||||||
|
}else if(e.type == SDL_JOYDEVICEREMOVED) {
|
||||||
|
auto j = SDL_JoystickFromInstanceID(e.jdevice.which);
|
||||||
|
if (j) {
|
||||||
|
removeJoystick(e.jdevice.which, controllerList, joystickToChannel);
|
||||||
|
SDL_JoystickClose(j);
|
||||||
|
}
|
||||||
|
}else if (e.type == SDL_FINGERDOWN || e.type == SDL_FINGERUP || e.type == SDL_FINGERMOTION){
|
||||||
|
controllerList[GuiTrigger::CHANNEL_1]->update(&e);
|
||||||
|
} else if (e.type == SDL_MOUSEBUTTONDOWN || e.type == SDL_MOUSEBUTTONUP || e.type == SDL_MOUSEMOTION){
|
||||||
|
controllerList[GuiTrigger::CHANNEL_1]->update(&e);
|
||||||
|
} else if (e.type == SDL_JOYAXISMOTION) {
|
||||||
|
jId = e.jaxis.which;
|
||||||
|
} else if (e.type == SDL_JOYHATMOTION) {
|
||||||
|
jId = e.jhat.which;
|
||||||
|
}else if (e.type == SDL_JOYBUTTONDOWN || e.type == SDL_JOYBUTTONUP) {
|
||||||
|
jId = e.jbutton.which;
|
||||||
|
} else if (e.type == SDL_QUIT || (e.type == SDL_KEYUP && e.key.keysym.sym == SDLK_ESCAPE)) {
|
||||||
|
quit = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(jId != -1){
|
||||||
|
if(joystickToChannel.find(jId) != joystickToChannel.end()){
|
||||||
|
controllerList[joystickToChannel[jId]]->update(&e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(quit){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( auto const& [joypad, controller] : controllerList ){
|
||||||
|
controller->after();
|
||||||
|
|
||||||
|
frame->update(controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
frame->process();
|
||||||
|
|
||||||
|
// clear the screen
|
||||||
|
SDL_RenderClear(video->getRenderer());
|
||||||
|
|
||||||
|
frame->draw(video);
|
||||||
|
|
||||||
|
frame->updateEffects();
|
||||||
|
|
||||||
|
// flip the backbuffer
|
||||||
|
// this means that everything that we prepared behind the screens is actually shown
|
||||||
|
SDL_RenderPresent(video->getRenderer());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
delete frame;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeJoystick(int32_t instanceId, std::map<GuiTrigger::eChannels, SDLController *> &controllerList, std::map<int32_t, GuiTrigger::eChannels>& joystickToChannel) {
|
||||||
|
auto channel = joystickToChannel[instanceId];
|
||||||
|
delete controllerList[channel];
|
||||||
|
controllerList.erase(channel);
|
||||||
|
joystickToChannel.erase(instanceId);
|
||||||
|
DEBUG_FUNCTION_LINE("Removed joystick: %d", instanceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool addJoystick(int deviceId, std::map<GuiTrigger::eChannels, SDLController *> &controllerList, std::map<int32_t, GuiTrigger::eChannels>& joystickToChannel) {
|
||||||
|
auto joystick = SDL_JoystickOpen(deviceId);
|
||||||
|
if (joystick == NULL){
|
||||||
|
DEBUG_FUNCTION_LINE("SDL_JoystickOpen failed: %s\n", SDL_GetError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto instanceId = SDL_JoystickInstanceID(joystick);
|
||||||
|
if(std::string("WiiU Gamepad").compare(SDL_JoystickName(joystick)) == 0){
|
||||||
|
controllerList[GuiTrigger::CHANNEL_1] = new SDLControllerWiiUGamepad(GuiTrigger::CHANNEL_1);
|
||||||
|
joystickToChannel[instanceId] = GuiTrigger::CHANNEL_1;
|
||||||
|
}else {
|
||||||
|
bool successfully_added = false;
|
||||||
|
auto channel = GuiTrigger::CHANNEL_2;
|
||||||
|
while(channel != GuiTrigger::CHANNEL_ALL){
|
||||||
|
if(controllerList.find(channel) == controllerList.end()) {
|
||||||
|
if (std::string(SDL_JoystickName(joystick)).find("Xbox") != std::string::npos){
|
||||||
|
controllerList[channel] = new SDLControllerXboxOne(channel);
|
||||||
|
}else if(std::string(SDL_JoystickName(joystick)).find("WiiU Pro Controller") != std::string::npos) {
|
||||||
|
controllerList[channel] = new SDLControllerWiiUProContoller(channel);
|
||||||
|
}else{
|
||||||
|
controllerList[channel] = new SDLControllerJoystick(channel, instanceId);
|
||||||
|
}
|
||||||
|
joystickToChannel[instanceId] = channel;
|
||||||
|
successfully_added = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
channel = increaseChannel(channel);
|
||||||
|
}
|
||||||
|
if(!successfully_added){
|
||||||
|
DEBUG_FUNCTION_LINE("Failed to add joystick. Closing it now");
|
||||||
|
SDL_JoystickClose(joystick);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DEBUG_FUNCTION_LINE("Added joystick %s", SDL_JoystickName(joystick));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiTrigger::eChannels increaseChannel(GuiTrigger::eChannels channel) {
|
||||||
|
switch(channel){
|
||||||
|
case GuiTrigger::CHANNEL_1:
|
||||||
|
return GuiTrigger::CHANNEL_2;
|
||||||
|
case GuiTrigger::CHANNEL_2:
|
||||||
|
return GuiTrigger::CHANNEL_3;
|
||||||
|
case GuiTrigger::CHANNEL_3:
|
||||||
|
return GuiTrigger::CHANNEL_4;
|
||||||
|
case GuiTrigger::CHANNEL_4:
|
||||||
|
return GuiTrigger::CHANNEL_5;
|
||||||
|
}
|
||||||
|
return GuiTrigger::CHANNEL_ALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void proccessEvents() {
|
||||||
|
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user