mirror of
https://github.com/hax4dazy/TinWoo.git
synced 2025-02-09 19:25:05 +01:00
Add files via upload
This commit is contained in:
parent
1105062b04
commit
2409270b37
128
include/Plutonium/Plutonium/Makefile
Normal file
128
include/Plutonium/Plutonium/Makefile
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ifeq ($(strip $(DEVKITPRO)),)
|
||||||
|
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(DEVKITPRO)/devkitA64/base_rules
|
||||||
|
include $(DEVKITPRO)/libnx/switch_rules
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# TARGET is the name of the output
|
||||||
|
# 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
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
BUILD := build
|
||||||
|
TARGET := pu
|
||||||
|
SOURCES := source source/pu source/pu/audio source/pu/ttf source/pu/sdl2 source/pu/ui source/pu/ui/elm source/pu/ui/extras source/pu/ui/render
|
||||||
|
INCLUDES := include
|
||||||
|
OUT_LIB := lib
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# options for code generation
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIC -ftls-model=local-exec
|
||||||
|
|
||||||
|
CFLAGS := -g -Wall -D__SWITCH__ -ffunction-sections -fdata-sections $(ARCH)
|
||||||
|
|
||||||
|
CFLAGS += $(INCLUDE) -I$(PORTLIBS)/include/freetype2 -DPU_MAJOR=$(PU_MAJOR) -DPU_MINOR=$(PU_MINOR) -DPU_MICRO=$(PU_MICRO) -DPU_VERSION=\"$(PU_MAJOR).$(PU_MINOR).$(PU_MICRO)\"
|
||||||
|
|
||||||
|
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17
|
||||||
|
|
||||||
|
ASFLAGS := -g $(ARCH)
|
||||||
|
LDFLAGS = -specs=${DEVKITPRO}/libnx/switch.specs -g $(ARCH) -Wl,-r,-Map,$(notdir $*.map)
|
||||||
|
|
||||||
|
SDL_IMAGE_LIBS := -lSDL2_image -lpng -ljpeg
|
||||||
|
SDL_GFX_LIBS := -lSDL2_gfx
|
||||||
|
SDL_MIXER_LIBS := -lSDL2_mixer -lmodplug -lmpg123 -lvorbisidec -logg
|
||||||
|
|
||||||
|
LIBS := $(SDL_IMAGE_LIBS) $(SDL_GFX_LIBS) $(SDL_MIXER_LIBS) -lEGL -lGLESv2 -lglapi `sdl2-config --libs` `freetype-config --libs`
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
# include and lib
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBDIRS := $(PORTLIBS) $(LIBNX)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# 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 VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
|
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 OUTPUT := $(CURDIR)/$(OUT_LIB)/lib$(TARGET).a
|
||||||
|
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||||
|
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 := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||||
|
|
||||||
|
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I$(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
.PHONY: $(BUILD) clean all
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all: $(BUILD)
|
||||||
|
|
||||||
|
$(BUILD):
|
||||||
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
@[ -d $(OUT_LIB) ] || mkdir -p $(OUT_LIB)
|
||||||
|
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr $(CURDIR)/$(BUILD)
|
||||||
|
@rm -fr $(CURDIR)/$(OUT_LIB)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
$(OUTPUT) : $(OFILES)
|
||||||
|
|
||||||
|
$(OFILES_SRC) : $(HFILES)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
%_bin.h %.bin.o : %.bin
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(bin2o)
|
||||||
|
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------------
|
39
include/Plutonium/Plutonium/include/pu/Plutonium
Normal file
39
include/Plutonium/Plutonium/include/pu/Plutonium
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file Plutonium
|
||||||
|
@brief Plutonium library's main header. (include this to use this library properly)
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <pu/pu_Include.hpp>
|
||||||
|
|
||||||
|
#include <pu/audio/audio_Music.hpp>
|
||||||
|
#include <pu/audio/audio_Sfx.hpp>
|
||||||
|
|
||||||
|
#include <pu/ui/ui_Application.hpp>
|
||||||
|
#include <pu/ui/ui_Types.hpp>
|
||||||
|
#include <pu/ui/ui_Container.hpp>
|
||||||
|
#include <pu/ui/ui_Dialog.hpp>
|
||||||
|
#include <pu/ui/ui_Layout.hpp>
|
||||||
|
#include <pu/ui/ui_Overlay.hpp>
|
||||||
|
|
||||||
|
#include <pu/ui/elm/elm_Button.hpp>
|
||||||
|
#include <pu/ui/elm/elm_Element.hpp>
|
||||||
|
#include <pu/ui/elm/elm_Image.hpp>
|
||||||
|
#include <pu/ui/elm/elm_Menu.hpp>
|
||||||
|
#include <pu/ui/elm/elm_ProgressBar.hpp>
|
||||||
|
#include <pu/ui/elm/elm_Rectangle.hpp>
|
||||||
|
#include <pu/ui/elm/elm_TextBlock.hpp>
|
||||||
|
#include <pu/ui/elm/elm_Toggle.hpp>
|
||||||
|
|
||||||
|
#include <pu/ui/extras/extras_Toast.hpp>
|
||||||
|
|
||||||
|
#include <pu/ui/render/render_Renderer.hpp>
|
||||||
|
#include <pu/ui/render/render_SDL2.hpp>
|
36
include/Plutonium/Plutonium/include/pu/audio/audio_Music.hpp
Normal file
36
include/Plutonium/Plutonium/include/pu/audio/audio_Music.hpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file audio_Music.hpp
|
||||||
|
@brief Music (BGM) support
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <SDL2/SDL_mixer.h>
|
||||||
|
#include <pu/pu_Include.hpp>
|
||||||
|
|
||||||
|
namespace pu::audio {
|
||||||
|
|
||||||
|
using Music = Mix_Music*;
|
||||||
|
|
||||||
|
Music OpenMusic(const std::string &path);
|
||||||
|
void PlayMusic(Music mus, const int loops);
|
||||||
|
void PlayMusicWithFadeIn(Music mus, const i32 llops, const i32 ms);
|
||||||
|
bool IsPlayingMusic();
|
||||||
|
void PauseMusic();
|
||||||
|
void ResumeMusic();
|
||||||
|
void SetMusicVolume(const i32 vol);
|
||||||
|
i32 GetMusicVolume();
|
||||||
|
void FadeOutMusic(const i32 ms);
|
||||||
|
void RewindMusic();
|
||||||
|
void StopMusic();
|
||||||
|
void SetMusicPosition(const double sec);
|
||||||
|
void DestroyMusic(Music &mus);
|
||||||
|
|
||||||
|
}
|
26
include/Plutonium/Plutonium/include/pu/audio/audio_Sfx.hpp
Normal file
26
include/Plutonium/Plutonium/include/pu/audio/audio_Sfx.hpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file audio_Sfx.hpp
|
||||||
|
@brief Sfx (sound effects) support
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <SDL2/SDL_mixer.h>
|
||||||
|
#include <pu/pu_Include.hpp>
|
||||||
|
|
||||||
|
namespace pu::audio {
|
||||||
|
|
||||||
|
using Sfx = Mix_Chunk*;
|
||||||
|
|
||||||
|
Sfx LoadSfx(const std::string &path);
|
||||||
|
void PlaySfx(Sfx sfx);
|
||||||
|
void DestroySfx(Sfx &sfx);
|
||||||
|
|
||||||
|
}
|
30
include/Plutonium/Plutonium/include/pu/pu_Include.hpp
Normal file
30
include/Plutonium/Plutonium/include/pu/pu_Include.hpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file pu_Include.hpp
|
||||||
|
@brief Basic includes and definitions for the library
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <switch.h>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
// Defines a static function (::New(...)) as a constructor for smart ptrs, also defines a custom type (::Ref) to simplify it
|
||||||
|
#define PU_SMART_CTOR(type) \
|
||||||
|
using Ref = std::shared_ptr<type>; \
|
||||||
|
template<typename ...Args> \
|
||||||
|
inline static Ref New(Args &&...ctor_args) { \
|
||||||
|
return std::move(std::make_shared<type>(std::forward<Args>(ctor_args)...)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace pu {
|
||||||
|
|
||||||
|
using i32 = s32;
|
||||||
|
|
||||||
|
}
|
276
include/Plutonium/Plutonium/include/pu/sdl2/sdl2_CustomTtf.h
Normal file
276
include/Plutonium/Plutonium/include/pu/sdl2/sdl2_CustomTtf.h
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
/*
|
||||||
|
SDL_ttf: A companion library to SDL for working with TrueType (tm) fonts
|
||||||
|
Copyright (C) 2001-2013 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This library is a wrapper around the excellent FreeType 2.0 library,
|
||||||
|
available at:
|
||||||
|
http://www.freetype.org/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SDL_TTF_H
|
||||||
|
#define _SDL_TTF_H
|
||||||
|
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/begin_code.h>
|
||||||
|
|
||||||
|
#include <switch.h>
|
||||||
|
|
||||||
|
/* Set up for C function definitions, even when using C++ */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL
|
||||||
|
*/
|
||||||
|
#define SDL_TTF_MAJOR_VERSION 2
|
||||||
|
#define SDL_TTF_MINOR_VERSION 0
|
||||||
|
#define SDL_TTF_PATCHLEVEL 12
|
||||||
|
|
||||||
|
/* This macro can be used to fill a version structure with the compile-time
|
||||||
|
* version of the SDL_ttf library.
|
||||||
|
*/
|
||||||
|
#define SDL_TTF_VERSION(X) \
|
||||||
|
{ \
|
||||||
|
(X)->major = SDL_TTF_MAJOR_VERSION; \
|
||||||
|
(X)->minor = SDL_TTF_MINOR_VERSION; \
|
||||||
|
(X)->patch = SDL_TTF_PATCHLEVEL; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Backwards compatibility */
|
||||||
|
#define TTF_MAJOR_VERSION SDL_TTF_MAJOR_VERSION
|
||||||
|
#define TTF_MINOR_VERSION SDL_TTF_MINOR_VERSION
|
||||||
|
#define TTF_PATCHLEVEL SDL_TTF_PATCHLEVEL
|
||||||
|
#define TTF_VERSION(X) SDL_TTF_VERSION(X)
|
||||||
|
|
||||||
|
/* This function gets the version of the dynamically linked SDL_ttf library.
|
||||||
|
it should NOT be used to fill a version structure, instead you should
|
||||||
|
use the SDL_TTF_VERSION() macro.
|
||||||
|
*/
|
||||||
|
extern DECLSPEC const SDL_version * SDLCALL TTF_Linked_Version(void);
|
||||||
|
|
||||||
|
/* ZERO WIDTH NO-BREAKSPACE (Unicode byte order mark) */
|
||||||
|
#define UNICODE_BOM_NATIVE 0xFEFF
|
||||||
|
#define UNICODE_BOM_SWAPPED 0xFFFE
|
||||||
|
|
||||||
|
/* This function tells the library whether UNICODE text is generally
|
||||||
|
byteswapped. A UNICODE BOM character in a string will override
|
||||||
|
this setting for the remainder of that string.
|
||||||
|
*/
|
||||||
|
extern DECLSPEC void SDLCALL TTF_ByteSwappedUNICODE(int swapped);
|
||||||
|
|
||||||
|
/* The internal structure containing font information */
|
||||||
|
typedef struct _TTF_Font TTF_Font;
|
||||||
|
|
||||||
|
/* Initialize the TTF engine - returns 0 if successful, -1 on error */
|
||||||
|
extern DECLSPEC int SDLCALL TTF_Init(void);
|
||||||
|
|
||||||
|
/* Open a font file and create a font of the specified point size.
|
||||||
|
* Some .fon fonts will have several sizes embedded in the file, so the
|
||||||
|
* point size becomes the index of choosing which size. If the value
|
||||||
|
* is too high, the last indexed size will be the default. */
|
||||||
|
extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFont(const char *file, int ptsize);
|
||||||
|
extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontIndex(const char *file, int ptsize, long index);
|
||||||
|
extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontRW(SDL_RWops *src, int freesrc, int ptsize);
|
||||||
|
extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontIndexRW(SDL_RWops *src, int freesrc, int ptsize, long index);
|
||||||
|
|
||||||
|
/* Set and retrieve the font style */
|
||||||
|
#define TTF_STYLE_NORMAL 0x00
|
||||||
|
#define TTF_STYLE_BOLD 0x01
|
||||||
|
#define TTF_STYLE_ITALIC 0x02
|
||||||
|
#define TTF_STYLE_UNDERLINE 0x04
|
||||||
|
#define TTF_STYLE_STRIKETHROUGH 0x08
|
||||||
|
extern DECLSPEC int SDLCALL TTF_GetFontStyle(const TTF_Font *font);
|
||||||
|
extern DECLSPEC void SDLCALL TTF_SetFontStyle(TTF_Font *font, int style);
|
||||||
|
extern DECLSPEC int SDLCALL TTF_GetFontOutline(const TTF_Font *font);
|
||||||
|
extern DECLSPEC void SDLCALL TTF_SetFontOutline(TTF_Font *font, int outline);
|
||||||
|
|
||||||
|
/* Set and retrieve FreeType hinter settings */
|
||||||
|
#define TTF_HINTING_NORMAL 0
|
||||||
|
#define TTF_HINTING_LIGHT 1
|
||||||
|
#define TTF_HINTING_MONO 2
|
||||||
|
#define TTF_HINTING_NONE 3
|
||||||
|
extern DECLSPEC int SDLCALL TTF_GetFontHinting(const TTF_Font *font);
|
||||||
|
extern DECLSPEC void SDLCALL TTF_SetFontHinting(TTF_Font *font, int hinting);
|
||||||
|
|
||||||
|
/* Get the total height of the font - usually equal to point size */
|
||||||
|
extern DECLSPEC int SDLCALL TTF_FontHeight(const TTF_Font *font);
|
||||||
|
|
||||||
|
/* Get the offset from the baseline to the top of the font
|
||||||
|
This is a positive value, relative to the baseline.
|
||||||
|
*/
|
||||||
|
extern DECLSPEC int SDLCALL TTF_FontAscent(const TTF_Font *font);
|
||||||
|
|
||||||
|
/* Get the offset from the baseline to the bottom of the font
|
||||||
|
This is a negative value, relative to the baseline.
|
||||||
|
*/
|
||||||
|
extern DECLSPEC int SDLCALL TTF_FontDescent(const TTF_Font *font);
|
||||||
|
|
||||||
|
/* Get the recommended spacing between lines of text for this font */
|
||||||
|
extern DECLSPEC int SDLCALL TTF_FontLineSkip(const TTF_Font *font);
|
||||||
|
|
||||||
|
/* Get/Set whether or not kerning is allowed for this font */
|
||||||
|
extern DECLSPEC int SDLCALL TTF_GetFontKerning(const TTF_Font *font);
|
||||||
|
extern DECLSPEC void SDLCALL TTF_SetFontKerning(TTF_Font *font, int allowed);
|
||||||
|
|
||||||
|
/* Get the number of faces of the font */
|
||||||
|
extern DECLSPEC long SDLCALL TTF_FontFaces(const TTF_Font *font);
|
||||||
|
|
||||||
|
/* Get the font face attributes, if any */
|
||||||
|
extern DECLSPEC int SDLCALL TTF_FontFaceIsFixedWidth(const TTF_Font *font);
|
||||||
|
extern DECLSPEC char * SDLCALL TTF_FontFaceFamilyName(const TTF_Font *font);
|
||||||
|
extern DECLSPEC char * SDLCALL TTF_FontFaceStyleName(const TTF_Font *font);
|
||||||
|
|
||||||
|
/* Check wether a glyph is provided by the font or not */
|
||||||
|
extern DECLSPEC int SDLCALL TTF_GlyphIsProvided(const TTF_Font *font, Uint16 ch);
|
||||||
|
|
||||||
|
/* Get the metrics (dimensions) of a glyph
|
||||||
|
To understand what these metrics mean, here is a useful link:
|
||||||
|
http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html
|
||||||
|
*/
|
||||||
|
extern DECLSPEC int SDLCALL TTF_GlyphMetrics(TTF_Font *font, Uint16 ch,
|
||||||
|
int *minx, int *maxx,
|
||||||
|
int *miny, int *maxy, int *advance);
|
||||||
|
|
||||||
|
/* Get the dimensions of a rendered string of text */
|
||||||
|
extern DECLSPEC int SDLCALL TTF_SizeText(TTF_Font *font, const char *text, int *w, int *h);
|
||||||
|
extern DECLSPEC int SDLCALL TTF_SizeUTF8(TTF_Font *font, const char *text, int *w, int *h);
|
||||||
|
extern DECLSPEC int SDLCALL TTF_SizeUNICODE(TTF_Font *font, const Uint16 *text, int *w, int *h);
|
||||||
|
|
||||||
|
/* Create an 8-bit palettized surface and render the given text at
|
||||||
|
fast quality with the given font and color. The 0 pixel is the
|
||||||
|
colorkey, giving a transparent background, and the 1 pixel is set
|
||||||
|
to the text color.
|
||||||
|
This function returns the new surface, or NULL if there was an error.
|
||||||
|
*/
|
||||||
|
extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Solid(TTF_Font *font,
|
||||||
|
const char *text, SDL_Color fg);
|
||||||
|
extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Solid(TTF_Font *font,
|
||||||
|
const char *text, SDL_Color fg);
|
||||||
|
extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Solid(TTF_Font *font,
|
||||||
|
const Uint16 *text, SDL_Color fg);
|
||||||
|
|
||||||
|
/* Create an 8-bit palettized surface and render the given glyph at
|
||||||
|
fast quality with the given font and color. The 0 pixel is the
|
||||||
|
colorkey, giving a transparent background, and the 1 pixel is set
|
||||||
|
to the text color. The glyph is rendered without any padding or
|
||||||
|
centering in the X direction, and aligned normally in the Y direction.
|
||||||
|
This function returns the new surface, or NULL if there was an error.
|
||||||
|
*/
|
||||||
|
extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_Solid(TTF_Font *font,
|
||||||
|
Uint16 ch, SDL_Color fg);
|
||||||
|
|
||||||
|
/* Create an 8-bit palettized surface and render the given text at
|
||||||
|
high quality with the given font and colors. The 0 pixel is background,
|
||||||
|
while other pixels have varying degrees of the foreground color.
|
||||||
|
This function returns the new surface, or NULL if there was an error.
|
||||||
|
*/
|
||||||
|
extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Shaded(TTF_Font *font,
|
||||||
|
const char *text, SDL_Color fg, SDL_Color bg);
|
||||||
|
extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Shaded(TTF_Font *font,
|
||||||
|
const char *text, SDL_Color fg, SDL_Color bg);
|
||||||
|
extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Shaded(TTF_Font *font,
|
||||||
|
const Uint16 *text, SDL_Color fg, SDL_Color bg);
|
||||||
|
|
||||||
|
/* Create an 8-bit palettized surface and render the given glyph at
|
||||||
|
high quality with the given font and colors. The 0 pixel is background,
|
||||||
|
while other pixels have varying degrees of the foreground color.
|
||||||
|
The glyph is rendered without any padding or centering in the X
|
||||||
|
direction, and aligned normally in the Y direction.
|
||||||
|
This function returns the new surface, or NULL if there was an error.
|
||||||
|
*/
|
||||||
|
extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_Shaded(TTF_Font *font,
|
||||||
|
Uint16 ch, SDL_Color fg, SDL_Color bg);
|
||||||
|
|
||||||
|
/* Create a 32-bit ARGB surface and render the given text at high quality,
|
||||||
|
using alpha blending to dither the font with the given color.
|
||||||
|
This function returns the new surface, or NULL if there was an error.
|
||||||
|
*/
|
||||||
|
extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Blended(TTF_Font *font,
|
||||||
|
const char *text, SDL_Color fg);
|
||||||
|
extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Blended(TTF_Font *font,
|
||||||
|
const char *text, SDL_Color fg);
|
||||||
|
extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Blended(TTF_Font *font,
|
||||||
|
const Uint16 *text, SDL_Color fg);
|
||||||
|
|
||||||
|
|
||||||
|
/* Create a 32-bit ARGB surface and render the given text at high quality,
|
||||||
|
using alpha blending to dither the font with the given color.
|
||||||
|
Text is wrapped to multiple lines on line endings and on word boundaries
|
||||||
|
if it extends beyond wrapLength in pixels.
|
||||||
|
This function returns the new surface, or NULL if there was an error.
|
||||||
|
*/
|
||||||
|
extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Blended_Wrapped(TTF_Font *font,
|
||||||
|
const char *text, SDL_Color fg, Uint32 wrapLength);
|
||||||
|
extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Blended_Wrapped(TTF_Font *font,
|
||||||
|
const char *text, SDL_Color fg, Uint32 wrapLength);
|
||||||
|
extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Blended_Wrapped(TTF_Font *font,
|
||||||
|
const Uint16 *text, SDL_Color fg, Uint32 wrapLength);
|
||||||
|
|
||||||
|
/* Create a 32-bit ARGB surface and render the given glyph at high quality,
|
||||||
|
using alpha blending to dither the font with the given color.
|
||||||
|
The glyph is rendered without any padding or centering in the X
|
||||||
|
direction, and aligned normally in the Y direction.
|
||||||
|
This function returns the new surface, or NULL if there was an error.
|
||||||
|
*/
|
||||||
|
extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_Blended(TTF_Font *font,
|
||||||
|
Uint16 ch, SDL_Color fg);
|
||||||
|
|
||||||
|
/* For compatibility with previous versions, here are the old functions */
|
||||||
|
#define TTF_RenderText(font, text, fg, bg) \
|
||||||
|
TTF_RenderText_Shaded(font, text, fg, bg)
|
||||||
|
#define TTF_RenderUTF8(font, text, fg, bg) \
|
||||||
|
TTF_RenderUTF8_Shaded(font, text, fg, bg)
|
||||||
|
#define TTF_RenderUNICODE(font, text, fg, bg) \
|
||||||
|
TTF_RenderUNICODE_Shaded(font, text, fg, bg)
|
||||||
|
|
||||||
|
/* Close an opened font file */
|
||||||
|
extern DECLSPEC void SDLCALL TTF_CloseFont(TTF_Font *font);
|
||||||
|
|
||||||
|
/* De-initialize the TTF engine */
|
||||||
|
extern DECLSPEC void SDLCALL TTF_Quit(void);
|
||||||
|
|
||||||
|
/* Check if the TTF engine is initialized */
|
||||||
|
extern DECLSPEC int SDLCALL TTF_WasInit(void);
|
||||||
|
|
||||||
|
/* Get the kerning size of two glyphs */
|
||||||
|
extern DECLSPEC int TTF_GetFontKerningSize(TTF_Font *font, int prev_index, int index);
|
||||||
|
|
||||||
|
/* Code present in C++ code */
|
||||||
|
TTF_Font *TTF_CppWrap_FindValidFont(TTF_Font *font, Uint16 ch);
|
||||||
|
|
||||||
|
/* Get the pointer to the C++ data */
|
||||||
|
void *TTF_CppWrap_GetCppPtrRef(TTF_Font *font);
|
||||||
|
|
||||||
|
/* Set the pointer to the C++ data */
|
||||||
|
void TTF_CppWrap_SetCppPtrRef(TTF_Font *font, void *cpp_ptr_ref);
|
||||||
|
|
||||||
|
/* We'll use SDL for reporting errors */
|
||||||
|
#define TTF_SetError SDL_SetError
|
||||||
|
#define TTF_GetError SDL_GetError
|
||||||
|
|
||||||
|
#define TMP_LOG(str) { const char *cstr = str; svcOutputDebugString(cstr, strlen(cstr)); }
|
||||||
|
|
||||||
|
/* Ends C function definitions when using C++ */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#include <SDL2/close_code.h>
|
||||||
|
|
||||||
|
#endif /* _SDL_TTF_H */
|
17
include/Plutonium/Plutonium/include/pu/sdl2/sdl2_Types.hpp
Normal file
17
include/Plutonium/Plutonium/include/pu/sdl2/sdl2_Types.hpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL2_gfxPrimitives.h>
|
||||||
|
#include <SDL2/SDL_image.h>
|
||||||
|
#include <SDL2/SDL_mixer.h>
|
||||||
|
#include <pu/sdl2/sdl2_CustomTtf.h>
|
||||||
|
|
||||||
|
namespace pu::sdl2 {
|
||||||
|
|
||||||
|
using Texture = SDL_Texture*;
|
||||||
|
using Window = SDL_Window*;
|
||||||
|
using Renderer = SDL_Renderer*;
|
||||||
|
using Font = TTF_Font*;
|
||||||
|
using Surface = SDL_Surface*;
|
||||||
|
|
||||||
|
}
|
87
include/Plutonium/Plutonium/include/pu/ttf/ttf_Font.hpp
Normal file
87
include/Plutonium/Plutonium/include/pu/ttf/ttf_Font.hpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <pu/sdl2/sdl2_Types.hpp>
|
||||||
|
#include <pu/ui/ui_Types.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace pu::ttf {
|
||||||
|
|
||||||
|
class Font {
|
||||||
|
private:
|
||||||
|
using FontFaceDisposingFunction = void(*)(void*);
|
||||||
|
|
||||||
|
struct FontFace {
|
||||||
|
sdl2::Font font;
|
||||||
|
void *ptr;
|
||||||
|
size_t ptr_sz;
|
||||||
|
FontFaceDisposingFunction dispose_fn;
|
||||||
|
|
||||||
|
FontFace(void *buf, const size_t buf_size, FontFaceDisposingFunction disp_fn, const u32 font_sz, void *font_class_ptr) : font(nullptr), ptr(buf), ptr_sz(buf_size), dispose_fn(disp_fn) {
|
||||||
|
this->font = TTF_OpenFontRW(SDL_RWFromMem(this->ptr, this->ptr_sz), 1, font_sz);
|
||||||
|
if(this->font != nullptr) {
|
||||||
|
TTF_CppWrap_SetCppPtrRef(this->font, font_class_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FontFace() : font(nullptr), ptr(nullptr), ptr_sz(0), dispose_fn(EmptyFontFaceDisposingFunction) {}
|
||||||
|
|
||||||
|
inline bool IsSourceValid() {
|
||||||
|
// AKA - is the base ptr and size valid?
|
||||||
|
return (this->ptr != nullptr) && (this->ptr_sz > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisposeFont() {
|
||||||
|
if(this->font != nullptr) {
|
||||||
|
TTF_CloseFont(this->font);
|
||||||
|
this->font = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dispose() {
|
||||||
|
this->DisposeFont();
|
||||||
|
if(this->IsSourceValid()) {
|
||||||
|
(this->dispose_fn)(this->ptr);
|
||||||
|
this->ptr = nullptr;
|
||||||
|
this->ptr_sz = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<std::pair<i32, std::unique_ptr<FontFace>>> font_faces;
|
||||||
|
u32 font_size;
|
||||||
|
|
||||||
|
inline sdl2::Font TryGetFirstFont() {
|
||||||
|
if(!this->font_faces.empty()) {
|
||||||
|
return this->font_faces.begin()->second->font;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr i32 InvalidFontFaceIndex = -1;
|
||||||
|
static constexpr u32 DefaultFontSize = 25;
|
||||||
|
|
||||||
|
static void EmptyFontFaceDisposingFunction(void*) {}
|
||||||
|
|
||||||
|
static inline constexpr bool IsValidFontFaceIndex(const i32 index) {
|
||||||
|
return index != InvalidFontFaceIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
Font(const u32 font_sz) : font_size(font_sz) {}
|
||||||
|
~Font();
|
||||||
|
|
||||||
|
i32 LoadFromMemory(void *ptr, const size_t size, FontFaceDisposingFunction disp_fn);
|
||||||
|
i32 LoadFromFile(const std::string &path);
|
||||||
|
void Unload(const i32 font_idx);
|
||||||
|
|
||||||
|
inline u32 GetFontSize() {
|
||||||
|
return this->font_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
sdl2::Font FindValidFontFor(const Uint16 ch);
|
||||||
|
std::pair<u32, u32> GetTextDimensions(const std::string &str);
|
||||||
|
sdl2::Texture RenderText(const std::string &str, const ui::Color clr);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
131
include/Plutonium/Plutonium/include/pu/ui/elm/elm_Button.hpp
Normal file
131
include/Plutonium/Plutonium/include/pu/ui/elm/elm_Button.hpp
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file Button.hpp
|
||||||
|
@brief A Button is an Element for option selecting.
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <functional>
|
||||||
|
#include <pu/ui/elm/elm_Element.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui::elm {
|
||||||
|
|
||||||
|
class Button : public Element {
|
||||||
|
public:
|
||||||
|
using OnClickCallback = std::function<void()>;
|
||||||
|
|
||||||
|
static constexpr u8 DarkerColorFactor = 70;
|
||||||
|
|
||||||
|
static constexpr u8 HoverAlphaIncrement = 48;
|
||||||
|
|
||||||
|
private:
|
||||||
|
i32 x;
|
||||||
|
i32 y;
|
||||||
|
i32 w;
|
||||||
|
i32 h;
|
||||||
|
std::string fnt_name;
|
||||||
|
Color bg_clr;
|
||||||
|
Color cnt_clr;
|
||||||
|
std::string cnt;
|
||||||
|
sdl2::Texture cnt_tex;
|
||||||
|
OnClickCallback on_click_cb;
|
||||||
|
bool hover;
|
||||||
|
i32 hover_alpha;
|
||||||
|
|
||||||
|
inline Color MakeHoverBackgroundColor(const i32 alpha) {
|
||||||
|
i32 base_r = this->bg_clr.r - DarkerColorFactor;
|
||||||
|
if(base_r < 0) {
|
||||||
|
base_r = 0;
|
||||||
|
}
|
||||||
|
i32 base_g = this->bg_clr.g - DarkerColorFactor;
|
||||||
|
if(base_g < 0) {
|
||||||
|
base_g = 0;
|
||||||
|
}
|
||||||
|
i32 base_b = this->bg_clr.b - DarkerColorFactor;
|
||||||
|
if(base_b < 0) {
|
||||||
|
base_b = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto base_a = this->bg_clr.a;
|
||||||
|
if(alpha >= 0) {
|
||||||
|
base_a = static_cast<u8>(alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { static_cast<u8>(base_r), static_cast<u8>(base_g), static_cast<u8>(base_b), base_a };
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Button(const i32 x, const i32 y, const i32 width, const i32 height, const std::string &content, const Color content_clr, const Color bg_clr);
|
||||||
|
PU_SMART_CTOR(Button)
|
||||||
|
~Button();
|
||||||
|
|
||||||
|
inline i32 GetX() override {
|
||||||
|
return this->x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetX(const i32 x) {
|
||||||
|
this->x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetY() override {
|
||||||
|
return this->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetY(const i32 y) {
|
||||||
|
this->y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetWidth() override {
|
||||||
|
return this->w;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetWidth(const i32 width) {
|
||||||
|
this->w = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetHeight() override {
|
||||||
|
return this->h;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetHeight(const i32 height) {
|
||||||
|
this->h = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string GetContent() {
|
||||||
|
return this->cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetContent(const std::string &content);
|
||||||
|
|
||||||
|
inline Color GetContentColor() {
|
||||||
|
return this->cnt_clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetContentColor(const Color content_clr);
|
||||||
|
|
||||||
|
inline Color GetBackgroundColor() {
|
||||||
|
return this->bg_clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetBackgroundColor(const Color bg_clr) {
|
||||||
|
this->bg_clr = bg_clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetContentFont(const std::string &font_name);
|
||||||
|
|
||||||
|
inline void SetOnClick(OnClickCallback on_click_cb) {
|
||||||
|
this->on_click_cb = on_click_cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnRender(render::Renderer::Ref &drawer, const i32 x, const i32 y) override;
|
||||||
|
void OnInput(const u64 keys_down, const u64 keys_up, const u64 keys_held, const TouchPoint touch_pos) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file Element.hpp
|
||||||
|
@brief An Element is the base of Plutonium UI's content.
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <pu/ui/render/render_Renderer.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui {
|
||||||
|
|
||||||
|
class Container;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace pu::ui::elm {
|
||||||
|
|
||||||
|
enum class HorizontalAlign {
|
||||||
|
Left,
|
||||||
|
Center,
|
||||||
|
Right
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class VerticalAlign {
|
||||||
|
Up,
|
||||||
|
Center,
|
||||||
|
Down
|
||||||
|
};
|
||||||
|
|
||||||
|
class Element {
|
||||||
|
protected:
|
||||||
|
bool visible;
|
||||||
|
HorizontalAlign h_align;
|
||||||
|
VerticalAlign v_align;
|
||||||
|
Container *parent_container;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Element() : visible(true), h_align(HorizontalAlign::Left), v_align(VerticalAlign::Up), parent_container(nullptr) {}
|
||||||
|
PU_SMART_CTOR(Element)
|
||||||
|
virtual ~Element() {}
|
||||||
|
|
||||||
|
virtual i32 GetX() = 0;
|
||||||
|
virtual i32 GetY() = 0;
|
||||||
|
virtual i32 GetWidth() = 0;
|
||||||
|
virtual i32 GetHeight() = 0;
|
||||||
|
virtual void OnRender(render::Renderer::Ref &drawer, const i32 x, const i32 y) = 0;
|
||||||
|
virtual void OnInput(const u64 keys_down, const u64 keys_up, const u64 keys_held, const TouchPoint touch_pos) = 0;
|
||||||
|
|
||||||
|
inline bool IsVisible() {
|
||||||
|
return this->visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetVisible(const bool visible) {
|
||||||
|
this->visible = visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetHorizontalAlign(const HorizontalAlign align) {
|
||||||
|
this->h_align = align;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline HorizontalAlign GetHorizontalAlign() {
|
||||||
|
return this->h_align;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetVerticalAlign(const VerticalAlign align) {
|
||||||
|
this->v_align = align;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline VerticalAlign GetVerticalAlign() {
|
||||||
|
return this->v_align;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetParentContainer(Container *parent_container) {
|
||||||
|
this->parent_container = parent_container;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 GetProcessedX();
|
||||||
|
i32 GetProcessedY();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
86
include/Plutonium/Plutonium/include/pu/ui/elm/elm_Image.hpp
Normal file
86
include/Plutonium/Plutonium/include/pu/ui/elm/elm_Image.hpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file Image.hpp
|
||||||
|
@brief An Image is an Element showing a picture. (JPEG, PNG, TGA, BMP)
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <pu/ui/elm/elm_Element.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui::elm {
|
||||||
|
|
||||||
|
class Image : public Element {
|
||||||
|
private:
|
||||||
|
std::string img_path;
|
||||||
|
sdl2::Texture img_tex;
|
||||||
|
render::TextureRenderOptions rend_opts;
|
||||||
|
i32 x;
|
||||||
|
i32 y;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Image(const i32 x, const i32 y, const std::string &image_path);
|
||||||
|
PU_SMART_CTOR(Image)
|
||||||
|
~Image();
|
||||||
|
|
||||||
|
inline i32 GetX() override {
|
||||||
|
return this->x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetX(const i32 x) {
|
||||||
|
this->x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetY() override {
|
||||||
|
return this->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetY(const i32 y) {
|
||||||
|
this->y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetWidth() override {
|
||||||
|
return this->rend_opts.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetWidth(const i32 width) {
|
||||||
|
this->rend_opts.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetHeight() override {
|
||||||
|
return this->rend_opts.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetHeight(const i32 height) {
|
||||||
|
this->rend_opts.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float GetRotationAngle() {
|
||||||
|
return this->rend_opts.rot_angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetRotationAngle(const float angle) {
|
||||||
|
this->rend_opts.rot_angle = angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string GetImagePath() {
|
||||||
|
return this->img_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetImage(const std::string &image_path);
|
||||||
|
|
||||||
|
inline bool IsImageValid() {
|
||||||
|
return this->img_tex != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnRender(render::Renderer::Ref &drawer, const i32 x, const i32 y) override;
|
||||||
|
void OnInput(const u64 keys_down, const u64 keys_up, const u64 keys_held, const TouchPoint touch_pos) override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
291
include/Plutonium/Plutonium/include/pu/ui/elm/elm_Menu.hpp
Normal file
291
include/Plutonium/Plutonium/include/pu/ui/elm/elm_Menu.hpp
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file Menu.hpp
|
||||||
|
@brief A Menu is a very useful Element for option browsing or selecting.
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <pu/ui/elm/elm_Element.hpp>
|
||||||
|
#include <chrono>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace pu::ui::elm {
|
||||||
|
|
||||||
|
class MenuItem {
|
||||||
|
public:
|
||||||
|
using OnKeyCallback = std::function<void()>;
|
||||||
|
static constexpr Color DefaultColor = { 10, 10, 10, 0xFF };
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string name;
|
||||||
|
Color items_clr;
|
||||||
|
std::string icon_path;
|
||||||
|
std::vector<OnKeyCallback> on_key_cbs;
|
||||||
|
std::vector<u64> on_key_cb_keys;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MenuItem(const std::string &name) : name(name), items_clr(DefaultColor) {}
|
||||||
|
PU_SMART_CTOR(MenuItem)
|
||||||
|
|
||||||
|
inline std::string GetName() {
|
||||||
|
return this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetName(const std::string &name) {
|
||||||
|
this->name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Color GetColor() {
|
||||||
|
return this->items_clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetColor(const Color items_clr) {
|
||||||
|
this->items_clr = items_clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddOnKey(OnKeyCallback on_key_cb, const u64 key = HidNpadButton_A);
|
||||||
|
|
||||||
|
inline u32 GetOnKeyCallbackCount() {
|
||||||
|
return this->on_key_cbs.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline OnKeyCallback GetOnKeyCallback(const u32 idx) {
|
||||||
|
if(idx < this->on_key_cbs.size()) {
|
||||||
|
return this->on_key_cbs.at(idx);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u64 GetOnKeyCallbackKey(const u32 idx) {
|
||||||
|
if(idx < this->on_key_cb_keys.size()) {
|
||||||
|
return this->on_key_cb_keys.at(idx);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string GetIconPath() {
|
||||||
|
return this->icon_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetIcon(const std::string &icon_path);
|
||||||
|
|
||||||
|
inline bool HasIcon() {
|
||||||
|
return !this->icon_path.empty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Menu : public Element {
|
||||||
|
public:
|
||||||
|
static constexpr Color DefaultScrollbarColor = { 110, 110, 110, 0xFF };
|
||||||
|
|
||||||
|
static constexpr u8 ItemAlphaIncrement = 48;
|
||||||
|
|
||||||
|
static constexpr float IconItemSizesFactor = 0.8f;
|
||||||
|
|
||||||
|
static constexpr u32 IconMargin = 25;
|
||||||
|
static constexpr u32 TextMargin = 25;
|
||||||
|
|
||||||
|
static constexpr u8 LightScrollbarColorFactor = 30;
|
||||||
|
|
||||||
|
static constexpr u32 ScrollbarWidth = 20;
|
||||||
|
|
||||||
|
static constexpr u32 ShadowHeight = 5;
|
||||||
|
static constexpr u8 ShadowBaseAlpha = 160;
|
||||||
|
|
||||||
|
using OnSelectionChangedCallback = std::function<void()>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
i32 x;
|
||||||
|
i32 y;
|
||||||
|
i32 w;
|
||||||
|
i32 items_h;
|
||||||
|
u32 items_to_show;
|
||||||
|
u32 selected_item_idx;
|
||||||
|
i32 selected_item_alpha;
|
||||||
|
i32 prev_selected_item_idx;
|
||||||
|
i32 prev_selected_item_alpha;
|
||||||
|
u32 advanced_item_count;
|
||||||
|
Color scrollbar_clr;
|
||||||
|
Color items_clr;
|
||||||
|
Color items_focus_clr;
|
||||||
|
bool cooldown_enabled;
|
||||||
|
bool item_touched;
|
||||||
|
u8 move_mode;
|
||||||
|
std::chrono::time_point<std::chrono::steady_clock> move_start_time;
|
||||||
|
OnSelectionChangedCallback on_selection_changed_cb;
|
||||||
|
std::vector<MenuItem::Ref> items;
|
||||||
|
std::string font_name;
|
||||||
|
std::vector<sdl2::Texture> loaded_name_texs;
|
||||||
|
std::vector<sdl2::Texture> loaded_icon_texs;
|
||||||
|
|
||||||
|
void ReloadItemRenders();
|
||||||
|
|
||||||
|
inline Color MakeItemsFocusColor(const u8 alpha) {
|
||||||
|
return { this->items_focus_clr.r, this->items_focus_clr.g, this->items_focus_clr.b, alpha };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr Color MakeLighterScrollbarColor() {
|
||||||
|
i32 base_r = this->scrollbar_clr.r - LightScrollbarColorFactor;
|
||||||
|
if(base_r < 0) {
|
||||||
|
base_r = 0;
|
||||||
|
}
|
||||||
|
i32 base_g = this->scrollbar_clr.g - LightScrollbarColorFactor;
|
||||||
|
if(base_g < 0) {
|
||||||
|
base_g = 0;
|
||||||
|
}
|
||||||
|
i32 base_b = this->scrollbar_clr.b - LightScrollbarColorFactor;
|
||||||
|
if(base_b < 0) {
|
||||||
|
base_b = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { static_cast<u8>(base_r), static_cast<u8>(base_g), static_cast<u8>(base_b), this->scrollbar_clr.a };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void HandleOnSelectionChanged() {
|
||||||
|
if(this->on_selection_changed_cb) {
|
||||||
|
(this->on_selection_changed_cb)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void RunSelectedItemCallback(const u64 keys) {
|
||||||
|
auto item = this->items.at(this->selected_item_idx);
|
||||||
|
const auto cb_count = item->GetOnKeyCallbackCount();
|
||||||
|
for(u32 i = 0; i < cb_count; i++) {
|
||||||
|
if(keys & item->GetOnKeyCallbackKey(i)) {
|
||||||
|
if(!this->cooldown_enabled) {
|
||||||
|
auto cb = item->GetOnKeyCallback(i);
|
||||||
|
if(cb) {
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->cooldown_enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u32 GetItemCount() {
|
||||||
|
auto item_count = this->items_to_show;
|
||||||
|
if(item_count > this->items.size()) {
|
||||||
|
item_count = this->items.size();
|
||||||
|
}
|
||||||
|
if((item_count + this->advanced_item_count) > this->items.size()) {
|
||||||
|
item_count = this->items.size() - this->advanced_item_count;
|
||||||
|
}
|
||||||
|
return item_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Menu(const i32 x, const i32 y, const i32 width, const Color items_clr, const Color items_focus_clr, const i32 items_height, const u32 items_to_show);
|
||||||
|
PU_SMART_CTOR(Menu)
|
||||||
|
|
||||||
|
inline i32 GetX() override {
|
||||||
|
return this->x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetX(const i32 x) {
|
||||||
|
this->x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetY() override {
|
||||||
|
return this->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetY(const i32 y) {
|
||||||
|
this->y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetWidth() override {
|
||||||
|
return this->w;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetWidth(const i32 width) {
|
||||||
|
this->w = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetHeight() override {
|
||||||
|
return this->items_h * this->items_to_show;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetItemsHeight() {
|
||||||
|
return this->items_h;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetItemsHeight(const i32 items_height) {
|
||||||
|
this->items_h = items_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetNumberOfItemsToShow() {
|
||||||
|
return this->items_to_show;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetNumberOfItemsToShow(const i32 items_to_show) {
|
||||||
|
this->items_to_show = items_to_show;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Color GetItemsColor() {
|
||||||
|
return this->items_clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetItemsColor(const Color items_clr) {
|
||||||
|
this->items_clr = items_clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Color GetItemsFocusColor() {
|
||||||
|
return this->items_focus_clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetItemsFocusColor(const Color items_focus_clr) {
|
||||||
|
this->items_focus_clr = items_focus_clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Color GetScrollbarColor() {
|
||||||
|
return this->scrollbar_clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetScrollbarColor(const Color scrollbar_clr) {
|
||||||
|
this->scrollbar_clr = scrollbar_clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetOnSelectionChanged(OnSelectionChangedCallback on_selection_changed_cb) {
|
||||||
|
this->on_selection_changed_cb = on_selection_changed_cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void AddItem(MenuItem::Ref &item) {
|
||||||
|
this->items.push_back(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearItems();
|
||||||
|
|
||||||
|
inline void SetCooldownEnabled(const bool enabled) {
|
||||||
|
this->cooldown_enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline MenuItem::Ref &GetSelectedItem() {
|
||||||
|
return this->items.at(this->selected_item_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::vector<MenuItem::Ref> &GetItems() {
|
||||||
|
return this->items;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetSelectedIndex() {
|
||||||
|
return this->selected_item_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSelectedIndex(const u32 idx);
|
||||||
|
|
||||||
|
void OnRender(render::Renderer::Ref &drawer, const i32 x, const i32 y) override;
|
||||||
|
void OnInput(const u64 keys_down, const u64 keys_up, const u64 keys_held, const TouchPoint touch_pos) override;
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,124 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file ProgressBar.hpp
|
||||||
|
@brief A ProgressBar is an Element which represents a progress (a percentage) by filling a bar.
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <pu/ui/elm/elm_Element.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui::elm {
|
||||||
|
|
||||||
|
class ProgressBar : public Element {
|
||||||
|
public:
|
||||||
|
static constexpr Color DefaultProgressColor = { 139, 195, 74, 255 };
|
||||||
|
static constexpr Color DefaultBackgroundColor = { 140, 140, 140, 255 };
|
||||||
|
|
||||||
|
private:
|
||||||
|
i32 x;
|
||||||
|
i32 y;
|
||||||
|
i32 w;
|
||||||
|
i32 h;
|
||||||
|
double val;
|
||||||
|
double max_val;
|
||||||
|
Color progress_clr;
|
||||||
|
Color bg_clr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ProgressBar(const i32 x, const i32 y, const i32 width, const i32 height, const double max_val) : Element(), x(x), y(y), w(width), h(height), val(0), max_val(max_val), progress_clr(DefaultProgressColor), bg_clr(DefaultBackgroundColor) {}
|
||||||
|
PU_SMART_CTOR(ProgressBar)
|
||||||
|
|
||||||
|
inline i32 GetX() override {
|
||||||
|
return this->x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetX(const i32 x) {
|
||||||
|
this->x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetY() override {
|
||||||
|
return this->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetY(const i32 y) {
|
||||||
|
this->y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetWidth() override {
|
||||||
|
return this->w;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetWidth(const i32 width) {
|
||||||
|
this->w = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetHeight() override {
|
||||||
|
return this->h;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetHeight(const i32 height) {
|
||||||
|
this->h = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Color GetProgressColor() {
|
||||||
|
return this->progress_clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetProgressColor(const Color progress_clr) {
|
||||||
|
this->progress_clr = progress_clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Color GetBackgroundColor() {
|
||||||
|
return this->bg_clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetBackgroundColor(const Color bg_clr) {
|
||||||
|
this->bg_clr = bg_clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double GetProgress() {
|
||||||
|
return this->val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetProgress(const double progress);
|
||||||
|
|
||||||
|
inline void IncrementProgress(const double extra_progress) {
|
||||||
|
this->SetProgress(this->val + extra_progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void DecrementProgress(const double extra_progress) {
|
||||||
|
this->SetProgress(this->val - extra_progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetMaxProgress(const double max_progress) {
|
||||||
|
this->max_val = max_progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double GetMaxProgress() {
|
||||||
|
return this->max_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FillProgress() {
|
||||||
|
this->SetProgress(this->max_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ClearProgress() {
|
||||||
|
this->SetProgress(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsCompleted() {
|
||||||
|
return this->val == this->max_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnRender(render::Renderer::Ref &drawer, const i32 x, const i32 y) override;
|
||||||
|
void OnInput(const u64 keys_down, const u64 keys_up, const u64 keys_held, const TouchPoint touch_pos) override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file Rectangle.hpp
|
||||||
|
@brief A Rectangle is an Element which simply draws a filled rectangle.
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <pu/ui/elm/elm_Element.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui::elm {
|
||||||
|
|
||||||
|
class Rectangle : public Element
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
i32 x;
|
||||||
|
i32 y;
|
||||||
|
i32 w;
|
||||||
|
i32 h;
|
||||||
|
Color clr;
|
||||||
|
i32 border_radius;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Rectangle(const i32 x, const i32 y, const i32 width, const i32 height, const Color clr, const i32 border_radius = 0) : Element(), x(x), y(y), w(width), h(height), clr(clr), border_radius(border_radius) {}
|
||||||
|
PU_SMART_CTOR(Rectangle)
|
||||||
|
|
||||||
|
inline i32 GetX() override {
|
||||||
|
return this->x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetX(const i32 x) {
|
||||||
|
this->x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetY() override {
|
||||||
|
return this->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetY(const i32 y) {
|
||||||
|
this->y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetWidth() override {
|
||||||
|
return this->w;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetWidth(const i32 width) {
|
||||||
|
this->w = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetHeight() override {
|
||||||
|
return this->h;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetHeight(const i32 height) {
|
||||||
|
this->h = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetBorderRadius() {
|
||||||
|
return this->border_radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetBorderRadius(const i32 border_radius) {
|
||||||
|
this->border_radius = border_radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Color GetColor() {
|
||||||
|
return this->clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetColor(const Color clr) {
|
||||||
|
this->clr = clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnRender(render::Renderer::Ref &drawer, const i32 x, const i32 y) override;
|
||||||
|
void OnInput(const u64 keys_down, const u64 keys_up, const u64 keys_held, const TouchPoint touch_pos) override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file TextBlock.hpp
|
||||||
|
@brief A TextBlock is a very useful Element which is used to draw text on the screen.
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <pu/ui/elm/elm_Element.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui::elm {
|
||||||
|
|
||||||
|
class TextBlock : public Element {
|
||||||
|
public:
|
||||||
|
static constexpr Color DefaultColor = { 0, 0, 0, 0xFF };
|
||||||
|
|
||||||
|
private:
|
||||||
|
i32 x;
|
||||||
|
i32 y;
|
||||||
|
Color clr;
|
||||||
|
std::string text;
|
||||||
|
sdl2::Texture text_tex;
|
||||||
|
std::string fnt_name;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TextBlock(const i32 x, const i32 y, const std::string &text);
|
||||||
|
PU_SMART_CTOR(TextBlock)
|
||||||
|
~TextBlock();
|
||||||
|
|
||||||
|
inline i32 GetX() override {
|
||||||
|
return this->x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetX(const i32 x) {
|
||||||
|
this->x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetY() override {
|
||||||
|
return this->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetY(const i32 y) {
|
||||||
|
this->y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 GetWidth() override;
|
||||||
|
i32 GetHeight() override;
|
||||||
|
|
||||||
|
inline std::string GetText() {
|
||||||
|
return this->text;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetText(const std::string &text);
|
||||||
|
void SetFont(const std::string &font_name);
|
||||||
|
|
||||||
|
inline Color GetColor() {
|
||||||
|
return this->clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetColor(const Color clr);
|
||||||
|
void OnRender(render::Renderer::Ref &drawer, const i32 x, const i32 y) override;
|
||||||
|
void OnInput(const u64 keys_down, const u64 keys_up, const u64 keys_held, const TouchPoint touch_pos) override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
94
include/Plutonium/Plutonium/include/pu/ui/elm/elm_Toggle.hpp
Normal file
94
include/Plutonium/Plutonium/include/pu/ui/elm/elm_Toggle.hpp
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file Toggle.hpp
|
||||||
|
@brief A Toggle is an Element used to switch between two options by toggling the item.
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <pu/ui/elm/elm_Element.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui::elm {
|
||||||
|
|
||||||
|
class Toggle : public Element {
|
||||||
|
public:
|
||||||
|
static constexpr u32 ContentHorizontalMargin = 30;
|
||||||
|
static constexpr u32 ContentVerticalMargin = 20;
|
||||||
|
|
||||||
|
static constexpr u8 ToggleAlphaIncrement = 48;
|
||||||
|
|
||||||
|
static constexpr Color MakeBackgroundColor(const u8 alpha) {
|
||||||
|
return { 130, 130, 130, alpha };
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
i32 x;
|
||||||
|
i32 y;
|
||||||
|
u64 key;
|
||||||
|
bool checked;
|
||||||
|
Color clr;
|
||||||
|
std::string fnt_name;
|
||||||
|
i32 toggle_alpha;
|
||||||
|
std::string cnt;
|
||||||
|
sdl2::Texture cnt_tex;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Toggle(const i32 x, const i32 y, const std::string &content, const u64 toggle_key, const Color clr);
|
||||||
|
PU_SMART_CTOR(Toggle)
|
||||||
|
~Toggle();
|
||||||
|
|
||||||
|
inline i32 GetX() override {
|
||||||
|
return this->x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetX(const i32 x) {
|
||||||
|
this->x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetY() override {
|
||||||
|
return this->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetY(const i32 y) {
|
||||||
|
this->y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 GetWidth() override;
|
||||||
|
i32 GetHeight() override;
|
||||||
|
|
||||||
|
inline std::string GetContent() {
|
||||||
|
return this->cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetContent(const std::string &content);
|
||||||
|
void SetFont(const std::string &font_name);
|
||||||
|
|
||||||
|
inline Color GetColor() {
|
||||||
|
return this->clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetColor(const Color clr);
|
||||||
|
|
||||||
|
inline u64 GetKey() {
|
||||||
|
return this->key;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetKey(const u64 toggle_key) {
|
||||||
|
this->key = toggle_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsChecked() {
|
||||||
|
return this->checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnRender(render::Renderer::Ref &drawer, const i32 x, const i32 y) override;
|
||||||
|
void OnInput(const u64 keys_down, const u64 keys_up, const u64 keys_held, const TouchPoint touch_pos) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file extras_Toast.hpp
|
||||||
|
@brief An Overlay similar to Android's toast notifications
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <pu/ui/ui_Overlay.hpp>
|
||||||
|
#include <pu/ui/elm/elm_TextBlock.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui::extras {
|
||||||
|
|
||||||
|
class Toast final : public Overlay {
|
||||||
|
public:
|
||||||
|
static constexpr i32 DefaultY = 550;
|
||||||
|
static constexpr i32 HeightAndTextHeightFactor = 3;
|
||||||
|
static constexpr i32 HorizontalMargin = 50;
|
||||||
|
static constexpr u8 BaseAlpha = 200;
|
||||||
|
|
||||||
|
private:
|
||||||
|
pu::ui::elm::TextBlock::Ref text;
|
||||||
|
|
||||||
|
void AdjustDimensions();
|
||||||
|
|
||||||
|
public:
|
||||||
|
Toast(const std::string &text, const std::string &font_name, const Color text_clr, const Color bg_clr);
|
||||||
|
PU_SMART_CTOR(Toast)
|
||||||
|
|
||||||
|
void SetText(const std::string &text);
|
||||||
|
void OnPreRender(render::Renderer::Ref &drawer) override;
|
||||||
|
void OnPostRender(render::Renderer::Ref &drawer) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,199 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file render_Renderer.hpp
|
||||||
|
@brief A Renderer is the object performing basic rendering. (simply, a SDL2 wrapper)
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <pu/ui/ui_Types.hpp>
|
||||||
|
#include <pu/ui/render/render_SDL2.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace pu::ui::render {
|
||||||
|
|
||||||
|
constexpr u32 ScreenWidth = 1280;
|
||||||
|
constexpr u32 ScreenHeight = 720;
|
||||||
|
|
||||||
|
struct RendererInitOptions {
|
||||||
|
u32 sdl_flags;
|
||||||
|
u32 sdl_render_flags;
|
||||||
|
u32 width;
|
||||||
|
u32 height;
|
||||||
|
bool init_ttf;
|
||||||
|
std::vector<u32> extra_default_font_sizes;
|
||||||
|
std::string default_font_path;
|
||||||
|
bool init_mixer;
|
||||||
|
u32 audio_mixer_flags;
|
||||||
|
bool init_img;
|
||||||
|
u32 sdl_img_flags;
|
||||||
|
bool init_pl;
|
||||||
|
bool init_romfs;
|
||||||
|
|
||||||
|
RendererInitOptions(const u32 sdl_flags, const u32 sdl_render_flags, const u32 w = ScreenWidth, const u32 h = ScreenHeight) : sdl_flags(sdl_flags), sdl_render_flags(sdl_render_flags), width(w), height(h), init_ttf(false), extra_default_font_sizes(), default_font_path(), init_mixer(false), audio_mixer_flags(0), init_img(false), sdl_img_flags(0), init_pl(false), init_romfs(false) {}
|
||||||
|
|
||||||
|
inline void UseTTF(const std::string &default_font_path = "") {
|
||||||
|
this->init_ttf = true;
|
||||||
|
|
||||||
|
// Empty font path = using shared font
|
||||||
|
if(!default_font_path.empty()) {
|
||||||
|
this->default_font_path = default_font_path;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->init_pl = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetExtraDefaultFontSize(const u32 font_size) {
|
||||||
|
this->extra_default_font_sizes.push_back(font_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void UseAudio(const u32 audio_mixer_flags) {
|
||||||
|
this->init_mixer = true;
|
||||||
|
this->audio_mixer_flags = audio_mixer_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void UseImage(const u32 sdl_img_flags) {
|
||||||
|
this->init_img = true;
|
||||||
|
this->sdl_img_flags = sdl_img_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void UseRomfs() {
|
||||||
|
this->init_romfs = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr u32 MixerAllFlags = MIX_INIT_FLAC | MIX_INIT_MOD | MIX_INIT_MP3 | MIX_INIT_OGG;
|
||||||
|
constexpr u32 IMGAllFlags = IMG_INIT_PNG | IMG_INIT_JPG | IMG_INIT_TIF | IMG_INIT_WEBP;
|
||||||
|
constexpr u32 RendererSoftwareFlags = SDL_RENDERER_SOFTWARE;
|
||||||
|
constexpr u32 RendererHardwareFlags = SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED;
|
||||||
|
|
||||||
|
struct TextureRenderOptions {
|
||||||
|
i32 alpha_mod;
|
||||||
|
i32 width;
|
||||||
|
i32 height;
|
||||||
|
float rot_angle;
|
||||||
|
|
||||||
|
static constexpr i32 NoAlpha = -1;
|
||||||
|
static constexpr i32 NoWidth = -1;
|
||||||
|
static constexpr i32 NoHeight = -1;
|
||||||
|
static constexpr float NoRotation = -1.0f;
|
||||||
|
|
||||||
|
static constexpr TextureRenderOptions Default() {
|
||||||
|
return { NoAlpha, NoWidth, NoHeight, NoRotation };
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr TextureRenderOptions WithCustomAlpha(const u8 alpha) {
|
||||||
|
return { alpha, NoWidth, NoHeight, NoRotation };
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr TextureRenderOptions WithCustomDimensions(const i32 width, const i32 height) {
|
||||||
|
return { NoAlpha, width, height, NoRotation };
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr TextureRenderOptions WithCustomAlphaAndDimensions(const u8 alpha, const i32 width, const i32 height) {
|
||||||
|
return { alpha, width, height, NoRotation };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Renderer {
|
||||||
|
private:
|
||||||
|
RendererInitOptions init_opts;
|
||||||
|
bool ok_romfs;
|
||||||
|
bool ok_pl;
|
||||||
|
bool initialized;
|
||||||
|
i32 base_x;
|
||||||
|
i32 base_y;
|
||||||
|
i32 base_a;
|
||||||
|
|
||||||
|
inline u8 GetActualAlpha(const u8 input_a) {
|
||||||
|
if(this->base_a >= 0) {
|
||||||
|
return static_cast<u8>(this->base_a);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return input_a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Renderer(const RendererInitOptions init_opts) : init_opts(init_opts), ok_romfs(false), ok_pl(false), initialized(false), base_x(0), base_y(0), base_a(0) {}
|
||||||
|
PU_SMART_CTOR(Renderer)
|
||||||
|
|
||||||
|
void Initialize();
|
||||||
|
void Finalize();
|
||||||
|
|
||||||
|
inline bool HasInitialized() {
|
||||||
|
return this->initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool HasRomFs() {
|
||||||
|
return this->ok_romfs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializeRender(const Color clr);
|
||||||
|
void FinalizeRender();
|
||||||
|
void RenderTexture(sdl2::Texture texture, const i32 x, const i32 y, const TextureRenderOptions opts = TextureRenderOptions::Default());
|
||||||
|
void RenderRectangle(const Color clr, const i32 x, const i32 y, const i32 width, const i32 height);
|
||||||
|
void RenderRectangleFill(const Color clr, const i32 x, const i32 y, const i32 width, const i32 height);
|
||||||
|
|
||||||
|
inline void RenderRectangleOutline(const Color clr, const i32 x, const i32 y, const i32 width, const i32 height, const i32 border_width) {
|
||||||
|
this->RenderRectangleFill(clr, x - border_width, y - border_width, width + (border_width * 2), height + (border_width * 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderRoundedRectangle(const Color clr, const i32 x, const i32 y, const i32 width, const i32 height, const i32 radius);
|
||||||
|
void RenderRoundedRectangleFill(const Color clr, const i32 x, const i32 y, const i32 width, const i32 height, const i32 radius);
|
||||||
|
void RenderCircle(const Color clr, const i32 x, const i32 y, const i32 radius);
|
||||||
|
void RenderCircleFill(const Color clr, const i32 x, const i32 y, const i32 radius);
|
||||||
|
void RenderShadowSimple(const i32 x, const i32 y, const i32 width, const i32 height, const i32 base_alpha, const u8 main_alpha = 0xFF);
|
||||||
|
|
||||||
|
inline void SetBaseRenderPosition(const i32 x, const i32 y) {
|
||||||
|
this->base_x = x;
|
||||||
|
this->base_y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ResetBaseRenderPosition() {
|
||||||
|
this->SetBaseRenderPosition(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetBaseRenderAlpha(const u8 alpha) {
|
||||||
|
this->base_a = alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ResetBaseRenderAlpha() {
|
||||||
|
this->base_a = -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Global rendering
|
||||||
|
|
||||||
|
sdl2::Renderer GetMainRenderer();
|
||||||
|
sdl2::Window GetMainWindow();
|
||||||
|
sdl2::Surface GetMainSurface();
|
||||||
|
|
||||||
|
std::pair<u32, u32> GetDimensions();
|
||||||
|
|
||||||
|
// Text rendering
|
||||||
|
|
||||||
|
bool AddSharedFont(const std::string &font_name, const u32 font_size, const PlSharedFontType type);
|
||||||
|
bool AddAllSharedFonts(const std::string &font_name, const u32 font_size);
|
||||||
|
bool AddFontFile(const std::string &font_name, const u32 font_size, const std::string &path);
|
||||||
|
|
||||||
|
inline void AddDefaultFontFromShared(const u32 font_size) {
|
||||||
|
AddAllSharedFonts(MakeDefaultFontName(font_size), font_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void AddDefaultFontFromFile(const u32 font_size, const std::string &path) {
|
||||||
|
AddFontFile(MakeDefaultFontName(font_size), font_size, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
sdl2::Texture RenderText(const std::string &font_name, const std::string &text, const Color clr);
|
||||||
|
i32 GetTextWidth(const std::string &font_name, const std::string &text);
|
||||||
|
i32 GetTextHeight(const std::string &font_name, const std::string &text);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file render_SDL2.hpp
|
||||||
|
@brief Wrapper code to simplify SDL2 usage
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <pu/ui/ui_Types.hpp>
|
||||||
|
#include <pu/sdl2/sdl2_Types.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui::render {
|
||||||
|
|
||||||
|
sdl2::Texture ConvertToTexture(sdl2::Surface surface);
|
||||||
|
sdl2::Texture LoadImage(const std::string &path);
|
||||||
|
i32 GetTextureWidth(sdl2::Texture texture);
|
||||||
|
i32 GetTextureHeight(sdl2::Texture texture);
|
||||||
|
void SetAlphaValue(sdl2::Texture texture, const u8 alpha);
|
||||||
|
void DeleteTexture(sdl2::Texture &texture);
|
||||||
|
|
||||||
|
}
|
142
include/Plutonium/Plutonium/include/pu/ui/ui_Application.hpp
Normal file
142
include/Plutonium/Plutonium/include/pu/ui/ui_Application.hpp
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file ui_Application.hpp
|
||||||
|
@brief An Application is the base to use the UI system of this library.
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <pu/ui/ui_Dialog.hpp>
|
||||||
|
#include <pu/ui/ui_Layout.hpp>
|
||||||
|
#include <pu/ui/ui_Overlay.hpp>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
namespace pu::ui {
|
||||||
|
|
||||||
|
class Application {
|
||||||
|
public:
|
||||||
|
using OnInputCallback = std::function<void(const u64, const u64, const u64, const TouchPoint)>;
|
||||||
|
using RenderCallback = std::function<void()>;
|
||||||
|
using RenderOverFunction = std::function<bool(render::Renderer::Ref&)>;
|
||||||
|
|
||||||
|
static constexpr u8 DefaultFadeAlphaIncrement = 35;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool loaded;
|
||||||
|
bool in_render_over;
|
||||||
|
RenderOverFunction render_over_fn;
|
||||||
|
bool is_shown;
|
||||||
|
u8 fade_alpha_increment;
|
||||||
|
i32 fade_alpha;
|
||||||
|
Layout::Ref lyt;
|
||||||
|
Overlay::Ref ovl;
|
||||||
|
u64 ovl_timeout_ms;
|
||||||
|
std::chrono::steady_clock::time_point ovl_start_time;
|
||||||
|
std::vector<RenderCallback> render_cbs;
|
||||||
|
OnInputCallback on_ipt_cb;
|
||||||
|
render::Renderer::Ref renderer;
|
||||||
|
PadState input_pad;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Application(render::Renderer::Ref renderer);
|
||||||
|
PU_SMART_CTOR(Application)
|
||||||
|
|
||||||
|
inline void LoadLayout(Layout::Ref lyt) {
|
||||||
|
this->lyt = lyt;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename L>
|
||||||
|
inline std::shared_ptr<L> GetLayout() {
|
||||||
|
static_assert(std::is_base_of_v<ui::Layout, L>);
|
||||||
|
return std::static_pointer_cast<L>(this->lyt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Prepare();
|
||||||
|
|
||||||
|
// Force create a derived Application class which initializes everything here
|
||||||
|
virtual void OnLoad() = 0;
|
||||||
|
|
||||||
|
inline void AddRenderCallback(RenderCallback render_cb) {
|
||||||
|
this->render_cbs.push_back(render_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetOnInput(OnInputCallback on_ipt_cb) {
|
||||||
|
this->on_ipt_cb = on_ipt_cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 ShowDialog(Dialog::Ref &dialog) {
|
||||||
|
return dialog->Show(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 CreateShowDialog(const std::string &title, const std::string &content, const std::vector<std::string> &opts, const bool use_last_opt_as_cancel, const std::string &icon_path = "");
|
||||||
|
|
||||||
|
inline void StartOverlay(Overlay::Ref ovl) {
|
||||||
|
if(this->ovl == nullptr) {
|
||||||
|
this->ovl = ovl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartOverlayWithTimeout(Overlay::Ref ovl, const u64 ms);
|
||||||
|
void EndOverlay();
|
||||||
|
void Show();
|
||||||
|
|
||||||
|
inline void ShowWithFadeIn() {
|
||||||
|
this->FadeIn();
|
||||||
|
this->Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsShown() {
|
||||||
|
return this->is_shown;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool CanBeShown() {
|
||||||
|
return this->loaded && (this->lyt != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CallForRender();
|
||||||
|
bool CallForRenderWithRenderOver(RenderOverFunction render_over_fn);
|
||||||
|
void FadeIn();
|
||||||
|
void FadeOut();
|
||||||
|
|
||||||
|
inline bool IsFadedIn() {
|
||||||
|
return this->fade_alpha > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetFadeAlphaIncrement(const u8 fade_alpha_increment) {
|
||||||
|
this->fade_alpha_increment = fade_alpha_increment;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnRender();
|
||||||
|
void Close();
|
||||||
|
|
||||||
|
inline void CloseWithFadeOut() {
|
||||||
|
this->FadeOut();
|
||||||
|
this->Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u64 GetButtonsDown() {
|
||||||
|
return padGetButtonsDown(&this->input_pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u64 GetButtonsUp() {
|
||||||
|
return padGetButtonsUp(&this->input_pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u64 GetButtonsHeld() {
|
||||||
|
return padGetButtons(&this->input_pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline HidTouchScreenState GetTouchState() {
|
||||||
|
HidTouchScreenState state = {};
|
||||||
|
hidGetTouchScreenStates(&state, 1);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
88
include/Plutonium/Plutonium/include/pu/ui/ui_Container.hpp
Normal file
88
include/Plutonium/Plutonium/include/pu/ui/ui_Container.hpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file ui_Container.hpp
|
||||||
|
@brief A Container is a basic object which contains a bunch of Elements.
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <pu/ui/elm/elm_Element.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include <bits/stdc++.h>
|
||||||
|
|
||||||
|
namespace pu::ui {
|
||||||
|
|
||||||
|
class Container {
|
||||||
|
protected:
|
||||||
|
i32 x;
|
||||||
|
i32 y;
|
||||||
|
i32 w;
|
||||||
|
i32 h;
|
||||||
|
std::vector<elm::Element::Ref> elems;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Container(const i32 x, const i32 y, const i32 width, const i32 height) : x(x), y(y), w(width), h(height), elems() {}
|
||||||
|
PU_SMART_CTOR(Container)
|
||||||
|
|
||||||
|
inline void Add(elm::Element::Ref elem) {
|
||||||
|
this->elems.push_back(elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline elm::Element::Ref &At(const i32 idx) {
|
||||||
|
return this->elems.at(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Has(elm::Element::Ref &elem) {
|
||||||
|
return std::find(this->elems.begin(), this->elems.end(), elem) != this->elems.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Clear() {
|
||||||
|
this->elems.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t GetCount() {
|
||||||
|
return this->elems.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetX(const i32 x) {
|
||||||
|
this->x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetX() {
|
||||||
|
return this->x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetY(const i32 y) {
|
||||||
|
this->y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetY() {
|
||||||
|
return this->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetWidth(const i32 width) {
|
||||||
|
this->w = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetWidth() {
|
||||||
|
return this->w;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetHeight(const i32 height) {
|
||||||
|
this->h = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetHeight() {
|
||||||
|
return this->h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreRender();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
128
include/Plutonium/Plutonium/include/pu/ui/ui_Dialog.hpp
Normal file
128
include/Plutonium/Plutonium/include/pu/ui/ui_Dialog.hpp
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file ui_Dialog.hpp
|
||||||
|
@brief A Dialog is an easy way to ask the user to choose between several options.
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <pu/ui/render/render_Renderer.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace pu::ui {
|
||||||
|
|
||||||
|
class Application;
|
||||||
|
|
||||||
|
class Dialog {
|
||||||
|
public:
|
||||||
|
static constexpr Color DefaultTitleColor = { 0xA, 0xA, 0xA, 0xFF };
|
||||||
|
static constexpr Color DefaultContentColor = { 0x14, 0x14, 0x14, 0xFF };
|
||||||
|
static constexpr Color DefaultOptionColor = { 0xA, 0xA, 0xA, 0xFF };
|
||||||
|
|
||||||
|
static constexpr u32 DialogExtraBaseWidth = 250;
|
||||||
|
static constexpr u32 DialogBorderRadius = 35;
|
||||||
|
|
||||||
|
static constexpr u32 SpaceBetweenOptions = 20;
|
||||||
|
|
||||||
|
static constexpr u32 TitleExtraWidth = 90;
|
||||||
|
static constexpr u32 ContentExtraWidth = 90;
|
||||||
|
static constexpr u32 SpaceBetweenContentAndOptions = 140;
|
||||||
|
static constexpr u32 TitleTopMargin = 20;
|
||||||
|
|
||||||
|
static constexpr u32 TitleX = 45;
|
||||||
|
static constexpr u32 TitleY = 55;
|
||||||
|
static constexpr u32 ContentX = 45;
|
||||||
|
static constexpr u32 ContentY = 140;
|
||||||
|
|
||||||
|
static constexpr u32 IconExtraHeight = 25;
|
||||||
|
|
||||||
|
static constexpr u32 OptionsBaseHorizontalMargin = 45;
|
||||||
|
static constexpr u32 OptionHeight = 60;
|
||||||
|
static constexpr u32 OptionHorizontalMargin = 30;
|
||||||
|
static constexpr u32 OptionBorderRadius = OptionHeight / 3;
|
||||||
|
static constexpr u32 OptionBottomMargin = 25;
|
||||||
|
|
||||||
|
static constexpr u8 MaxScreenFadeAlpha = 125;
|
||||||
|
|
||||||
|
static constexpr u32 IconMargin = 30;
|
||||||
|
|
||||||
|
static inline constexpr Color MakeDialogColor(const u8 alpha) {
|
||||||
|
return { 0xE1, 0xE1, 0xE1, alpha };
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline constexpr Color MakeOverColor(const u8 alpha) {
|
||||||
|
return { 0xB4, 0xB4, 0xC8, alpha };
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr u8 OverAlphaIncrement = 48;
|
||||||
|
static constexpr u8 FadeAlphaIncrement = 25;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string title_font_name;
|
||||||
|
std::string cnt_font_name;
|
||||||
|
std::string opt_font_name;
|
||||||
|
std::string title;
|
||||||
|
std::string cnt;
|
||||||
|
sdl2::Texture title_tex;
|
||||||
|
sdl2::Texture cnt_tex;
|
||||||
|
std::vector<std::string> opts;
|
||||||
|
std::vector<sdl2::Texture> opt_texs;
|
||||||
|
std::string cancel_opt;
|
||||||
|
u32 selected_opt_idx;
|
||||||
|
i32 selected_opt_over_alpha;
|
||||||
|
i32 prev_selected_opt_idx;
|
||||||
|
i32 prev_selected_opt_over_alpha;
|
||||||
|
bool user_cancelled;
|
||||||
|
sdl2::Texture icon_tex;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Dialog(const std::string &title, const std::string &content);
|
||||||
|
PU_SMART_CTOR(Dialog)
|
||||||
|
~Dialog();
|
||||||
|
|
||||||
|
void AddOption(const std::string &opt_name);
|
||||||
|
|
||||||
|
inline void SetCancelOption(const std::string &opt_name) {
|
||||||
|
this->cancel_opt = opt_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void RemoveCancelOption() {
|
||||||
|
this->SetCancelOption("");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool HasCancelOption() {
|
||||||
|
return !this->cancel_opt.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetIcon(const std::string &icon_path);
|
||||||
|
|
||||||
|
inline constexpr bool HasIcon() {
|
||||||
|
return this->icon_tex != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 Show(Application *app_ref);
|
||||||
|
|
||||||
|
inline constexpr bool UserCancelled() {
|
||||||
|
return this->user_cancelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsOk() {
|
||||||
|
if(this->user_cancelled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->HasCancelOption() && (this->selected_opt_idx == (this->opt_texs.size() - 1))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
82
include/Plutonium/Plutonium/include/pu/ui/ui_Layout.hpp
Normal file
82
include/Plutonium/Plutonium/include/pu/ui/ui_Layout.hpp
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file ui_Layout.hpp
|
||||||
|
@brief Contains pu::Layout class, the object used to render within applications
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <pu/ui/ui_Container.hpp>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace pu::ui {
|
||||||
|
|
||||||
|
class Layout : public Container {
|
||||||
|
public:
|
||||||
|
using OnInputCallback = std::function<void(const u64, const u64, const u64, const TouchPoint)>;
|
||||||
|
using RenderCallback = std::function<void()>;
|
||||||
|
|
||||||
|
static constexpr Color DefaultBackgroundColor = { 0xE1, 0xE1, 0xE1, 0xFF };
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool has_image;
|
||||||
|
Color over_bg_color;
|
||||||
|
TouchPoint sim_touch_pos;
|
||||||
|
sdl2::Texture over_bg_tex;
|
||||||
|
OnInputCallback on_ipt;
|
||||||
|
std::vector<RenderCallback> render_cbs;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Layout() : Container(0, 0, render::ScreenWidth, render::ScreenHeight), has_image(false), over_bg_color(DefaultBackgroundColor), sim_touch_pos(), over_bg_tex(), on_ipt(), render_cbs() {}
|
||||||
|
PU_SMART_CTOR(Layout)
|
||||||
|
~Layout();
|
||||||
|
|
||||||
|
inline bool HasChildren() {
|
||||||
|
return !this->elems.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetOnInput(OnInputCallback on_ipt_cb) {
|
||||||
|
this->on_ipt = on_ipt_cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline OnInputCallback GetOnInput() {
|
||||||
|
return this->on_ipt;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void AddRenderCallback(RenderCallback render_cb) {
|
||||||
|
this->render_cbs.push_back(render_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::vector<RenderCallback> &GetRenderCallbacks() {
|
||||||
|
return this->render_cbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool HasBackgroundImage() {
|
||||||
|
return this->has_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline sdl2::Texture GetBackgroundImageTexture() {
|
||||||
|
return this->over_bg_tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Color GetBackgroundColor() {
|
||||||
|
return this->over_bg_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetBackgroundImage(const std::string &path);
|
||||||
|
void SetBackgroundColor(const Color clr);
|
||||||
|
|
||||||
|
inline void SimulateTouchPosition(const TouchPoint sim_touch_pos) {
|
||||||
|
this->sim_touch_pos = sim_touch_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
TouchPoint ConsumeSimulatedTouchPosition();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
53
include/Plutonium/Plutonium/include/pu/ui/ui_Overlay.hpp
Normal file
53
include/Plutonium/Plutonium/include/pu/ui/ui_Overlay.hpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file ui_Overlay.hpp
|
||||||
|
@brief An overlay is some kind of "pop-up", like notification messages or similar items
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <pu/ui/ui_Container.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui {
|
||||||
|
|
||||||
|
class Overlay : public Container {
|
||||||
|
public:
|
||||||
|
static constexpr i32 DefaultRadius = 25;
|
||||||
|
static constexpr i32 MaxFadeAlpha = 200;
|
||||||
|
static constexpr i32 FadeAlphaVariation = 25;
|
||||||
|
|
||||||
|
private:
|
||||||
|
i32 fade_a;
|
||||||
|
Color bg_clr;
|
||||||
|
i32 rad;
|
||||||
|
bool is_ending;
|
||||||
|
bool round;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Overlay(const i32 x, const i32 y, const i32 width, const i32 height, const Color bg_clr, const bool round = true, const i32 radius = DefaultRadius) : Container(x, y, width, height), fade_a(0), bg_clr(bg_clr), rad(radius), is_ending(false), round(round) {}
|
||||||
|
PU_SMART_CTOR(Overlay)
|
||||||
|
|
||||||
|
inline void SetRadius(const i32 radius) {
|
||||||
|
this->rad = radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline i32 GetRadius() {
|
||||||
|
return this->rad;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnPreRender(render::Renderer::Ref &drawer) {}
|
||||||
|
virtual void OnPostRender(render::Renderer::Ref &drawer) {}
|
||||||
|
bool Render(render::Renderer::Ref &drawer);
|
||||||
|
|
||||||
|
inline void NotifyEnding(const bool ending) {
|
||||||
|
this->is_ending = ending;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
82
include/Plutonium/Plutonium/include/pu/ui/ui_Types.hpp
Normal file
82
include/Plutonium/Plutonium/include/pu/ui/ui_Types.hpp
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Plutonium library
|
||||||
|
|
||||||
|
@file ui_Types.hpp
|
||||||
|
@brief Several basic types helpful for UI and rendering, such as Color
|
||||||
|
@author XorTroll
|
||||||
|
|
||||||
|
@copyright Plutonium project - an easy-to-use UI framework for Nintendo Switch homebrew
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <pu/pu_Include.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui {
|
||||||
|
|
||||||
|
// Font sizes Plutonium components use by default
|
||||||
|
|
||||||
|
enum class DefaultFontSize : u32 {
|
||||||
|
Small,
|
||||||
|
Medium,
|
||||||
|
MediumLarge,
|
||||||
|
Large,
|
||||||
|
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline constexpr std::array<u32, static_cast<u32>(DefaultFontSize::Count)> DefaultFontSizes = { 18, 20, 25, 30 };
|
||||||
|
|
||||||
|
inline std::string MakeDefaultFontName(const u32 font_size) {
|
||||||
|
return "DefaultFont@" + std::to_string(font_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr u32 GetDefaultFontSize(const DefaultFontSize kind) {
|
||||||
|
return DefaultFontSizes[static_cast<u32>(kind)];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string GetDefaultFont(const DefaultFontSize kind) {
|
||||||
|
return MakeDefaultFontName(GetDefaultFontSize(kind));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Color {
|
||||||
|
u8 r;
|
||||||
|
u8 g;
|
||||||
|
u8 b;
|
||||||
|
u8 a;
|
||||||
|
|
||||||
|
constexpr Color() : r(0), g(0), b(0), a(0xFF) {}
|
||||||
|
constexpr Color(const u8 r, const u8 g, const u8 b, const u8 a) : r(r), g(g), b(b), a(a) {}
|
||||||
|
|
||||||
|
static Color FromHex(const std::string &str_clr);
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline constexpr bool TouchHitsRegion(const i32 touch_x, const i32 touch_y, const i32 region_x, const i32 region_y, const i32 region_w, const i32 region_h) {
|
||||||
|
return (touch_x >= region_x) && (touch_x < (region_x + region_w)) && (touch_y >= region_y) && (touch_y < (region_y + region_h));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr u64 TouchPseudoKey = HidNpadButton_29;
|
||||||
|
|
||||||
|
struct TouchPoint {
|
||||||
|
i32 x;
|
||||||
|
i32 y;
|
||||||
|
|
||||||
|
constexpr TouchPoint() : x(-1), y(-1) {}
|
||||||
|
constexpr TouchPoint(const u32 x, const u32 y) : x(x), y(y) {}
|
||||||
|
|
||||||
|
inline constexpr bool IsEmpty() const {
|
||||||
|
return (this->x < 0) && (this->y < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr bool HitsRegion(const i32 region_x, const i32 region_y, const i32 region_w, const i32 region_h) const {
|
||||||
|
if(this->IsEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TouchHitsRegion(this->x, this->y, region_x, region_y, region_w, region_h);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
58
include/Plutonium/Plutonium/source/pu/audio/audio_Music.cpp
Normal file
58
include/Plutonium/Plutonium/source/pu/audio/audio_Music.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include <pu/audio/audio_Music.hpp>
|
||||||
|
|
||||||
|
namespace pu::audio {
|
||||||
|
|
||||||
|
Music OpenMusic(const std::string &path) {
|
||||||
|
return Mix_LoadMUS(path.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayMusic(Music mus, const i32 loops) {
|
||||||
|
Mix_PlayMusic(mus, loops);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayMusicWithFadeIn(Music mus, const i32 loops, const i32 ms) {
|
||||||
|
Mix_FadeInMusic(mus, loops, ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsPlayingMusic() {
|
||||||
|
return Mix_PlayingMusic();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PauseMusic() {
|
||||||
|
Mix_PauseMusic();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResumeMusic() {
|
||||||
|
Mix_ResumeMusic();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetMusicVolume(const i32 vol) {
|
||||||
|
Mix_VolumeMusic(vol);
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 GetMusicVolume() {
|
||||||
|
return Mix_VolumeMusic(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeOutMusic(const i32 ms) {
|
||||||
|
Mix_FadeOutMusic(ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RewindMusic() {
|
||||||
|
Mix_RewindMusic();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StopMusic() {
|
||||||
|
Mix_HaltMusic();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetMusicPosition(const double sec) {
|
||||||
|
Mix_SetMusicPosition(sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DestroyMusic(Music &mus) {
|
||||||
|
Mix_FreeMusic(mus);
|
||||||
|
mus = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
18
include/Plutonium/Plutonium/source/pu/audio/audio_Sfx.cpp
Normal file
18
include/Plutonium/Plutonium/source/pu/audio/audio_Sfx.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <pu/audio/audio_Sfx.hpp>
|
||||||
|
|
||||||
|
namespace pu::audio {
|
||||||
|
|
||||||
|
Sfx LoadSfx(const std::string &path) {
|
||||||
|
return Mix_LoadWAV(path.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlaySfx(Sfx sfx) {
|
||||||
|
Mix_PlayChannel(-1, sfx, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DestroySfx(Sfx &sfx) {
|
||||||
|
Mix_FreeChunk(sfx);
|
||||||
|
sfx = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
2254
include/Plutonium/Plutonium/source/pu/sdl2/sdl2_CustomTtf.c
Normal file
2254
include/Plutonium/Plutonium/source/pu/sdl2/sdl2_CustomTtf.c
Normal file
File diff suppressed because it is too large
Load Diff
142
include/Plutonium/Plutonium/source/pu/ttf/ttf_Font.cpp
Normal file
142
include/Plutonium/Plutonium/source/pu/ttf/ttf_Font.cpp
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
#include <pu/ttf/ttf_Font.hpp>
|
||||||
|
#include <pu/ui/render/render_Renderer.hpp>
|
||||||
|
#include <pu/ui/render/render_SDL2.hpp>
|
||||||
|
|
||||||
|
namespace pu::ttf {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void FileBufferFontFaceDisposingFunction(void *ptr) {
|
||||||
|
if(ptr != nullptr) {
|
||||||
|
auto file_buf = reinterpret_cast<u8*>(ptr);
|
||||||
|
delete[] file_buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Font::~Font() {
|
||||||
|
for(auto &[idx, font] : this->font_faces) {
|
||||||
|
font->Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 Font::LoadFromMemory(void *ptr, const size_t size, FontFaceDisposingFunction disp_fn) {
|
||||||
|
const auto idx = rand();
|
||||||
|
auto font = std::make_unique<FontFace>(ptr, size, disp_fn, this->font_size, reinterpret_cast<void*>(this));
|
||||||
|
this->font_faces.push_back({ idx, std::move(font) });
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 Font::LoadFromFile(const std::string &path) {
|
||||||
|
auto f = fopen(path.c_str(), "rb");
|
||||||
|
if(f) {
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
const auto f_size = ftell(f);
|
||||||
|
rewind(f);
|
||||||
|
if(f_size > 0) {
|
||||||
|
auto font_buf = new u8[f_size]();
|
||||||
|
fread(font_buf, 1, f_size, f);
|
||||||
|
fclose(f);
|
||||||
|
return this->LoadFromMemory(font_buf, f_size, FileBufferFontFaceDisposingFunction);
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return InvalidFontFaceIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Font::Unload(const i32 font_idx) {
|
||||||
|
u32 i = 0;
|
||||||
|
for(auto &[idx, font]: this->font_faces) {
|
||||||
|
if(idx == font_idx) {
|
||||||
|
this->font_faces.erase(this->font_faces.begin() + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sdl2::Font Font::FindValidFontFor(const Uint16 ch) {
|
||||||
|
for(const auto &[idx, font] : this->font_faces) {
|
||||||
|
if(TTF_GlyphIsProvided(font->font, ch)) {
|
||||||
|
return font->font;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
inline void ProcessLineDimensionsImpl(sdl2::Font font, std::string &str, u32 &w, u32 &h) {
|
||||||
|
i32 str_w = 0;
|
||||||
|
i32 str_h = 0;
|
||||||
|
TTF_SizeUTF8(font, str.c_str(), &str_w, &str_h);
|
||||||
|
|
||||||
|
const auto str_w_32 = static_cast<u32>(str_w);
|
||||||
|
const auto str_h_32 = static_cast<u32>(str_h);
|
||||||
|
if(str_w_32 > w) {
|
||||||
|
w = str_w_32;
|
||||||
|
}
|
||||||
|
h += str_h_32;
|
||||||
|
str = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<u32, u32> Font::GetTextDimensions(const std::string &str) {
|
||||||
|
u32 w = 0;
|
||||||
|
u32 h = 0;
|
||||||
|
auto font = this->TryGetFirstFont();
|
||||||
|
if(font != nullptr) {
|
||||||
|
std::string tmp_line;
|
||||||
|
for(const auto &ch: str) {
|
||||||
|
if(ch == '\n') {
|
||||||
|
ProcessLineDimensionsImpl(font, tmp_line, w, h);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tmp_line += ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!tmp_line.empty()) {
|
||||||
|
ProcessLineDimensionsImpl(font, tmp_line, w, h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { w, h };
|
||||||
|
}
|
||||||
|
|
||||||
|
sdl2::Texture Font::RenderText(const std::string &str, const ui::Color clr) {
|
||||||
|
auto font = this->TryGetFirstFont();
|
||||||
|
if(font != nullptr) {
|
||||||
|
const auto [w, _] = ui::render::GetDimensions();
|
||||||
|
auto srf = TTF_RenderUTF8_Blended_Wrapped(font, str.c_str(), { clr.r, clr.g, clr.b, clr.a }, w);
|
||||||
|
return ui::render::ConvertToTexture(srf);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
pu::sdl2::Font TTF_CppWrap_FindValidFont(pu::sdl2::Font font, Uint16 ch) {
|
||||||
|
if(font != nullptr) {
|
||||||
|
auto raw_font_ptr = TTF_CppWrap_GetCppPtrRef(font);
|
||||||
|
if(raw_font_ptr != nullptr) {
|
||||||
|
auto font_ptr = reinterpret_cast<pu::ttf::Font*>(raw_font_ptr);
|
||||||
|
auto find_font = font_ptr->FindValidFontFor(ch);
|
||||||
|
if(find_font == nullptr) {
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return find_font;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
89
include/Plutonium/Plutonium/source/pu/ui/elm/elm_Button.cpp
Normal file
89
include/Plutonium/Plutonium/source/pu/ui/elm/elm_Button.cpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#include <pu/ui/elm/elm_Button.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui::elm {
|
||||||
|
|
||||||
|
Button::Button(const i32 x, const i32 y, const i32 width, const i32 height, const std::string &content, const Color content_clr, const Color bg_clr) : Element::Element() {
|
||||||
|
this->x = x;
|
||||||
|
this->y = y;
|
||||||
|
this->w = width;
|
||||||
|
this->h = height;
|
||||||
|
this->cnt = content;
|
||||||
|
this->cnt_clr = content_clr;
|
||||||
|
this->bg_clr = bg_clr;
|
||||||
|
this->hover = false;
|
||||||
|
this->hover_alpha = 0xFF;
|
||||||
|
this->fnt_name = GetDefaultFont(DefaultFontSize::MediumLarge);
|
||||||
|
this->cnt_tex = nullptr;
|
||||||
|
this->SetContent(content);
|
||||||
|
this->on_click_cb = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Button::~Button() {
|
||||||
|
render::DeleteTexture(this->cnt_tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Button::SetContent(const std::string &content) {
|
||||||
|
this->cnt = content;
|
||||||
|
render::DeleteTexture(this->cnt_tex);
|
||||||
|
this->cnt_tex = render::RenderText(this->fnt_name, content, this->cnt_clr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Button::SetContentColor(const Color content_clr) {
|
||||||
|
this->cnt_clr = content_clr;
|
||||||
|
this->SetContent(this->cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Button::SetContentFont(const std::string &font_name) {
|
||||||
|
this->fnt_name = font_name;
|
||||||
|
this->SetContent(this->cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Button::OnRender(render::Renderer::Ref &drawer, const i32 x, const i32 y) {
|
||||||
|
drawer->RenderRectangleFill(this->bg_clr, x, y, this->w, this->h);
|
||||||
|
if(this->hover) {
|
||||||
|
if(this->hover_alpha < 0xFF) {
|
||||||
|
const auto hover_bg_clr = this->MakeHoverBackgroundColor(this->hover_alpha);
|
||||||
|
drawer->RenderRectangleFill(hover_bg_clr, x, y, this->w, this->h);
|
||||||
|
this->hover_alpha += HoverAlphaIncrement;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->hover_alpha = 0xFF;
|
||||||
|
const auto darker_bg_clr = this->MakeHoverBackgroundColor(-1);
|
||||||
|
drawer->RenderRectangleFill(darker_bg_clr, x, y, this->w, this->h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(this->hover_alpha > 0) {
|
||||||
|
const auto hover_bg_clr = this->MakeHoverBackgroundColor(this->hover_alpha);
|
||||||
|
drawer->RenderRectangleFill(hover_bg_clr, x, y, this->w, this->h);
|
||||||
|
this->hover_alpha -= HoverAlphaIncrement;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->hover_alpha = 0;
|
||||||
|
drawer->RenderRectangleFill(this->bg_clr, x, y, this->w, this->h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto cnt_width = render::GetTextureWidth(this->cnt_tex);
|
||||||
|
const auto cnt_height = render::GetTextureHeight(this->cnt_tex);
|
||||||
|
const auto cnt_x = x + ((this->w - cnt_width) / 2);
|
||||||
|
const auto cnt_y = y + ((this->h - cnt_height) / 2);
|
||||||
|
drawer->RenderTexture(this->cnt_tex, cnt_x, cnt_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Button::OnInput(const u64 keys_down, const u64 keys_up, const u64 keys_held, const TouchPoint touch_pos) {
|
||||||
|
if(this->hover) {
|
||||||
|
if(touch_pos.IsEmpty()) {
|
||||||
|
(this->on_click_cb)();
|
||||||
|
this->hover = false;
|
||||||
|
this->hover_alpha = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(touch_pos.HitsRegion(this->x, this->y, this->w, this->h)) {
|
||||||
|
this->hover = true;
|
||||||
|
this->hover_alpha = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
include/Plutonium/Plutonium/source/pu/ui/elm/elm_Element.cpp
Normal file
38
include/Plutonium/Plutonium/source/pu/ui/elm/elm_Element.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include <pu/ui/elm/elm_Element.hpp>
|
||||||
|
#include <pu/ui/ui_Layout.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui::elm {
|
||||||
|
|
||||||
|
i32 Element::GetProcessedX() {
|
||||||
|
auto x = this->GetX();
|
||||||
|
if(this->parent_container != nullptr) {
|
||||||
|
auto container = reinterpret_cast<Container*>(this->parent_container);
|
||||||
|
x += container->GetX();
|
||||||
|
|
||||||
|
if(this->h_align == HorizontalAlign::Center) {
|
||||||
|
x = container->GetX() + ((container->GetWidth() - this->GetWidth()) / 2);
|
||||||
|
}
|
||||||
|
else if(this->h_align == HorizontalAlign::Right) {
|
||||||
|
x = container->GetX() + (container->GetWidth() - this->GetWidth());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 Element::GetProcessedY() {
|
||||||
|
auto y = this->GetY();
|
||||||
|
if(this->parent_container != nullptr) {
|
||||||
|
auto container = reinterpret_cast<Container*>(this->parent_container);
|
||||||
|
y += container->GetY();
|
||||||
|
|
||||||
|
if(this->v_align == VerticalAlign::Center) {
|
||||||
|
y = container->GetY() + ((container->GetHeight() - this->GetHeight()) / 2);
|
||||||
|
}
|
||||||
|
else if(this->v_align == VerticalAlign::Down) {
|
||||||
|
y = container->GetY() + (container->GetHeight() - this->GetHeight());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
34
include/Plutonium/Plutonium/source/pu/ui/elm/elm_Image.cpp
Normal file
34
include/Plutonium/Plutonium/source/pu/ui/elm/elm_Image.cpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include <pu/ui/elm/elm_Image.hpp>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
namespace pu::ui::elm {
|
||||||
|
|
||||||
|
Image::Image(const i32 x, const i32 y, const std::string &image_path) : Element::Element() {
|
||||||
|
this->x = x;
|
||||||
|
this->y = y;
|
||||||
|
this->img_tex = nullptr;
|
||||||
|
this->rend_opts = render::TextureRenderOptions::Default();
|
||||||
|
this->SetImage(image_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
Image::~Image() {
|
||||||
|
render::DeleteTexture(this->img_tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::SetImage(const std::string &image_path) {
|
||||||
|
render::DeleteTexture(this->img_tex);
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
if(stat(image_path.c_str(), &st) == 0) {
|
||||||
|
this->img_path = image_path;
|
||||||
|
this->img_tex = render::LoadImage(image_path);
|
||||||
|
this->rend_opts.width = render::GetTextureWidth(this->img_tex);
|
||||||
|
this->rend_opts.height = render::GetTextureHeight(this->img_tex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::OnRender(render::Renderer::Ref &drawer, const i32 x, const i32 y) {
|
||||||
|
drawer->RenderTexture(this->img_tex, x, y, this->rend_opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
310
include/Plutonium/Plutonium/source/pu/ui/elm/elm_Menu.cpp
Normal file
310
include/Plutonium/Plutonium/source/pu/ui/elm/elm_Menu.cpp
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
#include <pu/ui/elm/elm_Menu.hpp>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
namespace pu::ui::elm {
|
||||||
|
|
||||||
|
void MenuItem::AddOnKey(OnKeyCallback on_key_cb, const u64 key) {
|
||||||
|
this->on_key_cbs.push_back(on_key_cb);
|
||||||
|
this->on_key_cb_keys.push_back(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuItem::SetIcon(const std::string &icon_path) {
|
||||||
|
struct stat st;
|
||||||
|
if(stat(icon_path.c_str(), &st) == 0) {
|
||||||
|
this->icon_path = icon_path;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->icon_path = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Menu::ReloadItemRenders() {
|
||||||
|
for(auto &name_tex : this->loaded_name_texs) {
|
||||||
|
render::DeleteTexture(name_tex);
|
||||||
|
}
|
||||||
|
this->loaded_name_texs.clear();
|
||||||
|
for(auto &icon_tex : this->loaded_icon_texs) {
|
||||||
|
render::DeleteTexture(icon_tex);
|
||||||
|
}
|
||||||
|
this->loaded_icon_texs.clear();
|
||||||
|
|
||||||
|
const auto item_count = this->GetItemCount();
|
||||||
|
for(u32 i = this->advanced_item_count; i < (this->advanced_item_count + item_count); i++) {
|
||||||
|
auto &item = this->items.at(i);
|
||||||
|
auto name_tex = render::RenderText(this->font_name, item->GetName(), item->GetColor());
|
||||||
|
this->loaded_name_texs.push_back(name_tex);
|
||||||
|
|
||||||
|
if(item->HasIcon()) {
|
||||||
|
auto icon_tex = render::LoadImage(item->GetIconPath());
|
||||||
|
this->loaded_icon_texs.push_back(icon_tex);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->loaded_icon_texs.push_back(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu::Menu(const i32 x, const i32 y, const i32 width, const Color items_clr, const Color items_focus_clr, const i32 items_height, const u32 items_to_show) : Element::Element() {
|
||||||
|
this->x = x;
|
||||||
|
this->y = y;
|
||||||
|
this->w = width;
|
||||||
|
this->items_clr = items_clr;
|
||||||
|
this->scrollbar_clr = DefaultScrollbarColor;
|
||||||
|
this->items_h = items_height;
|
||||||
|
this->items_to_show = items_to_show;
|
||||||
|
this->prev_selected_item_idx = 0;
|
||||||
|
this->selected_item_idx = 0;
|
||||||
|
this->advanced_item_count = 0;
|
||||||
|
this->selected_item_alpha = 0xFF;
|
||||||
|
this->prev_selected_item_alpha = 0;
|
||||||
|
this->on_selection_changed_cb = {};
|
||||||
|
this->cooldown_enabled = false;
|
||||||
|
this->item_touched = false;
|
||||||
|
this->items_focus_clr = items_focus_clr;
|
||||||
|
this->move_mode = 0;
|
||||||
|
this->font_name = GetDefaultFont(DefaultFontSize::MediumLarge);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Menu::ClearItems() {
|
||||||
|
this->items.clear();
|
||||||
|
for(auto &name_tex : this->loaded_name_texs) {
|
||||||
|
render::DeleteTexture(name_tex);
|
||||||
|
}
|
||||||
|
this->loaded_name_texs.clear();
|
||||||
|
for(auto &icon_tex : this->loaded_icon_texs) {
|
||||||
|
render::DeleteTexture(icon_tex);
|
||||||
|
}
|
||||||
|
this->loaded_icon_texs.clear();
|
||||||
|
this->selected_item_idx = 0;
|
||||||
|
this->prev_selected_item_idx = 0;
|
||||||
|
this->advanced_item_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Menu::SetSelectedIndex(const u32 idx) {
|
||||||
|
if(idx < this->items.size()) {
|
||||||
|
this->selected_item_idx = idx;
|
||||||
|
this->advanced_item_count = 0;
|
||||||
|
if(this->selected_item_idx >= (this->items.size() - this->items_to_show)) {
|
||||||
|
this->advanced_item_count = this->items.size() - this->items_to_show;
|
||||||
|
}
|
||||||
|
else if(this->selected_item_idx < this->items_to_show) {
|
||||||
|
this->advanced_item_count = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->advanced_item_count = this->selected_item_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->ReloadItemRenders();
|
||||||
|
this->selected_item_alpha = 0xFF;
|
||||||
|
this->prev_selected_item_alpha = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Menu::OnRender(render::Renderer::Ref &drawer, const i32 x, const i32 y) {
|
||||||
|
if(!this->items.empty()) {
|
||||||
|
const auto item_count = this->GetItemCount();
|
||||||
|
|
||||||
|
if(this->loaded_name_texs.empty()) {
|
||||||
|
this->ReloadItemRenders();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cur_item_y = y;
|
||||||
|
for(u32 i = this->advanced_item_count; i < (this->advanced_item_count + item_count); i++) {
|
||||||
|
const auto loaded_tex_idx = i - this->advanced_item_count;
|
||||||
|
auto name_tex = this->loaded_name_texs.at(loaded_tex_idx);
|
||||||
|
auto icon_tex = this->loaded_icon_texs.at(loaded_tex_idx);
|
||||||
|
if(this->selected_item_idx == i) {
|
||||||
|
drawer->RenderRectangleFill(this->items_clr, x, cur_item_y, this->w, this->items_h);
|
||||||
|
if(this->selected_item_alpha < 0xFF) {
|
||||||
|
const auto focus_clr = this->MakeItemsFocusColor(this->selected_item_alpha);
|
||||||
|
drawer->RenderRectangleFill(focus_clr, x, cur_item_y, this->w, this->items_h);
|
||||||
|
this->selected_item_alpha += ItemAlphaIncrement;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
drawer->RenderRectangleFill(this->items_focus_clr, x, cur_item_y, this->w, this->items_h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(this->prev_selected_item_idx == static_cast<i32>(i)) {
|
||||||
|
drawer->RenderRectangleFill(this->items_clr, x, cur_item_y, this->w, this->items_h);
|
||||||
|
if(this->prev_selected_item_alpha > 0) {
|
||||||
|
const auto focus_clr = this->MakeItemsFocusColor(this->prev_selected_item_alpha);
|
||||||
|
drawer->RenderRectangleFill(focus_clr, x, cur_item_y, this->w, this->items_h);
|
||||||
|
this->prev_selected_item_alpha -= ItemAlphaIncrement;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
drawer->RenderRectangleFill(this->items_clr, x, cur_item_y, this->w, this->items_h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
drawer->RenderRectangleFill(this->items_clr, x, cur_item_y, this->w, this->items_h);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &item = this->items.at(i);
|
||||||
|
const auto name_height = render::GetTextureHeight(name_tex);
|
||||||
|
auto name_x = x + TextMargin;
|
||||||
|
const auto name_y = cur_item_y + ((this->items_h - name_height) / 2);
|
||||||
|
if(item->HasIcon()) {
|
||||||
|
const auto factor = (float)render::GetTextureHeight(icon_tex) / (float)render::GetTextureWidth(icon_tex);
|
||||||
|
auto icon_width = (i32)(this->items_h * IconItemSizesFactor);
|
||||||
|
auto icon_height = icon_width;
|
||||||
|
if(factor < 1) {
|
||||||
|
icon_height = (i32)(icon_width * factor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
icon_width = (i32)(icon_height * factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto icon_x = x + IconMargin;
|
||||||
|
const auto icon_y = cur_item_y + (this->items_h - icon_height) / 2;
|
||||||
|
name_x = icon_x + icon_width + TextMargin;
|
||||||
|
drawer->RenderTexture(icon_tex, icon_x, icon_y, render::TextureRenderOptions::WithCustomDimensions(icon_width, icon_height));
|
||||||
|
}
|
||||||
|
drawer->RenderTexture(name_tex, name_x, name_y);
|
||||||
|
cur_item_y += this->items_h;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->items_to_show < this->items.size()) {
|
||||||
|
const auto scrollbar_x = x + (this->w - ScrollbarWidth);
|
||||||
|
const auto scrollbar_height = this->GetHeight();
|
||||||
|
drawer->RenderRectangleFill(this->scrollbar_clr, scrollbar_x, y, ScrollbarWidth, scrollbar_height);
|
||||||
|
|
||||||
|
const auto light_scrollbar_clr = this->MakeLighterScrollbarColor();
|
||||||
|
const auto scrollbar_front_height = (this->items_to_show * scrollbar_height) / this->items.size();
|
||||||
|
const auto scrollbar_front_y = y + (this->advanced_item_count * (scrollbar_height / this->items.size()));
|
||||||
|
drawer->RenderRectangleFill(light_scrollbar_clr, scrollbar_x, scrollbar_front_y, ScrollbarWidth, scrollbar_front_height);
|
||||||
|
}
|
||||||
|
drawer->RenderShadowSimple(x, cur_item_y, this->w, ShadowHeight, ShadowBaseAlpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Menu::OnInput(const u64 keys_down, const u64 keys_up, const u64 keys_held, const TouchPoint touch_pos) {
|
||||||
|
if(this->items.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->move_mode == 1) {
|
||||||
|
const auto cur_time = std::chrono::steady_clock::now();
|
||||||
|
const auto time_diff_ms = std::chrono::duration_cast<std::chrono::milliseconds>(cur_time - this->move_start_time).count();
|
||||||
|
if(time_diff_ms >= 150) {
|
||||||
|
this->move_mode = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!touch_pos.IsEmpty()) {
|
||||||
|
const auto x = this->GetProcessedX();
|
||||||
|
auto cur_item_y = this->GetProcessedY();
|
||||||
|
const auto item_count = this->GetItemCount();
|
||||||
|
for(u32 i = this->advanced_item_count; i < (this->advanced_item_count + item_count); i++) {
|
||||||
|
if(touch_pos.HitsRegion(x, cur_item_y, this->w, this->items_h)) {
|
||||||
|
this->item_touched = true;
|
||||||
|
this->prev_selected_item_idx = this->selected_item_idx;
|
||||||
|
this->selected_item_idx = i;
|
||||||
|
this->HandleOnSelectionChanged();
|
||||||
|
if(i == this->selected_item_idx) {
|
||||||
|
this->selected_item_alpha = 0xFF;
|
||||||
|
}
|
||||||
|
else if(static_cast<i32>(i) == this->prev_selected_item_idx) {
|
||||||
|
this->prev_selected_item_alpha = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cur_item_y += this->items_h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(this->item_touched) {
|
||||||
|
if((this->selected_item_alpha >= 0xFF) && (this->prev_selected_item_alpha <= 0)) {
|
||||||
|
if(this->cooldown_enabled) {
|
||||||
|
this->cooldown_enabled = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->RunSelectedItemCallback(TouchPseudoKey);
|
||||||
|
}
|
||||||
|
this->item_touched = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(keys_down & HidNpadButton_AnyDown) {
|
||||||
|
auto move = true;
|
||||||
|
if(keys_held & HidNpadButton_StickRDown) {
|
||||||
|
move = false;
|
||||||
|
if(this->move_mode == 0) {
|
||||||
|
this->move_start_time = std::chrono::steady_clock::now();
|
||||||
|
this->move_mode = 1;
|
||||||
|
}
|
||||||
|
else if(move_mode == 2) {
|
||||||
|
this->move_mode = 0;
|
||||||
|
move = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(move) {
|
||||||
|
if(!this->items.empty() && (this->selected_item_idx < (this->items.size() - 1))) {
|
||||||
|
if((this->selected_item_idx - this->advanced_item_count) == (this->items_to_show - 1)) {
|
||||||
|
this->advanced_item_count++;
|
||||||
|
this->selected_item_idx++;
|
||||||
|
this->HandleOnSelectionChanged();
|
||||||
|
this->ReloadItemRenders();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->prev_selected_item_idx = this->selected_item_idx;
|
||||||
|
this->selected_item_idx++;
|
||||||
|
this->HandleOnSelectionChanged();
|
||||||
|
|
||||||
|
this->selected_item_alpha = 0;
|
||||||
|
this->prev_selected_item_alpha = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->selected_item_idx = 0;
|
||||||
|
this->advanced_item_count = 0;
|
||||||
|
if(this->items.size() >= this->items_to_show) {
|
||||||
|
this->ReloadItemRenders();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(keys_down & HidNpadButton_AnyUp) {
|
||||||
|
auto move = true;
|
||||||
|
if(keys_held & HidNpadButton_StickRUp) {
|
||||||
|
move = false;
|
||||||
|
if(this->move_mode == 0) {
|
||||||
|
this->move_start_time = std::chrono::steady_clock::now();
|
||||||
|
this->move_mode = 1;
|
||||||
|
}
|
||||||
|
else if(this->move_mode == 2) {
|
||||||
|
this->move_mode = 0;
|
||||||
|
move = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(move) {
|
||||||
|
if(this->selected_item_idx > 0) {
|
||||||
|
if(this->selected_item_idx == this->advanced_item_count) {
|
||||||
|
this->advanced_item_count--;
|
||||||
|
this->selected_item_idx--;
|
||||||
|
this->HandleOnSelectionChanged();
|
||||||
|
this->ReloadItemRenders();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->prev_selected_item_idx = this->selected_item_idx;
|
||||||
|
this->selected_item_idx--;
|
||||||
|
this->HandleOnSelectionChanged();
|
||||||
|
|
||||||
|
this->selected_item_alpha = 0;
|
||||||
|
this->prev_selected_item_alpha = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->selected_item_idx = this->items.size() - 1;
|
||||||
|
this->advanced_item_count = 0;
|
||||||
|
if(this->items.size() >= this->items_to_show) {
|
||||||
|
this->advanced_item_count = this->items.size() - this->items_to_show;
|
||||||
|
this->ReloadItemRenders();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->RunSelectedItemCallback(keys_down);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
#include <pu/ui/elm/elm_ProgressBar.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui::elm {
|
||||||
|
|
||||||
|
void ProgressBar::SetProgress(const double progress) {
|
||||||
|
if(progress >= this->max_val) {
|
||||||
|
this->val = this->max_val;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->val = progress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProgressBar::OnRender(render::Renderer::Ref &drawer, const i32 x, const i32 y) {
|
||||||
|
const auto progress_width = (i32)((this->val / this->max_val) * (double)this->w);
|
||||||
|
// TODO: set radius?
|
||||||
|
const auto radius = (this->h / 3);
|
||||||
|
drawer->RenderRoundedRectangleFill(this->bg_clr, x, y, this->w, this->h, radius);
|
||||||
|
drawer->RenderRoundedRectangleFill(this->progress_clr, x, y, progress_width, this->h, radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
#include <pu/ui/elm/elm_Rectangle.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui::elm {
|
||||||
|
|
||||||
|
void Rectangle::OnRender(render::Renderer::Ref &drawer, const i32 x, const i32 y) {
|
||||||
|
drawer->RenderRectangleFill(this->clr, x, y, this->w, this->h);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
#include <pu/ui/elm/elm_TextBlock.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui::elm {
|
||||||
|
|
||||||
|
TextBlock::TextBlock(const i32 x, const i32 y, const std::string &text) : Element::Element() {
|
||||||
|
this->x = x;
|
||||||
|
this->y = y;
|
||||||
|
this->clr = DefaultColor;
|
||||||
|
this->text_tex = nullptr;
|
||||||
|
this->fnt_name = GetDefaultFont(DefaultFontSize::MediumLarge);
|
||||||
|
this->SetText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextBlock::~TextBlock() {
|
||||||
|
render::DeleteTexture(this->text_tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 TextBlock::GetWidth() {
|
||||||
|
return render::GetTextureWidth(this->text_tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 TextBlock::GetHeight() {
|
||||||
|
return render::GetTextureHeight(this->text_tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBlock::SetText(const std::string &text) {
|
||||||
|
this->text = text;
|
||||||
|
render::DeleteTexture(this->text_tex);
|
||||||
|
this->text_tex = render::RenderText(this->fnt_name, text, this->clr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBlock::SetFont(const std::string &font_name) {
|
||||||
|
this->fnt_name = font_name;
|
||||||
|
this->SetText(this->text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBlock::SetColor(const Color clr) {
|
||||||
|
this->clr = clr;
|
||||||
|
this->SetText(this->text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBlock::OnRender(render::Renderer::Ref &drawer, const i32 x, const i32 y) {
|
||||||
|
drawer->RenderTexture(this->text_tex, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
80
include/Plutonium/Plutonium/source/pu/ui/elm/elm_Toggle.cpp
Normal file
80
include/Plutonium/Plutonium/source/pu/ui/elm/elm_Toggle.cpp
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#include <pu/ui/elm/elm_Toggle.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui::elm {
|
||||||
|
|
||||||
|
Toggle::Toggle(const i32 x, const i32 y, const std::string &content, const u64 toggle_key, const Color clr) : Element::Element() {
|
||||||
|
this->x = x;
|
||||||
|
this->y = y;
|
||||||
|
this->key = toggle_key;
|
||||||
|
this->clr = clr;
|
||||||
|
this->cnt_tex = nullptr;
|
||||||
|
this->fnt_name = GetDefaultFont(DefaultFontSize::MediumLarge);
|
||||||
|
this->toggle_alpha = 0xFF;
|
||||||
|
this->checked = false;
|
||||||
|
this->SetContent(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toggle::~Toggle() {
|
||||||
|
render::DeleteTexture(this->cnt_tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 Toggle::GetWidth() {
|
||||||
|
return render::GetTextureWidth(this->cnt_tex) + 2 * ContentHorizontalMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 Toggle::GetHeight() {
|
||||||
|
return render::GetTextureHeight(this->cnt_tex) + 2 * ContentVerticalMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toggle::SetContent(const std::string &content) {
|
||||||
|
this->cnt = content;
|
||||||
|
render::DeleteTexture(this->cnt_tex);
|
||||||
|
this->cnt_tex = render::RenderText(this->fnt_name, content, this->clr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toggle::SetFont(const std::string &font_name) {
|
||||||
|
this->fnt_name = font_name;
|
||||||
|
this->SetContent(this->cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toggle::SetColor(const Color clr) {
|
||||||
|
this->clr = clr;
|
||||||
|
this->SetContent(this->cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toggle::OnRender(render::Renderer::Ref &drawer, const i32 x, const i32 y) {
|
||||||
|
const auto bg_width = this->GetWidth();
|
||||||
|
const auto bg_height = this->GetHeight();
|
||||||
|
const auto cnt_x = x + ContentHorizontalMargin;
|
||||||
|
const auto cnt_y = y + ContentVerticalMargin;
|
||||||
|
if(this->checked) {
|
||||||
|
drawer->RenderRectangleFill(MakeBackgroundColor(0xFF), x, y, bg_width, bg_height);
|
||||||
|
if(this->toggle_alpha < 0xFF) {
|
||||||
|
drawer->RenderRectangleFill(MakeBackgroundColor(0xFF - this->toggle_alpha), x, y, bg_width, bg_height);
|
||||||
|
this->toggle_alpha += ToggleAlphaIncrement;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
drawer->RenderRectangleFill(MakeBackgroundColor(0xFF), x, y, bg_width, bg_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
drawer->RenderRectangleFill(this->clr, x, y, bg_width, bg_height);
|
||||||
|
if(this->toggle_alpha > 0)
|
||||||
|
{
|
||||||
|
drawer->RenderRectangleFill(MakeBackgroundColor(this->toggle_alpha), x, y, bg_width, bg_height);
|
||||||
|
this->toggle_alpha -= ToggleAlphaIncrement;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
drawer->RenderRectangleFill(this->clr, x, y, bg_width, bg_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drawer->RenderTexture(this->cnt_tex, cnt_x, cnt_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toggle::OnInput(const u64 keys_down, const u64 keys_up, const u64 keys_held, const TouchPoint touch_pos) {
|
||||||
|
if((keys_down & this->key) || ((this->key == TouchPseudoKey) && touch_pos.HitsRegion(this->x, this->y, this->GetWidth(), this->GetHeight()))) {
|
||||||
|
this->checked = !this->checked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
#include <pu/ui/extras/extras_Toast.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui::extras {
|
||||||
|
|
||||||
|
Toast::Toast(const std::string &text, const std::string &font_name, const Color text_clr, const Color bg_clr) : Overlay(0, DefaultY, 0, 0, bg_clr) {
|
||||||
|
this->text = elm::TextBlock::New(0, 0, text);
|
||||||
|
this->text->SetFont(font_name);
|
||||||
|
this->text->SetColor(text_clr);
|
||||||
|
this->text->SetHorizontalAlign(elm::HorizontalAlign::Center);
|
||||||
|
this->text->SetVerticalAlign(elm::VerticalAlign::Center);
|
||||||
|
this->AdjustDimensions();
|
||||||
|
this->Add(this->text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toast::AdjustDimensions() {
|
||||||
|
const auto text_width = this->text->GetWidth();
|
||||||
|
const auto text_height = this->text->GetHeight();
|
||||||
|
const auto toast_width = text_width + 2 * HorizontalMargin;
|
||||||
|
const auto toast_height = text_height * HeightAndTextHeightFactor;
|
||||||
|
this->SetX((render::ScreenWidth - toast_width) / 2);
|
||||||
|
this->SetWidth(toast_width);
|
||||||
|
this->SetHeight(toast_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toast::SetText(const std::string &text) {
|
||||||
|
this->text->SetText(text);
|
||||||
|
this->AdjustDimensions();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toast::OnPreRender(render::Renderer::Ref &drawer) {
|
||||||
|
drawer->SetBaseRenderAlpha(BaseAlpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toast::OnPostRender(render::Renderer::Ref &drawer) {
|
||||||
|
drawer->ResetBaseRenderAlpha();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,349 @@
|
|||||||
|
#include <pu/ui/render/render_Renderer.hpp>
|
||||||
|
#include <pu/ttf/ttf_Font.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui::render {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Global rendering vars
|
||||||
|
sdl2::Renderer g_Renderer = nullptr;
|
||||||
|
sdl2::Window g_Window = nullptr;
|
||||||
|
sdl2::Surface g_WindowSurface = nullptr;
|
||||||
|
|
||||||
|
// Global font object
|
||||||
|
std::vector<std::pair<std::string, std::shared_ptr<ttf::Font>>> g_FontTable;
|
||||||
|
|
||||||
|
inline bool DoAddSharedFont(std::shared_ptr<ttf::Font> &font, const PlSharedFontType type) {
|
||||||
|
// Let's assume pl services are initialized, and return if anything unexpected happens
|
||||||
|
PlFontData data = {};
|
||||||
|
if(R_FAILED(plGetSharedFontByType(&data, type))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!ttf::Font::IsValidFontFaceIndex(font->LoadFromMemory(data.address, data.size, ttf::Font::EmptyFontFaceDisposingFunction))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ExistsFont(const std::string &font_name) {
|
||||||
|
for(const auto &[name, font]: g_FontTable) {
|
||||||
|
if(name == font_name) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::Initialize() {
|
||||||
|
if(!this->initialized) {
|
||||||
|
if(this->init_opts.init_romfs) {
|
||||||
|
this->ok_romfs = R_SUCCEEDED(romfsInit());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->init_opts.init_pl) {
|
||||||
|
// TODO: choose pl service type?
|
||||||
|
this->ok_pl = R_SUCCEEDED(plInitialize(PlServiceType_User));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check sdl return errcodes!
|
||||||
|
|
||||||
|
SDL_Init(this->init_opts.sdl_flags);
|
||||||
|
g_Window = SDL_CreateWindow("Plutonium-SDL2", 0, 0, this->init_opts.width, this->init_opts.height, 0);
|
||||||
|
g_Renderer = SDL_CreateRenderer(g_Window, -1, this->init_opts.sdl_render_flags);
|
||||||
|
g_WindowSurface = SDL_GetWindowSurface(g_Window);
|
||||||
|
SDL_SetRenderDrawBlendMode(g_Renderer, SDL_BLENDMODE_BLEND);
|
||||||
|
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2");
|
||||||
|
|
||||||
|
if(this->init_opts.init_img) {
|
||||||
|
IMG_Init(this->init_opts.sdl_img_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->init_opts.init_ttf) {
|
||||||
|
TTF_Init();
|
||||||
|
if(!this->init_opts.default_font_path.empty()) {
|
||||||
|
for(const auto size: DefaultFontSizes) {
|
||||||
|
AddDefaultFontFromFile(size, this->init_opts.default_font_path);
|
||||||
|
}
|
||||||
|
for(const auto size: this->init_opts.extra_default_font_sizes) {
|
||||||
|
AddDefaultFontFromFile(size, this->init_opts.default_font_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for(const auto size: DefaultFontSizes) {
|
||||||
|
AddDefaultFontFromShared(size);
|
||||||
|
}
|
||||||
|
for(const auto size: this->init_opts.extra_default_font_sizes) {
|
||||||
|
AddDefaultFontFromShared(size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->init_opts.init_mixer) {
|
||||||
|
Mix_Init(this->init_opts.audio_mixer_flags);
|
||||||
|
Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 4096);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->initialized = true;
|
||||||
|
this->base_a = TextureRenderOptions::NoAlpha;
|
||||||
|
this->base_x = 0;
|
||||||
|
this->base_y = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::Finalize() {
|
||||||
|
if(this->initialized) {
|
||||||
|
// Close all the fonts before closing TTF
|
||||||
|
g_FontTable.clear();
|
||||||
|
|
||||||
|
if(this->init_opts.init_ttf) {
|
||||||
|
TTF_Quit();
|
||||||
|
}
|
||||||
|
if(this->init_opts.init_img) {
|
||||||
|
IMG_Quit();
|
||||||
|
}
|
||||||
|
if(this->init_opts.init_mixer) {
|
||||||
|
Mix_CloseAudio();
|
||||||
|
}
|
||||||
|
if(this->ok_pl) {
|
||||||
|
plExit();
|
||||||
|
}
|
||||||
|
if(this->ok_romfs) {
|
||||||
|
romfsExit();
|
||||||
|
}
|
||||||
|
SDL_DestroyRenderer(g_Renderer);
|
||||||
|
SDL_FreeSurface(g_WindowSurface);
|
||||||
|
SDL_DestroyWindow(g_Window);
|
||||||
|
SDL_Quit();
|
||||||
|
this->initialized = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::InitializeRender(const Color clr) {
|
||||||
|
SDL_SetRenderDrawColor(g_Renderer, clr.r, clr.g, clr.b, clr.a);
|
||||||
|
SDL_RenderClear(g_Renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::FinalizeRender() {
|
||||||
|
SDL_RenderPresent(g_Renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::RenderTexture(sdl2::Texture texture, const i32 x, const i32 y, const TextureRenderOptions opts) {
|
||||||
|
if(texture == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Rect pos = {
|
||||||
|
.x = x + this->base_x,
|
||||||
|
.y = y + this->base_y
|
||||||
|
};
|
||||||
|
if(opts.width != TextureRenderOptions::NoWidth) {
|
||||||
|
pos.w = opts.width;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SDL_QueryTexture(texture, nullptr, nullptr, &pos.w, nullptr);
|
||||||
|
}
|
||||||
|
if(opts.height != TextureRenderOptions::NoHeight) {
|
||||||
|
pos.h = opts.height;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SDL_QueryTexture(texture, nullptr, nullptr, nullptr, &pos.h);
|
||||||
|
}
|
||||||
|
|
||||||
|
float angle = 0;
|
||||||
|
if(opts.rot_angle != TextureRenderOptions::NoRotation) {
|
||||||
|
angle = opts.rot_angle;
|
||||||
|
}
|
||||||
|
if(opts.alpha_mod != TextureRenderOptions::NoAlpha) {
|
||||||
|
SetAlphaValue(texture, static_cast<u8>(opts.alpha_mod));
|
||||||
|
}
|
||||||
|
if(this->base_a >= 0) {
|
||||||
|
SetAlphaValue(texture, static_cast<u8>(this->base_a));
|
||||||
|
}
|
||||||
|
SDL_RenderCopyEx(g_Renderer, texture, nullptr, &pos, angle, nullptr, SDL_FLIP_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::RenderRectangle(const Color clr, const i32 x, const i32 y, const i32 width, const i32 height) {
|
||||||
|
const SDL_Rect rect = {
|
||||||
|
.x = x + this->base_x,
|
||||||
|
.y = y + this->base_y,
|
||||||
|
.w = width,
|
||||||
|
.h = height
|
||||||
|
};
|
||||||
|
SDL_SetRenderDrawColor(g_Renderer, clr.r, clr.g, clr.b, this->GetActualAlpha(clr.a));
|
||||||
|
SDL_RenderDrawRect(g_Renderer, &rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::RenderRectangleFill(const Color clr, const i32 x, const i32 y, const i32 width, const i32 height) {
|
||||||
|
const SDL_Rect rect = {
|
||||||
|
.x = x + this->base_x,
|
||||||
|
.y = y + this->base_y,
|
||||||
|
.w = width,
|
||||||
|
.h = height
|
||||||
|
};
|
||||||
|
SDL_SetRenderDrawColor(g_Renderer, clr.r, clr.g, clr.b, this->GetActualAlpha(clr.a));
|
||||||
|
SDL_RenderFillRect(g_Renderer, &rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::RenderRoundedRectangle(const Color clr, const i32 x, const i32 y, const i32 width, const i32 height, const i32 radius) {
|
||||||
|
auto proper_radius = radius;
|
||||||
|
if((2 * proper_radius) > width) {
|
||||||
|
proper_radius = width / 2;
|
||||||
|
}
|
||||||
|
if((2 * proper_radius) > height) {
|
||||||
|
proper_radius = height / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
roundedRectangleRGBA(g_Renderer, x + this->base_x, y + this->base_y, x + this->base_x + width, y + this->base_y + height, proper_radius, clr.r, clr.g, clr.b, this->GetActualAlpha(clr.a));
|
||||||
|
SDL_SetRenderDrawBlendMode(g_Renderer, SDL_BLENDMODE_BLEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::RenderRoundedRectangleFill(const Color clr, const i32 x, const i32 y, const i32 width, const i32 height, const i32 radius) {
|
||||||
|
auto proper_radius = radius;
|
||||||
|
if((2 * proper_radius) > width) {
|
||||||
|
proper_radius = width / 2;
|
||||||
|
}
|
||||||
|
if((2 * proper_radius) > height) {
|
||||||
|
proper_radius = height / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
roundedBoxRGBA(g_Renderer, x + this->base_x, y + this->base_y, x + this->base_x + width, y + this->base_y + height, proper_radius, clr.r, clr.g, clr.b, this->GetActualAlpha(clr.a));
|
||||||
|
SDL_SetRenderDrawBlendMode(g_Renderer, SDL_BLENDMODE_BLEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::RenderCircle(const Color clr, const i32 x, const i32 y, const i32 radius) {
|
||||||
|
circleRGBA(g_Renderer, x + this->base_x, y + this->base_y, radius - 1, clr.r, clr.g, clr.b, this->GetActualAlpha(clr.a));
|
||||||
|
aacircleRGBA(g_Renderer, x + this->base_x, y + this->base_y, radius - 1, clr.r, clr.g, clr.b, this->GetActualAlpha(clr.a));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::RenderCircleFill(const Color clr, const i32 x, const i32 y, const i32 radius) {
|
||||||
|
filledCircleRGBA(g_Renderer, x + this->base_x, y + this->base_y, radius - 1, clr.r, clr.g, clr.b, this->GetActualAlpha(clr.a));
|
||||||
|
aacircleRGBA(g_Renderer, x + this->base_x, y + this->base_y, radius - 1, clr.r, clr.g, clr.b, this->GetActualAlpha(clr.a));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::RenderShadowSimple(const i32 x, const i32 y, const i32 width, const i32 height, const i32 base_alpha, const u8 main_alpha) {
|
||||||
|
auto crop = false;
|
||||||
|
auto shadow_width = width;
|
||||||
|
auto shadow_x = x;
|
||||||
|
auto shadow_y = y;
|
||||||
|
for(auto cur_a = base_alpha; cur_a > 0; cur_a -= (180 / height)) {
|
||||||
|
const Color shadow_clr = { 130, 130, 130, static_cast<u8>(cur_a * (main_alpha / 0xFF)) };
|
||||||
|
this->RenderRectangleFill(shadow_clr, shadow_x + this->base_x, shadow_y + this->base_y, shadow_width, 1);
|
||||||
|
if(crop) {
|
||||||
|
shadow_width -= 2;
|
||||||
|
shadow_x++;
|
||||||
|
}
|
||||||
|
crop = !crop;
|
||||||
|
shadow_y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sdl2::Renderer GetMainRenderer() {
|
||||||
|
return g_Renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
sdl2::Window GetMainWindow() {
|
||||||
|
return g_Window;
|
||||||
|
}
|
||||||
|
|
||||||
|
sdl2::Surface GetMainSurface() {
|
||||||
|
return g_WindowSurface;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<u32, u32> GetDimensions() {
|
||||||
|
i32 w = 0;
|
||||||
|
i32 h = 0;
|
||||||
|
SDL_GetWindowSize(g_Window, &w, &h);
|
||||||
|
return { static_cast<u32>(w), static_cast<u32>(h) };
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AddSharedFont(const std::string &font_name, const u32 font_size, const PlSharedFontType type) {
|
||||||
|
if(ExistsFont(font_name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto font = std::make_shared<ttf::Font>(font_size);
|
||||||
|
if(!DoAddSharedFont(font, type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_FontTable.push_back(std::make_pair(font_name, std::move(font)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AddAllSharedFonts(const std::string &font_name, const u32 font_size) {
|
||||||
|
if(ExistsFont(font_name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto font = std::make_shared<ttf::Font>(font_size);
|
||||||
|
if(!DoAddSharedFont(font, PlSharedFontType_Standard)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!DoAddSharedFont(font, PlSharedFontType_NintendoExt)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!DoAddSharedFont(font, PlSharedFontType_ChineseSimplified)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!DoAddSharedFont(font, PlSharedFontType_ExtChineseSimplified)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!DoAddSharedFont(font, PlSharedFontType_ChineseTraditional)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!DoAddSharedFont(font, PlSharedFontType_KO)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_FontTable.push_back(std::make_pair(font_name, std::move(font)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AddFontFile(const std::string &font_name, const u32 font_size, const std::string &path) {
|
||||||
|
if(ExistsFont(font_name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto font = std::make_shared<ttf::Font>(font_size);
|
||||||
|
if(!ttf::Font::IsValidFontFaceIndex(font->LoadFromFile(path))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_FontTable.push_back(std::make_pair(font_name, std::move(font)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
sdl2::Texture RenderText(const std::string &font_name, const std::string &text, const Color clr) {
|
||||||
|
for(auto &[name, font]: g_FontTable) {
|
||||||
|
if(name == font_name) {
|
||||||
|
return font->RenderText(text, clr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 GetTextWidth(const std::string &font_name, const std::string &text) {
|
||||||
|
for(auto &[name, font]: g_FontTable) {
|
||||||
|
if(name == font_name) {
|
||||||
|
const auto [w, _] = font->GetTextDimensions(text);
|
||||||
|
return static_cast<i32>(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 GetTextHeight(const std::string &font_name, const std::string &text) {
|
||||||
|
for(auto &[name, font]: g_FontTable) {
|
||||||
|
if(name == font_name) {
|
||||||
|
const auto [_, h] = font->GetTextDimensions(text);
|
||||||
|
return static_cast<i32>(h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
#include <pu/ui/render/render_SDL2.hpp>
|
||||||
|
#include <pu/ui/render/render_Renderer.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui::render {
|
||||||
|
|
||||||
|
sdl2::Texture ConvertToTexture(sdl2::Surface surface) {
|
||||||
|
if(surface == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto tex = SDL_CreateTextureFromSurface(GetMainRenderer(), surface);
|
||||||
|
SDL_FreeSurface(surface);
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
sdl2::Texture LoadImage(const std::string &path) {
|
||||||
|
return ConvertToTexture(IMG_Load(path.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 GetTextureWidth(sdl2::Texture texture) {
|
||||||
|
if(texture == nullptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 w = 0;
|
||||||
|
SDL_QueryTexture(texture, nullptr, nullptr, &w, nullptr);
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 GetTextureHeight(sdl2::Texture texture) {
|
||||||
|
if(texture == nullptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 h = 0;
|
||||||
|
SDL_QueryTexture(texture, nullptr, nullptr, nullptr, &h);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetAlphaValue(sdl2::Texture texture, const u8 alpha) {
|
||||||
|
if(texture == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||||
|
SDL_SetTextureAlphaMod(texture, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeleteTexture(sdl2::Texture &texture) {
|
||||||
|
if(texture != nullptr) {
|
||||||
|
SDL_DestroyTexture(texture);
|
||||||
|
texture = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
212
include/Plutonium/Plutonium/source/pu/ui/ui_Application.cpp
Normal file
212
include/Plutonium/Plutonium/source/pu/ui/ui_Application.cpp
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
#include <pu/ui/ui_Application.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui {
|
||||||
|
|
||||||
|
Application::Application(render::Renderer::Ref renderer) {
|
||||||
|
this->renderer = renderer;
|
||||||
|
// TODO: do it outside ctor, get result...?
|
||||||
|
this->renderer->Initialize();
|
||||||
|
this->is_shown = false;
|
||||||
|
this->on_ipt_cb = {};
|
||||||
|
this->in_render_over = false;
|
||||||
|
this->ovl = nullptr;
|
||||||
|
this->lyt = nullptr;
|
||||||
|
this->loaded = false;
|
||||||
|
this->render_over_fn = {};
|
||||||
|
this->fade_alpha = 0xFF;
|
||||||
|
this->fade_alpha_increment = DefaultFadeAlphaIncrement;
|
||||||
|
padConfigureInput(1, HidNpadStyleSet_NpadStandard);
|
||||||
|
padInitializeDefault(&this->input_pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::Prepare() {
|
||||||
|
if(!this->loaded) {
|
||||||
|
this->OnLoad();
|
||||||
|
this->loaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 Application::CreateShowDialog(const std::string &title, const std::string &content, const std::vector<std::string> &opts, const bool use_last_opt_as_cancel, const std::string &icon_path) {
|
||||||
|
auto dialog = Dialog::New(title, content);
|
||||||
|
for(u32 i = 0; i < opts.size(); i++) {
|
||||||
|
const auto &opt = opts.at(i);
|
||||||
|
if(use_last_opt_as_cancel && (i == (opts.size() - 1))) {
|
||||||
|
dialog->SetCancelOption(opt);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dialog->AddOption(opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!icon_path.empty()) {
|
||||||
|
dialog->SetIcon(icon_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto opt = this->ShowDialog(dialog);
|
||||||
|
if(dialog->UserCancelled()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if(!dialog->IsOk()) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return opt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::StartOverlayWithTimeout(Overlay::Ref ovl, const u64 ms) {
|
||||||
|
if(this->ovl == nullptr) {
|
||||||
|
this->ovl = ovl;
|
||||||
|
this->ovl_timeout_ms = ms;
|
||||||
|
this->ovl_start_time = std::chrono::steady_clock::now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::EndOverlay() {
|
||||||
|
if(this->ovl != nullptr) {
|
||||||
|
this->ovl->NotifyEnding(false);
|
||||||
|
this->ovl_timeout_ms = 0;
|
||||||
|
this->ovl = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::Show() {
|
||||||
|
if(!this->CanBeShown()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->is_shown = true;
|
||||||
|
while(this->is_shown) {
|
||||||
|
this->CallForRender();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Application::CallForRender() {
|
||||||
|
if(!this->CanBeShown()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto continue_render = true;
|
||||||
|
this->renderer->InitializeRender(this->lyt->GetBackgroundColor());
|
||||||
|
this->OnRender();
|
||||||
|
if(this->in_render_over) {
|
||||||
|
continue_render = (this->render_over_fn)(this->renderer);
|
||||||
|
this->in_render_over = false;
|
||||||
|
this->render_over_fn = {};
|
||||||
|
}
|
||||||
|
this->renderer->FinalizeRender();
|
||||||
|
return continue_render;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Application::CallForRenderWithRenderOver(RenderOverFunction render_over_fn) {
|
||||||
|
this->in_render_over = true;
|
||||||
|
this->render_over_fn = render_over_fn;
|
||||||
|
return this->CallForRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::FadeIn() {
|
||||||
|
this->fade_alpha = 0;
|
||||||
|
while(true) {
|
||||||
|
this->CallForRender();
|
||||||
|
this->fade_alpha += this->fade_alpha_increment;
|
||||||
|
if(this->fade_alpha > 0xFF) {
|
||||||
|
this->fade_alpha = 0xFF;
|
||||||
|
this->CallForRender();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::FadeOut() {
|
||||||
|
this->fade_alpha = 0xFF;
|
||||||
|
while(true) {
|
||||||
|
this->CallForRender();
|
||||||
|
this->fade_alpha -= this->fade_alpha_increment;
|
||||||
|
if(this->fade_alpha < 0) {
|
||||||
|
this->fade_alpha = 0;
|
||||||
|
this->CallForRender();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::OnRender() {
|
||||||
|
padUpdate(&this->input_pad);
|
||||||
|
const auto keys_down = this->GetButtonsDown();
|
||||||
|
const auto keys_up = this->GetButtonsUp();
|
||||||
|
const auto keys_held = this->GetButtonsHeld();
|
||||||
|
|
||||||
|
const auto tch_state = this->GetTouchState();
|
||||||
|
TouchPoint tch_pos = {};
|
||||||
|
if(tch_state.count > 0) {
|
||||||
|
tch_pos = { tch_state.touches[0].x, tch_state.touches[0].y };
|
||||||
|
}
|
||||||
|
const auto sim_tch_pos = this->lyt->ConsumeSimulatedTouchPosition();
|
||||||
|
if(!sim_tch_pos.IsEmpty()) {
|
||||||
|
tch_pos = sim_tch_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto &render_cb: this->render_cbs) {
|
||||||
|
if(render_cb) {
|
||||||
|
render_cb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->lyt->PreRender();
|
||||||
|
|
||||||
|
for(auto &lyt_render_cb: this->lyt->GetRenderCallbacks()) {
|
||||||
|
if(lyt_render_cb) {
|
||||||
|
lyt_render_cb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this->in_render_over) {
|
||||||
|
if(this->on_ipt_cb) {
|
||||||
|
(this->on_ipt_cb)(keys_down, keys_up, keys_held, tch_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->lyt->HasBackgroundImage()) {
|
||||||
|
this->renderer->RenderTexture(this->lyt->GetBackgroundImageTexture(), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this->in_render_over) {
|
||||||
|
auto lyt_on_ipt_cb = this->lyt->GetOnInput();
|
||||||
|
if(lyt_on_ipt_cb) {
|
||||||
|
lyt_on_ipt_cb(keys_down, keys_up, keys_held, tch_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(u32 i = 0; i < this->lyt->GetCount(); i++) {
|
||||||
|
auto elm = this->lyt->At(i);
|
||||||
|
if(elm->IsVisible()) {
|
||||||
|
elm->OnRender(this->renderer, elm->GetProcessedX(), elm->GetProcessedY());
|
||||||
|
if(!this->in_render_over) {
|
||||||
|
elm->OnInput(keys_down, keys_up, keys_held, tch_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->ovl != nullptr) {
|
||||||
|
const auto ovl_continue_render = this->ovl->Render(this->renderer);
|
||||||
|
if(this->ovl_timeout_ms > 0) {
|
||||||
|
const auto time_now = std::chrono::steady_clock::now();
|
||||||
|
const u64 elapsed_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(time_now - this->ovl_start_time).count();
|
||||||
|
if(elapsed_time_ms >= this->ovl_timeout_ms) {
|
||||||
|
this->ovl->NotifyEnding(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!ovl_continue_render) {
|
||||||
|
this->EndOverlay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->renderer->RenderRectangleFill({ 0, 0, 0, static_cast<u8>(0xFF - this->fade_alpha) }, 0, 0, render::ScreenWidth, render::ScreenHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::Close() {
|
||||||
|
this->is_shown = false;
|
||||||
|
this->renderer->Finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
11
include/Plutonium/Plutonium/source/pu/ui/ui_Container.cpp
Normal file
11
include/Plutonium/Plutonium/source/pu/ui/ui_Container.cpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include <pu/ui/ui_Container.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui {
|
||||||
|
|
||||||
|
void Container::PreRender() {
|
||||||
|
for(auto &elm : this->elems) {
|
||||||
|
elm->SetParentContainer(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
250
include/Plutonium/Plutonium/source/pu/ui/ui_Dialog.cpp
Normal file
250
include/Plutonium/Plutonium/source/pu/ui/ui_Dialog.cpp
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
#include <pu/ui/ui_Dialog.hpp>
|
||||||
|
#include <pu/ui/ui_Application.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui {
|
||||||
|
|
||||||
|
Dialog::Dialog(const std::string &title, const std::string &content) {
|
||||||
|
this->title_font_name = GetDefaultFont(DefaultFontSize::Large);
|
||||||
|
this->cnt_font_name = GetDefaultFont(DefaultFontSize::Medium);
|
||||||
|
this->opt_font_name = GetDefaultFont(DefaultFontSize::Small);
|
||||||
|
this->title = title;
|
||||||
|
this->cnt = content;
|
||||||
|
this->title_tex = render::RenderText(this->title_font_name, title, DefaultTitleColor);
|
||||||
|
this->cnt_tex = render::RenderText(this->cnt_font_name, content, DefaultContentColor);
|
||||||
|
this->icon_tex = nullptr;
|
||||||
|
this->selected_opt_idx = 0;
|
||||||
|
this->prev_selected_opt_idx = 0;
|
||||||
|
this->selected_opt_over_alpha = 0xFF;
|
||||||
|
this->prev_selected_opt_over_alpha = 0;
|
||||||
|
this->user_cancelled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog::~Dialog() {
|
||||||
|
render::DeleteTexture(this->title_tex);
|
||||||
|
render::DeleteTexture(this->cnt_tex);
|
||||||
|
render::DeleteTexture(this->icon_tex);
|
||||||
|
for(auto &opt_tex: this->opt_texs) {
|
||||||
|
render::DeleteTexture(opt_tex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dialog::AddOption(const std::string &opt_name) {
|
||||||
|
this->opts.push_back(opt_name);
|
||||||
|
this->opt_texs.push_back(render::RenderText(this->opt_font_name, opt_name, DefaultOptionColor));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dialog::SetIcon(const std::string &icon_path) {
|
||||||
|
render::DeleteTexture(this->icon_tex);
|
||||||
|
this->icon_tex = render::LoadImage(icon_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 Dialog::Show(Application *app_ref) {
|
||||||
|
if(this->HasCancelOption()) {
|
||||||
|
this->AddOption(this->cancel_opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->opt_texs.empty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto opts_width = (SpaceBetweenOptions * (this->opt_texs.size() - 1)) + 2 * OptionsBaseHorizontalMargin;
|
||||||
|
for(const auto &opt_tex : this->opt_texs) {
|
||||||
|
const auto opt_width = render::GetTextureWidth(opt_tex) + 2 * OptionHorizontalMargin;
|
||||||
|
opts_width += opt_width;
|
||||||
|
}
|
||||||
|
auto dialog_width = opts_width;
|
||||||
|
|
||||||
|
const auto cnt_width = render::GetTextureWidth(this->cnt_tex) + ContentExtraWidth;
|
||||||
|
if(cnt_width > dialog_width) {
|
||||||
|
dialog_width = cnt_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto title_width = render::GetTextureWidth(this->title_tex) + TitleExtraWidth;
|
||||||
|
if(title_width > dialog_width) {
|
||||||
|
dialog_width = title_width;
|
||||||
|
}
|
||||||
|
const auto title_cnt_height = TitleTopMargin + render::GetTextureHeight(this->title_tex) + render::GetTextureHeight(this->cnt_tex) + SpaceBetweenContentAndOptions;
|
||||||
|
auto opt_base_y = title_cnt_height;
|
||||||
|
|
||||||
|
if(this->HasIcon()) {
|
||||||
|
const auto icon_height = render::GetTextureHeight(this->icon_tex) + 2 * IconMargin;
|
||||||
|
if(icon_height > opt_base_y) {
|
||||||
|
opt_base_y = icon_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto icon_width = render::GetTextureWidth(this->icon_tex) + 2 * IconMargin;
|
||||||
|
|
||||||
|
const auto icon_title_width = title_width + icon_width;
|
||||||
|
if(icon_title_width > dialog_width) {
|
||||||
|
dialog_width = icon_title_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto icon_cnt_width = cnt_width + icon_width;
|
||||||
|
if(icon_cnt_width > dialog_width) {
|
||||||
|
dialog_width = icon_cnt_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto icon_opts_width = opts_width + icon_width;
|
||||||
|
if(icon_opts_width > dialog_width) {
|
||||||
|
dialog_width = icon_opts_width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dialog_width > render::ScreenWidth) {
|
||||||
|
dialog_width = render::ScreenWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dialog_height = opt_base_y + OptionHeight + OptionBottomMargin;
|
||||||
|
if(dialog_height > render::ScreenHeight) {
|
||||||
|
dialog_height = render::ScreenHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto dialog_x = (render::ScreenWidth - dialog_width) / 2;
|
||||||
|
const auto dialog_y = (render::ScreenHeight - dialog_height) / 2;
|
||||||
|
opt_base_y += dialog_y;
|
||||||
|
|
||||||
|
auto is_finishing = false;
|
||||||
|
i32 initial_fade_alpha = 0;
|
||||||
|
while(true) {
|
||||||
|
const auto ok = app_ref->CallForRenderWithRenderOver([&](render::Renderer::Ref &drawer) -> bool {
|
||||||
|
const auto keys_down = app_ref->GetButtonsDown();
|
||||||
|
const auto tch_state = app_ref->GetTouchState();
|
||||||
|
const TouchPoint tch_pos = { tch_state.touches[0].x, tch_state.touches[0].y };
|
||||||
|
if(keys_down & HidNpadButton_AnyLeft) {
|
||||||
|
if(this->selected_opt_idx > 0) {
|
||||||
|
this->prev_selected_opt_idx = this->selected_opt_idx;
|
||||||
|
this->selected_opt_idx--;
|
||||||
|
|
||||||
|
this->selected_opt_over_alpha = 0;
|
||||||
|
this->prev_selected_opt_over_alpha = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(keys_down & HidNpadButton_AnyRight) {
|
||||||
|
if(this->selected_opt_idx < (this->opt_texs.size() - 1)) {
|
||||||
|
this->prev_selected_opt_idx = this->selected_opt_idx;
|
||||||
|
this->selected_opt_idx++;
|
||||||
|
|
||||||
|
this->selected_opt_over_alpha = 0;
|
||||||
|
this->prev_selected_opt_over_alpha = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(keys_down & HidNpadButton_A) {
|
||||||
|
this->user_cancelled = false;
|
||||||
|
is_finishing = true;
|
||||||
|
}
|
||||||
|
else if(keys_down & HidNpadButton_B) {
|
||||||
|
this->user_cancelled = true;
|
||||||
|
is_finishing = true;
|
||||||
|
}
|
||||||
|
if(tch_state.count > 0) {
|
||||||
|
auto cur_opt_x = dialog_x + OptionsBaseHorizontalMargin;
|
||||||
|
for(u32 i = 0; i < this->opts.size(); i++) {
|
||||||
|
auto &opt_tex = this->opt_texs.at(i);
|
||||||
|
const auto opt_name_width = render::GetTextureWidth(opt_tex);
|
||||||
|
const auto opt_width = opt_name_width + 2 * OptionHorizontalMargin;
|
||||||
|
|
||||||
|
if(tch_pos.HitsRegion(cur_opt_x, opt_base_y, opt_width, OptionHeight)) {
|
||||||
|
this->selected_opt_idx = i;
|
||||||
|
this->user_cancelled = false;
|
||||||
|
is_finishing = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_opt_x += opt_width + SpaceBetweenOptions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto dialog_clr = MakeDialogColor(static_cast<u8>(initial_fade_alpha));
|
||||||
|
auto screen_fade_alpha = initial_fade_alpha;
|
||||||
|
if(screen_fade_alpha < 0) {
|
||||||
|
screen_fade_alpha = 0;
|
||||||
|
}
|
||||||
|
if(screen_fade_alpha > MaxScreenFadeAlpha) {
|
||||||
|
screen_fade_alpha = MaxScreenFadeAlpha;
|
||||||
|
}
|
||||||
|
const Color screen_fade_clr = { 0, 0, 0, static_cast<u8>(screen_fade_alpha) };
|
||||||
|
drawer->RenderRectangleFill(screen_fade_clr, 0, 0, render::ScreenWidth, render::ScreenHeight);
|
||||||
|
|
||||||
|
drawer->RenderRoundedRectangleFill(dialog_clr, dialog_x, dialog_y, dialog_width, dialog_height, DialogBorderRadius);
|
||||||
|
|
||||||
|
render::SetAlphaValue(this->title_tex, initial_fade_alpha);
|
||||||
|
render::SetAlphaValue(this->cnt_tex, initial_fade_alpha);
|
||||||
|
drawer->RenderTexture(this->title_tex, dialog_x + TitleX, dialog_y + TitleY);
|
||||||
|
drawer->RenderTexture(this->cnt_tex, dialog_x + ContentX, dialog_y + ContentY);
|
||||||
|
|
||||||
|
if(this->HasIcon()) {
|
||||||
|
const auto icon_width = render::GetTextureWidth(this->icon_tex);
|
||||||
|
const auto icon_x = dialog_x + (dialog_width - (icon_width + 2 * IconMargin));
|
||||||
|
const auto icon_y = dialog_y + IconMargin;
|
||||||
|
drawer->RenderTexture(this->icon_tex, icon_x, icon_y, render::TextureRenderOptions::WithCustomAlpha(static_cast<u8>(initial_fade_alpha)));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cur_opt_x = dialog_x + OptionsBaseHorizontalMargin;
|
||||||
|
for(u32 i = 0; i < this->opt_texs.size(); i++) {
|
||||||
|
auto &opt_tex = this->opt_texs.at(i);
|
||||||
|
const auto opt_name_width = render::GetTextureWidth(opt_tex);
|
||||||
|
const auto opt_name_height = render::GetTextureHeight(opt_tex);
|
||||||
|
const auto opt_width = opt_name_width + 2 * OptionHorizontalMargin;
|
||||||
|
const auto opt_name_x = cur_opt_x + OptionHorizontalMargin;
|
||||||
|
const auto opt_name_y = opt_base_y + ((OptionHeight - opt_name_height) / 2);
|
||||||
|
if(this->selected_opt_idx == i) {
|
||||||
|
if(this->selected_opt_over_alpha < 0xFF) {
|
||||||
|
const auto over_clr = MakeOverColor(static_cast<u8>(this->selected_opt_over_alpha));
|
||||||
|
drawer->RenderRoundedRectangleFill(over_clr, cur_opt_x, opt_base_y, opt_width, OptionHeight, OptionBorderRadius);
|
||||||
|
this->selected_opt_over_alpha += OverAlphaIncrement;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->selected_opt_over_alpha = 0xFF;
|
||||||
|
const auto over_clr = MakeOverColor(static_cast<u8>(initial_fade_alpha));
|
||||||
|
drawer->RenderRoundedRectangleFill(over_clr, cur_opt_x, opt_base_y, opt_width, OptionHeight, OptionBorderRadius);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(this->prev_selected_opt_idx == static_cast<i32>(i)) {
|
||||||
|
if(this->prev_selected_opt_over_alpha > 0) {
|
||||||
|
const auto over_clr = MakeOverColor(static_cast<u8>(this->prev_selected_opt_over_alpha));
|
||||||
|
drawer->RenderRoundedRectangleFill(over_clr, cur_opt_x, opt_base_y, opt_width, OptionHeight, OptionBorderRadius);
|
||||||
|
this->prev_selected_opt_over_alpha -= OverAlphaIncrement;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->prev_selected_opt_over_alpha = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render::SetAlphaValue(opt_tex, static_cast<u8>(initial_fade_alpha));
|
||||||
|
drawer->RenderTexture(opt_tex, opt_name_x, opt_name_y);
|
||||||
|
cur_opt_x += opt_width + SpaceBetweenOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_finishing) {
|
||||||
|
if(initial_fade_alpha == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(initial_fade_alpha > 0) {
|
||||||
|
initial_fade_alpha -= FadeAlphaIncrement;
|
||||||
|
}
|
||||||
|
if(initial_fade_alpha < 0) {
|
||||||
|
initial_fade_alpha = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(initial_fade_alpha < 0xFF) {
|
||||||
|
initial_fade_alpha += FadeAlphaIncrement;
|
||||||
|
}
|
||||||
|
if(initial_fade_alpha > 0xFF) {
|
||||||
|
initial_fade_alpha = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!ok) {
|
||||||
|
app_ref->CallForRenderWithRenderOver([](render::Renderer::Ref&) -> bool { return false; });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this->selected_opt_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
27
include/Plutonium/Plutonium/source/pu/ui/ui_Layout.cpp
Normal file
27
include/Plutonium/Plutonium/source/pu/ui/ui_Layout.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include <pu/ui/ui_Layout.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui {
|
||||||
|
|
||||||
|
Layout::~Layout() {
|
||||||
|
render::DeleteTexture(this->over_bg_tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Layout::SetBackgroundImage(const std::string &path) {
|
||||||
|
render::DeleteTexture(this->over_bg_tex);
|
||||||
|
this->has_image = true;
|
||||||
|
this->over_bg_tex = render::LoadImage(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Layout::SetBackgroundColor(const Color clr) {
|
||||||
|
render::DeleteTexture(this->over_bg_tex);
|
||||||
|
this->has_image = false;
|
||||||
|
this->over_bg_color = clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
TouchPoint Layout::ConsumeSimulatedTouchPosition() {
|
||||||
|
auto touch_pos_copy = this->sim_touch_pos;
|
||||||
|
this->sim_touch_pos = {};
|
||||||
|
return touch_pos_copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
46
include/Plutonium/Plutonium/source/pu/ui/ui_Overlay.cpp
Normal file
46
include/Plutonium/Plutonium/source/pu/ui/ui_Overlay.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#include <pu/ui/ui_Overlay.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui {
|
||||||
|
|
||||||
|
bool Overlay::Render(render::Renderer::Ref &drawer) {
|
||||||
|
this->OnPreRender(drawer);
|
||||||
|
drawer->SetBaseRenderAlpha(static_cast<u8>(this->fade_a));
|
||||||
|
if(this->round) {
|
||||||
|
drawer->RenderRoundedRectangleFill(this->bg_clr, this->x, this->y, this->w, this->h, this->rad);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
drawer->RenderRectangleFill(this->bg_clr, this->x, this->y, this->w, this->h);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->PreRender();
|
||||||
|
for(auto &elem: this->elems) {
|
||||||
|
if(elem->IsVisible()) {
|
||||||
|
elem->OnRender(drawer, elem->GetProcessedX(), elem->GetProcessedY());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drawer->ResetBaseRenderAlpha();
|
||||||
|
if(this->is_ending) {
|
||||||
|
if(this->fade_a > 0) {
|
||||||
|
this->fade_a -= FadeAlphaVariation;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->fade_a = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(this->fade_a < MaxFadeAlpha) {
|
||||||
|
this->fade_a += FadeAlphaVariation;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->fade_a = MaxFadeAlpha;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->OnPostRender(drawer);
|
||||||
|
const auto is_finished = this->is_ending && (this->fade_a == 0);
|
||||||
|
if(is_finished) {
|
||||||
|
this->is_ending = false;
|
||||||
|
}
|
||||||
|
return !is_finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
30
include/Plutonium/Plutonium/source/pu/ui/ui_Types.cpp
Normal file
30
include/Plutonium/Plutonium/source/pu/ui/ui_Types.cpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#include <pu/ui/ui_Types.hpp>
|
||||||
|
|
||||||
|
namespace pu::ui {
|
||||||
|
|
||||||
|
Color Color::FromHex(const std::string &str_clr) {
|
||||||
|
// Format: '#rrggbbaa'
|
||||||
|
|
||||||
|
std::string r = "00";
|
||||||
|
std::string g = "00";
|
||||||
|
std::string b = "00";
|
||||||
|
std::string a = "FF";
|
||||||
|
|
||||||
|
if(str_clr.length() >= 9) {
|
||||||
|
a = str_clr.substr(7, 2);
|
||||||
|
}
|
||||||
|
if(str_clr.length() >= 7)
|
||||||
|
{
|
||||||
|
r = str_clr.substr(1, 2);
|
||||||
|
g = str_clr.substr(3, 2);
|
||||||
|
b = str_clr.substr(5, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto r_val = static_cast<u8>(std::stoul(r, nullptr, 16));
|
||||||
|
const auto g_val = static_cast<u8>(std::stoul(g, nullptr, 16));
|
||||||
|
const auto b_val = static_cast<u8>(std::stoul(b, nullptr, 16));
|
||||||
|
const auto a_val = static_cast<u8>(std::stoul(a, nullptr, 16));
|
||||||
|
return { r_val, g_val, b_val, a_val };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user