mirror of
https://github.com/wiiu-env/libgui.git
synced 2024-11-14 12:25:10 +01:00
First commit, have fun!
This commit is contained in:
parent
c16417d3f9
commit
345bb53c6a
49
.gitignore
vendored
49
.gitignore
vendored
@ -1,47 +1,2 @@
|
|||||||
# Windows image file caches
|
release/*
|
||||||
Thumbs.db
|
libgui.cbp
|
||||||
ehthumbs.db
|
|
||||||
|
|
||||||
# Folder config file
|
|
||||||
Desktop.ini
|
|
||||||
|
|
||||||
# Recycle Bin used on file shares
|
|
||||||
$RECYCLE.BIN/
|
|
||||||
|
|
||||||
# Windows Installer files
|
|
||||||
*.cab
|
|
||||||
*.msi
|
|
||||||
*.msm
|
|
||||||
*.msp
|
|
||||||
|
|
||||||
# Windows shortcuts
|
|
||||||
*.lnk
|
|
||||||
|
|
||||||
# =========================
|
|
||||||
# Operating System Files
|
|
||||||
# =========================
|
|
||||||
|
|
||||||
# OSX
|
|
||||||
# =========================
|
|
||||||
|
|
||||||
.DS_Store
|
|
||||||
.AppleDouble
|
|
||||||
.LSOverride
|
|
||||||
|
|
||||||
# Thumbnails
|
|
||||||
._*
|
|
||||||
|
|
||||||
# Files that might appear in the root of a volume
|
|
||||||
.DocumentRevisions-V100
|
|
||||||
.fseventsd
|
|
||||||
.Spotlight-V100
|
|
||||||
.TemporaryItems
|
|
||||||
.Trashes
|
|
||||||
.VolumeIcon.icns
|
|
||||||
|
|
||||||
# Directories potentially created on remote AFP share
|
|
||||||
.AppleDB
|
|
||||||
.AppleDesktop
|
|
||||||
Network Trash Folder
|
|
||||||
Temporary Items
|
|
||||||
.apdisk
|
|
140
Makefile
Normal file
140
Makefile
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
DO_LOGGING := 1
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(DEVKITPPC)),)
|
||||||
|
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC)
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(DEVKITPPC)/wii_rules
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# BUILD is the directory where object files & intermediate files will be placed
|
||||||
|
# SOURCES is a list of directories containing source code
|
||||||
|
# INCLUDES is a list of directories containing extra header files
|
||||||
|
# DATA is a list of directories containing binary files
|
||||||
|
# LIBDIR is where the built library will be placed
|
||||||
|
# all directories are relative to this makefile
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
BUILD ?= release
|
||||||
|
SOURCES := source \
|
||||||
|
source/gui \
|
||||||
|
source/resources \
|
||||||
|
source/sounds \
|
||||||
|
source/video \
|
||||||
|
source/video/shaders
|
||||||
|
INCLUDES := source \
|
||||||
|
include
|
||||||
|
DATA :=
|
||||||
|
LIB := lib
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# options for code generation
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
CFLAGS = -g -Os -Wall -D__wiiu__ -D_GNU_SOURCE $(MACHDEP) $(INCLUDE)
|
||||||
|
CXXFLAGS = $(CFLAGS)
|
||||||
|
|
||||||
|
ifeq ($(DO_LOGGING), 1)
|
||||||
|
CFLAGS += -D__LOGGING__
|
||||||
|
CXXFLAGS += -D__LOGGING__
|
||||||
|
endif
|
||||||
|
|
||||||
|
ASFLAGS := -mregnames
|
||||||
|
|
||||||
|
export WIIUBIN := $(LIB)/libgui.a
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# any extra libraries we wish to link with the project
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBS := -lutils -ldynamiclibs -lfreetype -lgd -lpng -ljpeg -lz -lmad -lvorbisidec
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
# include and lib
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBDIRS :=
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
|
# rules for different file extensions
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export TOPDIR ?= $(CURDIR)/..
|
||||||
|
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
export INCLUDEDIR := $(PORTLIBS)/include/libgui
|
||||||
|
|
||||||
|
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)))
|
||||||
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
||||||
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||||
|
|
||||||
|
|
||||||
|
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||||
|
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) $(sFILES:.s=.o)
|
||||||
|
|
||||||
|
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) -I$(LIBOGC_INC) \
|
||||||
|
-I$(CURDIR)/$(BUILD) -I$(PORTLIBS)/include \
|
||||||
|
-I$(PORTLIBS)/include/freetype2 -I$(PORTLIBS)/include/libutils
|
||||||
|
|
||||||
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) $(PORTLIBS)/lib
|
||||||
|
|
||||||
|
.PHONY: $(BUILD) clean
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
$(BUILD):
|
||||||
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr debug release $(LIB) include
|
||||||
|
|
||||||
|
all: $(WIIUBIN)
|
||||||
|
|
||||||
|
install:
|
||||||
|
@cp $(BUILD)/lib/libgui.a $(PORTLIBS)/lib
|
||||||
|
@mkdir -p $(INCLUDEDIR)/gui/
|
||||||
|
@mkdir -p $(INCLUDEDIR)/resources/
|
||||||
|
@mkdir -p $(INCLUDEDIR)/sounds/
|
||||||
|
@mkdir -p $(INCLUDEDIR)/video/shaders
|
||||||
|
@cp source/gui/*.h $(INCLUDEDIR)/gui/
|
||||||
|
@cp source/resources/*.h $(INCLUDEDIR)/resources/
|
||||||
|
@cp source/sounds/*.h $(INCLUDEDIR)/sounds/
|
||||||
|
@cp source/sounds/*.hpp $(INCLUDEDIR)/sounds/
|
||||||
|
@cp source/video/*.h $(INCLUDEDIR)/video/
|
||||||
|
@cp source/video/shaders/*.h $(INCLUDEDIR)/video/shaders/
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
$(WIIUBIN) : $(OFILES) $(LIB)
|
||||||
|
@rm -f "$(WIIUBIN)"
|
||||||
|
@$(AR) rcs "$(WIIUBIN)" $(OFILES)
|
||||||
|
@echo built ... $(notdir $@)
|
||||||
|
|
||||||
|
|
||||||
|
$(LIB):
|
||||||
|
mkdir $(LIB)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
|
51
README.md
Normal file
51
README.md
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# libgui
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
Following steps are required for initialization:
|
||||||
|
```
|
||||||
|
InitOSFunctionPointers(); // Load OS functions
|
||||||
|
InitPadScoreFunctionPointers();
|
||||||
|
InitVPadFunctionPointers(); // Input functions for GUI control
|
||||||
|
InitFSFunctionPointers(); // To load file from the SD Card
|
||||||
|
InitGX2FunctionPointers(); // For rendering
|
||||||
|
InitAXFunctionPointers(); // For sound
|
||||||
|
|
||||||
|
mount_sd_fat("sd"); // Mounting the SD Card
|
||||||
|
memoryInitialize(); // Initialize memory management
|
||||||
|
|
||||||
|
//DO GUI STUFF HERE!
|
||||||
|
|
||||||
|
memoryRelease();
|
||||||
|
unmount_sd_fat("sd");
|
||||||
|
```
|
||||||
|
|
||||||
|
Link the application with:
|
||||||
|
```
|
||||||
|
-lgui -lutils -ldynamiclibs -lfreetype -lgd -lpng -ljpeg -lz -lmad -lvorbisidec
|
||||||
|
```
|
||||||
|
|
||||||
|
TODO: provide more information
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
To be able to use libgui, you need to install the following dependencies:
|
||||||
|
|
||||||
|
- Application needs to be loaded from the [homebrew_launcher](https://github.com/dimok789/homebrew_launcher)
|
||||||
|
- [libutils](https://github.com/Maschell/libutils) for common functions.
|
||||||
|
- [dynamic_libs](https://github.com/Maschell/dynamic_libs/tree/lib) for access to the functions.
|
||||||
|
|
||||||
|
And other portable libraries that can be found in the "libs" folder of this repository. Extract the "portlibs.zip" into your devkitPro directory.
|
||||||
|
This package includes:
|
||||||
|
|
||||||
|
- freetype2
|
||||||
|
- libgd
|
||||||
|
- libpng
|
||||||
|
- libjpeg
|
||||||
|
- libz
|
||||||
|
- libmad
|
||||||
|
- vorbisidec
|
||||||
|
|
||||||
|
# Credits
|
||||||
|
- Orignally based on https://github.com/dborth/libwiigui
|
||||||
|
- Wii U port / modification / new functions / sound / much more by dimok.
|
||||||
|
- Minor changes by Maschell
|
BIN
libs/portlibs.zip
Normal file
BIN
libs/portlibs.zip
Normal file
Binary file not shown.
607
source/gui/FreeTypeGX.cpp
Normal file
607
source/gui/FreeTypeGX.cpp
Normal file
@ -0,0 +1,607 @@
|
|||||||
|
/*
|
||||||
|
* FreeTypeGX is a wrapper class for libFreeType which renders a compiled
|
||||||
|
* FreeType parsable font so a GX texture for Wii homebrew development.
|
||||||
|
* Copyright (C) 2008 Armin Tamzarian
|
||||||
|
* Modified by Dimok, 2015 for WiiU GX2
|
||||||
|
*
|
||||||
|
* This file is part of FreeTypeGX.
|
||||||
|
*
|
||||||
|
* FreeTypeGX is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FreeTypeGX is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with FreeTypeGX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FreeTypeGX.h"
|
||||||
|
#include "video/CVideo.h"
|
||||||
|
#include "video/shaders/Texture2DShader.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#define ALIGN4(x) (((x) + 3) & ~3)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor for the FreeTypeGX class for WiiXplorer.
|
||||||
|
*/
|
||||||
|
FreeTypeGX::FreeTypeGX(const uint8_t* fontBuffer, FT_Long bufferSize, bool lastFace)
|
||||||
|
{
|
||||||
|
int32_t faceIndex = 0;
|
||||||
|
ftPointSize = 0;
|
||||||
|
GX2InitSampler(&ftSampler, GX2_TEX_CLAMP_CLAMP_BORDER, GX2_TEX_XY_FILTER_BILINEAR);
|
||||||
|
|
||||||
|
FT_Init_FreeType(&ftLibrary);
|
||||||
|
if(lastFace)
|
||||||
|
{
|
||||||
|
FT_New_Memory_Face(ftLibrary, (FT_Byte *)fontBuffer, bufferSize, -1, &ftFace);
|
||||||
|
faceIndex = ftFace->num_faces - 1; // Use the last face
|
||||||
|
FT_Done_Face(ftFace);
|
||||||
|
ftFace = NULL;
|
||||||
|
}
|
||||||
|
FT_New_Memory_Face(ftLibrary, (FT_Byte *) fontBuffer, bufferSize, faceIndex, &ftFace);
|
||||||
|
|
||||||
|
ftKerningEnabled = FT_HAS_KERNING(ftFace);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default destructor for the FreeTypeGX class.
|
||||||
|
*/
|
||||||
|
FreeTypeGX::~FreeTypeGX()
|
||||||
|
{
|
||||||
|
unloadFont();
|
||||||
|
FT_Done_Face(ftFace);
|
||||||
|
FT_Done_FreeType(ftLibrary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a short char string to a wide char string.
|
||||||
|
*
|
||||||
|
* This routine converts a supplied short character string into a wide character string.
|
||||||
|
* Note that it is the user's responsibility to clear the returned buffer once it is no longer needed.
|
||||||
|
*
|
||||||
|
* @param strChar Character string to be converted.
|
||||||
|
* @return Wide character representation of supplied character string.
|
||||||
|
*/
|
||||||
|
|
||||||
|
wchar_t* FreeTypeGX::charToWideChar(const char* strChar)
|
||||||
|
{
|
||||||
|
if (!strChar) return NULL;
|
||||||
|
|
||||||
|
wchar_t *strWChar = new (std::nothrow) wchar_t[strlen(strChar) + 1];
|
||||||
|
if (!strWChar) return NULL;
|
||||||
|
|
||||||
|
int32_t bt = mbstowcs(strWChar, strChar, strlen(strChar));
|
||||||
|
if (bt > 0)
|
||||||
|
{
|
||||||
|
strWChar[bt] = 0;
|
||||||
|
return strWChar;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t *tempDest = strWChar;
|
||||||
|
while ((*tempDest++ = *strChar++))
|
||||||
|
;
|
||||||
|
|
||||||
|
return strWChar;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *FreeTypeGX::wideCharToUTF8(const wchar_t* strChar)
|
||||||
|
{
|
||||||
|
if(!strChar) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t len = 0;
|
||||||
|
wchar_t wc;
|
||||||
|
|
||||||
|
for (size_t i = 0; strChar[i]; ++i)
|
||||||
|
{
|
||||||
|
wc = strChar[i];
|
||||||
|
if (wc < 0x80)
|
||||||
|
++len;
|
||||||
|
else if (wc < 0x800)
|
||||||
|
len += 2;
|
||||||
|
else if (wc < 0x10000)
|
||||||
|
len += 3;
|
||||||
|
else
|
||||||
|
len += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *pOut = new (std::nothrow) char[len];
|
||||||
|
if(!pOut)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
size_t n = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; strChar[i]; ++i)
|
||||||
|
{
|
||||||
|
wc = strChar[i];
|
||||||
|
if (wc < 0x80)
|
||||||
|
pOut[n++] = (char)wc;
|
||||||
|
else if (wc < 0x800)
|
||||||
|
{
|
||||||
|
pOut[n++] = (char)((wc >> 6) | 0xC0);
|
||||||
|
pOut[n++] = (char)((wc & 0x3F) | 0x80);
|
||||||
|
}
|
||||||
|
else if (wc < 0x10000)
|
||||||
|
{
|
||||||
|
pOut[n++] = (char)((wc >> 12) | 0xE0);
|
||||||
|
pOut[n++] = (char)(((wc >> 6) & 0x3F) | 0x80);
|
||||||
|
pOut[n++] = (char)((wc & 0x3F) | 0x80);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pOut[n++] = (char)(((wc >> 18) & 0x07) | 0xF0);
|
||||||
|
pOut[n++] = (char)(((wc >> 12) & 0x3F) | 0x80);
|
||||||
|
pOut[n++] = (char)(((wc >> 6) & 0x3F) | 0x80);
|
||||||
|
pOut[n++] = (char)((wc & 0x3F) | 0x80);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears all loaded font glyph data.
|
||||||
|
*
|
||||||
|
* This routine clears all members of the font map structure and frees all allocated memory back to the system.
|
||||||
|
*/
|
||||||
|
void FreeTypeGX::unloadFont()
|
||||||
|
{
|
||||||
|
map<int16_t, ftGX2Data >::iterator itr;
|
||||||
|
map<wchar_t, ftgxCharData>::iterator itr2;
|
||||||
|
|
||||||
|
for (itr = fontData.begin(); itr != fontData.end(); itr++)
|
||||||
|
{
|
||||||
|
for (itr2 = itr->second.ftgxCharMap.begin(); itr2 != itr->second.ftgxCharMap.end(); itr2++)
|
||||||
|
{
|
||||||
|
if(itr2->second.texture)
|
||||||
|
{
|
||||||
|
if(itr2->second.texture->surface.image_data)
|
||||||
|
free(itr2->second.texture->surface.image_data);
|
||||||
|
|
||||||
|
delete itr2->second.texture;
|
||||||
|
itr2->second.texture = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fontData.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caches the given font glyph in the instance font texture buffer.
|
||||||
|
*
|
||||||
|
* This routine renders and stores the requested glyph's bitmap and relevant information into its own quickly addressible
|
||||||
|
* structure within an instance-specific map.
|
||||||
|
*
|
||||||
|
* @param charCode The requested glyph's character code.
|
||||||
|
* @return A pointer to the allocated font structure.
|
||||||
|
*/
|
||||||
|
ftgxCharData * FreeTypeGX::cacheGlyphData(wchar_t charCode, int16_t pixelSize)
|
||||||
|
{
|
||||||
|
map<int16_t, ftGX2Data>::iterator itr = fontData.find(pixelSize);
|
||||||
|
if (itr != fontData.end())
|
||||||
|
{
|
||||||
|
map<wchar_t, ftgxCharData>::iterator itr2 = itr->second.ftgxCharMap.find(charCode);
|
||||||
|
if (itr2 != itr->second.ftgxCharMap.end())
|
||||||
|
{
|
||||||
|
return &itr2->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//!Cache ascender and decender as well
|
||||||
|
ftGX2Data *ftData = &fontData[pixelSize];
|
||||||
|
|
||||||
|
FT_UInt gIndex;
|
||||||
|
uint16_t textureWidth = 0, textureHeight = 0;
|
||||||
|
if (ftPointSize != pixelSize)
|
||||||
|
{
|
||||||
|
ftPointSize = pixelSize;
|
||||||
|
FT_Set_Pixel_Sizes(ftFace, 0, ftPointSize);
|
||||||
|
ftData->ftgxAlign.ascender = (int16_t) ftFace->size->metrics.ascender >> 6;
|
||||||
|
ftData->ftgxAlign.descender = (int16_t) ftFace->size->metrics.descender >> 6;
|
||||||
|
ftData->ftgxAlign.max = 0;
|
||||||
|
ftData->ftgxAlign.min = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gIndex = FT_Get_Char_Index(ftFace, (FT_ULong) charCode);
|
||||||
|
if (gIndex != 0 && FT_Load_Glyph(ftFace, gIndex, FT_LOAD_DEFAULT | FT_LOAD_RENDER) == 0)
|
||||||
|
{
|
||||||
|
if (ftFace->glyph->format == FT_GLYPH_FORMAT_BITMAP)
|
||||||
|
{
|
||||||
|
FT_Bitmap *glyphBitmap = &ftFace->glyph->bitmap;
|
||||||
|
|
||||||
|
textureWidth = ALIGN4(glyphBitmap->width);
|
||||||
|
textureHeight = ALIGN4(glyphBitmap->rows);
|
||||||
|
if(textureWidth == 0)
|
||||||
|
textureWidth = 4;
|
||||||
|
if(textureHeight == 0)
|
||||||
|
textureHeight = 4;
|
||||||
|
|
||||||
|
ftgxCharData *charData = &ftData->ftgxCharMap[charCode];
|
||||||
|
charData->renderOffsetX = (int16_t) ftFace->glyph->bitmap_left;
|
||||||
|
charData->glyphAdvanceX = (uint16_t) (ftFace->glyph->advance.x >> 6);
|
||||||
|
charData->glyphAdvanceY = (uint16_t) (ftFace->glyph->advance.y >> 6);
|
||||||
|
charData->glyphIndex = (uint32_t) gIndex;
|
||||||
|
charData->renderOffsetY = (int16_t) ftFace->glyph->bitmap_top;
|
||||||
|
charData->renderOffsetMax = (int16_t) ftFace->glyph->bitmap_top;
|
||||||
|
charData->renderOffsetMin = (int16_t) glyphBitmap->rows - ftFace->glyph->bitmap_top;
|
||||||
|
|
||||||
|
//! Initialize texture
|
||||||
|
charData->texture = new GX2Texture;
|
||||||
|
GX2InitTexture(charData->texture, textureWidth, textureHeight, 1, 0, GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM, GX2_SURFACE_DIM_2D, GX2_TILE_MODE_LINEAR_ALIGNED);
|
||||||
|
|
||||||
|
loadGlyphData(glyphBitmap, charData);
|
||||||
|
|
||||||
|
return charData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locates each character in this wrapper's configured font face and proccess them.
|
||||||
|
*
|
||||||
|
* This routine locates each character in the configured font face and renders the glyph's bitmap.
|
||||||
|
* Each bitmap and relevant information is loaded into its own quickly addressible structure within an instance-specific map.
|
||||||
|
*/
|
||||||
|
uint16_t FreeTypeGX::cacheGlyphDataComplete(int16_t pixelSize)
|
||||||
|
{
|
||||||
|
uint32_t i = 0;
|
||||||
|
FT_UInt gIndex;
|
||||||
|
|
||||||
|
FT_ULong charCode = FT_Get_First_Char(ftFace, &gIndex);
|
||||||
|
while (gIndex != 0)
|
||||||
|
{
|
||||||
|
if (cacheGlyphData(charCode, pixelSize) != NULL) ++i;
|
||||||
|
charCode = FT_Get_Next_Char(ftFace, charCode, &gIndex);
|
||||||
|
}
|
||||||
|
return (uint16_t) (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the rendered bitmap into the relevant structure's data buffer.
|
||||||
|
*
|
||||||
|
* This routine does a simple byte-wise copy of the glyph's rendered 8-bit grayscale bitmap into the structure's buffer.
|
||||||
|
* Each byte is converted from the bitmap's intensity value into the a uint32_t RGBA value.
|
||||||
|
*
|
||||||
|
* @param bmp A pointer to the most recently rendered glyph's bitmap.
|
||||||
|
* @param charData A pointer to an allocated ftgxCharData structure whose data represent that of the last rendered glyph.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void FreeTypeGX::loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData)
|
||||||
|
{
|
||||||
|
charData->texture->surface.image_data = (uint8_t *) memalign(charData->texture->surface.align, charData->texture->surface.image_size);
|
||||||
|
if(!charData->texture->surface.image_data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memset(charData->texture->surface.image_data, 0x00, charData->texture->surface.image_size);
|
||||||
|
|
||||||
|
uint8_t *src = (uint8_t *)bmp->buffer;
|
||||||
|
uint16_t *dst = (uint16_t *)charData->texture->surface.image_data;
|
||||||
|
int32_t x, y;
|
||||||
|
|
||||||
|
for(y = 0; y < bmp->rows; y++)
|
||||||
|
{
|
||||||
|
for(x = 0; x < bmp->width; x++)
|
||||||
|
{
|
||||||
|
uint8_t intensity = src[y * bmp->width + x] >> 3;
|
||||||
|
dst[y * charData->texture->surface.pitch + x] = intensity ? ((intensity << 11) | (intensity << 6) | (intensity << 1) | 1) : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_TEXTURE, charData->texture->surface.image_data, charData->texture->surface.image_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the x offset of the rendered string.
|
||||||
|
*
|
||||||
|
* This routine calculates the x offset of the rendered string based off of a supplied positional format parameter.
|
||||||
|
*
|
||||||
|
* @param width Current pixel width of the string.
|
||||||
|
* @param format Positional format of the string.
|
||||||
|
*/
|
||||||
|
int16_t FreeTypeGX::getStyleOffsetWidth(uint16_t width, uint16_t format)
|
||||||
|
{
|
||||||
|
if (format & FTGX_JUSTIFY_LEFT)
|
||||||
|
return 0;
|
||||||
|
else if (format & FTGX_JUSTIFY_CENTER)
|
||||||
|
return -(width >> 1);
|
||||||
|
else if (format & FTGX_JUSTIFY_RIGHT) return -width;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the y offset of the rendered string.
|
||||||
|
*
|
||||||
|
* This routine calculates the y offset of the rendered string based off of a supplied positional format parameter.
|
||||||
|
*
|
||||||
|
* @param offset Current pixel offset data of the string.
|
||||||
|
* @param format Positional format of the string.
|
||||||
|
*/
|
||||||
|
int16_t FreeTypeGX::getStyleOffsetHeight(int16_t format, uint16_t pixelSize)
|
||||||
|
{
|
||||||
|
std::map<int16_t, ftGX2Data>::iterator itr = fontData.find(pixelSize);
|
||||||
|
if (itr == fontData.end()) return 0;
|
||||||
|
|
||||||
|
switch (format & FTGX_ALIGN_MASK)
|
||||||
|
{
|
||||||
|
case FTGX_ALIGN_TOP:
|
||||||
|
return itr->second.ftgxAlign.descender;
|
||||||
|
|
||||||
|
case FTGX_ALIGN_MIDDLE:
|
||||||
|
default:
|
||||||
|
return (itr->second.ftgxAlign.ascender + itr->second.ftgxAlign.descender + 1) >> 1;
|
||||||
|
|
||||||
|
case FTGX_ALIGN_BOTTOM:
|
||||||
|
return itr->second.ftgxAlign.ascender;
|
||||||
|
|
||||||
|
case FTGX_ALIGN_BASELINE:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case FTGX_ALIGN_GLYPH_TOP:
|
||||||
|
return itr->second.ftgxAlign.max;
|
||||||
|
|
||||||
|
case FTGX_ALIGN_GLYPH_MIDDLE:
|
||||||
|
return (itr->second.ftgxAlign.max + itr->second.ftgxAlign.min + 1) >> 1;
|
||||||
|
|
||||||
|
case FTGX_ALIGN_GLYPH_BOTTOM:
|
||||||
|
return itr->second.ftgxAlign.min;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes the supplied text string and prints the results at the specified coordinates.
|
||||||
|
*
|
||||||
|
* This routine processes each character of the supplied text string, loads the relevant preprocessed bitmap buffer,
|
||||||
|
* a texture from said buffer, and loads the resultant texture into the EFB.
|
||||||
|
*
|
||||||
|
* @param x Screen X coordinate at which to output the text.
|
||||||
|
* @param y Screen Y coordinate at which to output the text. Note that this value corresponds to the text string origin and not the top or bottom of the glyphs.
|
||||||
|
* @param text NULL terminated string to output.
|
||||||
|
* @param color Optional color to apply to the text characters. If not specified default value is ftgxWhite: (GXColor){0xff, 0xff, 0xff, 0xff}
|
||||||
|
* @param textStyle Flags which specify any styling which should be applied to the rendered string.
|
||||||
|
* @return The number of characters printed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint16_t FreeTypeGX::drawText(CVideo *video, int16_t x, int16_t y, int16_t z, const wchar_t *text, int16_t pixelSize, const glm::vec4 & color, uint16_t textStyle, uint16_t textWidth, const float &textBlur, const float & colorBlurIntensity, const glm::vec4 & blurColor, const float & internalRenderingScale)
|
||||||
|
{
|
||||||
|
if (!text)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
uint16_t fullTextWidth = (textWidth > 0) ? textWidth : getWidth(text, pixelSize);
|
||||||
|
uint16_t x_pos = x, printed = 0;
|
||||||
|
uint16_t x_offset = 0, y_offset = 0;
|
||||||
|
FT_Vector pairDelta;
|
||||||
|
|
||||||
|
if (textStyle & FTGX_JUSTIFY_MASK)
|
||||||
|
{
|
||||||
|
x_offset = getStyleOffsetWidth(fullTextWidth, textStyle);
|
||||||
|
}
|
||||||
|
if (textStyle & FTGX_ALIGN_MASK)
|
||||||
|
{
|
||||||
|
y_offset = getStyleOffsetHeight(textStyle, pixelSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t i = 0;
|
||||||
|
while (text[i])
|
||||||
|
{
|
||||||
|
ftgxCharData* glyphData = cacheGlyphData(text[i], pixelSize);
|
||||||
|
|
||||||
|
if (glyphData != NULL)
|
||||||
|
{
|
||||||
|
if (ftKerningEnabled && i > 0)
|
||||||
|
{
|
||||||
|
FT_Get_Kerning(ftFace, fontData[pixelSize].ftgxCharMap[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta);
|
||||||
|
x_pos += (pairDelta.x >> 6);
|
||||||
|
|
||||||
|
}
|
||||||
|
copyTextureToFramebuffer(video, glyphData->texture,x_pos + glyphData->renderOffsetX + x_offset, y + glyphData->renderOffsetY - y_offset, z, color, textBlur, colorBlurIntensity, blurColor,internalRenderingScale);
|
||||||
|
|
||||||
|
x_pos += glyphData->glyphAdvanceX;
|
||||||
|
++printed;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return printed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes the supplied string and return the width of the string in pixels.
|
||||||
|
*
|
||||||
|
* This routine processes each character of the supplied text string and calculates the width of the entire string.
|
||||||
|
* Note that if precaching of the entire font set is not enabled any uncached glyph will be cached after the call to this function.
|
||||||
|
*
|
||||||
|
* @param text NULL terminated string to calculate.
|
||||||
|
* @return The width of the text string in pixels.
|
||||||
|
*/
|
||||||
|
uint16_t FreeTypeGX::getWidth(const wchar_t *text, int16_t pixelSize)
|
||||||
|
{
|
||||||
|
if (!text) return 0;
|
||||||
|
|
||||||
|
uint16_t strWidth = 0;
|
||||||
|
FT_Vector pairDelta;
|
||||||
|
int32_t i = 0;
|
||||||
|
|
||||||
|
while (text[i])
|
||||||
|
{
|
||||||
|
ftgxCharData* glyphData = cacheGlyphData(text[i], pixelSize);
|
||||||
|
|
||||||
|
if (glyphData != NULL)
|
||||||
|
{
|
||||||
|
if (ftKerningEnabled && (i > 0))
|
||||||
|
{
|
||||||
|
FT_Get_Kerning(ftFace, fontData[pixelSize].ftgxCharMap[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta);
|
||||||
|
strWidth += pairDelta.x >> 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
strWidth += glyphData->glyphAdvanceX;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return strWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Single char width
|
||||||
|
*/
|
||||||
|
uint16_t FreeTypeGX::getCharWidth(const wchar_t wChar, int16_t pixelSize, const wchar_t prevChar)
|
||||||
|
{
|
||||||
|
uint16_t strWidth = 0;
|
||||||
|
ftgxCharData * glyphData = cacheGlyphData(wChar, pixelSize);
|
||||||
|
|
||||||
|
if (glyphData != NULL)
|
||||||
|
{
|
||||||
|
if (ftKerningEnabled && prevChar != 0x0000)
|
||||||
|
{
|
||||||
|
FT_Vector pairDelta;
|
||||||
|
FT_Get_Kerning(ftFace, fontData[pixelSize].ftgxCharMap[prevChar].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta);
|
||||||
|
strWidth += pairDelta.x >> 6;
|
||||||
|
}
|
||||||
|
strWidth += glyphData->glyphAdvanceX;
|
||||||
|
}
|
||||||
|
|
||||||
|
return strWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes the supplied string and return the height of the string in pixels.
|
||||||
|
*
|
||||||
|
* This routine processes each character of the supplied text string and calculates the height of the entire string.
|
||||||
|
* Note that if precaching of the entire font set is not enabled any uncached glyph will be cached after the call to this function.
|
||||||
|
*
|
||||||
|
* @param text NULL terminated string to calculate.
|
||||||
|
* @return The height of the text string in pixels.
|
||||||
|
*/
|
||||||
|
uint16_t FreeTypeGX::getHeight(const wchar_t *text, int16_t pixelSize)
|
||||||
|
{
|
||||||
|
getOffset(text, pixelSize);
|
||||||
|
return fontData[pixelSize].ftgxAlign.max - fontData[pixelSize].ftgxAlign.min;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximum offset above and minimum offset below the font origin line.
|
||||||
|
*
|
||||||
|
* This function calculates the maximum pixel height above the font origin line and the minimum
|
||||||
|
* pixel height below the font origin line and returns the values in an addressible structure.
|
||||||
|
*
|
||||||
|
* @param text NULL terminated string to calculate.
|
||||||
|
* @param offset returns the max and min values above and below the font origin line
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void FreeTypeGX::getOffset(const wchar_t *text, int16_t pixelSize, uint16_t widthLimit)
|
||||||
|
{
|
||||||
|
if (fontData.find(pixelSize) != fontData.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int16_t strMax = 0, strMin = 9999;
|
||||||
|
uint16_t currWidth = 0;
|
||||||
|
|
||||||
|
int32_t i = 0;
|
||||||
|
|
||||||
|
while (text[i])
|
||||||
|
{
|
||||||
|
if (widthLimit > 0 && currWidth >= widthLimit) break;
|
||||||
|
|
||||||
|
ftgxCharData* glyphData = cacheGlyphData(text[i], pixelSize);
|
||||||
|
|
||||||
|
if (glyphData != NULL)
|
||||||
|
{
|
||||||
|
strMax = glyphData->renderOffsetMax > strMax ? glyphData->renderOffsetMax : strMax;
|
||||||
|
strMin = glyphData->renderOffsetMin < strMin ? glyphData->renderOffsetMin : strMin;
|
||||||
|
currWidth += glyphData->glyphAdvanceX;
|
||||||
|
}
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftPointSize != pixelSize)
|
||||||
|
{
|
||||||
|
ftPointSize = pixelSize;
|
||||||
|
FT_Set_Pixel_Sizes(ftFace, 0, ftPointSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
fontData[pixelSize].ftgxAlign.ascender = ftFace->size->metrics.ascender >> 6;
|
||||||
|
fontData[pixelSize].ftgxAlign.descender = ftFace->size->metrics.descender >> 6;
|
||||||
|
fontData[pixelSize].ftgxAlign.max = strMax;
|
||||||
|
fontData[pixelSize].ftgxAlign.min = strMin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the supplied texture quad to the EFB.
|
||||||
|
*
|
||||||
|
* This routine uses the in-built GX quad builder functions to define the texture bounds and location on the EFB target.
|
||||||
|
*
|
||||||
|
* @param texObj A pointer to the glyph's initialized texture object.
|
||||||
|
* @param texWidth The pixel width of the texture object.
|
||||||
|
* @param texHeight The pixel height of the texture object.
|
||||||
|
* @param screenX The screen X coordinate at which to output the rendered texture.
|
||||||
|
* @param screenY The screen Y coordinate at which to output the rendered texture.
|
||||||
|
* @param color Color to apply to the texture.
|
||||||
|
*/
|
||||||
|
void FreeTypeGX::copyTextureToFramebuffer(CVideo *pVideo, GX2Texture *texture, int16_t x, int16_t y, int16_t z, const glm::vec4 & color, const float & defaultBlur, const float & blurIntensity, const glm::vec4 & blurColor, const float & internalRenderingScale)
|
||||||
|
{
|
||||||
|
static const f32 imageAngle = 0.0f;
|
||||||
|
static const f32 blurScale = (2.0f/ (internalRenderingScale));
|
||||||
|
|
||||||
|
f32 offsetLeft = blurScale * ((f32)x + 0.5f * (f32)texture->surface.width) * (f32)pVideo->getWidthScaleFactor();
|
||||||
|
f32 offsetTop = blurScale * ((f32)y - 0.5f * (f32)texture->surface.height) * (f32)pVideo->getHeightScaleFactor();
|
||||||
|
|
||||||
|
f32 widthScale = blurScale * (f32)texture->surface.width * pVideo->getWidthScaleFactor();
|
||||||
|
f32 heightScale = blurScale * (f32)texture->surface.height * pVideo->getHeightScaleFactor();
|
||||||
|
|
||||||
|
glm::vec3 positionOffsets( offsetLeft, offsetTop, (f32)z );
|
||||||
|
|
||||||
|
//! blur doubles due to blur we have to scale the texture
|
||||||
|
glm::vec3 scaleFactor( widthScale, heightScale, 1.0f );
|
||||||
|
|
||||||
|
glm::vec3 blurDirection;
|
||||||
|
blurDirection[2] = 1.0f;
|
||||||
|
|
||||||
|
Texture2DShader::instance()->setShaders();
|
||||||
|
Texture2DShader::instance()->setAttributeBuffer();
|
||||||
|
Texture2DShader::instance()->setAngle(imageAngle);
|
||||||
|
Texture2DShader::instance()->setOffset(positionOffsets);
|
||||||
|
Texture2DShader::instance()->setScale(scaleFactor);
|
||||||
|
Texture2DShader::instance()->setTextureAndSampler(texture, &ftSampler);
|
||||||
|
|
||||||
|
if(blurIntensity > 0.0f)
|
||||||
|
{
|
||||||
|
//! glow blur color
|
||||||
|
Texture2DShader::instance()->setColorIntensity(blurColor);
|
||||||
|
|
||||||
|
//! glow blur horizontal
|
||||||
|
blurDirection[0] = blurIntensity;
|
||||||
|
blurDirection[1] = 0.0f;
|
||||||
|
Texture2DShader::instance()->setBlurring(blurDirection);
|
||||||
|
Texture2DShader::instance()->draw();
|
||||||
|
|
||||||
|
//! glow blur vertical
|
||||||
|
blurDirection[0] = 0.0f;
|
||||||
|
blurDirection[1] = blurIntensity;
|
||||||
|
Texture2DShader::instance()->setBlurring(blurDirection);
|
||||||
|
Texture2DShader::instance()->draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! set text color
|
||||||
|
Texture2DShader::instance()->setColorIntensity(color);
|
||||||
|
|
||||||
|
//! blur horizontal
|
||||||
|
blurDirection[0] = defaultBlur;
|
||||||
|
blurDirection[1] = 0.0f;
|
||||||
|
Texture2DShader::instance()->setBlurring(blurDirection);
|
||||||
|
Texture2DShader::instance()->draw();
|
||||||
|
|
||||||
|
//! blur vertical
|
||||||
|
blurDirection[0] = 0.0f;
|
||||||
|
blurDirection[1] = defaultBlur;
|
||||||
|
Texture2DShader::instance()->setBlurring(blurDirection);
|
||||||
|
Texture2DShader::instance()->draw();
|
||||||
|
}
|
155
source/gui/FreeTypeGX.h
Normal file
155
source/gui/FreeTypeGX.h
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* FreeTypeGX is a wrapper class for libFreeType which renders a compiled
|
||||||
|
* FreeType parsable font into a GX texture for Wii homebrew development.
|
||||||
|
* Copyright (C) 2008 Armin Tamzarian
|
||||||
|
* Modified by Dimok, 2015 for WiiU GX2
|
||||||
|
*
|
||||||
|
* This file is part of FreeTypeGX.
|
||||||
|
*
|
||||||
|
* FreeTypeGX is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FreeTypeGX is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with FreeTypeGX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FREETYPEGX_H_
|
||||||
|
#define FREETYPEGX_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <ft2build.h>
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
#include FT_BITMAP_H
|
||||||
|
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
|
#include <dynamic_libs/gx2_functions.h>
|
||||||
|
|
||||||
|
/*! \struct ftgxCharData_
|
||||||
|
*
|
||||||
|
* Font face character glyph relevant data structure.
|
||||||
|
*/
|
||||||
|
typedef struct ftgxCharData_
|
||||||
|
{
|
||||||
|
int16_t renderOffsetX; /**< Texture X axis bearing offset. */
|
||||||
|
uint16_t glyphAdvanceX; /**< Character glyph X coordinate advance in pixels. */
|
||||||
|
uint16_t glyphAdvanceY; /**< Character glyph Y coordinate advance in pixels. */
|
||||||
|
uint32_t glyphIndex; /**< Charachter glyph index in the font face. */
|
||||||
|
|
||||||
|
int16_t renderOffsetY; /**< Texture Y axis bearing offset. */
|
||||||
|
int16_t renderOffsetMax; /**< Texture Y axis bearing maximum value. */
|
||||||
|
int16_t renderOffsetMin; /**< Texture Y axis bearing minimum value. */
|
||||||
|
|
||||||
|
GX2Texture * texture;
|
||||||
|
} ftgxCharData;
|
||||||
|
|
||||||
|
/*! \struct ftgxDataOffset_
|
||||||
|
*
|
||||||
|
* Offset structure which hold both a maximum and minimum value.
|
||||||
|
*/
|
||||||
|
typedef struct ftgxDataOffset_
|
||||||
|
{
|
||||||
|
int16_t ascender; /**< Maximum data offset. */
|
||||||
|
int16_t descender; /**< Minimum data offset. */
|
||||||
|
int16_t max; /**< Maximum data offset. */
|
||||||
|
int16_t min; /**< Minimum data offset. */
|
||||||
|
} ftgxDataOffset;
|
||||||
|
|
||||||
|
typedef struct ftgxCharData_ ftgxCharData;
|
||||||
|
typedef struct ftgxDataOffset_ ftgxDataOffset;
|
||||||
|
#define _TEXT(t) L ## t /**< Unicode helper macro. */
|
||||||
|
|
||||||
|
#define FTGX_NULL 0x0000
|
||||||
|
#define FTGX_JUSTIFY_LEFT 0x0001
|
||||||
|
#define FTGX_JUSTIFY_CENTER 0x0002
|
||||||
|
#define FTGX_JUSTIFY_RIGHT 0x0004
|
||||||
|
#define FTGX_JUSTIFY_MASK 0x000f
|
||||||
|
|
||||||
|
#define FTGX_ALIGN_TOP 0x0010
|
||||||
|
#define FTGX_ALIGN_MIDDLE 0x0020
|
||||||
|
#define FTGX_ALIGN_BOTTOM 0x0040
|
||||||
|
#define FTGX_ALIGN_BASELINE 0x0080
|
||||||
|
#define FTGX_ALIGN_GLYPH_TOP 0x0100
|
||||||
|
#define FTGX_ALIGN_GLYPH_MIDDLE 0x0200
|
||||||
|
#define FTGX_ALIGN_GLYPH_BOTTOM 0x0400
|
||||||
|
#define FTGX_ALIGN_MASK 0x0ff0
|
||||||
|
|
||||||
|
#define FTGX_STYLE_UNDERLINE 0x1000
|
||||||
|
#define FTGX_STYLE_STRIKE 0x2000
|
||||||
|
#define FTGX_STYLE_MASK 0xf000
|
||||||
|
|
||||||
|
/**< Constant color value used only to sanitize Doxygen documentation. */
|
||||||
|
static const GX2ColorF32 ftgxWhite = (GX2ColorF32){ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
|
||||||
|
|
||||||
|
//! forward declaration
|
||||||
|
class CVideo;
|
||||||
|
|
||||||
|
/*! \class FreeTypeGX
|
||||||
|
* \brief Wrapper class for the libFreeType library with GX rendering.
|
||||||
|
* \author Armin Tamzarian
|
||||||
|
* \version 0.2.4
|
||||||
|
*
|
||||||
|
* FreeTypeGX acts as a wrapper class for the libFreeType library. It supports precaching of transformed glyph data into
|
||||||
|
* a specified texture format. Rendering of the data to the EFB is accomplished through the application of high performance
|
||||||
|
* GX texture functions resulting in high throughput of string rendering.
|
||||||
|
*/
|
||||||
|
class FreeTypeGX
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
FT_Library ftLibrary; /**< FreeType FT_Library instance. */
|
||||||
|
FT_Face ftFace; /**< FreeType reusable FT_Face typographic object. */
|
||||||
|
int16_t ftPointSize; /**< Current set size of the rendered font. */
|
||||||
|
bool ftKerningEnabled; /**< Flag indicating the availability of font kerning data. */
|
||||||
|
uint8_t vertexIndex; /**< Vertex format descriptor index. */
|
||||||
|
GX2Sampler ftSampler;
|
||||||
|
|
||||||
|
typedef struct _ftGX2Data
|
||||||
|
{
|
||||||
|
ftgxDataOffset ftgxAlign;
|
||||||
|
std::map<wchar_t, ftgxCharData> ftgxCharMap;
|
||||||
|
} ftGX2Data;
|
||||||
|
|
||||||
|
std::map<int16_t, ftGX2Data> fontData; /**< Map which holds the glyph data structures for the corresponding characters in one size. */
|
||||||
|
|
||||||
|
int16_t getStyleOffsetWidth(uint16_t width, uint16_t format);
|
||||||
|
int16_t getStyleOffsetHeight(int16_t format, uint16_t pixelSize);
|
||||||
|
|
||||||
|
void unloadFont();
|
||||||
|
ftgxCharData *cacheGlyphData(wchar_t charCode, int16_t pixelSize);
|
||||||
|
uint16_t cacheGlyphDataComplete(int16_t pixelSize);
|
||||||
|
void loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData);
|
||||||
|
|
||||||
|
void copyTextureToFramebuffer(CVideo * pVideo, GX2Texture *tex, int16_t screenX, int16_t screenY, int16_t screenZ, const glm::vec4 & color, const float &textBlur, const float &colorBlurIntensity, const glm::vec4 & blurColor, const float & internalRenderingScale);
|
||||||
|
|
||||||
|
public:
|
||||||
|
FreeTypeGX(const uint8_t* fontBuffer, FT_Long bufferSize, bool lastFace = false);
|
||||||
|
~FreeTypeGX();
|
||||||
|
|
||||||
|
uint16_t drawText(CVideo * pVideo, int16_t x, int16_t y, int16_t z, const wchar_t *text, int16_t pixelSize, const glm::vec4 & color,
|
||||||
|
uint16_t textStyling, uint16_t textWidth, const float &textBlur, const float &colorBlurIntensity, const glm::vec4 & blurColor, const float & internalRenderingScale);
|
||||||
|
|
||||||
|
uint16_t getWidth(const wchar_t *text, int16_t pixelSize);
|
||||||
|
uint16_t getCharWidth(const wchar_t wChar, int16_t pixelSize, const wchar_t prevChar = 0x0000);
|
||||||
|
uint16_t getHeight(const wchar_t *text, int16_t pixelSize);
|
||||||
|
void getOffset(const wchar_t *text, int16_t pixelSize, uint16_t widthLimit = 0);
|
||||||
|
|
||||||
|
static wchar_t* charToWideChar(const char* p);
|
||||||
|
static char* wideCharToUTF8(const wchar_t* strChar);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FREETYPEGX_H_ */
|
42
source/gui/GameBgImage.cpp
Normal file
42
source/gui/GameBgImage.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include "GameBgImage.h"
|
||||||
|
#include "video/CVideo.h"
|
||||||
|
#include "video/shaders/Shader3D.h"
|
||||||
|
|
||||||
|
GameBgImage::GameBgImage(const std::string & filename, GuiImageData *preloadImage)
|
||||||
|
: GuiImageAsync(filename, preloadImage)
|
||||||
|
{
|
||||||
|
identity = glm::mat4(1.0f);
|
||||||
|
alphaFadeOut = glm::vec4(1.0f, 0.075f, 5.305f, 2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
GameBgImage::~GameBgImage()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameBgImage::draw(CVideo *pVideo)
|
||||||
|
{
|
||||||
|
if(!getImageData() || !getImageData()->getTexture())
|
||||||
|
return;
|
||||||
|
|
||||||
|
//! first setup 2D GUI positions
|
||||||
|
f32 currPosX = getCenterX();
|
||||||
|
f32 currPosY = getCenterY();
|
||||||
|
f32 currPosZ = getDepth();
|
||||||
|
f32 currScaleX = getScaleX() * (f32)getWidth() * pVideo->getWidthScaleFactor();
|
||||||
|
f32 currScaleY = getScaleY() * (f32)getHeight() * pVideo->getHeightScaleFactor();
|
||||||
|
f32 currScaleZ = getScaleZ() * (f32)getWidth() * pVideo->getDepthScaleFactor();
|
||||||
|
|
||||||
|
glm::mat4 m_modelView = glm::translate(identity, glm::vec3(currPosX,currPosY, currPosZ));
|
||||||
|
m_modelView = glm::scale(m_modelView, glm::vec3(currScaleX, currScaleY, currScaleZ));
|
||||||
|
|
||||||
|
Shader3D::instance()->setShaders();
|
||||||
|
Shader3D::instance()->setProjectionMtx(identity);
|
||||||
|
Shader3D::instance()->setViewMtx(identity);
|
||||||
|
Shader3D::instance()->setModelViewMtx(m_modelView);
|
||||||
|
Shader3D::instance()->setTextureAndSampler(getImageData()->getTexture(), getImageData()->getSampler());
|
||||||
|
Shader3D::instance()->setAlphaFadeOut(alphaFadeOut);
|
||||||
|
Shader3D::instance()->setDistanceFadeOut(0.0f);
|
||||||
|
Shader3D::instance()->setColorIntensity(glm::vec4(1.0f, 1.0f, 1.0f, getAlpha()));
|
||||||
|
Shader3D::instance()->setAttributeBuffer();
|
||||||
|
Shader3D::instance()->draw();
|
||||||
|
}
|
23
source/gui/GameBgImage.h
Normal file
23
source/gui/GameBgImage.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef _GAME_BG_IMAGE_H_
|
||||||
|
#define _GAME_BG_IMAGE_H_
|
||||||
|
|
||||||
|
#include "GuiImageAsync.h"
|
||||||
|
#include "video/shaders/Shader3D.h"
|
||||||
|
|
||||||
|
class GameBgImage : public GuiImageAsync
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GameBgImage(const std::string & filename, GuiImageData *preloadImage);
|
||||||
|
virtual ~GameBgImage();
|
||||||
|
|
||||||
|
void setAlphaFadeOut(const glm::vec4 & a) {
|
||||||
|
alphaFadeOut = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw(CVideo *pVideo);
|
||||||
|
private:
|
||||||
|
glm::mat4 identity;
|
||||||
|
glm::vec4 alphaFadeOut;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _GAME_BG_IMAGE_H_
|
100
source/gui/GridBackground.cpp
Normal file
100
source/gui/GridBackground.cpp
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#include "GridBackground.h"
|
||||||
|
#include "video/CVideo.h"
|
||||||
|
#include "video/shaders/Shader3D.h"
|
||||||
|
|
||||||
|
static const float bgRepeat = 1000.0f;
|
||||||
|
static const float bgTexRotate = 39.0f;
|
||||||
|
|
||||||
|
GridBackground::GridBackground(GuiImageData *img)
|
||||||
|
: GuiImage(img)
|
||||||
|
{
|
||||||
|
colorIntensity = glm::vec4(1.0f, 1.0f, 1.0f, 0.9f);
|
||||||
|
alphaFadeOut = glm::vec4(0.0f);
|
||||||
|
distanceFadeOut = 0.15f;
|
||||||
|
|
||||||
|
vtxCount = 4;
|
||||||
|
|
||||||
|
//! texture and vertex coordinates
|
||||||
|
f32 *m_posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, vtxCount * Shader3D::cuVertexAttrSize);
|
||||||
|
f32 *m_texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, vtxCount * Shader3D::cuTexCoordAttrSize);
|
||||||
|
|
||||||
|
if(m_posVtxs)
|
||||||
|
{
|
||||||
|
s32 i = 0;
|
||||||
|
m_posVtxs[i++] = -1.0f; m_posVtxs[i++] = 0.0f; m_posVtxs[i++] = 1.0f;
|
||||||
|
m_posVtxs[i++] = 1.0f; m_posVtxs[i++] = 0.0f; m_posVtxs[i++] = 1.0f;
|
||||||
|
m_posVtxs[i++] = 1.0f; m_posVtxs[i++] = 0.0f; m_posVtxs[i++] = -1.0f;
|
||||||
|
m_posVtxs[i++] = -1.0f; m_posVtxs[i++] = 0.0f; m_posVtxs[i++] = -1.0f;
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, m_posVtxs, vtxCount * Shader3D::cuVertexAttrSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_texCoords)
|
||||||
|
{
|
||||||
|
glm::vec2 texCoordVec[4];
|
||||||
|
texCoordVec[0][0] = -0.5f * bgRepeat; texCoordVec[0][1] = 0.5f * bgRepeat;
|
||||||
|
texCoordVec[1][0] = 0.5f * bgRepeat; texCoordVec[1][1] = 0.5f * bgRepeat;
|
||||||
|
texCoordVec[2][0] = 0.5f * bgRepeat; texCoordVec[2][1] = -0.5f * bgRepeat;
|
||||||
|
texCoordVec[3][0] = -0.5f * bgRepeat; texCoordVec[3][1] = -0.5f * bgRepeat;
|
||||||
|
|
||||||
|
const float cosRot = cosf(DegToRad(bgTexRotate));
|
||||||
|
const float sinRot = sinf(DegToRad(bgTexRotate));
|
||||||
|
|
||||||
|
glm::mat2 texRotateMtx({
|
||||||
|
cosRot, -sinRot,
|
||||||
|
sinRot, cosRot
|
||||||
|
});
|
||||||
|
|
||||||
|
for(s32 i = 0; i < 4; i++) {
|
||||||
|
texCoordVec[i] = texRotateMtx * texCoordVec[i];
|
||||||
|
m_texCoords[i*2 + 0] = texCoordVec[i][0];
|
||||||
|
m_texCoords[i*2 + 1] = texCoordVec[i][1];
|
||||||
|
}
|
||||||
|
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, m_texCoords, vtxCount * Shader3D::cuTexCoordAttrSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! assign to internal variables which are const but oh well
|
||||||
|
posVtxs = m_posVtxs;
|
||||||
|
texCoords = m_texCoords;
|
||||||
|
}
|
||||||
|
|
||||||
|
GridBackground::~GridBackground()
|
||||||
|
{
|
||||||
|
//! remove image so it can not be drawn anymore from this point on
|
||||||
|
imageData = NULL;
|
||||||
|
|
||||||
|
//! main image vertexes
|
||||||
|
if(posVtxs)
|
||||||
|
{
|
||||||
|
free((void*)posVtxs);
|
||||||
|
posVtxs = NULL;
|
||||||
|
}
|
||||||
|
if(texCoords)
|
||||||
|
{
|
||||||
|
free((void*)texCoords);
|
||||||
|
texCoords = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridBackground::draw(CVideo *pVideo, const glm::mat4 & modelView)
|
||||||
|
{
|
||||||
|
//! first setup 2D GUI positions
|
||||||
|
f32 currScaleX = bgRepeat * scaleX * (f32)getWidth() * pVideo->getWidthScaleFactor();
|
||||||
|
f32 currScaleY = 1.0f;
|
||||||
|
f32 currScaleZ = bgRepeat * scaleZ * (f32)getHeight() * pVideo->getDepthScaleFactor();
|
||||||
|
|
||||||
|
m_modelView = glm::scale(modelView, glm::vec3(currScaleX, currScaleY, currScaleZ));
|
||||||
|
|
||||||
|
colorIntensity[3] = getAlpha();
|
||||||
|
|
||||||
|
Shader3D::instance()->setShaders();
|
||||||
|
Shader3D::instance()->setTextureAndSampler(imageData->getTexture(), imageData->getSampler());
|
||||||
|
Shader3D::instance()->setProjectionMtx(pVideo->getProjectionMtx());
|
||||||
|
Shader3D::instance()->setViewMtx(pVideo->getViewMtx());
|
||||||
|
Shader3D::instance()->setModelViewMtx(m_modelView);
|
||||||
|
Shader3D::instance()->setDistanceFadeOut(distanceFadeOut);
|
||||||
|
Shader3D::instance()->setAlphaFadeOut(alphaFadeOut);
|
||||||
|
Shader3D::instance()->setColorIntensity(colorIntensity);
|
||||||
|
Shader3D::instance()->setAttributeBuffer(vtxCount, posVtxs, texCoords);
|
||||||
|
Shader3D::instance()->draw(GX2_PRIMITIVE_QUADS, vtxCount);
|
||||||
|
}
|
30
source/gui/GridBackground.h
Normal file
30
source/gui/GridBackground.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef _GRID_BACKGROUND_H_
|
||||||
|
#define _GRID_BACKGROUND_H_
|
||||||
|
|
||||||
|
#include "GuiImage.h"
|
||||||
|
#include "video/shaders/Shader.h"
|
||||||
|
|
||||||
|
class GridBackground : public GuiImage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GridBackground(GuiImageData *imgData);
|
||||||
|
virtual ~GridBackground();
|
||||||
|
|
||||||
|
void setColorIntensity(const glm::vec4 & color) {
|
||||||
|
colorIntensity = color;
|
||||||
|
}
|
||||||
|
const glm::vec4 & getColorIntensity() const {
|
||||||
|
return colorIntensity;
|
||||||
|
}
|
||||||
|
void setDistanceFadeOut(const float & a) {
|
||||||
|
distanceFadeOut = a;
|
||||||
|
}
|
||||||
|
void draw(CVideo *pVideo, const glm::mat4 & modelView);
|
||||||
|
private:
|
||||||
|
glm::mat4 m_modelView;
|
||||||
|
glm::vec4 colorIntensity;
|
||||||
|
glm::vec4 alphaFadeOut;
|
||||||
|
float distanceFadeOut;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _GRID_BACKGROUND_H_
|
42
source/gui/Gui.h
Normal file
42
source/gui/Gui.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef __GUI_H
|
||||||
|
#define __GUI_H
|
||||||
|
|
||||||
|
#include "FreeTypeGX.h"
|
||||||
|
#include "GameBgImage.h"
|
||||||
|
#include "GuiButton.h"
|
||||||
|
#include "GuiCheckBox.h"
|
||||||
|
#include "GuiController.h"
|
||||||
|
#include "GuiDragListener.h"
|
||||||
|
#include "GuiElement.h"
|
||||||
|
#include "GuiFrame.h"
|
||||||
|
#include "GuiImage.h"
|
||||||
|
#include "GuiImageAsync.h"
|
||||||
|
#include "GuiImageData.h"
|
||||||
|
#include "GuiParticleImage.h"
|
||||||
|
#include "GuiSelectBox.h"
|
||||||
|
#include "GuiSound.h"
|
||||||
|
#include "GuiSwitch.h"
|
||||||
|
#include "GuiText.h"
|
||||||
|
#include "GuiToggle.h"
|
||||||
|
#include "GuiTrigger.h"
|
||||||
|
#include "GuiScrollbar.h"
|
||||||
|
#include "VPadController.h"
|
||||||
|
#include "WPadController.h"
|
||||||
|
|
||||||
|
#endif
|
301
source/gui/GuiButton.cpp
Normal file
301
source/gui/GuiButton.cpp
Normal file
@ -0,0 +1,301 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include "GuiButton.h"
|
||||||
|
#include "GuiTrigger.h"
|
||||||
|
#include "GuiController.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the GuiButton class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GuiButton::GuiButton(f32 w, f32 h)
|
||||||
|
{
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
|
image = NULL;
|
||||||
|
imageOver = NULL;
|
||||||
|
imageHold = NULL;
|
||||||
|
imageClick = NULL;
|
||||||
|
icon = NULL;
|
||||||
|
iconOver = NULL;
|
||||||
|
|
||||||
|
for(s32 i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
label[i] = NULL;
|
||||||
|
labelOver[i] = NULL;
|
||||||
|
labelHold[i] = NULL;
|
||||||
|
labelClick[i] = NULL;
|
||||||
|
}
|
||||||
|
for(s32 i = 0; i < iMaxGuiTriggers; i++)
|
||||||
|
{
|
||||||
|
trigger[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
soundOver = NULL;
|
||||||
|
soundHold = NULL;
|
||||||
|
soundClick = NULL;
|
||||||
|
clickedTrigger = NULL;
|
||||||
|
heldTrigger = NULL;
|
||||||
|
selectable = true;
|
||||||
|
holdable = false;
|
||||||
|
clickable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor for the GuiButton class.
|
||||||
|
*/
|
||||||
|
GuiButton::~GuiButton()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiButton::setImage(GuiImage* img)
|
||||||
|
{
|
||||||
|
image = img;
|
||||||
|
if(img) img->setParent(this);
|
||||||
|
}
|
||||||
|
void GuiButton::setImageOver(GuiImage* img)
|
||||||
|
{
|
||||||
|
imageOver = img;
|
||||||
|
if(img) img->setParent(this);
|
||||||
|
}
|
||||||
|
void GuiButton::setImageHold(GuiImage* img)
|
||||||
|
{
|
||||||
|
imageHold = img;
|
||||||
|
if(img) img->setParent(this);
|
||||||
|
}
|
||||||
|
void GuiButton::setImageClick(GuiImage* img)
|
||||||
|
{
|
||||||
|
imageClick = img;
|
||||||
|
if(img) img->setParent(this);
|
||||||
|
}
|
||||||
|
void GuiButton::setIcon(GuiImage* img)
|
||||||
|
{
|
||||||
|
icon = img;
|
||||||
|
if(img) img->setParent(this);
|
||||||
|
}
|
||||||
|
void GuiButton::setIconOver(GuiImage* img)
|
||||||
|
{
|
||||||
|
iconOver = img;
|
||||||
|
if(img) img->setParent(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiButton::setLabel(GuiText* txt, s32 n)
|
||||||
|
{
|
||||||
|
label[n] = txt;
|
||||||
|
if(txt) txt->setParent(this);
|
||||||
|
}
|
||||||
|
void GuiButton::setLabelOver(GuiText* txt, s32 n)
|
||||||
|
{
|
||||||
|
labelOver[n] = txt;
|
||||||
|
if(txt) txt->setParent(this);
|
||||||
|
}
|
||||||
|
void GuiButton::setLabelHold(GuiText* txt, s32 n)
|
||||||
|
{
|
||||||
|
labelHold[n] = txt;
|
||||||
|
if(txt) txt->setParent(this);
|
||||||
|
}
|
||||||
|
void GuiButton::setLabelClick(GuiText* txt, s32 n)
|
||||||
|
{
|
||||||
|
labelClick[n] = txt;
|
||||||
|
if(txt) txt->setParent(this);
|
||||||
|
}
|
||||||
|
void GuiButton::setSoundOver(GuiSound * snd)
|
||||||
|
{
|
||||||
|
soundOver = snd;
|
||||||
|
}
|
||||||
|
void GuiButton::setSoundHold(GuiSound * snd)
|
||||||
|
{
|
||||||
|
soundHold = snd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiButton::setSoundClick(GuiSound * snd)
|
||||||
|
{
|
||||||
|
soundClick = snd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiButton::setTrigger(GuiTrigger * t, s32 idx)
|
||||||
|
{
|
||||||
|
if(idx >= 0 && idx < iMaxGuiTriggers)
|
||||||
|
{
|
||||||
|
trigger[idx] = t;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(s32 i = 0; i < iMaxGuiTriggers; i++)
|
||||||
|
{
|
||||||
|
if(!trigger[i])
|
||||||
|
{
|
||||||
|
trigger[i] = t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiButton::resetState(void)
|
||||||
|
{
|
||||||
|
clickedTrigger = NULL;
|
||||||
|
heldTrigger = NULL;
|
||||||
|
GuiElement::resetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw the button on screen
|
||||||
|
*/
|
||||||
|
void GuiButton::draw(CVideo *v)
|
||||||
|
{
|
||||||
|
if(!this->isVisible())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// draw image
|
||||||
|
if((isDrawOverOnlyWhenSelected() && (isStateSet(STATE_SELECTED) && imageOver)) ||
|
||||||
|
(!isDrawOverOnlyWhenSelected() && (isStateSet(STATE_OVER | STATE_SELECTED | STATE_CLICKED | STATE_HELD) && imageOver)))
|
||||||
|
imageOver->draw(v);
|
||||||
|
else if(image)
|
||||||
|
image->draw(v);
|
||||||
|
|
||||||
|
if((isDrawOverOnlyWhenSelected() && (isStateSet(STATE_SELECTED) && iconOver)) ||
|
||||||
|
(!isDrawOverOnlyWhenSelected() && (isStateSet(STATE_OVER | STATE_SELECTED | STATE_CLICKED | STATE_HELD) && iconOver)))
|
||||||
|
iconOver->draw(v);
|
||||||
|
else if(icon)
|
||||||
|
icon->draw(v);
|
||||||
|
|
||||||
|
// draw text
|
||||||
|
for(s32 i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if(isStateSet(STATE_OVER | STATE_SELECTED | STATE_CLICKED | STATE_HELD) && labelOver[i])
|
||||||
|
labelOver[i]->draw(v);
|
||||||
|
else if(label[i])
|
||||||
|
label[i]->draw(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiButton::update(GuiController * c)
|
||||||
|
{
|
||||||
|
if(!c || isStateSet(STATE_DISABLED|STATE_HIDDEN|STATE_DISABLE_INPUT, c->chan))
|
||||||
|
return;
|
||||||
|
else if(parentElement && (parentElement->isStateSet(STATE_DISABLED|STATE_HIDDEN|STATE_DISABLE_INPUT, c->chan)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(selectable)
|
||||||
|
{
|
||||||
|
if(c->data.validPointer && this->isInside(c->data.x, c->data.y))
|
||||||
|
{
|
||||||
|
if(!isStateSet(STATE_OVER, c->chan))
|
||||||
|
{
|
||||||
|
setState(STATE_OVER, c->chan);
|
||||||
|
|
||||||
|
//if(this->isRumbleActive())
|
||||||
|
// this->rumble(t->chan);
|
||||||
|
|
||||||
|
if(soundOver)
|
||||||
|
soundOver->Play();
|
||||||
|
|
||||||
|
if(effectsOver && !effects)
|
||||||
|
{
|
||||||
|
// initiate effects
|
||||||
|
effects = effectsOver;
|
||||||
|
effectAmount = effectAmountOver;
|
||||||
|
effectTarget = effectTargetOver;
|
||||||
|
}
|
||||||
|
|
||||||
|
pointedOn(this, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(isStateSet(STATE_OVER, c->chan))
|
||||||
|
{
|
||||||
|
this->clearState(STATE_OVER, c->chan);
|
||||||
|
pointedOff(this, c);
|
||||||
|
|
||||||
|
if(effectTarget == effectTargetOver && effectAmount == effectAmountOver)
|
||||||
|
{
|
||||||
|
// initiate effects (in reverse)
|
||||||
|
effects = effectsOver;
|
||||||
|
effectAmount = -effectAmountOver;
|
||||||
|
effectTarget = 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(s32 i = 0; i < iMaxGuiTriggers; i++)
|
||||||
|
{
|
||||||
|
if(!trigger[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// button triggers
|
||||||
|
if(clickable)
|
||||||
|
{
|
||||||
|
|
||||||
|
s32 isClicked = trigger[i]->clicked(c);
|
||||||
|
|
||||||
|
if( !clickedTrigger && (isClicked != GuiTrigger::CLICKED_NONE)
|
||||||
|
&& (trigger[i]->isClickEverywhere() || (isStateSet(STATE_SELECTED | STATE_OVER, c->chan) && trigger[i]->isSelectionClickEverywhere()) || this->isInside(c->data.x, c->data.y)))
|
||||||
|
{
|
||||||
|
if(soundClick)
|
||||||
|
soundClick->Play();
|
||||||
|
|
||||||
|
clickedTrigger = trigger[i];
|
||||||
|
|
||||||
|
if(!isStateSet(STATE_CLICKED, c->chan)){
|
||||||
|
if(isClicked == GuiTrigger::CLICKED_TOUCH){
|
||||||
|
setState(STATE_CLICKED_TOUCH, c->chan);
|
||||||
|
}else{
|
||||||
|
setState(STATE_CLICKED, c->chan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clicked(this, c, trigger[i]);
|
||||||
|
}
|
||||||
|
else if((isStateSet(STATE_CLICKED, c->chan) || isStateSet(STATE_CLICKED_TOUCH, c->chan)) && (clickedTrigger == trigger[i]) && !isStateSet(STATE_HELD, c->chan) && !trigger[i]->held(c) && ((isClicked == GuiTrigger::CLICKED_NONE) || trigger[i]->released(c)))
|
||||||
|
{
|
||||||
|
if((isStateSet(STATE_CLICKED_TOUCH, c->chan) && this->isInside(c->data.x, c->data.y)) || (isStateSet(STATE_CLICKED, c->chan))){
|
||||||
|
clickedTrigger = NULL;
|
||||||
|
clearState(STATE_CLICKED, c->chan);
|
||||||
|
released(this, c, trigger[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(holdable)
|
||||||
|
{
|
||||||
|
bool isHeld = trigger[i]->held(c);
|
||||||
|
|
||||||
|
if( (!heldTrigger || heldTrigger == trigger[i]) && isHeld
|
||||||
|
&& (trigger[i]->isHoldEverywhere() || (isStateSet(STATE_SELECTED | STATE_OVER, c->chan) && trigger[i]->isSelectionClickEverywhere()) || this->isInside(c->data.x, c->data.y)))
|
||||||
|
{
|
||||||
|
heldTrigger = trigger[i];
|
||||||
|
|
||||||
|
if(!isStateSet(STATE_HELD, c->chan))
|
||||||
|
setState(STATE_HELD, c->chan);
|
||||||
|
|
||||||
|
held(this, c, trigger[i]);
|
||||||
|
}
|
||||||
|
else if(isStateSet(STATE_HELD, c->chan) && (heldTrigger == trigger[i]) && (!isHeld || trigger[i]->released(c)))
|
||||||
|
{
|
||||||
|
//! click is removed at this point and converted to held
|
||||||
|
if(clickedTrigger == trigger[i])
|
||||||
|
{
|
||||||
|
clickedTrigger = NULL;
|
||||||
|
clearState(STATE_CLICKED, c->chan);
|
||||||
|
}
|
||||||
|
heldTrigger = NULL;
|
||||||
|
clearState(STATE_HELD, c->chan);
|
||||||
|
released(this, c, trigger[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
117
source/gui/GuiButton.h
Normal file
117
source/gui/GuiButton.h
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef GUI_BUTTON_H_
|
||||||
|
#define GUI_BUTTON_H_
|
||||||
|
|
||||||
|
#include "GuiElement.h"
|
||||||
|
#include "GuiText.h"
|
||||||
|
#include "GuiController.h"
|
||||||
|
#include "GuiImage.h"
|
||||||
|
#include "GuiSound.h"
|
||||||
|
#include "GuiTrigger.h"
|
||||||
|
|
||||||
|
//!Display, manage, and manipulate buttons in the GUI. Buttons can have images, icons, text, and sound set (all of which are optional)
|
||||||
|
class GuiButton : public GuiElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//!Constructor
|
||||||
|
//!\param w Width
|
||||||
|
//!\param h Height
|
||||||
|
GuiButton(f32 w, f32 h);
|
||||||
|
//!Destructor
|
||||||
|
virtual ~GuiButton();
|
||||||
|
//!Sets the button's image
|
||||||
|
//!\param i Pointer to GuiImage object
|
||||||
|
void setImage(GuiImage* i);
|
||||||
|
//!Sets the button's image on over
|
||||||
|
//!\param i Pointer to GuiImage object
|
||||||
|
void setImageOver(GuiImage* i);
|
||||||
|
|
||||||
|
void setIcon(GuiImage* i);
|
||||||
|
void setIconOver(GuiImage* i);
|
||||||
|
//!Sets the button's image on hold
|
||||||
|
//!\param i Pointer to GuiImage object
|
||||||
|
void setImageHold(GuiImage* i);
|
||||||
|
//!Sets the button's image on click
|
||||||
|
//!\param i Pointer to GuiImage object
|
||||||
|
void setImageClick(GuiImage* i);
|
||||||
|
//!Sets the button's label
|
||||||
|
//!\param t Pointer to GuiText object
|
||||||
|
//!\param n Index of label to set (optional, default is 0)
|
||||||
|
void setLabel(GuiText* t, s32 n = 0);
|
||||||
|
//!Sets the button's label on over (eg: different colored text)
|
||||||
|
//!\param t Pointer to GuiText object
|
||||||
|
//!\param n Index of label to set (optional, default is 0)
|
||||||
|
void setLabelOver(GuiText* t, s32 n = 0);
|
||||||
|
//!Sets the button's label on hold
|
||||||
|
//!\param t Pointer to GuiText object
|
||||||
|
//!\param n Index of label to set (optional, default is 0)
|
||||||
|
void setLabelHold(GuiText* t, s32 n = 0);
|
||||||
|
//!Sets the button's label on click
|
||||||
|
//!\param t Pointer to GuiText object
|
||||||
|
//!\param n Index of label to set (optional, default is 0)
|
||||||
|
void setLabelClick(GuiText* t, s32 n = 0);
|
||||||
|
//!Sets the sound to play on over
|
||||||
|
//!\param s Pointer to GuiSound object
|
||||||
|
void setSoundOver(GuiSound * s);
|
||||||
|
//!Sets the sound to play on hold
|
||||||
|
//!\param s Pointer to GuiSound object
|
||||||
|
void setSoundHold(GuiSound * s);
|
||||||
|
//!Sets the sound to play on click
|
||||||
|
//!\param s Pointer to GuiSound object
|
||||||
|
void setSoundClick(GuiSound * s);
|
||||||
|
//!Set a new GuiTrigger for the element
|
||||||
|
//!\param i Index of trigger array to set
|
||||||
|
//!\param t Pointer to GuiTrigger
|
||||||
|
void setTrigger(GuiTrigger * t, s32 idx = -1);
|
||||||
|
//!
|
||||||
|
void resetState(void);
|
||||||
|
//!Constantly called to draw the GuiButton
|
||||||
|
void draw(CVideo *video);
|
||||||
|
//!Constantly called to allow the GuiButton to respond to updated input data
|
||||||
|
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
|
||||||
|
void update(GuiController * c);
|
||||||
|
|
||||||
|
sigslot::signal2<GuiButton *, const GuiController *> selected;
|
||||||
|
sigslot::signal2<GuiButton *, const GuiController *> deSelected;
|
||||||
|
sigslot::signal2<GuiButton *, const GuiController *> pointedOn;
|
||||||
|
sigslot::signal2<GuiButton *, const GuiController *> pointedOff;
|
||||||
|
sigslot::signal3<GuiButton *, const GuiController *, GuiTrigger *> clicked;
|
||||||
|
sigslot::signal3<GuiButton *, const GuiController *, GuiTrigger *> held;
|
||||||
|
sigslot::signal3<GuiButton *, const GuiController *, GuiTrigger *> released;
|
||||||
|
protected:
|
||||||
|
static const s32 iMaxGuiTriggers = 10;
|
||||||
|
|
||||||
|
GuiImage * image; //!< Button image (default)
|
||||||
|
GuiImage * imageOver; //!< Button image for STATE_SELECTED
|
||||||
|
GuiImage * imageHold; //!< Button image for STATE_HELD
|
||||||
|
GuiImage * imageClick; //!< Button image for STATE_CLICKED
|
||||||
|
GuiImage * icon;
|
||||||
|
GuiImage * iconOver;
|
||||||
|
GuiText * label[4]; //!< Label(s) to display (default)
|
||||||
|
GuiText * labelOver[4]; //!< Label(s) to display for STATE_SELECTED
|
||||||
|
GuiText * labelHold[4]; //!< Label(s) to display for STATE_HELD
|
||||||
|
GuiText * labelClick[4]; //!< Label(s) to display for STATE_CLICKED
|
||||||
|
GuiSound * soundOver; //!< Sound to play for STATE_SELECTED
|
||||||
|
GuiSound * soundHold; //!< Sound to play for STATE_HELD
|
||||||
|
GuiSound * soundClick; //!< Sound to play for STATE_CLICKED
|
||||||
|
GuiTrigger * trigger[iMaxGuiTriggers]; //!< GuiTriggers (input actions) that this element responds to
|
||||||
|
GuiTrigger * clickedTrigger;
|
||||||
|
GuiTrigger * heldTrigger;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
63
source/gui/GuiCheckBox.cpp
Normal file
63
source/gui/GuiCheckBox.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2016,2017 Maschell
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include "GuiCheckBox.h"
|
||||||
|
#include "GuiImage.h"
|
||||||
|
#include "GuiImageData.h"
|
||||||
|
/**
|
||||||
|
* Constructor for the GuiCheckBox class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GuiCheckBox::GuiCheckBox(bool checked, f32 width,f32 height)
|
||||||
|
: GuiToggle(checked,width,height){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor for the GuiCheckBox class.
|
||||||
|
*/
|
||||||
|
GuiCheckBox::~GuiCheckBox(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiCheckBox::setImageBackground(GuiImage* img){
|
||||||
|
backgroundImg = img;
|
||||||
|
if(img){ img->setParent(this); }
|
||||||
|
setImage(img);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiCheckBox::setImageSelected(GuiImage* img){
|
||||||
|
selectedImg = img;
|
||||||
|
if(img){ img->setParent(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiCheckBox::setImageHighlighted(GuiImage* img){
|
||||||
|
highlightedImg = img;
|
||||||
|
if(img){ img->setParent(this); }
|
||||||
|
setIconOver(img);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiCheckBox::update(GuiController * c){
|
||||||
|
if(bChanged){
|
||||||
|
if(selected){
|
||||||
|
GuiButton::setImage(selectedImg);
|
||||||
|
}else{
|
||||||
|
GuiButton::setImage(backgroundImg);
|
||||||
|
}
|
||||||
|
bChanged = false;
|
||||||
|
}
|
||||||
|
GuiToggle::update(c);
|
||||||
|
}
|
48
source/gui/GuiCheckBox.h
Normal file
48
source/gui/GuiCheckBox.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2016,2017 Maschell
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef GUI_CHECKBOX_H_
|
||||||
|
#define GUI_CHECKBOX_H_
|
||||||
|
|
||||||
|
#include "GuiToggle.h"
|
||||||
|
#include "GuiImage.h"
|
||||||
|
#include "GuiImageData.h"
|
||||||
|
|
||||||
|
//!A simple CheckBox
|
||||||
|
class GuiCheckBox : public GuiToggle{
|
||||||
|
public:
|
||||||
|
//!Constructor
|
||||||
|
//!\param checked Checked
|
||||||
|
GuiCheckBox(bool checked, f32 width = 0.0f,f32 height= 0.0f);
|
||||||
|
|
||||||
|
//!Destructor
|
||||||
|
virtual ~GuiCheckBox();
|
||||||
|
|
||||||
|
void setImageBackground(GuiImage* img);
|
||||||
|
|
||||||
|
void setImageSelected(GuiImage* img);
|
||||||
|
|
||||||
|
void setImageHighlighted(GuiImage* img);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
GuiImage * backgroundImg = NULL;
|
||||||
|
GuiImage * selectedImg = NULL;
|
||||||
|
GuiImage * highlightedImg = NULL;
|
||||||
|
|
||||||
|
void update(GuiController * c);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
78
source/gui/GuiController.h
Normal file
78
source/gui/GuiController.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef GUI_CONTROLLER_H_
|
||||||
|
#define GUI_CONTROLLER_H_
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "GuiTrigger.h"
|
||||||
|
|
||||||
|
class GuiController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//!Constructor
|
||||||
|
GuiController(s32 channel)
|
||||||
|
: chan(channel)
|
||||||
|
{
|
||||||
|
memset(&lastData, 0, sizeof(lastData));
|
||||||
|
memset(&data, 0, sizeof(data));
|
||||||
|
|
||||||
|
switch(chan)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case GuiTrigger::CHANNEL_1:
|
||||||
|
chanIdx = 0;
|
||||||
|
break;
|
||||||
|
case GuiTrigger::CHANNEL_2:
|
||||||
|
chanIdx = 1;
|
||||||
|
break;
|
||||||
|
case GuiTrigger::CHANNEL_3:
|
||||||
|
chanIdx = 2;
|
||||||
|
break;
|
||||||
|
case GuiTrigger::CHANNEL_4:
|
||||||
|
chanIdx = 3;
|
||||||
|
break;
|
||||||
|
case GuiTrigger::CHANNEL_5:
|
||||||
|
chanIdx = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//!Destructor
|
||||||
|
virtual ~GuiController() {}
|
||||||
|
|
||||||
|
virtual bool update(s32 width, s32 height) = 0;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u32 buttons_h;
|
||||||
|
u32 buttons_d;
|
||||||
|
u32 buttons_r;
|
||||||
|
bool validPointer;
|
||||||
|
bool touched;
|
||||||
|
float pointerAngle;
|
||||||
|
s32 x;
|
||||||
|
s32 y;
|
||||||
|
} PadData;
|
||||||
|
|
||||||
|
s32 chan;
|
||||||
|
s32 chanIdx;
|
||||||
|
PadData data;
|
||||||
|
PadData lastData;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
86
source/gui/GuiDragListener.cpp
Normal file
86
source/gui/GuiDragListener.cpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2016 Maschell
|
||||||
|
* based on GuiButton by dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include "GuiDragListener.h"
|
||||||
|
#include "GuiController.h"
|
||||||
|
#include <utils/logger.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the GuiDragListener class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GuiDragListener::GuiDragListener(f32 w,f32 h){
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
|
for(s32 i = 0; i < iMaxGuiTriggers; i++)
|
||||||
|
{
|
||||||
|
trigger[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor for the GuiDragListener class.
|
||||||
|
*/
|
||||||
|
GuiDragListener::~GuiDragListener(){
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiDragListener::setState(s32 i, s32 c){
|
||||||
|
GuiElement::setState(i,c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiDragListener::setTrigger(GuiTrigger * t, s32 idx){
|
||||||
|
if(idx >= 0 && idx < iMaxGuiTriggers)
|
||||||
|
{
|
||||||
|
trigger[idx] = t;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(s32 i = 0; i < iMaxGuiTriggers; i++)
|
||||||
|
{
|
||||||
|
if(!trigger[i])
|
||||||
|
{
|
||||||
|
trigger[i] = t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiDragListener::update(GuiController * c){
|
||||||
|
if(!c || isStateSet(STATE_DISABLED|STATE_HIDDEN|STATE_DISABLE_INPUT, c->chan))
|
||||||
|
return;
|
||||||
|
else if(parentElement && (parentElement->isStateSet(STATE_DISABLED|STATE_HIDDEN|STATE_DISABLE_INPUT, c->chan)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(s32 i = 0; i < iMaxGuiTriggers; i++){
|
||||||
|
if(!trigger[i]){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isHeld = trigger[i]->held(c);
|
||||||
|
|
||||||
|
|
||||||
|
if(isHeld && this->isInside(c->data.x, c->data.y)){
|
||||||
|
s32 dx = c->data.x - c->lastData.x;
|
||||||
|
s32 dy = c->data.y - c->lastData.y;
|
||||||
|
|
||||||
|
if(dx == 0 && dy == 0) continue;
|
||||||
|
|
||||||
|
dragged(this, c, trigger[i],dx,dy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
53
source/gui/GuiDragListener.h
Normal file
53
source/gui/GuiDragListener.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2016 Maschell
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef GUI_DRAG_LISTENER_H_
|
||||||
|
#define GUI_DRAG_LISTENER_H_
|
||||||
|
|
||||||
|
#include "GuiElement.h"
|
||||||
|
#include "GuiController.h"
|
||||||
|
#include "GuiTrigger.h"
|
||||||
|
#include "GuiButton.h"
|
||||||
|
|
||||||
|
class GuiDragListener : public GuiElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//!Constructor
|
||||||
|
//!\param w Width
|
||||||
|
//!\param h Height
|
||||||
|
GuiDragListener(f32 w,f32 h);
|
||||||
|
//!Destructor
|
||||||
|
virtual ~GuiDragListener();
|
||||||
|
|
||||||
|
void setState(s32 i, s32 c);
|
||||||
|
|
||||||
|
//!Set a new GuiTrigger for the element
|
||||||
|
//!\param i Index of trigger array to set
|
||||||
|
//!\param t Pointer to GuiTrigger
|
||||||
|
void setTrigger(GuiTrigger * t, s32 idx = -1);
|
||||||
|
|
||||||
|
//!Constantly called to allow the GuiDragListener to respond to updated input data
|
||||||
|
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
|
||||||
|
void update(GuiController * c);
|
||||||
|
|
||||||
|
sigslot::signal5<GuiDragListener *, const GuiController *, GuiTrigger *,s32,s32> dragged;
|
||||||
|
protected:
|
||||||
|
static const s32 iMaxGuiTriggers = 10;
|
||||||
|
|
||||||
|
GuiTrigger * trigger[iMaxGuiTriggers]; //!< GuiTriggers (input actions) that this element responds to
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
343
source/gui/GuiElement.cpp
Normal file
343
source/gui/GuiElement.cpp
Normal file
@ -0,0 +1,343 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include "GuiElement.h"
|
||||||
|
|
||||||
|
//! TODO remove this!
|
||||||
|
static s32 screenwidth = 1280;
|
||||||
|
static s32 screenheight = 720;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the Object class.
|
||||||
|
*/
|
||||||
|
GuiElement::GuiElement()
|
||||||
|
{
|
||||||
|
xoffset = 0.0f;
|
||||||
|
yoffset = 0.0f;
|
||||||
|
zoffset = 0.0f;
|
||||||
|
width = 0.0f;
|
||||||
|
height = 0.0f;
|
||||||
|
alpha = 1.0f;
|
||||||
|
scaleX = 1.0f;
|
||||||
|
scaleY = 1.0f;
|
||||||
|
scaleZ = 1.0f;
|
||||||
|
for(s32 i = 0; i < 4; i++)
|
||||||
|
state[i] = STATE_DEFAULT;
|
||||||
|
stateChan = -1;
|
||||||
|
parentElement = NULL;
|
||||||
|
rumble = true;
|
||||||
|
selectable = false;
|
||||||
|
clickable = false;
|
||||||
|
holdable = false;
|
||||||
|
drawOverOnlyWhenSelected = false;
|
||||||
|
visible = true;
|
||||||
|
yoffsetDyn = 0;
|
||||||
|
xoffsetDyn = 0;
|
||||||
|
alphaDyn = -1;
|
||||||
|
scaleDyn = 1;
|
||||||
|
effects = EFFECT_NONE;
|
||||||
|
effectAmount = 0;
|
||||||
|
effectTarget = 0;
|
||||||
|
effectsOver = EFFECT_NONE;
|
||||||
|
effectAmountOver = 0;
|
||||||
|
effectTargetOver = 0;
|
||||||
|
angle = 0.0f;
|
||||||
|
|
||||||
|
// default alignment - align to top left
|
||||||
|
alignment = (ALIGN_CENTER | ALIGN_MIDDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the left position of the GuiElement.
|
||||||
|
* @see SetLeft()
|
||||||
|
* @return Left position in pixel.
|
||||||
|
*/
|
||||||
|
f32 GuiElement::getLeft()
|
||||||
|
{
|
||||||
|
f32 pWidth = 0;
|
||||||
|
f32 pLeft = 0;
|
||||||
|
f32 pScaleX = 1.0f;
|
||||||
|
|
||||||
|
if(parentElement)
|
||||||
|
{
|
||||||
|
pWidth = parentElement->getWidth();
|
||||||
|
pLeft = parentElement->getLeft();
|
||||||
|
pScaleX = parentElement->getScaleX();
|
||||||
|
}
|
||||||
|
|
||||||
|
pLeft += xoffsetDyn;
|
||||||
|
|
||||||
|
f32 x = pLeft;
|
||||||
|
|
||||||
|
//! TODO: the conversion from int to float and back to int is bad for performance, change that
|
||||||
|
if(alignment & ALIGN_CENTER)
|
||||||
|
{
|
||||||
|
x = pLeft + pWidth * 0.5f * pScaleX - width * 0.5f * getScaleX();
|
||||||
|
}
|
||||||
|
else if(alignment & ALIGN_RIGHT)
|
||||||
|
{
|
||||||
|
x = pLeft + pWidth * pScaleX - width * getScaleX();
|
||||||
|
}
|
||||||
|
|
||||||
|
return x + xoffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the top position of the GuiElement.
|
||||||
|
* @see SetTop()
|
||||||
|
* @return Top position in pixel.
|
||||||
|
*/
|
||||||
|
f32 GuiElement::getTop()
|
||||||
|
{
|
||||||
|
f32 pHeight = 0;
|
||||||
|
f32 pTop = 0;
|
||||||
|
f32 pScaleY = 1.0f;
|
||||||
|
|
||||||
|
if(parentElement)
|
||||||
|
{
|
||||||
|
pHeight = parentElement->getHeight();
|
||||||
|
pTop = parentElement->getTop();
|
||||||
|
pScaleY = parentElement->getScaleY();
|
||||||
|
}
|
||||||
|
|
||||||
|
pTop += yoffsetDyn;
|
||||||
|
|
||||||
|
f32 y = pTop;
|
||||||
|
|
||||||
|
//! TODO: the conversion from int to float and back to int is bad for performance, change that
|
||||||
|
if(alignment & ALIGN_MIDDLE)
|
||||||
|
{
|
||||||
|
y = pTop + pHeight * 0.5f * pScaleY - getHeight() * 0.5f * getScaleY();
|
||||||
|
}
|
||||||
|
else if(alignment & ALIGN_BOTTOM)
|
||||||
|
{
|
||||||
|
y = pTop + pHeight * pScaleY - getHeight() * getScaleY();
|
||||||
|
}
|
||||||
|
|
||||||
|
return y + yoffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiElement::setEffect(s32 eff, s32 amount, s32 target)
|
||||||
|
{
|
||||||
|
if(eff & EFFECT_SLIDE_IN)
|
||||||
|
{
|
||||||
|
// these calculations overcompensate a little
|
||||||
|
if(eff & EFFECT_SLIDE_TOP)
|
||||||
|
{
|
||||||
|
if(eff & EFFECT_SLIDE_FROM)
|
||||||
|
yoffsetDyn = (s32) -getHeight()*scaleY;
|
||||||
|
else
|
||||||
|
yoffsetDyn = -screenheight;
|
||||||
|
}
|
||||||
|
else if(eff & EFFECT_SLIDE_LEFT)
|
||||||
|
{
|
||||||
|
if(eff & EFFECT_SLIDE_FROM)
|
||||||
|
xoffsetDyn = (s32) -getWidth()*scaleX;
|
||||||
|
else
|
||||||
|
xoffsetDyn = -screenwidth;
|
||||||
|
}
|
||||||
|
else if(eff & EFFECT_SLIDE_BOTTOM)
|
||||||
|
{
|
||||||
|
if(eff & EFFECT_SLIDE_FROM)
|
||||||
|
yoffsetDyn = (s32) getHeight()*scaleY;
|
||||||
|
else
|
||||||
|
yoffsetDyn = screenheight;
|
||||||
|
}
|
||||||
|
else if(eff & EFFECT_SLIDE_RIGHT)
|
||||||
|
{
|
||||||
|
if(eff & EFFECT_SLIDE_FROM)
|
||||||
|
xoffsetDyn = (s32) getWidth()*scaleX;
|
||||||
|
else
|
||||||
|
xoffsetDyn = screenwidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if((eff & EFFECT_FADE) && amount > 0)
|
||||||
|
{
|
||||||
|
alphaDyn = 0;
|
||||||
|
}
|
||||||
|
else if((eff & EFFECT_FADE) && amount < 0)
|
||||||
|
{
|
||||||
|
alphaDyn = alpha;
|
||||||
|
}
|
||||||
|
effects |= eff;
|
||||||
|
effectAmount = amount;
|
||||||
|
effectTarget = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
//!Sets an effect to be enabled on wiimote cursor over
|
||||||
|
//!\param e Effect to enable
|
||||||
|
//!\param a Amount of the effect (usage varies on effect)
|
||||||
|
//!\param t Target amount of the effect (usage varies on effect)
|
||||||
|
void GuiElement::setEffectOnOver(s32 e, s32 a, s32 t)
|
||||||
|
{
|
||||||
|
effectsOver |= e;
|
||||||
|
effectAmountOver = a;
|
||||||
|
effectTargetOver = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiElement::resetEffects()
|
||||||
|
{
|
||||||
|
yoffsetDyn = 0;
|
||||||
|
xoffsetDyn = 0;
|
||||||
|
alphaDyn = -1;
|
||||||
|
scaleDyn = 1;
|
||||||
|
effects = EFFECT_NONE;
|
||||||
|
effectAmount = 0;
|
||||||
|
effectTarget = 0;
|
||||||
|
effectsOver = EFFECT_NONE;
|
||||||
|
effectAmountOver = 0;
|
||||||
|
effectTargetOver = 0;
|
||||||
|
}
|
||||||
|
void GuiElement::updateEffects()
|
||||||
|
{
|
||||||
|
if(!this->isVisible() && parentElement)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(effects & (EFFECT_SLIDE_IN | EFFECT_SLIDE_OUT | EFFECT_SLIDE_FROM))
|
||||||
|
{
|
||||||
|
if(effects & EFFECT_SLIDE_IN)
|
||||||
|
{
|
||||||
|
if(effects & EFFECT_SLIDE_LEFT)
|
||||||
|
{
|
||||||
|
xoffsetDyn += effectAmount;
|
||||||
|
|
||||||
|
if(xoffsetDyn >= 0)
|
||||||
|
{
|
||||||
|
xoffsetDyn = 0;
|
||||||
|
effects = 0;
|
||||||
|
effectFinished(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(effects & EFFECT_SLIDE_RIGHT)
|
||||||
|
{
|
||||||
|
xoffsetDyn -= effectAmount;
|
||||||
|
|
||||||
|
if(xoffsetDyn <= 0)
|
||||||
|
{
|
||||||
|
xoffsetDyn = 0;
|
||||||
|
effects = 0;
|
||||||
|
effectFinished(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(effects & EFFECT_SLIDE_TOP)
|
||||||
|
{
|
||||||
|
yoffsetDyn += effectAmount;
|
||||||
|
|
||||||
|
if(yoffsetDyn >= 0)
|
||||||
|
{
|
||||||
|
yoffsetDyn = 0;
|
||||||
|
effects = 0;
|
||||||
|
effectFinished(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(effects & EFFECT_SLIDE_BOTTOM)
|
||||||
|
{
|
||||||
|
yoffsetDyn -= effectAmount;
|
||||||
|
|
||||||
|
if(yoffsetDyn <= 0)
|
||||||
|
{
|
||||||
|
yoffsetDyn = 0;
|
||||||
|
effects = 0;
|
||||||
|
effectFinished(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(effects & EFFECT_SLIDE_LEFT)
|
||||||
|
{
|
||||||
|
xoffsetDyn -= effectAmount;
|
||||||
|
|
||||||
|
if(xoffsetDyn <= -screenwidth) {
|
||||||
|
effects = 0; // shut off effect
|
||||||
|
effectFinished(this);
|
||||||
|
}
|
||||||
|
else if((effects & EFFECT_SLIDE_FROM) && xoffsetDyn <= -getWidth()) {
|
||||||
|
effects = 0; // shut off effect
|
||||||
|
effectFinished(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(effects & EFFECT_SLIDE_RIGHT)
|
||||||
|
{
|
||||||
|
xoffsetDyn += effectAmount;
|
||||||
|
|
||||||
|
if(xoffsetDyn >= screenwidth) {
|
||||||
|
effects = 0; // shut off effect
|
||||||
|
effectFinished(this);
|
||||||
|
}
|
||||||
|
else if((effects & EFFECT_SLIDE_FROM) && xoffsetDyn >= getWidth()*scaleX) {
|
||||||
|
effects = 0; // shut off effect
|
||||||
|
effectFinished(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(effects & EFFECT_SLIDE_TOP)
|
||||||
|
{
|
||||||
|
yoffsetDyn -= effectAmount;
|
||||||
|
|
||||||
|
if(yoffsetDyn <= -screenheight) {
|
||||||
|
effects = 0; // shut off effect
|
||||||
|
effectFinished(this);
|
||||||
|
}
|
||||||
|
else if((effects & EFFECT_SLIDE_FROM) && yoffsetDyn <= -getHeight()) {
|
||||||
|
effects = 0; // shut off effect
|
||||||
|
effectFinished(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(effects & EFFECT_SLIDE_BOTTOM)
|
||||||
|
{
|
||||||
|
yoffsetDyn += effectAmount;
|
||||||
|
|
||||||
|
if(yoffsetDyn >= screenheight) {
|
||||||
|
effects = 0; // shut off effect
|
||||||
|
effectFinished(this);
|
||||||
|
}
|
||||||
|
else if((effects & EFFECT_SLIDE_FROM) && yoffsetDyn >= getHeight()) {
|
||||||
|
effects = 0; // shut off effect
|
||||||
|
effectFinished(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(effects & EFFECT_FADE)
|
||||||
|
{
|
||||||
|
alphaDyn += effectAmount * (1.0f / 255.0f);
|
||||||
|
|
||||||
|
if(effectAmount < 0 && alphaDyn <= 0)
|
||||||
|
{
|
||||||
|
alphaDyn = 0;
|
||||||
|
effects = 0; // shut off effect
|
||||||
|
effectFinished(this);
|
||||||
|
}
|
||||||
|
else if(effectAmount > 0 && alphaDyn >= alpha)
|
||||||
|
{
|
||||||
|
alphaDyn = alpha;
|
||||||
|
effects = 0; // shut off effect
|
||||||
|
effectFinished(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(effects & EFFECT_SCALE)
|
||||||
|
{
|
||||||
|
scaleDyn += effectAmount * 0.01f;
|
||||||
|
|
||||||
|
if((effectAmount < 0 && scaleDyn <= (effectTarget * 0.01f))
|
||||||
|
|| (effectAmount > 0 && scaleDyn >= (effectTarget * 0.01f)))
|
||||||
|
{
|
||||||
|
scaleDyn = effectTarget * 0.01f;
|
||||||
|
effects = 0; // shut off effect
|
||||||
|
effectFinished(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
529
source/gui/GuiElement.h
Normal file
529
source/gui/GuiElement.h
Normal file
@ -0,0 +1,529 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef GUI_ELEMENT_H_
|
||||||
|
#define GUI_ELEMENT_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "sigslot.h"
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <dynamic_libs/gx2_types.h>
|
||||||
|
#include <system/AsyncDeleter.h>
|
||||||
|
#include <utils/logger.h>
|
||||||
|
|
||||||
|
#include "resources/Resources.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
EFFECT_NONE = 0x00,
|
||||||
|
EFFECT_SLIDE_TOP = 0x01,
|
||||||
|
EFFECT_SLIDE_BOTTOM = 0x02,
|
||||||
|
EFFECT_SLIDE_RIGHT = 0x04,
|
||||||
|
EFFECT_SLIDE_LEFT = 0x08,
|
||||||
|
EFFECT_SLIDE_IN = 0x10,
|
||||||
|
EFFECT_SLIDE_OUT = 0x20,
|
||||||
|
EFFECT_SLIDE_FROM = 0x40,
|
||||||
|
EFFECT_FADE = 0x80,
|
||||||
|
EFFECT_SCALE = 0x100,
|
||||||
|
EFFECT_COLOR_TRANSITION = 0x200
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ALIGN_LEFT = 0x01,
|
||||||
|
ALIGN_CENTER = 0x02,
|
||||||
|
ALIGN_RIGHT = 0x04,
|
||||||
|
ALIGN_TOP = 0x10,
|
||||||
|
ALIGN_MIDDLE = 0x20,
|
||||||
|
ALIGN_BOTTOM = 0x40,
|
||||||
|
ALIGN_TOP_LEFT = ALIGN_LEFT | ALIGN_TOP,
|
||||||
|
ALIGN_TOP_CENTER = ALIGN_CENTER | ALIGN_TOP,
|
||||||
|
ALIGN_TOP_RIGHT = ALIGN_RIGHT | ALIGN_TOP,
|
||||||
|
ALIGN_CENTERED = ALIGN_CENTER | ALIGN_MIDDLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
//!Forward declaration
|
||||||
|
class GuiController;
|
||||||
|
class CVideo;
|
||||||
|
|
||||||
|
//!Primary GUI class. Most other classes inherit from this class.
|
||||||
|
class GuiElement : public AsyncDeleter::Element
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//!Constructor
|
||||||
|
GuiElement();
|
||||||
|
//!Destructor
|
||||||
|
virtual ~GuiElement() {}
|
||||||
|
//!Set the element's parent
|
||||||
|
//!\param e Pointer to parent element
|
||||||
|
virtual void setParent(GuiElement * e) { parentElement = e; }
|
||||||
|
//!Gets the element's parent
|
||||||
|
//!\return Pointer to parent element
|
||||||
|
virtual GuiElement * getParent() { return parentElement; }
|
||||||
|
//!Gets the current leftmost coordinate of the element
|
||||||
|
//!Considers horizontal alignment, x offset, width, and parent element's GetLeft() / GetWidth() values
|
||||||
|
//!\return left coordinate
|
||||||
|
virtual f32 getLeft();
|
||||||
|
//!Gets the current topmost coordinate of the element
|
||||||
|
//!Considers vertical alignment, y offset, height, and parent element's GetTop() / GetHeight() values
|
||||||
|
//!\return top coordinate
|
||||||
|
virtual f32 getTop();
|
||||||
|
//!Gets the current Z coordinate of the element
|
||||||
|
//!\return Z coordinate
|
||||||
|
virtual f32 getDepth()
|
||||||
|
{
|
||||||
|
f32 zParent = 0.0f;
|
||||||
|
|
||||||
|
if(parentElement)
|
||||||
|
zParent = parentElement->getDepth();
|
||||||
|
|
||||||
|
return zParent+zoffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual f32 getCenterX(void)
|
||||||
|
{
|
||||||
|
f32 pCenterX = 0.0f;
|
||||||
|
|
||||||
|
if(parentElement)
|
||||||
|
pCenterX = parentElement->getCenterX();
|
||||||
|
|
||||||
|
pCenterX += xoffset + xoffsetDyn;
|
||||||
|
|
||||||
|
if(alignment & ALIGN_LEFT)
|
||||||
|
{
|
||||||
|
f32 pWidth = 0.0f;
|
||||||
|
f32 pScale = 0.0f;
|
||||||
|
|
||||||
|
if(parentElement)
|
||||||
|
{
|
||||||
|
pWidth = parentElement->getWidth();
|
||||||
|
pScale = parentElement->getScaleX();
|
||||||
|
}
|
||||||
|
|
||||||
|
pCenterX -= pWidth * 0.5f * pScale - width * 0.5f * getScaleX();
|
||||||
|
}
|
||||||
|
else if(alignment & ALIGN_RIGHT)
|
||||||
|
{
|
||||||
|
f32 pWidth = 0.0f;
|
||||||
|
f32 pScale = 0.0f;
|
||||||
|
|
||||||
|
if(parentElement)
|
||||||
|
{
|
||||||
|
pWidth = parentElement->getWidth();
|
||||||
|
pScale = parentElement->getScaleX();
|
||||||
|
}
|
||||||
|
|
||||||
|
pCenterX += pWidth * 0.5f * pScale - width * 0.5f * getScaleX();
|
||||||
|
}
|
||||||
|
return pCenterX;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual f32 getCenterY(void)
|
||||||
|
{
|
||||||
|
f32 pCenterY = 0.0f;
|
||||||
|
|
||||||
|
if(parentElement)
|
||||||
|
pCenterY = parentElement->getCenterY();
|
||||||
|
|
||||||
|
pCenterY += yoffset + yoffsetDyn;
|
||||||
|
|
||||||
|
if(alignment & ALIGN_TOP)
|
||||||
|
{
|
||||||
|
f32 pHeight = 0.0f;
|
||||||
|
f32 pScale = 0.0f;
|
||||||
|
|
||||||
|
if(parentElement)
|
||||||
|
{
|
||||||
|
pHeight = parentElement->getHeight();
|
||||||
|
pScale = parentElement->getScaleY();
|
||||||
|
}
|
||||||
|
|
||||||
|
pCenterY += pHeight * 0.5f * pScale - getHeight() * 0.5f * getScaleY();
|
||||||
|
}
|
||||||
|
else if(alignment & ALIGN_BOTTOM)
|
||||||
|
{
|
||||||
|
f32 pHeight = 0.0f;
|
||||||
|
f32 pScale = 0.0f;
|
||||||
|
|
||||||
|
if(parentElement)
|
||||||
|
{
|
||||||
|
pHeight = parentElement->getHeight();
|
||||||
|
pScale = parentElement->getScaleY();
|
||||||
|
}
|
||||||
|
|
||||||
|
pCenterY -= pHeight * 0.5f * pScale - getHeight() * 0.5f * getScaleY();
|
||||||
|
}
|
||||||
|
return pCenterY;
|
||||||
|
}
|
||||||
|
//!Gets elements xoffset
|
||||||
|
virtual f32 getOffsetX() { return xoffset; }
|
||||||
|
//!Gets elements yoffset
|
||||||
|
virtual f32 getOffsetY() { return yoffset; }
|
||||||
|
//!Gets the current width of the element. Does not currently consider the scale
|
||||||
|
//!\return width
|
||||||
|
virtual f32 getWidth() { return width; };
|
||||||
|
//!Gets the height of the element. Does not currently consider the scale
|
||||||
|
//!\return height
|
||||||
|
virtual f32 getHeight() { return height; }
|
||||||
|
//!Sets the size (width/height) of the element
|
||||||
|
//!\param w Width of element
|
||||||
|
//!\param h Height of element
|
||||||
|
virtual void setSize(f32 w, f32 h)
|
||||||
|
{
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
|
}
|
||||||
|
//!Sets the element's visibility
|
||||||
|
//!\param v Visibility (true = visible)
|
||||||
|
virtual void setVisible(bool v)
|
||||||
|
{
|
||||||
|
visible = v;
|
||||||
|
visibleChanged(this, v);
|
||||||
|
}
|
||||||
|
//!Checks whether or not the element is visible
|
||||||
|
//!\return true if visible, false otherwise
|
||||||
|
virtual bool isVisible() const { return !isStateSet(STATE_HIDDEN) && visible; };
|
||||||
|
//!Checks whether or not the element is selectable
|
||||||
|
//!\return true if selectable, false otherwise
|
||||||
|
virtual bool isSelectable()
|
||||||
|
{
|
||||||
|
return !isStateSet(STATE_DISABLED) && selectable;
|
||||||
|
}
|
||||||
|
virtual bool isDrawOverOnlyWhenSelected()
|
||||||
|
{
|
||||||
|
return drawOverOnlyWhenSelected;
|
||||||
|
}
|
||||||
|
virtual void setdrawOverOnlyWhenSelected(bool s) { drawOverOnlyWhenSelected = s; }
|
||||||
|
//!Checks whether or not the element is clickable
|
||||||
|
//!\return true if clickable, false otherwise
|
||||||
|
virtual bool isClickable()
|
||||||
|
{
|
||||||
|
return !isStateSet(STATE_DISABLED) && clickable;
|
||||||
|
}
|
||||||
|
//!Checks whether or not the element is holdable
|
||||||
|
//!\return true if holdable, false otherwise
|
||||||
|
virtual bool isHoldable() { return !isStateSet(STATE_DISABLED) && holdable; }
|
||||||
|
//!Sets whether or not the element is selectable
|
||||||
|
//!\param s Selectable
|
||||||
|
virtual void setSelectable(bool s) { selectable = s; }
|
||||||
|
//!Sets whether or not the element is clickable
|
||||||
|
//!\param c Clickable
|
||||||
|
virtual void setClickable(bool c) { clickable = c; }
|
||||||
|
//!Sets whether or not the element is holdable
|
||||||
|
//!\param c Holdable
|
||||||
|
virtual void setHoldable(bool d) { holdable = d; }
|
||||||
|
//!Sets the element's state
|
||||||
|
//!\param s State (STATE_DEFAULT, STATE_SELECTED, STATE_CLICKED, STATE_DISABLED)
|
||||||
|
//!\param c Controller channel (0-3, -1 = none)
|
||||||
|
virtual void setState(s32 s, s32 c = -1)
|
||||||
|
{
|
||||||
|
if(c >= 0 && c < 4)
|
||||||
|
{
|
||||||
|
state[c] |= s;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(s32 i = 0; i < 4; i++)
|
||||||
|
state[i] |= s;
|
||||||
|
}
|
||||||
|
stateChan = c;
|
||||||
|
stateChanged(this, s, c);
|
||||||
|
}
|
||||||
|
virtual void clearState(s32 s, s32 c = -1)
|
||||||
|
{
|
||||||
|
if(c >= 0 && c < 4)
|
||||||
|
{
|
||||||
|
state[c] &= ~s;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(s32 i = 0; i < 4; i++)
|
||||||
|
state[i] &= ~s;
|
||||||
|
}
|
||||||
|
stateChan = c;
|
||||||
|
stateChanged(this, s, c);
|
||||||
|
}
|
||||||
|
virtual bool isStateSet(s32 s, s32 c = -1) const
|
||||||
|
{
|
||||||
|
if(c >= 0 && c < 4)
|
||||||
|
{
|
||||||
|
return (state[c] & s) != 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(s32 i = 0; i < 4; i++)
|
||||||
|
if((state[i] & s) != 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//!Gets the element's current state
|
||||||
|
//!\return state
|
||||||
|
virtual s32 getState(s32 c = 0) { return state[c]; };
|
||||||
|
//!Gets the controller channel that last changed the element's state
|
||||||
|
//!\return Channel number (0-3, -1 = no channel)
|
||||||
|
virtual s32 getStateChan() { return stateChan; };
|
||||||
|
//!Resets the element's state to STATE_DEFAULT
|
||||||
|
virtual void resetState()
|
||||||
|
{
|
||||||
|
for(s32 i = 0; i < 4; i++)
|
||||||
|
state[i] = STATE_DEFAULT;
|
||||||
|
stateChan = -1;
|
||||||
|
}
|
||||||
|
//!Sets the element's alpha value
|
||||||
|
//!\param a alpha value
|
||||||
|
virtual void setAlpha(f32 a) { alpha = a; }
|
||||||
|
//!Gets the element's alpha value
|
||||||
|
//!Considers alpha, alphaDyn, and the parent element's getAlpha() value
|
||||||
|
//!\return alpha
|
||||||
|
virtual f32 getAlpha()
|
||||||
|
{
|
||||||
|
f32 a;
|
||||||
|
|
||||||
|
if(alphaDyn >= 0)
|
||||||
|
a = alphaDyn;
|
||||||
|
else
|
||||||
|
a = alpha;
|
||||||
|
|
||||||
|
if(parentElement)
|
||||||
|
a = (a * parentElement->getAlpha());
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
//!Sets the element's scale
|
||||||
|
//!\param s scale (1 is 100%)
|
||||||
|
virtual void setScale(float s)
|
||||||
|
{
|
||||||
|
scaleX = s;
|
||||||
|
scaleY = s;
|
||||||
|
scaleZ = s;
|
||||||
|
}
|
||||||
|
//!Sets the element's scale
|
||||||
|
//!\param s scale (1 is 100%)
|
||||||
|
virtual void setScaleX(float s) { scaleX = s; }
|
||||||
|
//!Sets the element's scale
|
||||||
|
//!\param s scale (1 is 100%)
|
||||||
|
virtual void setScaleY(float s) { scaleY = s; }
|
||||||
|
//!Sets the element's scale
|
||||||
|
//!\param s scale (1 is 100%)
|
||||||
|
virtual void setScaleZ(float s) { scaleZ = s; }
|
||||||
|
//!Gets the element's current scale
|
||||||
|
//!Considers scale, scaleDyn, and the parent element's getScale() value
|
||||||
|
virtual float getScale()
|
||||||
|
{
|
||||||
|
float s = 0.5f * (scaleX+scaleY) * scaleDyn;
|
||||||
|
|
||||||
|
if(parentElement)
|
||||||
|
s *= parentElement->getScale();
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
//!Gets the element's current scale
|
||||||
|
//!Considers scale, scaleDyn, and the parent element's getScale() value
|
||||||
|
virtual float getScaleX()
|
||||||
|
{
|
||||||
|
float s = scaleX * scaleDyn;
|
||||||
|
|
||||||
|
if(parentElement)
|
||||||
|
s *= parentElement->getScaleX();
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
//!Gets the element's current scale
|
||||||
|
//!Considers scale, scaleDyn, and the parent element's getScale() value
|
||||||
|
virtual float getScaleY()
|
||||||
|
{
|
||||||
|
float s = scaleY * scaleDyn;
|
||||||
|
|
||||||
|
if(parentElement)
|
||||||
|
s *= parentElement->getScaleY();
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
//!Gets the element's current scale
|
||||||
|
//!Considers scale, scaleDyn, and the parent element's getScale() value
|
||||||
|
virtual float getScaleZ()
|
||||||
|
{
|
||||||
|
float s = scaleZ;
|
||||||
|
|
||||||
|
if(parentElement)
|
||||||
|
s *= parentElement->getScaleZ();
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
//!Checks whether rumble was requested by the element
|
||||||
|
//!\return true is rumble was requested, false otherwise
|
||||||
|
virtual bool isRumbleActive() { return rumble; }
|
||||||
|
//!Sets whether or not the element is requesting a rumble event
|
||||||
|
//!\param r true if requesting rumble, false if not
|
||||||
|
virtual void setRumble(bool r) { rumble = r; }
|
||||||
|
//!Set an effect for the element
|
||||||
|
//!\param e Effect to enable
|
||||||
|
//!\param a Amount of the effect (usage varies on effect)
|
||||||
|
//!\param t Target amount of the effect (usage varies on effect)
|
||||||
|
virtual void setEffect(s32 e, s32 a, s32 t=0);
|
||||||
|
//!Sets an effect to be enabled on wiimote cursor over
|
||||||
|
//!\param e Effect to enable
|
||||||
|
//!\param a Amount of the effect (usage varies on effect)
|
||||||
|
//!\param t Target amount of the effect (usage varies on effect)
|
||||||
|
virtual void setEffectOnOver(s32 e, s32 a, s32 t=0);
|
||||||
|
//!Shortcut to SetEffectOnOver(EFFECT_SCALE, 4, 110)
|
||||||
|
virtual void setEffectGrow() { setEffectOnOver(EFFECT_SCALE, 4, 110); }
|
||||||
|
//!Reset all applied effects
|
||||||
|
virtual void resetEffects();
|
||||||
|
//!Gets the current element effects
|
||||||
|
//!\return element effects
|
||||||
|
virtual s32 getEffect() const { return effects; }
|
||||||
|
//!\return true if element animation is on going
|
||||||
|
virtual bool isAnimated() const { return (parentElement != 0) && (getEffect() > 0); }
|
||||||
|
//!Checks whether the specified coordinates are within the element's boundaries
|
||||||
|
//!\param x X coordinate
|
||||||
|
//!\param y Y coordinate
|
||||||
|
//!\return true if contained within, false otherwise
|
||||||
|
virtual bool isInside(f32 x, f32 y)
|
||||||
|
{
|
||||||
|
return ( x > (this->getCenterX() - getScaleX() * getWidth() * 0.5f)
|
||||||
|
&& x < (this->getCenterX() + getScaleX() * getWidth() * 0.5f)
|
||||||
|
&& y > (this->getCenterY() - getScaleY() * getHeight() * 0.5f)
|
||||||
|
&& y < (this->getCenterY() + getScaleY() * getHeight() * 0.5f));
|
||||||
|
}
|
||||||
|
//!Sets the element's position
|
||||||
|
//!\param x X coordinate
|
||||||
|
//!\param y Y coordinate
|
||||||
|
virtual void setPosition(f32 x, f32 y)
|
||||||
|
{
|
||||||
|
xoffset = x;
|
||||||
|
yoffset = y;
|
||||||
|
}
|
||||||
|
//!Sets the element's position
|
||||||
|
//!\param x X coordinate
|
||||||
|
//!\param y Y coordinate
|
||||||
|
//!\param z Z coordinate
|
||||||
|
virtual void setPosition(f32 x, f32 y, f32 z)
|
||||||
|
{
|
||||||
|
xoffset = x;
|
||||||
|
yoffset = y;
|
||||||
|
zoffset = z;
|
||||||
|
}
|
||||||
|
//!Gets whether or not the element is in STATE_SELECTED
|
||||||
|
//!\return true if selected, false otherwise
|
||||||
|
virtual s32 getSelected() { return -1; }
|
||||||
|
//!Sets the element's alignment respective to its parent element
|
||||||
|
//!Bitwise ALIGN_LEFT | ALIGN_RIGHT | ALIGN_CENTRE, ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE)
|
||||||
|
//!\param align Alignment
|
||||||
|
virtual void setAlignment(s32 a) { alignment = a; }
|
||||||
|
//!Gets the element's alignment
|
||||||
|
virtual s32 getAlignment() const { return alignment; }
|
||||||
|
//!Angle of the object
|
||||||
|
virtual void setAngle(f32 a) { angle = a; }
|
||||||
|
//!Angle of the object
|
||||||
|
virtual f32 getAngle() const { f32 r_angle = angle; if(parentElement) r_angle += parentElement->getAngle(); return r_angle; }
|
||||||
|
//!Called constantly to allow the element to respond to the current input data
|
||||||
|
//!\param t Pointer to a GuiController, containing the current input data from PAD/WPAD/VPAD
|
||||||
|
virtual void update(GuiController * t) { }
|
||||||
|
//!Called constantly to redraw the element
|
||||||
|
virtual void draw(CVideo * v) { }
|
||||||
|
//!Called constantly to process stuff in the element
|
||||||
|
virtual void process() { }
|
||||||
|
|
||||||
|
//!Updates the element's effects (dynamic values)
|
||||||
|
//!Called by Draw(), used for animation purposes
|
||||||
|
virtual void updateEffects();
|
||||||
|
|
||||||
|
typedef struct _POINT {
|
||||||
|
s32 x;
|
||||||
|
s32 y;
|
||||||
|
} POINT;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
STATE_DEFAULT = 0,
|
||||||
|
STATE_SELECTED = 0x01,
|
||||||
|
STATE_CLICKED = 0x02,
|
||||||
|
STATE_HELD = 0x04,
|
||||||
|
STATE_OVER = 0x08,
|
||||||
|
STATE_HIDDEN = 0x10,
|
||||||
|
STATE_DISABLE_INPUT = 0x20,
|
||||||
|
STATE_CLICKED_TOUCH = 0x40,
|
||||||
|
STATE_DISABLED = 0x80
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Switch pointer from control to screen position
|
||||||
|
POINT PtrToScreen(POINT p)
|
||||||
|
{
|
||||||
|
//! TODO for 3D
|
||||||
|
//POINT r = { p.x + getLeft(), p.y + getTop() };
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
//! Switch pointer screen to control position
|
||||||
|
POINT PtrToControl(POINT p)
|
||||||
|
{
|
||||||
|
//! TODO for 3D
|
||||||
|
//POINT r = { p.x - getLeft(), p.y - getTop() };
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
//! Signals
|
||||||
|
sigslot::signal2<GuiElement *, bool> visibleChanged;
|
||||||
|
sigslot::signal3<GuiElement *, s32, s32> stateChanged;
|
||||||
|
sigslot::signal1<GuiElement *> effectFinished;
|
||||||
|
protected:
|
||||||
|
bool rumble; //!< Wiimote rumble (on/off) - set to on when this element requests a rumble event
|
||||||
|
bool visible; //!< Visibility of the element. If false, Draw() is skipped
|
||||||
|
bool selectable; //!< Whether or not this element selectable (can change to SELECTED state)
|
||||||
|
bool clickable; //!< Whether or not this element is clickable (can change to CLICKED state)
|
||||||
|
bool holdable; //!< Whether or not this element is holdable (can change to HELD state)
|
||||||
|
bool drawOverOnlyWhenSelected; //!< Whether or not this element is holdable (can change to HELD state)
|
||||||
|
f32 width; //!< Element width
|
||||||
|
f32 height; //!< Element height
|
||||||
|
f32 xoffset; //!< Element X offset
|
||||||
|
f32 yoffset; //!< Element Y offset
|
||||||
|
f32 zoffset; //!< Element Z offset
|
||||||
|
f32 alpha; //!< Element alpha value (0-255)
|
||||||
|
f32 angle; //!< Angle of the object (0-360)
|
||||||
|
f32 scaleX; //!< Element scale (1 = 100%)
|
||||||
|
f32 scaleY; //!< Element scale (1 = 100%)
|
||||||
|
f32 scaleZ; //!< Element scale (1 = 100%)
|
||||||
|
s32 alignment; //!< Horizontal element alignment, respective to parent element
|
||||||
|
s32 state[4]; //!< Element state (DEFAULT, SELECTED, CLICKED, DISABLED)
|
||||||
|
s32 stateChan; //!< Which controller channel is responsible for the last change in state
|
||||||
|
GuiElement * parentElement; //!< Parent element
|
||||||
|
|
||||||
|
//! TODO: Move me to some Animator class
|
||||||
|
s32 xoffsetDyn; //!< Element X offset, dynamic (added to xoffset value for animation effects)
|
||||||
|
s32 yoffsetDyn; //!< Element Y offset, dynamic (added to yoffset value for animation effects)
|
||||||
|
f32 alphaDyn; //!< Element alpha, dynamic (multiplied by alpha value for blending/fading effects)
|
||||||
|
f32 scaleDyn; //!< Element scale, dynamic (multiplied by alpha value for blending/fading effects)
|
||||||
|
s32 effects; //!< Currently enabled effect(s). 0 when no effects are enabled
|
||||||
|
s32 effectAmount; //!< Effect amount. Used by different effects for different purposes
|
||||||
|
s32 effectTarget; //!< Effect target amount. Used by different effects for different purposes
|
||||||
|
s32 effectsOver; //!< Effects to enable when wiimote cursor is over this element. Copied to effects variable on over event
|
||||||
|
s32 effectAmountOver; //!< EffectAmount to set when wiimote cursor is over this element
|
||||||
|
s32 effectTargetOver; //!< EffectTarget to set when wiimote cursor is over this element
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
230
source/gui/GuiFrame.cpp
Normal file
230
source/gui/GuiFrame.cpp
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include "GuiFrame.h"
|
||||||
|
|
||||||
|
GuiFrame::GuiFrame(GuiFrame *p)
|
||||||
|
{
|
||||||
|
parent = p;
|
||||||
|
width = 0;
|
||||||
|
height = 0;
|
||||||
|
dim = false;
|
||||||
|
|
||||||
|
if(parent)
|
||||||
|
parent->append(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiFrame::GuiFrame(f32 w, f32 h, GuiFrame *p)
|
||||||
|
{
|
||||||
|
parent = p;
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
|
dim = false;
|
||||||
|
|
||||||
|
if(parent)
|
||||||
|
parent->append(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiFrame::~GuiFrame()
|
||||||
|
{
|
||||||
|
closing(this);
|
||||||
|
|
||||||
|
if(parent)
|
||||||
|
parent->remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::append(GuiElement* e)
|
||||||
|
{
|
||||||
|
if (e == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
remove(e);
|
||||||
|
elements.push_back(e);
|
||||||
|
e->setParent(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::insert(GuiElement* e, u32 index)
|
||||||
|
{
|
||||||
|
if (e == NULL || (index >= elements.size()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
remove(e);
|
||||||
|
elements.insert(elements.begin()+index, e);
|
||||||
|
e->setParent(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::remove(GuiElement* e)
|
||||||
|
{
|
||||||
|
if (e == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (u32 i = 0; i < elements.size(); ++i)
|
||||||
|
{
|
||||||
|
if(e == elements[i])
|
||||||
|
{
|
||||||
|
elements.erase(elements.begin()+i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::removeAll()
|
||||||
|
{
|
||||||
|
elements.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::close()
|
||||||
|
{
|
||||||
|
//Application::instance()->pushForDelete(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::dimBackground(bool d)
|
||||||
|
{
|
||||||
|
dim = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiElement* GuiFrame::getGuiElementAt(u32 index) const
|
||||||
|
{
|
||||||
|
if (index >= elements.size())
|
||||||
|
return NULL;
|
||||||
|
return elements[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GuiFrame::getSize()
|
||||||
|
{
|
||||||
|
return elements.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::resetState()
|
||||||
|
{
|
||||||
|
GuiElement::resetState();
|
||||||
|
|
||||||
|
for (u32 i = 0; i < elements.size(); ++i)
|
||||||
|
{
|
||||||
|
elements[i]->resetState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::setState(s32 s, s32 c)
|
||||||
|
{
|
||||||
|
GuiElement::setState(s, c);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < elements.size(); ++i)
|
||||||
|
{
|
||||||
|
elements[i]->setState(s, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::clearState(s32 s, s32 c)
|
||||||
|
{
|
||||||
|
GuiElement::clearState(s, c);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < elements.size(); ++i)
|
||||||
|
{
|
||||||
|
elements[i]->clearState(s, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::setVisible(bool v)
|
||||||
|
{
|
||||||
|
visible = v;
|
||||||
|
|
||||||
|
for (u32 i = 0; i < elements.size(); ++i)
|
||||||
|
{
|
||||||
|
elements[i]->setVisible(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 GuiFrame::getSelected()
|
||||||
|
{
|
||||||
|
// find selected element
|
||||||
|
s32 found = -1;
|
||||||
|
for (u32 i = 0; i < elements.size(); ++i)
|
||||||
|
{
|
||||||
|
if(elements[i]->isStateSet(STATE_SELECTED | STATE_OVER))
|
||||||
|
{
|
||||||
|
found = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::draw(CVideo * v)
|
||||||
|
{
|
||||||
|
if(!this->isVisible() && parentElement)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(parentElement && dim == true)
|
||||||
|
{
|
||||||
|
//GXColor dimColor = (GXColor){0, 0, 0, 0x70};
|
||||||
|
//Menu_DrawRectangle(0, 0, GetZPosition(), screenwidth,screenheight, &dimColor, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! render appended items next frame but allow stop of render if size is reached
|
||||||
|
u32 size = elements.size();
|
||||||
|
|
||||||
|
for (u32 i = 0; i < size && i < elements.size(); ++i)
|
||||||
|
{
|
||||||
|
elements[i]->draw(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::updateEffects()
|
||||||
|
{
|
||||||
|
if(!this->isVisible() && parentElement)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GuiElement::updateEffects();
|
||||||
|
|
||||||
|
//! render appended items next frame but allow stop of render if size is reached
|
||||||
|
u32 size = elements.size();
|
||||||
|
|
||||||
|
for (u32 i = 0; i < size && i < elements.size(); ++i)
|
||||||
|
{
|
||||||
|
elements[i]->updateEffects();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::process()
|
||||||
|
{
|
||||||
|
if(!this->isVisible() && parentElement)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GuiElement::process();
|
||||||
|
|
||||||
|
//! render appended items next frame but allow stop of render if size is reached
|
||||||
|
u32 size = elements.size();
|
||||||
|
|
||||||
|
for (u32 i = 0; i < size && i < elements.size(); ++i)
|
||||||
|
{
|
||||||
|
elements[i]->process();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiFrame::update(GuiController * c)
|
||||||
|
{
|
||||||
|
if(isStateSet(STATE_DISABLED) && parentElement)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//! update appended items next frame
|
||||||
|
u32 size = elements.size();
|
||||||
|
|
||||||
|
for (u32 i = 0; i < size && i < elements.size(); ++i)
|
||||||
|
{
|
||||||
|
elements[i]->update(c);
|
||||||
|
}
|
||||||
|
}
|
98
source/gui/GuiFrame.h
Normal file
98
source/gui/GuiFrame.h
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef GUI_FRAME_H_
|
||||||
|
#define GUI_FRAME_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "GuiElement.h"
|
||||||
|
#include "sigslot.h"
|
||||||
|
|
||||||
|
//!Allows GuiElements to be grouped together into a "window"
|
||||||
|
class GuiFrame : public GuiElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//!Constructor
|
||||||
|
GuiFrame(GuiFrame *parent = 0);
|
||||||
|
//!\overload
|
||||||
|
//!\param w Width of window
|
||||||
|
//!\param h Height of window
|
||||||
|
GuiFrame(f32 w, f32 h, GuiFrame *parent = 0);
|
||||||
|
//!Destructor
|
||||||
|
virtual ~GuiFrame();
|
||||||
|
//!Appends a GuiElement to the GuiFrame
|
||||||
|
//!\param e The GuiElement to append. If it is already in the GuiFrame, it is removed first
|
||||||
|
void append(GuiElement* e);
|
||||||
|
//!Inserts a GuiElement into the GuiFrame at the specified index
|
||||||
|
//!\param e The GuiElement to insert. If it is already in the GuiFrame, it is removed first
|
||||||
|
//!\param i Index in which to insert the element
|
||||||
|
void insert(GuiElement* e, u32 i);
|
||||||
|
//!Removes the specified GuiElement from the GuiFrame
|
||||||
|
//!\param e GuiElement to be removed
|
||||||
|
void remove(GuiElement* e);
|
||||||
|
//!Removes all GuiElements
|
||||||
|
void removeAll();
|
||||||
|
//!Bring element to front of the window
|
||||||
|
void bringToFront(GuiElement *e) { remove(e); append(e); }
|
||||||
|
//!Returns the GuiElement at the specified index
|
||||||
|
//!\param index The index of the element
|
||||||
|
//!\return A pointer to the element at the index, NULL on error (eg: out of bounds)
|
||||||
|
GuiElement* getGuiElementAt(u32 index) const;
|
||||||
|
//!Returns the size of the list of elements
|
||||||
|
//!\return The size of the current element list
|
||||||
|
u32 getSize();
|
||||||
|
//!Sets the visibility of the window
|
||||||
|
//!\param v visibility (true = visible)
|
||||||
|
void setVisible(bool v);
|
||||||
|
//!Resets the window's state to STATE_DEFAULT
|
||||||
|
void resetState();
|
||||||
|
//!Sets the window's state
|
||||||
|
//!\param s State
|
||||||
|
void setState(s32 s, s32 c = -1);
|
||||||
|
void clearState(s32 s, s32 c = -1);
|
||||||
|
//!Gets the index of the GuiElement inside the window that is currently selected
|
||||||
|
//!\return index of selected GuiElement
|
||||||
|
s32 getSelected();
|
||||||
|
//!Dim the Window's background
|
||||||
|
void dimBackground(bool d);
|
||||||
|
//!Draws all the elements in this GuiFrame
|
||||||
|
void draw(CVideo * v);
|
||||||
|
//!Updates the window and all elements contains within
|
||||||
|
//!Allows the GuiFrame and all elements to respond to the input data specified
|
||||||
|
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
|
||||||
|
void update(GuiController * t);
|
||||||
|
//!virtual Close Window - this will put the object on the delete queue in MainWindow
|
||||||
|
virtual void close();
|
||||||
|
//!virtual show window function
|
||||||
|
virtual void show() {}
|
||||||
|
//!virtual hide window function
|
||||||
|
virtual void hide() {}
|
||||||
|
//!virtual enter main loop function (blocking)
|
||||||
|
virtual void exec() {}
|
||||||
|
//!virtual updateEffects which is called by the main loop
|
||||||
|
virtual void updateEffects();
|
||||||
|
//!virtual process which is called by the main loop
|
||||||
|
virtual void process();
|
||||||
|
//! Signals
|
||||||
|
//! On Closing
|
||||||
|
sigslot::signal1<GuiFrame *> closing;
|
||||||
|
protected:
|
||||||
|
bool dim; //! Enable/disable dim of a window only
|
||||||
|
GuiFrame *parent; //!< Parent Window
|
||||||
|
std::vector<GuiElement*> elements; //!< Contains all elements within the GuiFrame
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
289
source/gui/GuiImage.cpp
Normal file
289
source/gui/GuiImage.cpp
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include "GuiImage.h"
|
||||||
|
#include "video/CVideo.h"
|
||||||
|
#include "video/shaders/Texture2DShader.h"
|
||||||
|
#include "video/shaders/ColorShader.h"
|
||||||
|
|
||||||
|
static const f32 fPiDiv180 = ((f32)M_PI / 180.0f);
|
||||||
|
|
||||||
|
GuiImage::GuiImage(GuiImageData * img)
|
||||||
|
{
|
||||||
|
if(img && img->getTexture())
|
||||||
|
{
|
||||||
|
width = img->getWidth();
|
||||||
|
height = img->getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
internalInit(width, height);
|
||||||
|
imageData = img;
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiImage::GuiImage(s32 w, s32 h, const GX2Color & c, s32 type)
|
||||||
|
{
|
||||||
|
internalInit(w, h);
|
||||||
|
imgType = type;
|
||||||
|
colorCount = ColorShader::cuColorVtxsSize / ColorShader::cuColorAttrSize;
|
||||||
|
|
||||||
|
colorVtxs = (u8 *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, colorCount * ColorShader::cuColorAttrSize);
|
||||||
|
if(colorVtxs)
|
||||||
|
{
|
||||||
|
for(u32 i = 0; i < colorCount; i++)
|
||||||
|
setImageColor(c, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiImage::GuiImage(s32 w, s32 h, const GX2Color *c, u32 color_count, s32 type)
|
||||||
|
{
|
||||||
|
internalInit(w, h);
|
||||||
|
imgType = type;
|
||||||
|
colorCount = ColorShader::cuColorVtxsSize / ColorShader::cuColorAttrSize;
|
||||||
|
if(colorCount < color_count)
|
||||||
|
colorCount = color_count;
|
||||||
|
|
||||||
|
colorVtxs = (u8 *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, colorCount * ColorShader::cuColorAttrSize);
|
||||||
|
if(colorVtxs)
|
||||||
|
{
|
||||||
|
for(u32 i = 0; i < colorCount; i++)
|
||||||
|
{
|
||||||
|
// take the last as reference if not enough colors defined
|
||||||
|
s32 idx = (i < color_count) ? i : (color_count - 1);
|
||||||
|
setImageColor(c[idx], i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor for the GuiImage class.
|
||||||
|
*/
|
||||||
|
GuiImage::~GuiImage()
|
||||||
|
{
|
||||||
|
if(colorVtxs) {
|
||||||
|
free(colorVtxs);
|
||||||
|
colorVtxs = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImage::internalInit(s32 w, s32 h)
|
||||||
|
{
|
||||||
|
imageData = NULL;
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
|
tileHorizontal = -1;
|
||||||
|
tileVertical = -1;
|
||||||
|
imgType = IMAGE_TEXTURE;
|
||||||
|
colorVtxsDirty = false;
|
||||||
|
colorVtxs = NULL;
|
||||||
|
colorCount = 0;
|
||||||
|
posVtxs = NULL;
|
||||||
|
texCoords = NULL;
|
||||||
|
vtxCount = 4;
|
||||||
|
primitive = GX2_PRIMITIVE_QUADS;
|
||||||
|
|
||||||
|
imageAngle = 0.0f;
|
||||||
|
blurDirection = glm::vec3(0.0f);
|
||||||
|
positionOffsets = glm::vec3(0.0f);
|
||||||
|
scaleFactor = glm::vec3(1.0f);
|
||||||
|
colorIntensity = glm::vec4(1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImage::setImageData(GuiImageData * img)
|
||||||
|
{
|
||||||
|
imageData = img;
|
||||||
|
width = 0;
|
||||||
|
height = 0;
|
||||||
|
if(img && img->getTexture())
|
||||||
|
{
|
||||||
|
width = img->getWidth();
|
||||||
|
height = img->getHeight();
|
||||||
|
}
|
||||||
|
imgType = IMAGE_TEXTURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GX2Color GuiImage::getPixel(s32 x, s32 y)
|
||||||
|
{
|
||||||
|
if(!imageData || this->getWidth() <= 0 || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight())
|
||||||
|
return (GX2Color){0, 0, 0, 0};
|
||||||
|
|
||||||
|
u32 pitch = imageData->getTexture()->surface.pitch;
|
||||||
|
u32 *imagePtr = (u32*)imageData->getTexture()->surface.image_data;
|
||||||
|
|
||||||
|
u32 color_u32 = imagePtr[y * pitch + x];
|
||||||
|
GX2Color color;
|
||||||
|
color.r = (color_u32 >> 24) & 0xFF;
|
||||||
|
color.g = (color_u32 >> 16) & 0xFF;
|
||||||
|
color.b = (color_u32 >> 8) & 0xFF;
|
||||||
|
color.a = (color_u32 >> 0) & 0xFF;
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImage::setPixel(s32 x, s32 y, const GX2Color & color)
|
||||||
|
{
|
||||||
|
if(!imageData || this->getWidth() <= 0 || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight())
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
u32 pitch = imageData->getTexture()->surface.pitch;
|
||||||
|
u32 *imagePtr = (u32*)imageData->getTexture()->surface.image_data;
|
||||||
|
imagePtr[y * pitch + x] = (color.r << 24) | (color.g << 16) | (color.b << 8) | (color.a << 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImage::setImageColor(const GX2Color & c, s32 idx)
|
||||||
|
{
|
||||||
|
if(!colorVtxs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(idx >= 0 && idx < (s32)colorCount)
|
||||||
|
{
|
||||||
|
colorVtxs[(idx << 2) + 0] = c.r;
|
||||||
|
colorVtxs[(idx << 2) + 1] = c.g;
|
||||||
|
colorVtxs[(idx << 2) + 2] = c.b;
|
||||||
|
colorVtxs[(idx << 2) + 3] = c.a;
|
||||||
|
colorVtxsDirty = true;
|
||||||
|
}
|
||||||
|
else if(colorVtxs)
|
||||||
|
{
|
||||||
|
for(u32 i = 0; i < (ColorShader::cuColorVtxsSize / sizeof(u8)); i += 4)
|
||||||
|
{
|
||||||
|
colorVtxs[i + 0] = c.r;
|
||||||
|
colorVtxs[i + 1] = c.g;
|
||||||
|
colorVtxs[i + 2] = c.b;
|
||||||
|
colorVtxs[i + 3] = c.a;
|
||||||
|
}
|
||||||
|
colorVtxsDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImage::setSize(s32 w, s32 h)
|
||||||
|
{
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImage::setPrimitiveVertex(s32 prim, const f32 *posVtx, const f32 *texCoord, u32 vtxcount)
|
||||||
|
{
|
||||||
|
primitive = prim;
|
||||||
|
vtxCount = vtxcount;
|
||||||
|
posVtxs = posVtx;
|
||||||
|
texCoords = texCoord;
|
||||||
|
|
||||||
|
if(imgType == IMAGE_COLOR)
|
||||||
|
{
|
||||||
|
u8 * newColorVtxs = (u8 *) memalign(0x40, ColorShader::cuColorAttrSize * vtxCount);
|
||||||
|
|
||||||
|
for(u32 i = 0; i < vtxCount; i++)
|
||||||
|
{
|
||||||
|
s32 newColorIdx = (i << 2);
|
||||||
|
s32 colorIdx = (i < colorCount) ? (newColorIdx) : ((colorCount - 1) << 2);
|
||||||
|
|
||||||
|
newColorVtxs[newColorIdx + 0] = colorVtxs[colorIdx + 0];
|
||||||
|
newColorVtxs[newColorIdx + 1] = colorVtxs[colorIdx + 1];
|
||||||
|
newColorVtxs[newColorIdx + 2] = colorVtxs[colorIdx + 2];
|
||||||
|
newColorVtxs[newColorIdx + 3] = colorVtxs[colorIdx + 3];
|
||||||
|
}
|
||||||
|
|
||||||
|
free(colorVtxs);
|
||||||
|
colorVtxs = newColorVtxs;
|
||||||
|
colorCount = vtxCount;
|
||||||
|
colorVtxsDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImage::draw(CVideo *pVideo)
|
||||||
|
{
|
||||||
|
if(!this->isVisible() || tileVertical == 0 || tileHorizontal == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
f32 currScaleX = getScaleX();
|
||||||
|
f32 currScaleY = getScaleY();
|
||||||
|
|
||||||
|
positionOffsets[0] = getCenterX() * pVideo->getWidthScaleFactor() * 2.0f;
|
||||||
|
positionOffsets[1] = getCenterY() * pVideo->getHeightScaleFactor() * 2.0f;
|
||||||
|
positionOffsets[2] = getDepth() * pVideo->getDepthScaleFactor() * 2.0f;
|
||||||
|
|
||||||
|
scaleFactor[0] = currScaleX * getWidth() * pVideo->getWidthScaleFactor();
|
||||||
|
scaleFactor[1] = currScaleY * getHeight() * pVideo->getHeightScaleFactor();
|
||||||
|
scaleFactor[2] = getScaleZ();
|
||||||
|
|
||||||
|
//! add other colors intensities parameters
|
||||||
|
colorIntensity[3] = getAlpha();
|
||||||
|
|
||||||
|
//! angle of the object
|
||||||
|
imageAngle = DegToRad(getAngle());
|
||||||
|
|
||||||
|
// if(image && tileHorizontal > 0 && tileVertical > 0)
|
||||||
|
// {
|
||||||
|
// for(s32 n=0; n<tileVertical; n++)
|
||||||
|
// for(s32 i=0; i<tileHorizontal; i++)
|
||||||
|
// {
|
||||||
|
// if(bUnCut)
|
||||||
|
// Menu_DrawImg(image, width, height, format, currLeft+width*i, currTop+width*n, currZ, imageangle, currScaleX, currScaleY, currAlpha);
|
||||||
|
// else
|
||||||
|
// Menu_DrawImgCut(image, width, height, format, currLeft+width*i, currTop+width*n, currZ, imageangle, currScaleX, currScaleY, currAlpha, cutBoundsRect.x1(), cutBoundsRect.x2(), cutBoundsRect.y1(), cutBoundsRect.y2());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else if(image && tileHorizontal > 0)
|
||||||
|
// {
|
||||||
|
// for(s32 i=0; i<tileHorizontal; i++)
|
||||||
|
// {
|
||||||
|
// s32 widthTile = (imageangle == 90 || imageangle == 270) ? height : width;
|
||||||
|
// if(bUnCut)
|
||||||
|
// Menu_DrawImg(image, width, height, format, currLeft+widthTile*i, currTop, currZ, imageangle, currScaleX, currScaleY, currAlpha);
|
||||||
|
// else
|
||||||
|
// Menu_DrawImgCut(image, width, height, format, currLeft+widthTile*i, currTop, currZ, imageangle, currScaleX, currScaleY, currAlpha, cutBoundsRect.x1(), cutBoundsRect.x2(), cutBoundsRect.y1(), cutBoundsRect.y2());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else if(image && tileVertical > 0)
|
||||||
|
// {
|
||||||
|
// for(s32 i=0; i<tileVertical; i++)
|
||||||
|
// {
|
||||||
|
// if(bUnCut)
|
||||||
|
// Menu_DrawImg(image, width, height, format, currLeft, currTop+height*i, currZ, imageangle, currScaleX, currScaleY, currAlpha);
|
||||||
|
// else
|
||||||
|
// Menu_DrawImgCut(image, width, height, format, currLeft, currTop+height*i, currZ, imageangle, currScaleX, currScaleY, currAlpha, cutBoundsRect.x1(), cutBoundsRect.x2(), cutBoundsRect.y1(), cutBoundsRect.y2());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
if(colorVtxsDirty && colorVtxs) {
|
||||||
|
//! flush color vertex only on main GX2 thread
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, colorVtxs, colorCount * ColorShader::cuColorAttrSize);
|
||||||
|
colorVtxsDirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(imgType == IMAGE_COLOR && colorVtxs)
|
||||||
|
{
|
||||||
|
ColorShader::instance()->setShaders();
|
||||||
|
ColorShader::instance()->setAttributeBuffer(colorVtxs, posVtxs, vtxCount);
|
||||||
|
ColorShader::instance()->setAngle(imageAngle);
|
||||||
|
ColorShader::instance()->setOffset(positionOffsets);
|
||||||
|
ColorShader::instance()->setScale(scaleFactor);
|
||||||
|
ColorShader::instance()->setColorIntensity(colorIntensity);
|
||||||
|
ColorShader::instance()->draw(primitive, vtxCount);
|
||||||
|
}
|
||||||
|
else if(imageData)
|
||||||
|
{
|
||||||
|
Texture2DShader::instance()->setShaders();
|
||||||
|
Texture2DShader::instance()->setAttributeBuffer(texCoords, posVtxs, vtxCount);
|
||||||
|
Texture2DShader::instance()->setAngle(imageAngle);
|
||||||
|
Texture2DShader::instance()->setOffset(positionOffsets);
|
||||||
|
Texture2DShader::instance()->setScale(scaleFactor);
|
||||||
|
Texture2DShader::instance()->setColorIntensity(colorIntensity);
|
||||||
|
Texture2DShader::instance()->setBlurring(blurDirection);
|
||||||
|
Texture2DShader::instance()->setTextureAndSampler(imageData->getTexture(), imageData->getSampler());
|
||||||
|
Texture2DShader::instance()->draw(primitive, vtxCount);
|
||||||
|
}
|
||||||
|
}
|
110
source/gui/GuiImage.h
Normal file
110
source/gui/GuiImage.h
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef GUI_IMAGE_H_
|
||||||
|
#define GUI_IMAGE_H_
|
||||||
|
|
||||||
|
#include "video/shaders/Shader.h"
|
||||||
|
#include "GuiElement.h"
|
||||||
|
#include "GuiImageData.h"
|
||||||
|
|
||||||
|
//!Display, manage, and manipulate images in the GUI
|
||||||
|
class GuiImage : public GuiElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum ImageTypes
|
||||||
|
{
|
||||||
|
IMAGE_TEXTURE,
|
||||||
|
IMAGE_COLOR
|
||||||
|
};
|
||||||
|
|
||||||
|
//!\overload
|
||||||
|
//!\param img Pointer to GuiImageData element
|
||||||
|
GuiImage(GuiImageData * img);
|
||||||
|
//!\overload
|
||||||
|
//!Creates an image filled with the specified color
|
||||||
|
//!\param w Image width
|
||||||
|
//!\param h Image height
|
||||||
|
//!\param c Array with 4 x image color (BL, BR, TL, TR)
|
||||||
|
GuiImage(s32 w, s32 h, const GX2Color & c, s32 imgType = IMAGE_COLOR);
|
||||||
|
GuiImage(s32 w, s32 h, const GX2Color * c, u32 colorCount = 1, s32 imgType = IMAGE_COLOR);
|
||||||
|
//!Destructor
|
||||||
|
virtual ~GuiImage();
|
||||||
|
//!Sets the number of times to draw the image horizontally
|
||||||
|
//!\param t Number of times to draw the image
|
||||||
|
void setTileHorizontal(s32 t) { tileHorizontal = t; }
|
||||||
|
//!Sets the number of times to draw the image vertically
|
||||||
|
//!\param t Number of times to draw the image
|
||||||
|
void setTileVertical(s32 t) { tileVertical = t; }
|
||||||
|
//!Constantly called to draw the image
|
||||||
|
void draw(CVideo *pVideo);
|
||||||
|
//!Gets the image data
|
||||||
|
//!\return pointer to image data
|
||||||
|
GuiImageData * getImageData() const { return imageData; }
|
||||||
|
//!Sets up a new image using the GuiImageData object specified
|
||||||
|
//!\param img Pointer to GuiImageData object
|
||||||
|
void setImageData(GuiImageData * img);
|
||||||
|
//!Gets the pixel color at the specified coordinates of the image
|
||||||
|
//!\param x X coordinate
|
||||||
|
//!\param y Y coordinate
|
||||||
|
GX2Color getPixel(s32 x, s32 y);
|
||||||
|
//!Sets the pixel color at the specified coordinates of the image
|
||||||
|
//!\param x X coordinate
|
||||||
|
//!\param y Y coordinate
|
||||||
|
//!\param color Pixel color
|
||||||
|
void setPixel(s32 x, s32 y, const GX2Color & color);
|
||||||
|
//!Change ImageColor
|
||||||
|
void setImageColor(const GX2Color & c, s32 idx = -1);
|
||||||
|
//!Change ImageColor
|
||||||
|
void setSize(s32 w, s32 h);
|
||||||
|
|
||||||
|
void setPrimitiveVertex(s32 prim, const f32 *pos, const f32 *tex, u32 count);
|
||||||
|
|
||||||
|
void setBlurDirection(u8 dir, f32 value)
|
||||||
|
{
|
||||||
|
if(dir < 2) {
|
||||||
|
blurDirection[dir] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void setColorIntensity(const glm::vec4 & col)
|
||||||
|
{
|
||||||
|
colorIntensity = col;
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
void internalInit(s32 w, s32 h);
|
||||||
|
|
||||||
|
s32 imgType; //!< Type of image data (IMAGE_TEXTURE, IMAGE_COLOR, IMAGE_DATA)
|
||||||
|
GuiImageData * imageData; //!< Poiner to image data. May be shared with GuiImageData data
|
||||||
|
s32 tileHorizontal; //!< Number of times to draw (tile) the image horizontally
|
||||||
|
s32 tileVertical; //!< Number of times to draw (tile) the image vertically
|
||||||
|
|
||||||
|
//! Internally used variables for rendering
|
||||||
|
u8 *colorVtxs;
|
||||||
|
u32 colorCount;
|
||||||
|
bool colorVtxsDirty;
|
||||||
|
glm::vec3 positionOffsets;
|
||||||
|
glm::vec3 scaleFactor;
|
||||||
|
glm::vec4 colorIntensity;
|
||||||
|
f32 imageAngle;
|
||||||
|
glm::vec3 blurDirection;
|
||||||
|
|
||||||
|
const f32 * posVtxs;
|
||||||
|
const f32 * texCoords;
|
||||||
|
u32 vtxCount;
|
||||||
|
s32 primitive;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
174
source/gui/GuiImageAsync.cpp
Normal file
174
source/gui/GuiImageAsync.cpp
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "GuiImageAsync.h"
|
||||||
|
#include <fs/FSUtils.h>
|
||||||
|
|
||||||
|
std::vector<GuiImageAsync *> GuiImageAsync::imageQueue;
|
||||||
|
CThread * GuiImageAsync::pThread = NULL;
|
||||||
|
CMutex * GuiImageAsync::pMutex = NULL;
|
||||||
|
u32 GuiImageAsync::threadRefCounter = 0;
|
||||||
|
bool GuiImageAsync::bExitRequested = false;
|
||||||
|
GuiImageAsync * GuiImageAsync::pInUse = NULL;
|
||||||
|
|
||||||
|
GuiImageAsync::GuiImageAsync(const u8 *imageBuffer, const u32 & imageBufferSize, GuiImageData * preloadImg)
|
||||||
|
: GuiImage(preloadImg)
|
||||||
|
, imgData(NULL)
|
||||||
|
, imgBuffer(imageBuffer)
|
||||||
|
, imgBufferSize(imageBufferSize)
|
||||||
|
{
|
||||||
|
threadInit();
|
||||||
|
threadAddImage(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiImageAsync::GuiImageAsync(const std::string & file, GuiImageData * preloadImg)
|
||||||
|
: GuiImage(preloadImg)
|
||||||
|
, imgData(NULL)
|
||||||
|
, filename(file)
|
||||||
|
, imgBuffer(NULL)
|
||||||
|
, imgBufferSize(0)
|
||||||
|
{
|
||||||
|
threadInit();
|
||||||
|
threadAddImage(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiImageAsync::~GuiImageAsync()
|
||||||
|
{
|
||||||
|
threadRemoveImage(this);
|
||||||
|
while(pInUse == this)
|
||||||
|
os_usleep(1000);
|
||||||
|
|
||||||
|
if (imgData)
|
||||||
|
delete imgData;
|
||||||
|
|
||||||
|
//threadExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImageAsync::threadAddImage(GuiImageAsync *Image)
|
||||||
|
{
|
||||||
|
pMutex->lock();
|
||||||
|
imageQueue.push_back(Image);
|
||||||
|
pMutex->unlock();
|
||||||
|
pThread->resumeThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImageAsync::threadRemoveImage(GuiImageAsync *image)
|
||||||
|
{
|
||||||
|
pMutex->lock();
|
||||||
|
for(u32 i = 0; i < imageQueue.size(); ++i)
|
||||||
|
{
|
||||||
|
if(imageQueue[i] == image)
|
||||||
|
{
|
||||||
|
imageQueue.erase(imageQueue.begin() + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pMutex->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImageAsync::clearQueue()
|
||||||
|
{
|
||||||
|
pMutex->lock();
|
||||||
|
imageQueue.clear();
|
||||||
|
pMutex->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImageAsync::guiImageAsyncThread(CThread *thread, void *arg)
|
||||||
|
{
|
||||||
|
while(!bExitRequested)
|
||||||
|
{
|
||||||
|
if(imageQueue.empty() && !bExitRequested)
|
||||||
|
pThread->suspendThread();
|
||||||
|
|
||||||
|
if(!imageQueue.empty() && !bExitRequested)
|
||||||
|
{
|
||||||
|
pMutex->lock();
|
||||||
|
pInUse = imageQueue.front();
|
||||||
|
imageQueue.erase(imageQueue.begin());
|
||||||
|
pMutex->unlock();
|
||||||
|
|
||||||
|
if (!pInUse)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
if(pInUse->imgBuffer && pInUse->imgBufferSize)
|
||||||
|
{
|
||||||
|
pInUse->imgData = new GuiImageData(pInUse->imgBuffer, pInUse->imgBufferSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u8 *buffer = NULL;
|
||||||
|
u32 bufferSize = 0;
|
||||||
|
|
||||||
|
s32 iResult = FSUtils::LoadFileToMem(pInUse->filename.c_str(), &buffer, &bufferSize);
|
||||||
|
if(iResult > 0)
|
||||||
|
{
|
||||||
|
pInUse->imgData = new GuiImageData(buffer, bufferSize, GX2_TEX_CLAMP_MIRROR);
|
||||||
|
|
||||||
|
//! free original image buffer which is converted to texture now and not needed anymore
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pInUse->imgData)
|
||||||
|
{
|
||||||
|
if(pInUse->imgData->getTexture())
|
||||||
|
{
|
||||||
|
pInUse->width = pInUse->imgData->getWidth();
|
||||||
|
pInUse->height = pInUse->imgData->getHeight();
|
||||||
|
pInUse->imageData = pInUse->imgData;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete pInUse->imgData;
|
||||||
|
pInUse->imgData = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pInUse->imageLoaded(pInUse);
|
||||||
|
pInUse = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImageAsync::threadInit()
|
||||||
|
{
|
||||||
|
if (pThread == NULL)
|
||||||
|
{
|
||||||
|
bExitRequested = false;
|
||||||
|
pMutex = new CMutex();
|
||||||
|
pThread = CThread::create(GuiImageAsync::guiImageAsyncThread, NULL, CThread::eAttributeAffCore1 | CThread::eAttributePinnedAff, 10);
|
||||||
|
pThread->resumeThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
++threadRefCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImageAsync::threadExit()
|
||||||
|
{
|
||||||
|
if(threadRefCounter){
|
||||||
|
--threadRefCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(/*(threadRefCounter == 0) &&*/ (pThread != NULL))
|
||||||
|
{
|
||||||
|
bExitRequested = true;
|
||||||
|
delete pThread;
|
||||||
|
delete pMutex;
|
||||||
|
pThread = NULL;
|
||||||
|
pMutex = NULL;
|
||||||
|
}
|
||||||
|
}
|
62
source/gui/GuiImageAsync.h
Normal file
62
source/gui/GuiImageAsync.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef _GUIIMAGEASYNC_H_
|
||||||
|
#define _GUIIMAGEASYNC_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "GuiImage.h"
|
||||||
|
#include <system/CThread.h>
|
||||||
|
#include <system/CMutex.h>
|
||||||
|
#include <dynamic_libs/os_functions.h>
|
||||||
|
|
||||||
|
class GuiImageAsync : public GuiImage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GuiImageAsync(const u8 *imageBuffer, const u32 & imageBufferSize, GuiImageData * preloadImg);
|
||||||
|
GuiImageAsync(const std::string & filename, GuiImageData * preloadImg);
|
||||||
|
virtual ~GuiImageAsync();
|
||||||
|
|
||||||
|
static void clearQueue();
|
||||||
|
static void removeFromQueue(GuiImageAsync * image) {
|
||||||
|
threadRemoveImage(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! don't forget to LOCK GUI if using this asynchron call
|
||||||
|
sigslot::signal1<GuiImageAsync *> imageLoaded;
|
||||||
|
static void threadExit();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void threadInit();
|
||||||
|
|
||||||
|
GuiImageData *imgData;
|
||||||
|
std::string filename;
|
||||||
|
const u8 *imgBuffer;
|
||||||
|
const u32 imgBufferSize;
|
||||||
|
|
||||||
|
static void guiImageAsyncThread(CThread *thread, void *arg);
|
||||||
|
static void threadAddImage(GuiImageAsync* Image);
|
||||||
|
static void threadRemoveImage(GuiImageAsync* Image);
|
||||||
|
|
||||||
|
static std::vector<GuiImageAsync *> imageQueue;
|
||||||
|
static CThread *pThread;
|
||||||
|
static CMutex * pMutex;
|
||||||
|
static u32 threadRefCounter;
|
||||||
|
static GuiImageAsync * pInUse;
|
||||||
|
static bool bExitRequested;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /*_GUIIMAGEASYNC_H_*/
|
207
source/gui/GuiImageData.cpp
Normal file
207
source/gui/GuiImageData.cpp
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "GuiImageData.h"
|
||||||
|
#include <system/memory.h>
|
||||||
|
/**
|
||||||
|
* Constructor for the GuiImageData class.
|
||||||
|
*/
|
||||||
|
GuiImageData::GuiImageData()
|
||||||
|
{
|
||||||
|
texture = NULL;
|
||||||
|
sampler = NULL;
|
||||||
|
memoryType = eMemTypeMEM2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the GuiImageData class.
|
||||||
|
*/
|
||||||
|
GuiImageData::GuiImageData(const u8 * img, s32 imgSize, s32 textureClamp, s32 textureFormat)
|
||||||
|
{
|
||||||
|
texture = NULL;
|
||||||
|
sampler = NULL;
|
||||||
|
loadImage(img, imgSize, textureClamp, textureFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor for the GuiImageData class.
|
||||||
|
*/
|
||||||
|
GuiImageData::~GuiImageData()
|
||||||
|
{
|
||||||
|
releaseData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImageData::releaseData(void)
|
||||||
|
{
|
||||||
|
if(texture) {
|
||||||
|
if(texture->surface.image_data)
|
||||||
|
{
|
||||||
|
switch(memoryType)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case eMemTypeMEM2:
|
||||||
|
free(texture->surface.image_data);
|
||||||
|
break;
|
||||||
|
case eMemTypeMEM1:
|
||||||
|
MEM1_free(texture->surface.image_data);
|
||||||
|
break;
|
||||||
|
case eMemTypeMEMBucket:
|
||||||
|
MEMBucket_free(texture->surface.image_data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete texture;
|
||||||
|
texture = NULL;
|
||||||
|
}
|
||||||
|
if(sampler) {
|
||||||
|
delete sampler;
|
||||||
|
sampler = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImageData::loadImage(const u8 *img, s32 imgSize, s32 textureClamp, s32 textureFormat)
|
||||||
|
{
|
||||||
|
if(!img || (imgSize < 8))
|
||||||
|
return;
|
||||||
|
|
||||||
|
releaseData();
|
||||||
|
gdImagePtr gdImg = 0;
|
||||||
|
|
||||||
|
if (img[0] == 0xFF && img[1] == 0xD8)
|
||||||
|
{
|
||||||
|
//! not needed for now therefore comment out to safe ELF size
|
||||||
|
//! if needed uncomment, adds 200 kb to the ELF size
|
||||||
|
// IMAGE_JPEG
|
||||||
|
gdImg = gdImageCreateFromJpegPtr(imgSize, (u8*) img);
|
||||||
|
}
|
||||||
|
else if (img[0] == 'B' && img[1] == 'M')
|
||||||
|
{
|
||||||
|
// IMAGE_BMP
|
||||||
|
gdImg = gdImageCreateFromBmpPtr(imgSize, (u8*) img);
|
||||||
|
}
|
||||||
|
else if (img[0] == 0x89 && img[1] == 'P' && img[2] == 'N' && img[3] == 'G')
|
||||||
|
{
|
||||||
|
// IMAGE_PNG
|
||||||
|
gdImg = gdImageCreateFromPngPtr(imgSize, (u8*) img);
|
||||||
|
}
|
||||||
|
//!This must be last since it can also intefere with outher formats
|
||||||
|
else if(img[0] == 0x00)
|
||||||
|
{
|
||||||
|
// Try loading TGA image
|
||||||
|
gdImg = gdImageCreateFromTgaPtr(imgSize, (u8*) img);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(gdImg == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u32 width = (gdImageSX(gdImg));
|
||||||
|
u32 height = (gdImageSY(gdImg));
|
||||||
|
|
||||||
|
//! Initialize texture
|
||||||
|
texture = new GX2Texture;
|
||||||
|
GX2InitTexture(texture, width, height, 1, 0, textureFormat, GX2_SURFACE_DIM_2D, GX2_TILE_MODE_LINEAR_ALIGNED);
|
||||||
|
|
||||||
|
//! if this fails something went horribly wrong
|
||||||
|
if(texture->surface.image_size == 0) {
|
||||||
|
delete texture;
|
||||||
|
texture = NULL;
|
||||||
|
gdImageDestroy(gdImg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! allocate memory for the surface
|
||||||
|
memoryType = eMemTypeMEM2;
|
||||||
|
texture->surface.image_data = memalign(texture->surface.align, texture->surface.image_size);
|
||||||
|
//! try MEM1 on failure
|
||||||
|
if(!texture->surface.image_data) {
|
||||||
|
memoryType = eMemTypeMEM1;
|
||||||
|
texture->surface.image_data = MEM1_alloc(texture->surface.image_size, texture->surface.align);
|
||||||
|
}
|
||||||
|
//! try MEM bucket on failure
|
||||||
|
if(!texture->surface.image_data) {
|
||||||
|
memoryType = eMemTypeMEMBucket;
|
||||||
|
texture->surface.image_data = MEMBucket_alloc(texture->surface.image_size, texture->surface.align);
|
||||||
|
}
|
||||||
|
//! check if memory is available for image
|
||||||
|
if(!texture->surface.image_data) {
|
||||||
|
gdImageDestroy(gdImg);
|
||||||
|
delete texture;
|
||||||
|
texture = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//! set mip map data pointer
|
||||||
|
texture->surface.mip_data = NULL;
|
||||||
|
//! convert image to texture
|
||||||
|
switch(textureFormat)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM:
|
||||||
|
gdImageToUnormR8G8B8A8(gdImg, (u32*)texture->surface.image_data, texture->surface.width, texture->surface.height, texture->surface.pitch);
|
||||||
|
break;
|
||||||
|
case GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM:
|
||||||
|
gdImageToUnormR5G6B5(gdImg, (u16*)texture->surface.image_data, texture->surface.width, texture->surface.height, texture->surface.pitch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! free memory of image as its not needed anymore
|
||||||
|
gdImageDestroy(gdImg);
|
||||||
|
|
||||||
|
//! invalidate the memory
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_TEXTURE, texture->surface.image_data, texture->surface.image_size);
|
||||||
|
//! initialize the sampler
|
||||||
|
sampler = new GX2Sampler;
|
||||||
|
GX2InitSampler(sampler, textureClamp, GX2_TEX_XY_FILTER_BILINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImageData::gdImageToUnormR8G8B8A8(gdImagePtr gdImg, u32 *imgBuffer, u32 width, u32 height, u32 pitch)
|
||||||
|
{
|
||||||
|
for(u32 y = 0; y < height; ++y)
|
||||||
|
{
|
||||||
|
for(u32 x = 0; x < width; ++x)
|
||||||
|
{
|
||||||
|
u32 pixel = gdImageGetPixel(gdImg, x, y);
|
||||||
|
|
||||||
|
u8 a = 254 - 2*((u8)gdImageAlpha(gdImg, pixel));
|
||||||
|
if(a == 254) a++;
|
||||||
|
|
||||||
|
u8 r = gdImageRed(gdImg, pixel);
|
||||||
|
u8 g = gdImageGreen(gdImg, pixel);
|
||||||
|
u8 b = gdImageBlue(gdImg, pixel);
|
||||||
|
|
||||||
|
imgBuffer[y * pitch + x] = (r << 24) | (g << 16) | (b << 8) | (a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! TODO: figure out why this seems to not work correct yet
|
||||||
|
void GuiImageData::gdImageToUnormR5G6B5(gdImagePtr gdImg, u16 *imgBuffer, u32 width, u32 height, u32 pitch)
|
||||||
|
{
|
||||||
|
for(u32 y = 0; y < height; ++y)
|
||||||
|
{
|
||||||
|
for(u32 x = 0; x < width; ++x)
|
||||||
|
{
|
||||||
|
u32 pixel = gdImageGetPixel(gdImg, x, y);
|
||||||
|
|
||||||
|
u8 r = gdImageRed(gdImg, pixel);
|
||||||
|
u8 g = gdImageGreen(gdImg, pixel);
|
||||||
|
u8 b = gdImageBlue(gdImg, pixel);
|
||||||
|
|
||||||
|
imgBuffer[y * pitch + x] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
67
source/gui/GuiImageData.h
Normal file
67
source/gui/GuiImageData.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef GUI_IMAGEDATA_H_
|
||||||
|
#define GUI_IMAGEDATA_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <gd.h>
|
||||||
|
#include <dynamic_libs/gx2_functions.h>
|
||||||
|
#include <system/AsyncDeleter.h>
|
||||||
|
|
||||||
|
class GuiImageData : public AsyncDeleter::Element
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//!Constructor
|
||||||
|
GuiImageData();
|
||||||
|
//!\param img Image data
|
||||||
|
//!\param imgSize The image size
|
||||||
|
GuiImageData(const u8 * img, s32 imgSize, s32 textureClamp = GX2_TEX_CLAMP_CLAMP, s32 textureFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM);
|
||||||
|
//!Destructor
|
||||||
|
virtual ~GuiImageData();
|
||||||
|
//!Load image from buffer
|
||||||
|
//!\param img Image data
|
||||||
|
//!\param imgSize The image size
|
||||||
|
void loadImage(const u8 * img, s32 imgSize, s32 textureClamp = GX2_TEX_CLAMP_CLAMP, s32 textureFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM);
|
||||||
|
//! getter functions
|
||||||
|
const GX2Texture * getTexture() const { return texture; };
|
||||||
|
const GX2Sampler * getSampler() const { return sampler; };
|
||||||
|
//!Gets the image width
|
||||||
|
//!\return image width
|
||||||
|
s32 getWidth() const { if(texture) return texture->surface.width; else return 0; };
|
||||||
|
//!Gets the image height
|
||||||
|
//!\return image height
|
||||||
|
s32 getHeight() const { if(texture) return texture->surface.height; else return 0; };
|
||||||
|
//! release memory of the image data
|
||||||
|
void releaseData(void);
|
||||||
|
private:
|
||||||
|
void gdImageToUnormR8G8B8A8(gdImagePtr gdImg, u32 *imgBuffer, u32 width, u32 height, u32 pitch);
|
||||||
|
void gdImageToUnormR5G6B5(gdImagePtr gdImg, u16 *imgBuffer, u32 width, u32 height, u32 pitch);
|
||||||
|
|
||||||
|
GX2Texture *texture;
|
||||||
|
GX2Sampler *sampler;
|
||||||
|
|
||||||
|
enum eMemoryTypes
|
||||||
|
{
|
||||||
|
eMemTypeMEM2,
|
||||||
|
eMemTypeMEM1,
|
||||||
|
eMemTypeMEMBucket
|
||||||
|
};
|
||||||
|
|
||||||
|
u8 memoryType;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
128
source/gui/GuiParticleImage.cpp
Normal file
128
source/gui/GuiParticleImage.cpp
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include "GuiParticleImage.h"
|
||||||
|
#include "video/CVideo.h"
|
||||||
|
#include "video/shaders/ColorShader.h"
|
||||||
|
|
||||||
|
#define CIRCLE_VERTEX_COUNT 36
|
||||||
|
|
||||||
|
static inline f32 getRandZeroToOneF32()
|
||||||
|
{
|
||||||
|
return (rand() % 10000) * 0.0001f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline f32 getRandMinusOneToOneF32()
|
||||||
|
{
|
||||||
|
return getRandZeroToOneF32() * 2.0f - 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiParticleImage::GuiParticleImage(s32 w, s32 h, u32 particleCount)
|
||||||
|
: GuiImage(NULL)
|
||||||
|
{
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
|
imgType = IMAGE_COLOR;
|
||||||
|
|
||||||
|
posVertexs = (f32 *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ColorShader::cuVertexAttrSize * CIRCLE_VERTEX_COUNT);
|
||||||
|
colorVertexs = (u8 *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ColorShader::cuColorAttrSize * CIRCLE_VERTEX_COUNT);
|
||||||
|
|
||||||
|
for(u32 i = 0; i < CIRCLE_VERTEX_COUNT; i++)
|
||||||
|
{
|
||||||
|
posVertexs[i * 3 + 0] = cosf(DegToRad(i * 360.0f / CIRCLE_VERTEX_COUNT));
|
||||||
|
posVertexs[i * 3 + 1] = sinf(DegToRad(i * 360.0f / CIRCLE_VERTEX_COUNT));
|
||||||
|
posVertexs[i * 3 + 2] = 0.0f;
|
||||||
|
|
||||||
|
colorVertexs[i * 4 + 0] = 0xff;
|
||||||
|
colorVertexs[i * 4 + 1] = 0xff;
|
||||||
|
colorVertexs[i * 4 + 2] = 0xff;
|
||||||
|
colorVertexs[i * 4 + 3] = 0xff;
|
||||||
|
}
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, posVertexs, ColorShader::cuVertexAttrSize * CIRCLE_VERTEX_COUNT);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, colorVertexs, ColorShader::cuColorAttrSize * CIRCLE_VERTEX_COUNT);
|
||||||
|
|
||||||
|
particles.resize(particleCount);
|
||||||
|
|
||||||
|
for(u32 i = 0; i < particleCount; i++)
|
||||||
|
{
|
||||||
|
particles[i].position.x = getRandMinusOneToOneF32() * getWidth() * 0.5f;
|
||||||
|
particles[i].position.y = getRandMinusOneToOneF32() * getHeight() * 0.5f;
|
||||||
|
particles[i].position.z = 0.0f;
|
||||||
|
particles[i].colors = glm::vec4(1.0f, 1.0f, 1.0f, (getRandZeroToOneF32() * 0.6f) + 0.05f);
|
||||||
|
particles[i].radius = getRandZeroToOneF32() * 30.0f + 60.0f;
|
||||||
|
particles[i].speed = (getRandZeroToOneF32() * 0.4f) + 0.6f;
|
||||||
|
particles[i].direction = getRandMinusOneToOneF32();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiParticleImage::~GuiParticleImage()
|
||||||
|
{
|
||||||
|
free(posVertexs);
|
||||||
|
free(colorVertexs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiParticleImage::draw(CVideo *pVideo)
|
||||||
|
{
|
||||||
|
if(!this->isVisible())
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
f32 currScaleX = getScaleX();
|
||||||
|
f32 currScaleY = getScaleY();
|
||||||
|
|
||||||
|
positionOffsets[2] = getDepth() * pVideo->getDepthScaleFactor() * 2.0f;
|
||||||
|
|
||||||
|
scaleFactor[2] = getScaleZ();
|
||||||
|
|
||||||
|
//! add other colors intensities parameters
|
||||||
|
colorIntensity[3] = getAlpha();
|
||||||
|
|
||||||
|
for(u32 i = 0; i < particles.size(); ++i)
|
||||||
|
{
|
||||||
|
if(particles[i].position.y > (getHeight() * 0.5f + 30.0f))
|
||||||
|
{
|
||||||
|
particles[i].position.x = getRandMinusOneToOneF32() * getWidth() * 0.5f;
|
||||||
|
particles[i].position.y = -getHeight() * 0.5f - 30.0f;
|
||||||
|
particles[i].colors = glm::vec4(1.0f, 1.0f, 1.0f, (getRandZeroToOneF32() * 0.6f) + 0.05f);
|
||||||
|
particles[i].radius = getRandZeroToOneF32() * 30.0f + 60.0f;
|
||||||
|
particles[i].speed = (getRandZeroToOneF32() * 0.4f) + 0.6f;
|
||||||
|
particles[i].direction = getRandMinusOneToOneF32();
|
||||||
|
}
|
||||||
|
if(particles[i].position.x < (-getWidth() * 0.5f - 50.0f))
|
||||||
|
{
|
||||||
|
particles[i].position.x = -particles[i].position.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
particles[i].direction += getRandMinusOneToOneF32() * 0.03f;
|
||||||
|
particles[i].position.x += particles[i].speed * particles[i].direction;
|
||||||
|
particles[i].position.y += particles[i].speed;
|
||||||
|
|
||||||
|
positionOffsets[0] = (getCenterX() + particles[i].position.x) * pVideo->getWidthScaleFactor() * 2.0f;
|
||||||
|
positionOffsets[1] = (getCenterY() + particles[i].position.y) * pVideo->getHeightScaleFactor() * 2.0f;
|
||||||
|
|
||||||
|
scaleFactor[0] = currScaleX * particles[i].radius * pVideo->getWidthScaleFactor();
|
||||||
|
scaleFactor[1] = currScaleY * particles[i].radius * pVideo->getHeightScaleFactor();
|
||||||
|
|
||||||
|
ColorShader::instance()->setShaders();
|
||||||
|
ColorShader::instance()->setAttributeBuffer(colorVertexs, posVertexs, CIRCLE_VERTEX_COUNT);
|
||||||
|
ColorShader::instance()->setAngle(0.0f);
|
||||||
|
ColorShader::instance()->setOffset(positionOffsets);
|
||||||
|
ColorShader::instance()->setScale(scaleFactor);
|
||||||
|
ColorShader::instance()->setColorIntensity(colorIntensity * particles[i].colors);
|
||||||
|
ColorShader::instance()->draw(GX2_PRIMITIVE_TRIANGLE_FAN, CIRCLE_VERTEX_COUNT);
|
||||||
|
}
|
||||||
|
}
|
45
source/gui/GuiParticleImage.h
Normal file
45
source/gui/GuiParticleImage.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef _GUI_PARTICLE_IMAGE_H_
|
||||||
|
#define _GUI_PARTICLE_IMAGE_H_
|
||||||
|
|
||||||
|
#include "GuiImage.h"
|
||||||
|
|
||||||
|
class GuiParticleImage : public GuiImage, public sigslot::has_slots<>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GuiParticleImage(s32 w, s32 h, u32 particleCount);
|
||||||
|
virtual ~GuiParticleImage();
|
||||||
|
|
||||||
|
void draw(CVideo *pVideo);
|
||||||
|
private:
|
||||||
|
f32 *posVertexs;
|
||||||
|
u8 *colorVertexs;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
glm::vec3 position;
|
||||||
|
glm::vec4 colors;
|
||||||
|
f32 radius;
|
||||||
|
f32 speed;
|
||||||
|
f32 direction;
|
||||||
|
} Particle;
|
||||||
|
|
||||||
|
std::vector<Particle> particles;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _GUI_ICON_GRID_H_
|
279
source/gui/GuiScrollbar.cpp
Normal file
279
source/gui/GuiScrollbar.cpp
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2011
|
||||||
|
* by Dimok
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
***************************************************************************/
|
||||||
|
#include "GuiScrollbar.h"
|
||||||
|
#include "resources/Resources.h"
|
||||||
|
|
||||||
|
Scrollbar::Scrollbar(s32 h)
|
||||||
|
: touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH)
|
||||||
|
, wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A)
|
||||||
|
{
|
||||||
|
SelItem = 0;
|
||||||
|
SelInd = 0;
|
||||||
|
PageSize = 0;
|
||||||
|
EntrieCount = 0;
|
||||||
|
ScrollSpeed = 15;
|
||||||
|
ScrollState = 0;
|
||||||
|
|
||||||
|
listChanged.connect(this, &Scrollbar::setScrollboxPosition);
|
||||||
|
|
||||||
|
btnSoundClick = Resources::GetSound("button_click.mp3");
|
||||||
|
scrollbarLine = Resources::GetImageData("scrollbarLine.png");
|
||||||
|
arrowDown = Resources::GetImageData("scrollbarArrowDown.png");
|
||||||
|
arrowUp = Resources::GetImageData("scrollbarArrowUp.png");
|
||||||
|
scrollbarBox = Resources::GetImageData("scrollbarButton.png");
|
||||||
|
|
||||||
|
height = h;
|
||||||
|
width = scrollbarBox->getWidth();
|
||||||
|
|
||||||
|
MaxHeight = height * 0.5f - (scrollbarBox ? (scrollbarBox->getHeight() * 0.5f) : 0) - (arrowUp ? arrowUp->getHeight() : 0);
|
||||||
|
MinHeight = -height * 0.5f + (scrollbarBox ? (scrollbarBox->getHeight() * 0.5f) : 0) + (arrowDown ? arrowDown->getHeight() : 0);
|
||||||
|
|
||||||
|
scrollbarLineImg = new GuiImage(scrollbarLine);
|
||||||
|
scrollbarLineImg->setParent(this);
|
||||||
|
scrollbarLineImg->setAlignment(ALIGN_CENTER | ALIGN_MIDDLE);
|
||||||
|
scrollbarLineImg->setPosition(0, 0);
|
||||||
|
|
||||||
|
arrowDownImg = new GuiImage(arrowDown);
|
||||||
|
arrowUpImg = new GuiImage(arrowUp);
|
||||||
|
scrollbarBoxImg = new GuiImage(scrollbarBox);
|
||||||
|
|
||||||
|
arrowUpBtn = new GuiButton(arrowUpImg->getWidth(), arrowUpImg->getHeight());
|
||||||
|
arrowUpBtn->setParent(this);
|
||||||
|
arrowUpBtn->setImage(arrowUpImg);
|
||||||
|
arrowUpBtn->setAlignment(ALIGN_CENTER | ALIGN_TOP);
|
||||||
|
arrowUpBtn->setPosition(0, 0);
|
||||||
|
arrowUpBtn->setTrigger(&touchTrigger, 0);
|
||||||
|
arrowUpBtn->setTrigger(&wpadTouchTrigger, 1);
|
||||||
|
arrowUpBtn->setSoundClick(btnSoundClick);
|
||||||
|
arrowUpBtn->setEffectGrow();
|
||||||
|
arrowUpBtn->clicked.connect(this, &Scrollbar::OnUpButtonClick);
|
||||||
|
|
||||||
|
arrowDownBtn = new GuiButton(arrowDownImg->getWidth(), arrowDownImg->getHeight());
|
||||||
|
arrowDownBtn->setParent(this);
|
||||||
|
arrowDownBtn->setImage(arrowDownImg);
|
||||||
|
arrowDownBtn->setAlignment(ALIGN_CENTER | ALIGN_BOTTOM);
|
||||||
|
arrowDownBtn->setPosition(0, 0);
|
||||||
|
arrowDownBtn->setTrigger(&touchTrigger, 0);
|
||||||
|
arrowDownBtn->setTrigger(&wpadTouchTrigger, 1);
|
||||||
|
arrowDownBtn->setSoundClick(btnSoundClick);
|
||||||
|
arrowDownBtn->setEffectGrow();
|
||||||
|
arrowDownBtn->clicked.connect(this, &Scrollbar::OnDownButtonClick);
|
||||||
|
|
||||||
|
scrollbarBoxBtn = new GuiButton(scrollbarBoxImg->getWidth(), height);
|
||||||
|
scrollbarBoxBtn->setParent(this);
|
||||||
|
scrollbarBoxBtn->setImage(scrollbarBoxImg);
|
||||||
|
scrollbarBoxBtn->setAlignment(ALIGN_CENTER | ALIGN_TOP);
|
||||||
|
scrollbarBoxBtn->setPosition(0, MaxHeight);
|
||||||
|
scrollbarBoxBtn->setHoldable(true);
|
||||||
|
scrollbarBoxBtn->setTrigger(&touchTrigger, 0);
|
||||||
|
scrollbarBoxBtn->setTrigger(&wpadTouchTrigger, 1);
|
||||||
|
scrollbarBoxBtn->setEffectGrow();
|
||||||
|
scrollbarBoxBtn->held.connect(this, &Scrollbar::OnBoxButtonHold);
|
||||||
|
}
|
||||||
|
|
||||||
|
Scrollbar::~Scrollbar()
|
||||||
|
{
|
||||||
|
Resources::RemoveSound(btnSoundClick);
|
||||||
|
Resources::RemoveImageData(scrollbarLine);
|
||||||
|
Resources::RemoveImageData(arrowDown);
|
||||||
|
Resources::RemoveImageData(arrowUp);
|
||||||
|
Resources::RemoveImageData(scrollbarBox);
|
||||||
|
|
||||||
|
delete arrowUpBtn;
|
||||||
|
delete arrowDownBtn;
|
||||||
|
delete scrollbarBoxBtn;
|
||||||
|
|
||||||
|
delete scrollbarLineImg;
|
||||||
|
|
||||||
|
delete arrowDownImg;
|
||||||
|
delete arrowUpImg;
|
||||||
|
delete scrollbarBoxImg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scrollbar::ScrollOneUp()
|
||||||
|
{
|
||||||
|
if(SelItem == 0 && SelInd > 0)
|
||||||
|
{
|
||||||
|
// move list up by 1
|
||||||
|
--SelInd;
|
||||||
|
}
|
||||||
|
else if(SelInd+SelItem > 0)
|
||||||
|
{
|
||||||
|
--SelItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scrollbar::ScrollOneDown()
|
||||||
|
{
|
||||||
|
if(SelInd+SelItem + 1 < EntrieCount)
|
||||||
|
{
|
||||||
|
if(SelItem == PageSize-1)
|
||||||
|
{
|
||||||
|
// move list down by 1
|
||||||
|
SelInd++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SelItem++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scrollbar::OnUpButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)
|
||||||
|
{
|
||||||
|
if(ScrollState < ScrollSpeed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ScrollOneUp();
|
||||||
|
|
||||||
|
ScrollState = 0;
|
||||||
|
listChanged(SelItem, SelInd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scrollbar::OnDownButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)
|
||||||
|
{
|
||||||
|
if(ScrollState < ScrollSpeed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ScrollOneDown();
|
||||||
|
|
||||||
|
ScrollState = 0;
|
||||||
|
listChanged(SelItem, SelInd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scrollbar::OnBoxButtonHold(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)
|
||||||
|
{
|
||||||
|
if(EntrieCount == 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!controller->data.validPointer){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 y = controller->data.y - this->getCenterY();
|
||||||
|
|
||||||
|
s32 positionWiimote = LIMIT(y - MinHeight, 0, MaxHeight - MinHeight);
|
||||||
|
|
||||||
|
s32 newSelected = (EntrieCount - 1) - (s32) ((float) positionWiimote / (float) (MaxHeight-MinHeight) * (float) (EntrieCount-1));
|
||||||
|
|
||||||
|
s32 diff = newSelected-SelInd-SelItem;
|
||||||
|
|
||||||
|
if(newSelected <= 0)
|
||||||
|
{
|
||||||
|
SelItem = 0;
|
||||||
|
SelInd = 0;
|
||||||
|
}
|
||||||
|
else if(newSelected >= EntrieCount-1)
|
||||||
|
{
|
||||||
|
SelItem = (PageSize-1 < EntrieCount-1) ? PageSize-1 : EntrieCount-1;
|
||||||
|
SelInd = EntrieCount-PageSize;
|
||||||
|
}
|
||||||
|
else if(newSelected < PageSize && SelInd == 0 && diff < 0)
|
||||||
|
{
|
||||||
|
SelItem = std::max(SelItem+diff, (s32)0);
|
||||||
|
}
|
||||||
|
else if(EntrieCount-newSelected < PageSize && SelInd == EntrieCount-PageSize && diff > 0)
|
||||||
|
{
|
||||||
|
SelItem = std::min(SelItem+diff, PageSize-1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SelInd = LIMIT(SelInd+diff, 0, ((EntrieCount-PageSize < 0) ? 0 : EntrieCount-PageSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollState = 0;
|
||||||
|
listChanged(SelItem, SelInd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scrollbar::SetPageSize(s32 size)
|
||||||
|
{
|
||||||
|
if(PageSize == size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PageSize = size;
|
||||||
|
listChanged(SelItem, SelInd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scrollbar::SetSelectedItem(s32 pos)
|
||||||
|
{
|
||||||
|
if(SelItem == pos)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SelItem = LIMIT(pos, 0, EntrieCount-1);
|
||||||
|
listChanged(SelItem, SelInd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scrollbar::SetSelectedIndex(s32 pos)
|
||||||
|
{
|
||||||
|
if(SelInd == pos)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SelInd = pos;
|
||||||
|
listChanged(SelItem, SelInd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scrollbar::SetEntrieCount(s32 cnt)
|
||||||
|
{
|
||||||
|
if(EntrieCount == cnt)
|
||||||
|
return;
|
||||||
|
|
||||||
|
EntrieCount = cnt;
|
||||||
|
listChanged(SelItem, SelInd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scrollbar::setScrollboxPosition(s32 SelItem, s32 SelInd)
|
||||||
|
{
|
||||||
|
s32 position = MaxHeight-(MaxHeight-MinHeight)*(SelInd+SelItem)/(EntrieCount-1);
|
||||||
|
|
||||||
|
if(position < MinHeight || (SelInd+SelItem >= EntrieCount-1))
|
||||||
|
position = MinHeight;
|
||||||
|
else if(position > MaxHeight || (SelInd+SelItem) == 0)
|
||||||
|
position = MaxHeight;
|
||||||
|
|
||||||
|
scrollbarBoxBtn->setPosition(0, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scrollbar::draw(CVideo * video)
|
||||||
|
{
|
||||||
|
scrollbarLineImg->draw(video);
|
||||||
|
arrowUpBtn->draw(video);
|
||||||
|
arrowDownBtn->draw(video);
|
||||||
|
scrollbarBoxBtn->draw(video);
|
||||||
|
|
||||||
|
updateEffects();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scrollbar::update(GuiController * t)
|
||||||
|
{
|
||||||
|
if(this->isStateSet(STATE_DISABLED))
|
||||||
|
return;
|
||||||
|
|
||||||
|
arrowUpBtn->update(t);
|
||||||
|
arrowDownBtn->update(t);
|
||||||
|
scrollbarBoxBtn->update(t);
|
||||||
|
|
||||||
|
++ScrollState;
|
||||||
|
}
|
||||||
|
|
84
source/gui/GuiScrollbar.h
Normal file
84
source/gui/GuiScrollbar.h
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2011
|
||||||
|
* by Dimok
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef SCROLLBAR_HPP_
|
||||||
|
#define SCROLLBAR_HPP_
|
||||||
|
|
||||||
|
#include "gui/GuiElement.h"
|
||||||
|
#include "gui/GuiButton.h"
|
||||||
|
|
||||||
|
class Scrollbar : public GuiElement, public sigslot::has_slots<>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Scrollbar(s32 height);
|
||||||
|
virtual ~Scrollbar();
|
||||||
|
void ScrollOneUp();
|
||||||
|
void ScrollOneDown();
|
||||||
|
s32 GetSelectedItem() { return SelItem; }
|
||||||
|
s32 GetSelectedIndex() { return SelInd; }
|
||||||
|
void draw(CVideo * video);
|
||||||
|
void update(GuiController * t);
|
||||||
|
|
||||||
|
//! Signals
|
||||||
|
sigslot::signal2<s32, s32> listChanged;
|
||||||
|
//! Slots
|
||||||
|
void SetPageSize(s32 size);
|
||||||
|
void SetRowSize(s32 size);
|
||||||
|
void SetSelectedItem(s32 pos);
|
||||||
|
void SetSelectedIndex(s32 pos);
|
||||||
|
void SetEntrieCount(s32 cnt);
|
||||||
|
protected:
|
||||||
|
void setScrollboxPosition(s32 SelItem, s32 SelInd);
|
||||||
|
void OnUpButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);
|
||||||
|
void OnDownButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);
|
||||||
|
void OnBoxButtonHold(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);
|
||||||
|
|
||||||
|
u32 ScrollState;
|
||||||
|
u16 ScrollSpeed;
|
||||||
|
|
||||||
|
s32 MinHeight;
|
||||||
|
s32 MaxHeight;
|
||||||
|
s32 SelItem;
|
||||||
|
s32 SelInd;
|
||||||
|
s32 PageSize;
|
||||||
|
s32 EntrieCount;
|
||||||
|
s32 pressedChan;
|
||||||
|
|
||||||
|
GuiButton * arrowUpBtn;
|
||||||
|
GuiButton * arrowDownBtn;
|
||||||
|
GuiButton * scrollbarBoxBtn;
|
||||||
|
GuiImage * scrollbarLineImg;
|
||||||
|
GuiImage * arrowDownImg;
|
||||||
|
GuiImage * arrowUpImg;
|
||||||
|
GuiImage * scrollbarBoxImg;
|
||||||
|
GuiImageData * scrollbarLine;
|
||||||
|
GuiImageData * arrowDown;
|
||||||
|
GuiImageData * arrowUp;
|
||||||
|
GuiImageData * scrollbarBox;
|
||||||
|
GuiSound * btnSoundClick;
|
||||||
|
|
||||||
|
GuiTrigger touchTrigger;
|
||||||
|
GuiTrigger wpadTouchTrigger;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
307
source/gui/GuiSelectBox.cpp
Normal file
307
source/gui/GuiSelectBox.cpp
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2016 Maschell
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include "GuiSelectBox.h"
|
||||||
|
#include "GuiImage.h"
|
||||||
|
#include "GuiTrigger.h"
|
||||||
|
#include "GuiImageData.h"
|
||||||
|
#include "utils/StringTools.h"
|
||||||
|
/**
|
||||||
|
* Constructor for the GuiCheckBox class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GuiSelectBox::GuiSelectBox(std::string caption,GuiFrame *parent)
|
||||||
|
: GuiFrame(300,300,parent)
|
||||||
|
,selected(0)
|
||||||
|
,captionText(caption)
|
||||||
|
,topValueImageData(Resources::GetImageData("gameSettingsButton.png"))
|
||||||
|
,topValueImage(topValueImageData)
|
||||||
|
,topValueImageSelectedData(Resources::GetImageData("gameSettingsButtonSelected.png"))
|
||||||
|
,topValueImageSelected(topValueImageSelectedData)
|
||||||
|
,topValueButton(topValueImage.getWidth(),topValueImage.getHeight())
|
||||||
|
,valueImageData(Resources::GetImageData("gameSettingsButtonEx.png"))
|
||||||
|
,valueSelectedImageData(Resources::GetImageData("gameSettingsButtonExSelected.png"))
|
||||||
|
,valueHighlightedImageData(Resources::GetImageData("gameSettingsButtonExHighlighted.png"))
|
||||||
|
,touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH)
|
||||||
|
,wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A)
|
||||||
|
,buttonATrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_A, true)
|
||||||
|
,buttonBTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_B, true)
|
||||||
|
,buttonUpTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_UP | GuiTrigger::STICK_L_UP, true)
|
||||||
|
,buttonDownTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_DOWN | GuiTrigger::STICK_L_DOWN, true)
|
||||||
|
,DPADButtons(5,5)
|
||||||
|
,buttonClickSound(Resources::GetSound("settings_click_2.mp3"))
|
||||||
|
{
|
||||||
|
showValues = false;
|
||||||
|
bChanged = false;
|
||||||
|
bSelectedChanged = false;
|
||||||
|
opened = false;
|
||||||
|
topValueText.setFontSize(32);
|
||||||
|
topValueText.setAlignment(ALIGN_LEFT);
|
||||||
|
topValueText.setPosition(10,-7);
|
||||||
|
topValueButton.setLabel(&topValueText);
|
||||||
|
topValueButton.setImage(&topValueImage);
|
||||||
|
topValueButton.setIconOver(&topValueImageSelected);
|
||||||
|
topValueButton.setTrigger(&touchTrigger);
|
||||||
|
topValueButton.setTrigger(&wpadTouchTrigger);
|
||||||
|
topValueButton.setSoundClick(buttonClickSound);
|
||||||
|
topValueButton.clicked.connect(this, &GuiSelectBox::OnTopValueClicked);
|
||||||
|
|
||||||
|
valuesFrame.setState(STATE_HIDDEN);
|
||||||
|
|
||||||
|
DPADButtons.setTrigger(&buttonBTrigger);
|
||||||
|
DPADButtons.setTrigger(&buttonATrigger);
|
||||||
|
DPADButtons.setTrigger(&buttonDownTrigger);
|
||||||
|
DPADButtons.setTrigger(&buttonUpTrigger);
|
||||||
|
DPADButtons.clicked.connect(this, &GuiSelectBox::OnDPADClick);
|
||||||
|
DPADButtons.setState(STATE_DISABLE_INPUT);
|
||||||
|
|
||||||
|
append(&DPADButtons);
|
||||||
|
append(&valuesFrame);
|
||||||
|
append(&topValueButton);
|
||||||
|
|
||||||
|
showValues = false;
|
||||||
|
bChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSelectBox::OnValueClicked(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)
|
||||||
|
{
|
||||||
|
for(u32 i = 0; i < valueButtons.size(); ++i){
|
||||||
|
if(valueButtons[i].valueButton == button){
|
||||||
|
selected = i;
|
||||||
|
SelectValue(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSelectBox::SelectValue(u32 value){
|
||||||
|
if(value < valueButtons.size()){
|
||||||
|
const wchar_t* w_text = valueButtons[value].valueButtonText->getText();
|
||||||
|
std::wstring ws(w_text);
|
||||||
|
std::string text(ws.begin(), ws.end());
|
||||||
|
topValueText.setText(text.c_str());
|
||||||
|
|
||||||
|
std::string real_value = buttonToValue[valueButtons[value].valueButton];
|
||||||
|
if(real_value.compare(std::string()) == 0) real_value = "<error>";
|
||||||
|
|
||||||
|
valueChanged(this,real_value);
|
||||||
|
ShowHideValues(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSelectBox::OnTopValueClicked(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)
|
||||||
|
{
|
||||||
|
ShowHideValues(!showValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSelectBox::ShowHideValues(bool showhide)
|
||||||
|
{
|
||||||
|
showValues = showhide;
|
||||||
|
bChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSelectBox::OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)
|
||||||
|
{
|
||||||
|
if(opened == true){
|
||||||
|
if(trigger == &buttonATrigger)
|
||||||
|
{
|
||||||
|
//! do not auto launch when wiimote is pointing to screen and presses A
|
||||||
|
if((controller->chan & (GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5)) && controller->data.validPointer)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SelectValue(selected);
|
||||||
|
}
|
||||||
|
else if(trigger == &buttonBTrigger)
|
||||||
|
{
|
||||||
|
if(button == &DPADButtons){
|
||||||
|
ShowHideValues(false);
|
||||||
|
}else{
|
||||||
|
}
|
||||||
|
}else if(trigger == &buttonUpTrigger){
|
||||||
|
if(selected > 0 ) selected--;
|
||||||
|
bSelectedChanged = true;
|
||||||
|
}
|
||||||
|
else if(trigger == &buttonDownTrigger){
|
||||||
|
selected++;
|
||||||
|
if(selected >= valueButtons.size()) selected = valueButtons.size() - 1;
|
||||||
|
bSelectedChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSelectBox::Init(std::map<std::string,std::string> values, s32 valueID)
|
||||||
|
{
|
||||||
|
if((u32)valueID >= values.size()){
|
||||||
|
valueID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
selected = valueID;
|
||||||
|
bSelectedChanged = true;
|
||||||
|
|
||||||
|
DeleteValueData();
|
||||||
|
|
||||||
|
valueButtons.resize(values.size());
|
||||||
|
|
||||||
|
s32 i = 0;
|
||||||
|
f32 imgScale = 1.0f;
|
||||||
|
std::map<std::string, std::string>::iterator itr;
|
||||||
|
for(itr = values.begin(); itr != values.end(); itr++) {
|
||||||
|
if(i == valueID){
|
||||||
|
topValueText.setText(itr->first.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
valueButtons[i].valueButtonImg = new GuiImage(valueImageData);
|
||||||
|
|
||||||
|
valueButtons[i].valueButtonCheckedImg = new GuiImage(valueSelectedImageData);
|
||||||
|
valueButtons[i].valueButtonHighlightedImg = new GuiImage(valueHighlightedImageData);
|
||||||
|
valueButtons[i].valueButton = new GuiButton(valueButtons[i].valueButtonImg->getWidth() * imgScale, valueButtons[i].valueButtonImg->getHeight() * imgScale);
|
||||||
|
valueButtons[i].valueButtonText = new GuiText(itr->first.c_str(),32,glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
|
|
||||||
|
valueButtons[i].valueButtonText->setMaxWidth(valueButtons[i].valueButtonImg->getWidth() * imgScale - 20.0f, GuiText::WRAP);
|
||||||
|
valueButtons[i].valueButtonText->setPosition(0, 0);
|
||||||
|
|
||||||
|
valueButtons[i].valueButtonImg->setScale(imgScale);
|
||||||
|
valueButtons[i].valueButtonCheckedImg->setScale(imgScale);
|
||||||
|
|
||||||
|
valueButtons[i].valueButton->setImage(valueButtons[i].valueButtonImg);
|
||||||
|
valueButtons[i].valueButton->setIconOver(valueButtons[i].valueButtonHighlightedImg);
|
||||||
|
valueButtons[i].valueButton->setTrigger(&touchTrigger);
|
||||||
|
valueButtons[i].valueButton->setTrigger(&wpadTouchTrigger);
|
||||||
|
valueButtons[i].valueButton->clicked.connect(this,&GuiSelectBox::OnValueClicked);
|
||||||
|
valueButtons[i].valueButton->setSoundClick(buttonClickSound);
|
||||||
|
valueButtons[i].valueButton->setLabel(valueButtons[i].valueButtonText);
|
||||||
|
|
||||||
|
//valueButtons[i].valueButton->setState(STATE_HIDDEN); //Wont get disabled soon enough
|
||||||
|
|
||||||
|
buttonToValue[valueButtons[i].valueButton] = itr->second;
|
||||||
|
s32 ypos = (((valueButtons[i].valueButtonImg->getHeight()*getScale()) * (i))+ (topValueImage.getHeight()-5)*getScale())*-1.0f;
|
||||||
|
valueButtons[i].valueButton->setPosition(0, ypos);
|
||||||
|
valuesFrame.append(valueButtons[i].valueButton);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Collapse the thing!
|
||||||
|
showValues = false;
|
||||||
|
bChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSelectBox::DeleteValueData()
|
||||||
|
{
|
||||||
|
for(u32 i = 0; i < valueButtons.size(); ++i)
|
||||||
|
{
|
||||||
|
valuesFrame.remove(valueButtons[i].valueButton);
|
||||||
|
delete valueButtons[i].valueButtonImg;
|
||||||
|
delete valueButtons[i].valueButtonCheckedImg;
|
||||||
|
delete valueButtons[i].valueButtonHighlightedImg;
|
||||||
|
delete valueButtons[i].valueButton;
|
||||||
|
delete valueButtons[i].valueButtonText;
|
||||||
|
}
|
||||||
|
buttonToValue.clear();
|
||||||
|
valueButtons.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor for the GuiButton class.
|
||||||
|
*/
|
||||||
|
GuiSelectBox::~GuiSelectBox()
|
||||||
|
{
|
||||||
|
DeleteValueData();
|
||||||
|
bChanged = false;
|
||||||
|
selected = 0;
|
||||||
|
showValues = false;
|
||||||
|
Resources::RemoveSound(buttonClickSound);
|
||||||
|
Resources::RemoveImageData(topValueImageData);
|
||||||
|
Resources::RemoveImageData(topValueImageSelectedData);
|
||||||
|
Resources::RemoveImageData(valueImageData);
|
||||||
|
Resources::RemoveImageData(valueHighlightedImageData);
|
||||||
|
Resources::RemoveImageData(valueSelectedImageData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GuiSelectBox::setState(s32 s, s32 c)
|
||||||
|
{
|
||||||
|
GuiElement::setState(s, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSelectBox::OnValueCloseEffectFinish(GuiElement *element)
|
||||||
|
{
|
||||||
|
valuesFrame.effectFinished.disconnect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 GuiSelectBox::getTopValueHeight() {
|
||||||
|
return topValueImage.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 GuiSelectBox::getTopValueWidth() {
|
||||||
|
return topValueImage.getWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 GuiSelectBox::getHeight(){
|
||||||
|
return getTopValueHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 GuiSelectBox::getWidth(){
|
||||||
|
return getTopValueWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GuiSelectBox::OnValueOpenEffectFinish(GuiElement *element)
|
||||||
|
{
|
||||||
|
valuesFrame.effectFinished.disconnect(this);
|
||||||
|
opened = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSelectBox::update(GuiController * c){
|
||||||
|
if(bChanged){
|
||||||
|
showhide(this,showValues);
|
||||||
|
if(showValues){
|
||||||
|
for(u32 i = 0; i < valueButtons.size(); ++i){ //TODO: only set when it really changed
|
||||||
|
if(i == selected){
|
||||||
|
valueButtons[i].valueButton->setImage(valueButtons[i].valueButtonCheckedImg);
|
||||||
|
}else{
|
||||||
|
valueButtons[i].valueButton->setImage(valueButtons[i].valueButtonImg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
valuesFrame.clearState(STATE_HIDDEN);
|
||||||
|
DPADButtons.clearState(STATE_DISABLE_INPUT);
|
||||||
|
valuesFrame.setEffect(EFFECT_FADE, 10, 255);
|
||||||
|
valuesFrame.effectFinished.connect(this, &GuiSelectBox::OnValueCloseEffectFinish);
|
||||||
|
}else{
|
||||||
|
opened = false;
|
||||||
|
valuesFrame.setState(STATE_HIDDEN);
|
||||||
|
DPADButtons.setState(STATE_DISABLE_INPUT);
|
||||||
|
valuesFrame.setEffect(EFFECT_FADE, -10, 0);
|
||||||
|
valuesFrame.effectFinished.connect(this, &GuiSelectBox::OnValueOpenEffectFinish);
|
||||||
|
}
|
||||||
|
|
||||||
|
bChanged = false;
|
||||||
|
}
|
||||||
|
if(bSelectedChanged){
|
||||||
|
for(u32 i = 0; i < valueButtons.size(); ++i){
|
||||||
|
if(i == selected){
|
||||||
|
valueButtons[i].valueButton->setState(STATE_SELECTED);
|
||||||
|
}else{
|
||||||
|
valueButtons[i].valueButton->clearState(STATE_SELECTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
topValueButton.setState(getState());
|
||||||
|
GuiFrame::update(c);
|
||||||
|
}
|
104
source/gui/GuiSelectBox.h
Normal file
104
source/gui/GuiSelectBox.h
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2016 Maschell
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef GUI_SELECTBOX_H_
|
||||||
|
#define GUI_SELECTBOX_H_
|
||||||
|
|
||||||
|
#include "Gui.h"
|
||||||
|
#include "GuiImage.h"
|
||||||
|
#include "GuiImageData.h"
|
||||||
|
|
||||||
|
//!A simple CheckBox
|
||||||
|
class GuiSelectBox : public GuiFrame, public sigslot::has_slots<>{
|
||||||
|
public:
|
||||||
|
//!Constructor
|
||||||
|
//!\param checked Checked
|
||||||
|
GuiSelectBox(std::string caption,GuiFrame *parent = 0);
|
||||||
|
//!Destructor
|
||||||
|
virtual ~GuiSelectBox();
|
||||||
|
|
||||||
|
sigslot::signal2<GuiSelectBox *, std::string> valueChanged;
|
||||||
|
sigslot::signal2<GuiSelectBox *, bool> showhide;
|
||||||
|
void OnTopValueClicked(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);
|
||||||
|
void Init(std::map<std::string,std::string> values, s32 valueID);
|
||||||
|
|
||||||
|
void setState(s32 s, s32 c = -1);
|
||||||
|
|
||||||
|
virtual f32 getTopValueHeight();
|
||||||
|
virtual f32 getTopValueWidth();
|
||||||
|
|
||||||
|
virtual f32 getHeight();
|
||||||
|
virtual f32 getWidth();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void DeleteValueData();
|
||||||
|
void update(GuiController * c);
|
||||||
|
|
||||||
|
void OnValueClicked(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);
|
||||||
|
|
||||||
|
void OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);
|
||||||
|
void OnValueOpenEffectFinish(GuiElement *element);
|
||||||
|
void OnValueCloseEffectFinish(GuiElement *element);
|
||||||
|
void ShowHideValues(bool showhide);
|
||||||
|
void SelectValue(u32 value);
|
||||||
|
|
||||||
|
u32 selected;
|
||||||
|
bool bChanged;
|
||||||
|
bool bSelectedChanged;
|
||||||
|
bool showValues;
|
||||||
|
bool opened;
|
||||||
|
std::string captionText;
|
||||||
|
GuiFrame valuesFrame;
|
||||||
|
GuiImageData *topValueImageData;
|
||||||
|
GuiImage topValueImage;
|
||||||
|
GuiImageData *topValueImageSelectedData;
|
||||||
|
GuiImage topValueImageSelected;
|
||||||
|
|
||||||
|
GuiButton topValueButton;
|
||||||
|
GuiImageData * valueImageData;
|
||||||
|
GuiImageData * valueSelectedImageData;
|
||||||
|
GuiImageData * valueHighlightedImageData;
|
||||||
|
GuiText topValueText;
|
||||||
|
|
||||||
|
GuiTrigger touchTrigger;
|
||||||
|
GuiTrigger wpadTouchTrigger;
|
||||||
|
|
||||||
|
GuiTrigger buttonATrigger;
|
||||||
|
GuiTrigger buttonBTrigger;
|
||||||
|
GuiTrigger buttonLeftTrigger;
|
||||||
|
GuiTrigger buttonRightTrigger;
|
||||||
|
GuiTrigger buttonUpTrigger;
|
||||||
|
GuiTrigger buttonDownTrigger;
|
||||||
|
|
||||||
|
GuiButton DPADButtons;
|
||||||
|
|
||||||
|
GuiSound* buttonClickSound;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GuiImage *valueButtonImg;
|
||||||
|
GuiImage *valueButtonCheckedImg;
|
||||||
|
GuiImage *valueButtonHighlightedImg;
|
||||||
|
GuiButton *valueButton;
|
||||||
|
GuiText *valueButtonText;
|
||||||
|
} SelectBoxValueButton;
|
||||||
|
|
||||||
|
std::map<GuiButton * ,std::string> buttonToValue;
|
||||||
|
std::vector<SelectBoxValueButton> valueButtons;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
194
source/gui/GuiSound.cpp
Normal file
194
source/gui/GuiSound.cpp
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include "GuiSound.h"
|
||||||
|
#include "sounds/SoundHandler.hpp"
|
||||||
|
#include <dynamic_libs/os_functions.h>
|
||||||
|
|
||||||
|
GuiSound::GuiSound(const char * filepath)
|
||||||
|
{
|
||||||
|
voice = -1;
|
||||||
|
Load(filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiSound::GuiSound(const u8 * snd, s32 length)
|
||||||
|
{
|
||||||
|
voice = -1;
|
||||||
|
Load(snd, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiSound::~GuiSound()
|
||||||
|
{
|
||||||
|
if(voice >= 0)
|
||||||
|
{
|
||||||
|
SoundHandler::instance()->RemoveDecoder(voice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool GuiSound::Load(const char * filepath)
|
||||||
|
{
|
||||||
|
if(voice >= 0)
|
||||||
|
{
|
||||||
|
SoundHandler::instance()->RemoveDecoder(voice);
|
||||||
|
voice = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! find next free decoder
|
||||||
|
for(s32 i = 0; i < MAX_DECODERS; i++)
|
||||||
|
{
|
||||||
|
SoundDecoder * decoder = SoundHandler::instance()->getDecoder(i);
|
||||||
|
if(decoder == NULL)
|
||||||
|
{
|
||||||
|
SoundHandler::instance()->AddDecoder(i, filepath);
|
||||||
|
decoder = SoundHandler::instance()->getDecoder(i);
|
||||||
|
if(decoder)
|
||||||
|
{
|
||||||
|
voice = i;
|
||||||
|
SoundHandler::instance()->ThreadSignal();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(voice < 0){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GuiSound::Load(const u8 * snd, s32 len)
|
||||||
|
{
|
||||||
|
if(voice >= 0)
|
||||||
|
{
|
||||||
|
SoundHandler::instance()->RemoveDecoder(voice);
|
||||||
|
voice = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!snd)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//! find next free decoder
|
||||||
|
for(s32 i = 0; i < MAX_DECODERS; i++)
|
||||||
|
{
|
||||||
|
SoundDecoder * decoder = SoundHandler::instance()->getDecoder(i);
|
||||||
|
if(decoder == NULL)
|
||||||
|
{
|
||||||
|
SoundHandler::instance()->AddDecoder(i, snd, len);
|
||||||
|
decoder = SoundHandler::instance()->getDecoder(i);
|
||||||
|
if(decoder)
|
||||||
|
{
|
||||||
|
voice = i;
|
||||||
|
SoundHandler::instance()->ThreadSignal();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(voice < 0){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSound::Play()
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
|
||||||
|
Voice * v = SoundHandler::instance()->getVoice(voice);
|
||||||
|
if(v)
|
||||||
|
v->setState(Voice::STATE_START);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSound::Stop()
|
||||||
|
{
|
||||||
|
Voice * v = SoundHandler::instance()->getVoice(voice);
|
||||||
|
if(v)
|
||||||
|
{
|
||||||
|
if((v->getState() != Voice::STATE_STOP) && (v->getState() != Voice::STATE_STOPPED))
|
||||||
|
v->setState(Voice::STATE_STOP);
|
||||||
|
|
||||||
|
while(v->getState() != Voice::STATE_STOPPED)
|
||||||
|
os_usleep(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundDecoder * decoder = SoundHandler::instance()->getDecoder(voice);
|
||||||
|
if(decoder)
|
||||||
|
{
|
||||||
|
decoder->Lock();
|
||||||
|
decoder->Rewind();
|
||||||
|
decoder->ClearBuffer();
|
||||||
|
SoundHandler::instance()->ThreadSignal();
|
||||||
|
decoder->Unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSound::Pause()
|
||||||
|
{
|
||||||
|
if(!IsPlaying())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Voice * v = SoundHandler::instance()->getVoice(voice);
|
||||||
|
if(v)
|
||||||
|
v->setState(Voice::STATE_STOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSound::Resume()
|
||||||
|
{
|
||||||
|
if(IsPlaying())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Voice * v = SoundHandler::instance()->getVoice(voice);
|
||||||
|
if(v)
|
||||||
|
v->setState(Voice::STATE_START);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GuiSound::IsPlaying()
|
||||||
|
{
|
||||||
|
Voice * v = SoundHandler::instance()->getVoice(voice);
|
||||||
|
if(v){
|
||||||
|
return v->getState() == Voice::STATE_PLAYING;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSound::SetVolume(u32 vol)
|
||||||
|
{
|
||||||
|
if(vol > 100)
|
||||||
|
vol = 100;
|
||||||
|
|
||||||
|
u32 volumeConv = ( (0x8000 * vol) / 100 ) << 16;
|
||||||
|
|
||||||
|
Voice * v = SoundHandler::instance()->getVoice(voice);
|
||||||
|
if(v)
|
||||||
|
v->setVolume(volumeConv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSound::SetLoop(bool l)
|
||||||
|
{
|
||||||
|
SoundDecoder * decoder = SoundHandler::instance()->getDecoder(voice);
|
||||||
|
if(decoder)
|
||||||
|
decoder->SetLoop(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSound::Rewind()
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
}
|
60
source/gui/GuiSound.h
Normal file
60
source/gui/GuiSound.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef GUI_SOUND_H_
|
||||||
|
#define GUI_SOUND_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <system/AsyncDeleter.h>
|
||||||
|
|
||||||
|
//!Sound conversion and playback. A wrapper for other sound libraries - ASND, libmad, ltremor, etc
|
||||||
|
class GuiSound : public AsyncDeleter::Element
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//!Constructor
|
||||||
|
//!\param sound Pointer to the sound data
|
||||||
|
//!\param filesize Length of sound data
|
||||||
|
GuiSound(const char * filepath);
|
||||||
|
GuiSound(const u8 * sound, s32 length);
|
||||||
|
//!Destructor
|
||||||
|
virtual ~GuiSound();
|
||||||
|
//!Load a file and replace the old one
|
||||||
|
bool Load(const char * filepath);
|
||||||
|
//!Load a file and replace the old one
|
||||||
|
bool Load(const u8 * snd, s32 len);
|
||||||
|
//!Start sound playback
|
||||||
|
void Play();
|
||||||
|
//!Stop sound playback
|
||||||
|
void Stop();
|
||||||
|
//!Pause sound playback
|
||||||
|
void Pause();
|
||||||
|
//!Resume sound playback
|
||||||
|
void Resume();
|
||||||
|
//!Checks if the sound is currently playing
|
||||||
|
//!\return true if sound is playing, false otherwise
|
||||||
|
bool IsPlaying();
|
||||||
|
//!Rewind the music
|
||||||
|
void Rewind();
|
||||||
|
//!Set sound volume
|
||||||
|
//!\param v Sound volume (0-100)
|
||||||
|
void SetVolume(u32 v);
|
||||||
|
//!\param l Loop (true to loop)
|
||||||
|
void SetLoop(bool l);
|
||||||
|
protected:
|
||||||
|
s32 voice; //!< Currently assigned ASND voice channel
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
73
source/gui/GuiSwitch.cpp
Normal file
73
source/gui/GuiSwitch.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2016,2017 Maschell
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include "GuiSwitch.h"
|
||||||
|
#include "GuiImage.h"
|
||||||
|
#include "GuiImageData.h"
|
||||||
|
#include <utils/logger.h>
|
||||||
|
/**
|
||||||
|
* Constructor for the GuiSwitch class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GuiSwitch::GuiSwitch(bool checked,f32 w, f32 h)
|
||||||
|
: GuiToggle(checked,w,h){
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Destructor for the GuiSwitch class.
|
||||||
|
*/
|
||||||
|
GuiSwitch::~GuiSwitch(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSwitch::setImageBackground(GuiImage* img){
|
||||||
|
backgroundImg = img;
|
||||||
|
if(img){
|
||||||
|
img->setParent(this);
|
||||||
|
|
||||||
|
}
|
||||||
|
setImage(img);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSwitch::setImageOn(GuiImage* img){
|
||||||
|
onImg = img;
|
||||||
|
if(img){
|
||||||
|
img->setParent(this);
|
||||||
|
img->setAlignment(ALIGN_RIGHT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSwitch::setImageOff(GuiImage* img){
|
||||||
|
offImg = img;
|
||||||
|
if(img){
|
||||||
|
img->setParent(this);
|
||||||
|
img->setAlignment(ALIGN_LEFT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSwitch::setImageHighlighted(GuiImage* img){
|
||||||
|
highlightedImg = img;
|
||||||
|
setIconOver(img);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiSwitch::draw(CVideo *v){
|
||||||
|
GuiToggle::draw(v);
|
||||||
|
if(getValue()){
|
||||||
|
if(onImg != NULL){ onImg->draw(v); }
|
||||||
|
}else{
|
||||||
|
if(offImg != NULL){ offImg->draw(v); }
|
||||||
|
}
|
||||||
|
}
|
51
source/gui/GuiSwitch.h
Normal file
51
source/gui/GuiSwitch.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2016,2017 Maschell
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef GUI_SWTICH_H_
|
||||||
|
#define GUI_SWTICH_H_
|
||||||
|
|
||||||
|
#include "GuiToggle.h"
|
||||||
|
#include "GuiImage.h"
|
||||||
|
#include "GuiImageData.h"
|
||||||
|
|
||||||
|
//!A simple switch
|
||||||
|
class GuiSwitch : public GuiToggle{
|
||||||
|
public:
|
||||||
|
//!Constructor
|
||||||
|
//!\param checked Checked
|
||||||
|
GuiSwitch(bool checked,f32 w = 0.0f, f32 h = 0.0f);
|
||||||
|
//!Destructor
|
||||||
|
virtual ~GuiSwitch();
|
||||||
|
|
||||||
|
void setImageBackground(GuiImage* img);
|
||||||
|
|
||||||
|
void setImageOn(GuiImage* img);
|
||||||
|
|
||||||
|
void setImageOff(GuiImage* img);
|
||||||
|
|
||||||
|
void setImageHighlighted(GuiImage* img);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
GuiImage * backgroundImg;
|
||||||
|
GuiImage * onImg;
|
||||||
|
GuiImage * offImg;
|
||||||
|
GuiImage * highlightedImg;
|
||||||
|
|
||||||
|
void draw(CVideo * v);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
615
source/gui/GuiText.cpp
Normal file
615
source/gui/GuiText.cpp
Normal file
@ -0,0 +1,615 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include "GuiText.h"
|
||||||
|
#include "FreeTypeGX.h"
|
||||||
|
#include "video/CVideo.h"
|
||||||
|
|
||||||
|
FreeTypeGX * GuiText::presentFont = NULL;
|
||||||
|
s32 GuiText::presetSize = 28;
|
||||||
|
float GuiText::presetInternalRenderingScale = 2.0f; //Lets render the font at the doubled size. This make it even smoother!
|
||||||
|
s32 GuiText::presetMaxWidth = 0xFFFF;
|
||||||
|
s32 GuiText::presetAlignment = ALIGN_CENTER | ALIGN_MIDDLE;
|
||||||
|
GX2ColorF32 GuiText::presetColor = (GX2ColorF32){ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
|
||||||
|
#define TEXT_SCROLL_DELAY 6
|
||||||
|
#define TEXT_SCROLL_INITIAL_DELAY 10
|
||||||
|
#define MAX_LINES_TO_DRAW 10
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the GuiText class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GuiText::GuiText()
|
||||||
|
{
|
||||||
|
text = NULL;
|
||||||
|
size = presetSize;
|
||||||
|
currentSize = size;
|
||||||
|
color = glm::vec4(presetColor.r, presetColor.g, presetColor.b, presetColor.a);
|
||||||
|
alpha = presetColor.a;
|
||||||
|
alignment = presetAlignment;
|
||||||
|
maxWidth = presetMaxWidth;
|
||||||
|
wrapMode = 0;
|
||||||
|
textWidth = 0;
|
||||||
|
font = presentFont;
|
||||||
|
linestodraw = MAX_LINES_TO_DRAW;
|
||||||
|
textScrollPos = 0;
|
||||||
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
||||||
|
textScrollDelay = TEXT_SCROLL_DELAY;
|
||||||
|
defaultBlur = 4.0f;
|
||||||
|
blurGlowIntensity = 0.0f;
|
||||||
|
blurAlpha = 0.0f;
|
||||||
|
blurGlowColor = glm::vec4(0.0f);
|
||||||
|
internalRenderingScale = presetInternalRenderingScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiText::GuiText(const char * t, s32 s, const glm::vec4 & c)
|
||||||
|
{
|
||||||
|
text = NULL;
|
||||||
|
size = s;
|
||||||
|
currentSize = size;
|
||||||
|
color = c;
|
||||||
|
alpha = c[3];
|
||||||
|
alignment = ALIGN_CENTER | ALIGN_MIDDLE;
|
||||||
|
maxWidth = presetMaxWidth;
|
||||||
|
wrapMode = 0;
|
||||||
|
textWidth = 0;
|
||||||
|
font = presentFont;
|
||||||
|
linestodraw = MAX_LINES_TO_DRAW;
|
||||||
|
textScrollPos = 0;
|
||||||
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
||||||
|
textScrollDelay = TEXT_SCROLL_DELAY;
|
||||||
|
defaultBlur = 4.0f;
|
||||||
|
blurGlowIntensity = 0.0f;
|
||||||
|
blurAlpha = 0.0f;
|
||||||
|
blurGlowColor = glm::vec4(0.0f);
|
||||||
|
internalRenderingScale = presetInternalRenderingScale;
|
||||||
|
|
||||||
|
if(t)
|
||||||
|
{
|
||||||
|
text = FreeTypeGX::charToWideChar(t);
|
||||||
|
if(!text)
|
||||||
|
return;
|
||||||
|
|
||||||
|
textWidth = font->getWidth(text, currentSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiText::GuiText(const wchar_t * t, s32 s, const glm::vec4 & c)
|
||||||
|
{
|
||||||
|
text = NULL;
|
||||||
|
size = s;
|
||||||
|
currentSize = size;
|
||||||
|
color = c;
|
||||||
|
alpha = c[3];
|
||||||
|
alignment = ALIGN_CENTER | ALIGN_MIDDLE;
|
||||||
|
maxWidth = presetMaxWidth;
|
||||||
|
wrapMode = 0;
|
||||||
|
textWidth = 0;
|
||||||
|
font = presentFont;
|
||||||
|
linestodraw = MAX_LINES_TO_DRAW;
|
||||||
|
textScrollPos = 0;
|
||||||
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
||||||
|
textScrollDelay = TEXT_SCROLL_DELAY;
|
||||||
|
defaultBlur = 4.0f;
|
||||||
|
blurGlowIntensity = 0.0f;
|
||||||
|
blurAlpha = 0.0f;
|
||||||
|
blurGlowColor = glm::vec4(0.0f);
|
||||||
|
internalRenderingScale = presetInternalRenderingScale;
|
||||||
|
|
||||||
|
if(t)
|
||||||
|
{
|
||||||
|
text = new (std::nothrow) wchar_t[wcslen(t)+1];
|
||||||
|
if(!text)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wcscpy(text, t);
|
||||||
|
|
||||||
|
textWidth = font->getWidth(text, currentSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the GuiText class, uses presets
|
||||||
|
*/
|
||||||
|
GuiText::GuiText(const char * t)
|
||||||
|
{
|
||||||
|
text = NULL;
|
||||||
|
size = presetSize;
|
||||||
|
currentSize = size;
|
||||||
|
color = glm::vec4(presetColor.r, presetColor.g, presetColor.b, presetColor.a);
|
||||||
|
alpha = presetColor.a;
|
||||||
|
alignment = presetAlignment;
|
||||||
|
maxWidth = presetMaxWidth;
|
||||||
|
wrapMode = 0;
|
||||||
|
textWidth = 0;
|
||||||
|
font = presentFont;
|
||||||
|
linestodraw = MAX_LINES_TO_DRAW;
|
||||||
|
textScrollPos = 0;
|
||||||
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
||||||
|
textScrollDelay = TEXT_SCROLL_DELAY;
|
||||||
|
defaultBlur = 4.0f;
|
||||||
|
blurGlowIntensity = 0.0f;
|
||||||
|
blurAlpha = 0.0f;
|
||||||
|
blurGlowColor = glm::vec4(0.0f);
|
||||||
|
internalRenderingScale = presetInternalRenderingScale;
|
||||||
|
|
||||||
|
if(t)
|
||||||
|
{
|
||||||
|
text = FreeTypeGX::charToWideChar(t);
|
||||||
|
if(!text)
|
||||||
|
return;
|
||||||
|
|
||||||
|
textWidth = font->getWidth(text, currentSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor for the GuiText class.
|
||||||
|
*/
|
||||||
|
GuiText::~GuiText()
|
||||||
|
{
|
||||||
|
if(text)
|
||||||
|
delete [] text;
|
||||||
|
text = NULL;
|
||||||
|
|
||||||
|
clearDynamicText();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiText::setText(const char * t)
|
||||||
|
{
|
||||||
|
if(text)
|
||||||
|
delete [] text;
|
||||||
|
text = NULL;
|
||||||
|
|
||||||
|
clearDynamicText();
|
||||||
|
|
||||||
|
textScrollPos = 0;
|
||||||
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
||||||
|
|
||||||
|
if(t)
|
||||||
|
{
|
||||||
|
text = FreeTypeGX::charToWideChar(t);
|
||||||
|
if(!text)
|
||||||
|
return;
|
||||||
|
|
||||||
|
textWidth = font->getWidth(text, currentSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiText::setTextf(const char *format, ...)
|
||||||
|
{
|
||||||
|
if(!format)
|
||||||
|
{
|
||||||
|
setText((char *) NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 max_len = strlen(format) + 8192;
|
||||||
|
char *tmp = new char[max_len];
|
||||||
|
va_list va;
|
||||||
|
va_start(va, format);
|
||||||
|
if((vsnprintf(tmp, max_len, format, va) >= 0) && tmp)
|
||||||
|
{
|
||||||
|
setText(tmp);
|
||||||
|
}
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
if(tmp)
|
||||||
|
delete [] tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GuiText::setText(const wchar_t * t)
|
||||||
|
{
|
||||||
|
if(text)
|
||||||
|
delete [] text;
|
||||||
|
text = NULL;
|
||||||
|
|
||||||
|
clearDynamicText();
|
||||||
|
|
||||||
|
textScrollPos = 0;
|
||||||
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
||||||
|
|
||||||
|
if(t)
|
||||||
|
{
|
||||||
|
text = new (std::nothrow) wchar_t[wcslen(t)+1];
|
||||||
|
if(!text)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wcscpy(text, t);
|
||||||
|
|
||||||
|
textWidth = font->getWidth(text, currentSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiText::clearDynamicText()
|
||||||
|
{
|
||||||
|
for(u32 i = 0; i < textDyn.size(); i++)
|
||||||
|
{
|
||||||
|
if(textDyn[i])
|
||||||
|
delete [] textDyn[i];
|
||||||
|
}
|
||||||
|
textDyn.clear();
|
||||||
|
textDynWidth.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiText::setPresets(s32 sz, const glm::vec4 & c, s32 w, s32 a)
|
||||||
|
{
|
||||||
|
presetSize = sz;
|
||||||
|
presetColor = (GX2ColorF32) { (f32)c.r / 255.0f, (f32)c.g / 255.0f, (f32)c.b / 255.0f, (f32)c.a / 255.0f };
|
||||||
|
presetMaxWidth = w;
|
||||||
|
presetAlignment = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiText::setPresetFont(FreeTypeGX *f)
|
||||||
|
{
|
||||||
|
presentFont = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiText::setFontSize(s32 s)
|
||||||
|
{
|
||||||
|
size = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiText::setMaxWidth(s32 width, s32 w)
|
||||||
|
{
|
||||||
|
maxWidth = width;
|
||||||
|
wrapMode = w;
|
||||||
|
|
||||||
|
if(w == SCROLL_HORIZONTAL)
|
||||||
|
{
|
||||||
|
textScrollPos = 0;
|
||||||
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
||||||
|
textScrollDelay = TEXT_SCROLL_DELAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearDynamicText();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiText::setColor(const glm::vec4 & c)
|
||||||
|
{
|
||||||
|
color = c;
|
||||||
|
alpha = c[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiText::setBlurGlowColor(float blur, const glm::vec4 & c)
|
||||||
|
{
|
||||||
|
blurGlowColor = c;
|
||||||
|
blurGlowIntensity = blur;
|
||||||
|
blurAlpha = c[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 GuiText::getTextWidth(s32 ind)
|
||||||
|
{
|
||||||
|
if(ind < 0 || ind >= (s32) textDyn.size())
|
||||||
|
return this->getTextWidth();
|
||||||
|
|
||||||
|
return font->getWidth(textDyn[ind], currentSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
const wchar_t * GuiText::getDynText(s32 ind)
|
||||||
|
{
|
||||||
|
if(ind < 0 || ind >= (s32) textDyn.size())
|
||||||
|
return text;
|
||||||
|
|
||||||
|
return textDyn[ind];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change font
|
||||||
|
*/
|
||||||
|
bool GuiText::setFont(FreeTypeGX *f)
|
||||||
|
{
|
||||||
|
if(!f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
font = f;
|
||||||
|
textWidth = font->getWidth(text, currentSize);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GuiText::toUTF8(void) const
|
||||||
|
{
|
||||||
|
if(!text)
|
||||||
|
return std::string();
|
||||||
|
|
||||||
|
char *pUtf8 = FreeTypeGX::wideCharToUTF8(text);
|
||||||
|
if(!pUtf8)
|
||||||
|
return std::string();
|
||||||
|
|
||||||
|
std::string strOutput(pUtf8);
|
||||||
|
|
||||||
|
delete [] pUtf8;
|
||||||
|
|
||||||
|
return strOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiText::makeDottedText()
|
||||||
|
{
|
||||||
|
s32 pos = textDyn.size();
|
||||||
|
textDyn.resize(pos + 1);
|
||||||
|
|
||||||
|
s32 i = 0, currentWidth = 0;
|
||||||
|
textDyn[pos] = new (std::nothrow) wchar_t[maxWidth];
|
||||||
|
if(!textDyn[pos]) {
|
||||||
|
textDyn.resize(pos);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (text[i])
|
||||||
|
{
|
||||||
|
currentWidth += font->getCharWidth(text[i], currentSize, i > 0 ? text[i - 1] : 0);
|
||||||
|
if (currentWidth >= maxWidth && i > 2)
|
||||||
|
{
|
||||||
|
textDyn[pos][i - 2] = '.';
|
||||||
|
textDyn[pos][i - 1] = '.';
|
||||||
|
textDyn[pos][i] = '.';
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
textDyn[pos][i] = text[i];
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
textDyn[pos][i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiText::scrollText(u32 frameCount)
|
||||||
|
{
|
||||||
|
if (textDyn.size() == 0)
|
||||||
|
{
|
||||||
|
s32 pos = textDyn.size();
|
||||||
|
s32 i = 0, currentWidth = 0;
|
||||||
|
textDyn.resize(pos + 1);
|
||||||
|
|
||||||
|
textDyn[pos] = new (std::nothrow) wchar_t[maxWidth];
|
||||||
|
if(!textDyn[pos]) {
|
||||||
|
textDyn.resize(pos);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (text[i] && currentWidth < maxWidth)
|
||||||
|
{
|
||||||
|
textDyn[pos][i] = text[i];
|
||||||
|
|
||||||
|
currentWidth += font->getCharWidth(text[i], currentSize, i > 0 ? text[i - 1] : 0);
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
textDyn[pos][i] = 0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frameCount % textScrollDelay != 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (textScrollInitialDelay)
|
||||||
|
{
|
||||||
|
--textScrollInitialDelay;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 stringlen = wcslen(text);
|
||||||
|
|
||||||
|
++textScrollPos;
|
||||||
|
if (textScrollPos > stringlen)
|
||||||
|
{
|
||||||
|
textScrollPos = 0;
|
||||||
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 ch = textScrollPos;
|
||||||
|
s32 pos = textDyn.size() - 1;
|
||||||
|
|
||||||
|
if (!textDyn[pos])
|
||||||
|
textDyn[pos] = new (std::nothrow) wchar_t[maxWidth];
|
||||||
|
|
||||||
|
if(!textDyn[pos]) {
|
||||||
|
textDyn.resize(pos);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 i = 0, currentWidth = 0;
|
||||||
|
|
||||||
|
while (currentWidth < maxWidth)
|
||||||
|
{
|
||||||
|
if (ch > stringlen - 1)
|
||||||
|
{
|
||||||
|
textDyn[pos][i++] = ' ';
|
||||||
|
currentWidth += font->getCharWidth(L' ', currentSize, ch > 0 ? text[ch - 1] : 0);
|
||||||
|
textDyn[pos][i++] = ' ';
|
||||||
|
currentWidth += font->getCharWidth(L' ', currentSize, L' ');
|
||||||
|
textDyn[pos][i++] = ' ';
|
||||||
|
currentWidth += font->getCharWidth(L' ', currentSize, L' ');
|
||||||
|
ch = 0;
|
||||||
|
|
||||||
|
if(currentWidth >= maxWidth)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
textDyn[pos][i] = text[ch];
|
||||||
|
currentWidth += font->getCharWidth(text[ch], currentSize, ch > 0 ? text[ch - 1] : 0);
|
||||||
|
++ch;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
textDyn[pos][i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiText::wrapText()
|
||||||
|
{
|
||||||
|
if (textDyn.size() > 0) return;
|
||||||
|
|
||||||
|
s32 i = 0;
|
||||||
|
s32 ch = 0;
|
||||||
|
s32 linenum = 0;
|
||||||
|
s32 lastSpace = -1;
|
||||||
|
s32 lastSpaceIndex = -1;
|
||||||
|
s32 currentWidth = 0;
|
||||||
|
|
||||||
|
while (text[ch] && linenum < linestodraw)
|
||||||
|
{
|
||||||
|
if (linenum >= (s32) textDyn.size())
|
||||||
|
{
|
||||||
|
textDyn.resize(linenum + 1);
|
||||||
|
textDyn[linenum] = new (std::nothrow) wchar_t[maxWidth];
|
||||||
|
if(!textDyn[linenum]) {
|
||||||
|
textDyn.resize(linenum);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
textDyn[linenum][i] = text[ch];
|
||||||
|
textDyn[linenum][i + 1] = 0;
|
||||||
|
|
||||||
|
currentWidth += font->getCharWidth(text[ch], currentSize, ch > 0 ? text[ch - 1] : 0x0000);
|
||||||
|
|
||||||
|
if (currentWidth >= maxWidth || (text[ch] == '\n'))
|
||||||
|
{
|
||||||
|
if(text[ch] == '\n')
|
||||||
|
{
|
||||||
|
lastSpace = -1;
|
||||||
|
lastSpaceIndex = -1;
|
||||||
|
}
|
||||||
|
else if (lastSpace >= 0)
|
||||||
|
{
|
||||||
|
textDyn[linenum][lastSpaceIndex] = 0; // discard space, and everything after
|
||||||
|
ch = lastSpace; // go backwards to the last space
|
||||||
|
lastSpace = -1; // we have used this space
|
||||||
|
lastSpaceIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linenum + 1 == linestodraw && text[ch + 1] != 0x0000)
|
||||||
|
{
|
||||||
|
if(i < 2)
|
||||||
|
i = 2;
|
||||||
|
|
||||||
|
textDyn[linenum][i - 2] = '.';
|
||||||
|
textDyn[linenum][i - 1] = '.';
|
||||||
|
textDyn[linenum][i] = '.';
|
||||||
|
textDyn[linenum][i + 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentWidth = 0;
|
||||||
|
++linenum;
|
||||||
|
i = -1;
|
||||||
|
}
|
||||||
|
if (text[ch] == ' ' && i >= 0)
|
||||||
|
{
|
||||||
|
lastSpace = ch;
|
||||||
|
lastSpaceIndex = i;
|
||||||
|
}
|
||||||
|
++ch;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw the text on screen
|
||||||
|
*/
|
||||||
|
void GuiText::draw(CVideo *pVideo)
|
||||||
|
{
|
||||||
|
if(!text)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!isVisible())
|
||||||
|
return;
|
||||||
|
|
||||||
|
color[3] = getAlpha();
|
||||||
|
blurGlowColor[3] = blurAlpha * getAlpha();
|
||||||
|
|
||||||
|
float finalRenderingScale = 2.0f * internalRenderingScale;
|
||||||
|
|
||||||
|
s32 newSize = size * getScale() * finalRenderingScale;
|
||||||
|
s32 normal_size = size * getScale();
|
||||||
|
|
||||||
|
if(newSize != currentSize)
|
||||||
|
{
|
||||||
|
currentSize = normal_size;
|
||||||
|
|
||||||
|
if(text)
|
||||||
|
textWidth = font->getWidth(text, normal_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 x_pos = getCenterX() * finalRenderingScale;
|
||||||
|
f32 y_pos = getCenterY() * finalRenderingScale;
|
||||||
|
|
||||||
|
if(maxWidth > 0 && maxWidth <= textWidth)
|
||||||
|
{
|
||||||
|
if(wrapMode == DOTTED) // text dotted
|
||||||
|
{
|
||||||
|
if(textDyn.size() == 0)
|
||||||
|
makeDottedText();
|
||||||
|
|
||||||
|
if(textDynWidth.size() != textDyn.size())
|
||||||
|
{
|
||||||
|
textDynWidth.resize(textDyn.size());
|
||||||
|
|
||||||
|
for(u32 i = 0; i < textDynWidth.size(); i++)
|
||||||
|
textDynWidth[i] = font->getWidth(textDyn[i], newSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(textDyn.size() > 0)
|
||||||
|
font->drawText(pVideo, x_pos, y_pos, getDepth(), textDyn[textDyn.size()-1], newSize, color, alignment, textDynWidth[textDyn.size()-1], defaultBlur, blurGlowIntensity, blurGlowColor,finalRenderingScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(wrapMode == SCROLL_HORIZONTAL)
|
||||||
|
{
|
||||||
|
scrollText(pVideo->getFrameCount());
|
||||||
|
|
||||||
|
if(textDyn.size() > 0)
|
||||||
|
font->drawText(pVideo, x_pos, y_pos, getDepth(), textDyn[textDyn.size()-1], newSize, color, alignment, maxWidth*finalRenderingScale, defaultBlur, blurGlowIntensity, blurGlowColor,finalRenderingScale);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(wrapMode == WRAP)
|
||||||
|
{
|
||||||
|
s32 lineheight = newSize + 6;
|
||||||
|
s32 yoffset = 0;
|
||||||
|
s32 voffset = 0;
|
||||||
|
|
||||||
|
if(textDyn.size() == 0)
|
||||||
|
wrapText();
|
||||||
|
|
||||||
|
if(textDynWidth.size() != textDyn.size())
|
||||||
|
{
|
||||||
|
textDynWidth.resize(textDyn.size());
|
||||||
|
|
||||||
|
for(u32 i = 0; i < textDynWidth.size(); i++)
|
||||||
|
textDynWidth[i] = font->getWidth(textDyn[i], newSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(alignment & ALIGN_MIDDLE)
|
||||||
|
voffset = (lineheight * (textDyn.size()-1)) >> 1;
|
||||||
|
|
||||||
|
for(u32 i = 0; i < textDyn.size(); i++)
|
||||||
|
{
|
||||||
|
font->drawText(pVideo, x_pos, y_pos + voffset + yoffset, getDepth(), textDyn[i], newSize, color, alignment, textDynWidth[i], defaultBlur, blurGlowIntensity, blurGlowColor,finalRenderingScale);
|
||||||
|
yoffset -= lineheight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint16_t newtextWidth = font->getWidth(text, newSize);
|
||||||
|
font->drawText(pVideo, x_pos, y_pos, getDepth(), text, newSize, color, alignment, newtextWidth, defaultBlur, blurGlowIntensity, blurGlowColor,finalRenderingScale);
|
||||||
|
}
|
||||||
|
}
|
141
source/gui/GuiText.h
Normal file
141
source/gui/GuiText.h
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef GUI_TEXT_H_
|
||||||
|
#define GUI_TEXT_H_
|
||||||
|
|
||||||
|
#include "GuiElement.h"
|
||||||
|
//!Forward declaration
|
||||||
|
class FreeTypeGX;
|
||||||
|
|
||||||
|
//!Display, manage, and manipulate text in the GUI
|
||||||
|
class GuiText : public GuiElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//!Constructor
|
||||||
|
GuiText();
|
||||||
|
//!\param t Text
|
||||||
|
//!\param s Font size
|
||||||
|
//!\param c Font color
|
||||||
|
GuiText(const char * t, s32 s, const glm::vec4 & c);
|
||||||
|
//!\overload
|
||||||
|
//!\param t Text
|
||||||
|
//!\param s Font size
|
||||||
|
//!\param c Font color
|
||||||
|
GuiText(const wchar_t * t, s32 s, const glm::vec4 & c);
|
||||||
|
//!\overload
|
||||||
|
//!\Assumes SetPresets() has been called to setup preferred text attributes
|
||||||
|
//!\param t Text
|
||||||
|
GuiText(const char * t);
|
||||||
|
//!Destructor
|
||||||
|
virtual ~GuiText();
|
||||||
|
//!Sets the text of the GuiText element
|
||||||
|
//!\param t Text
|
||||||
|
virtual void setText(const char * t);
|
||||||
|
virtual void setText(const wchar_t * t);
|
||||||
|
virtual void setTextf(const char *format, ...) __attribute__((format(printf,2,3)));
|
||||||
|
//!Sets up preset values to be used by GuiText(t)
|
||||||
|
//!Useful when printing multiple text elements, all with the same attributes set
|
||||||
|
//!\param sz Font size
|
||||||
|
//!\param c Font color
|
||||||
|
//!\param w Maximum width of texture image (for text wrapping)
|
||||||
|
//!\param wrap Wrapmode when w>0
|
||||||
|
//!\param a Text alignment
|
||||||
|
static void setPresets(s32 sz, const glm::vec4 & c, s32 w, s32 a);
|
||||||
|
static void setPresetFont(FreeTypeGX *font);
|
||||||
|
//!Sets the font size
|
||||||
|
//!\param s Font size
|
||||||
|
void setFontSize(s32 s);
|
||||||
|
//!Sets the maximum width of the drawn texture image
|
||||||
|
//!If the text exceeds this, it is wrapped to the next line
|
||||||
|
//!\param w Maximum width
|
||||||
|
//!\param m WrapMode
|
||||||
|
void setMaxWidth(s32 w = 0, s32 m = WRAP);
|
||||||
|
//!Sets the font color
|
||||||
|
//!\param c Font color
|
||||||
|
void setColor(const glm::vec4 & c);
|
||||||
|
|
||||||
|
void setBlurGlowColor(float blurIntensity, const glm::vec4 & c);
|
||||||
|
|
||||||
|
void setTextBlur(float blur) { defaultBlur = blur; }
|
||||||
|
//!Get the original text as char
|
||||||
|
virtual const wchar_t * getText() const { return text; }
|
||||||
|
virtual std::string toUTF8(void) const;
|
||||||
|
//!Get the Horizontal Size of Text
|
||||||
|
s32 getTextWidth() { return textWidth; }
|
||||||
|
s32 getTextWidth(s32 ind);
|
||||||
|
//!Get the max textwidth
|
||||||
|
s32 getTextMaxWidth() { return maxWidth; }
|
||||||
|
//!Get fontsize
|
||||||
|
s32 getFontSize() { return size; };
|
||||||
|
//!Set max lines to draw
|
||||||
|
void setLinesToDraw(s32 l) { linestodraw = l; }
|
||||||
|
//!Get current Textline (for position calculation)
|
||||||
|
const wchar_t * getDynText(s32 ind = 0);
|
||||||
|
virtual const wchar_t * getTextLine(s32 ind) { return getDynText(ind); };
|
||||||
|
//!Change the font
|
||||||
|
bool setFont(FreeTypeGX *font);
|
||||||
|
//! virtual function used in child classes
|
||||||
|
virtual s32 getStartWidth() { return 0; };
|
||||||
|
//!Constantly called to draw the text
|
||||||
|
void draw(CVideo *pVideo);
|
||||||
|
//! text enums
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
WRAP,
|
||||||
|
DOTTED,
|
||||||
|
SCROLL_HORIZONTAL,
|
||||||
|
SCROLL_NONE
|
||||||
|
};
|
||||||
|
protected:
|
||||||
|
static FreeTypeGX * presentFont;
|
||||||
|
static s32 presetSize;
|
||||||
|
static s32 presetMaxWidth;
|
||||||
|
static float presetInternalRenderingScale;
|
||||||
|
static s32 presetAlignment;
|
||||||
|
static GX2ColorF32 presetColor;
|
||||||
|
|
||||||
|
//!Clear the dynamic text
|
||||||
|
void clearDynamicText();
|
||||||
|
//!Create a dynamic dotted text if the text is too long
|
||||||
|
void makeDottedText();
|
||||||
|
//!Scroll the text once
|
||||||
|
void scrollText(u32 frameCount);
|
||||||
|
//!Wrap the text to several lines
|
||||||
|
void wrapText();
|
||||||
|
|
||||||
|
wchar_t * text;
|
||||||
|
std::vector<wchar_t *> textDyn;
|
||||||
|
std::vector<uint16_t> textDynWidth;
|
||||||
|
s32 wrapMode; //!< Wrapping toggle
|
||||||
|
s32 textScrollPos; //!< Current starting index of text string for scrolling
|
||||||
|
s32 textScrollInitialDelay; //!< Delay to wait before starting to scroll
|
||||||
|
s32 textScrollDelay; //!< Scrolling speed
|
||||||
|
s32 size; //!< Font size
|
||||||
|
s32 maxWidth; //!< Maximum width of the generated text object (for text wrapping)
|
||||||
|
FreeTypeGX *font;
|
||||||
|
s32 textWidth;
|
||||||
|
s32 currentSize;
|
||||||
|
s32 linestodraw;
|
||||||
|
glm::vec4 color;
|
||||||
|
float defaultBlur;
|
||||||
|
float blurGlowIntensity;
|
||||||
|
float blurAlpha;
|
||||||
|
glm::vec4 blurGlowColor;
|
||||||
|
float internalRenderingScale;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
52
source/gui/GuiToggle.cpp
Normal file
52
source/gui/GuiToggle.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2016 Maschell
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include "GuiToggle.h"
|
||||||
|
/**
|
||||||
|
* Constructor for the GuiToggle class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GuiToggle::GuiToggle(bool checked,f32 width,f32 height)
|
||||||
|
: GuiButton(width,height)
|
||||||
|
{
|
||||||
|
bChanged = false;
|
||||||
|
selected = checked;
|
||||||
|
clicked.connect(this,&GuiToggle::OnToggleClick);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor for the GuiButton class.
|
||||||
|
*/
|
||||||
|
GuiToggle::~GuiToggle()
|
||||||
|
{
|
||||||
|
bChanged = false;
|
||||||
|
selected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiToggle::OnToggleClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger){
|
||||||
|
if(!isStateSet(STATE_DISABLED | STATE_HIDDEN | STATE_DISABLE_INPUT)){
|
||||||
|
if(selected){
|
||||||
|
setUnchecked();
|
||||||
|
}else{
|
||||||
|
setChecked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiToggle::update(GuiController * c){
|
||||||
|
GuiButton::update(c);
|
||||||
|
}
|
||||||
|
|
59
source/gui/GuiToggle.h
Normal file
59
source/gui/GuiToggle.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2016 Maschell
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef GUI_TOGGLE_H_
|
||||||
|
#define GUI_TOGGLE_H_
|
||||||
|
|
||||||
|
#include "GuiButton.h"
|
||||||
|
#include "GuiFrame.h"
|
||||||
|
|
||||||
|
//!A simple CheckBox
|
||||||
|
class GuiToggle : public GuiButton, public sigslot::has_slots<>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//!Constructor
|
||||||
|
//!\param checked Checked
|
||||||
|
GuiToggle(bool checked,f32 width,f32 height);
|
||||||
|
//!Destructor
|
||||||
|
virtual ~GuiToggle();
|
||||||
|
void setValue(bool checked){
|
||||||
|
if(selected != checked){
|
||||||
|
selected = checked;
|
||||||
|
bChanged=true;
|
||||||
|
valueChanged(this,selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void setChecked(){
|
||||||
|
setValue(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
void setUnchecked(){
|
||||||
|
setValue(false);
|
||||||
|
}
|
||||||
|
bool getValue(){
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
sigslot::signal2<GuiToggle *, bool> valueChanged;
|
||||||
|
void OnToggleClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);
|
||||||
|
protected:
|
||||||
|
|
||||||
|
bool selected;
|
||||||
|
bool bChanged;
|
||||||
|
|
||||||
|
void update(GuiController * c);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
174
source/gui/GuiTrigger.cpp
Normal file
174
source/gui/GuiTrigger.cpp
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include "GuiElement.h"
|
||||||
|
#include "GuiController.h"
|
||||||
|
#include "GuiTrigger.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the GuiTrigger class.
|
||||||
|
*/
|
||||||
|
GuiTrigger::GuiTrigger()
|
||||||
|
: chan(CHANNEL_ALL)
|
||||||
|
, btns(BUTTON_NONE)
|
||||||
|
, bClickEverywhere(false)
|
||||||
|
, bHoldEverywhere(false)
|
||||||
|
, bSelectionClickEverywhere(false)
|
||||||
|
, bLastTouched(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiTrigger::GuiTrigger(u32 ch, u32 btn, bool clickEverywhere, bool holdEverywhere, bool selectionClickEverywhere)
|
||||||
|
: chan(ch)
|
||||||
|
, btns(btn)
|
||||||
|
, bClickEverywhere(clickEverywhere)
|
||||||
|
, bHoldEverywhere(holdEverywhere)
|
||||||
|
, bSelectionClickEverywhere(selectionClickEverywhere)
|
||||||
|
, bLastTouched(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor for the GuiTrigger class.
|
||||||
|
*/
|
||||||
|
GuiTrigger::~GuiTrigger()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a simple trigger. Requires:
|
||||||
|
* - Element is selected
|
||||||
|
* - Trigger button is pressed
|
||||||
|
*/
|
||||||
|
void GuiTrigger::setTrigger(u32 ch, u32 btn)
|
||||||
|
{
|
||||||
|
chan = ch;
|
||||||
|
btns = btn;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GuiTrigger::left(const GuiController *controller) const
|
||||||
|
{
|
||||||
|
if((controller->chan & chan) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_LEFT | STICK_L_LEFT))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GuiTrigger::right(const GuiController *controller) const
|
||||||
|
{
|
||||||
|
if((controller->chan & chan) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_RIGHT | STICK_L_RIGHT))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GuiTrigger::up(const GuiController *controller) const
|
||||||
|
{
|
||||||
|
if((controller->chan & chan) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_UP | STICK_L_UP))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GuiTrigger::down(const GuiController *controller) const
|
||||||
|
{
|
||||||
|
if((controller->chan & chan) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_DOWN | STICK_L_DOWN))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 GuiTrigger::clicked(const GuiController *controller) const
|
||||||
|
{
|
||||||
|
if((controller->chan & chan) == 0) {
|
||||||
|
return CLICKED_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 bResult = CLICKED_NONE;
|
||||||
|
|
||||||
|
if(controller->data.touched && controller->data.validPointer && (btns & VPAD_TOUCH) && !controller->lastData.touched)
|
||||||
|
{
|
||||||
|
bResult = CLICKED_TOUCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(controller->data.buttons_d & btns)
|
||||||
|
{
|
||||||
|
bResult = CLICKED_BUTTON;
|
||||||
|
}
|
||||||
|
return bResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GuiTrigger::held(const GuiController *controller) const
|
||||||
|
{
|
||||||
|
if((controller->chan & chan) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bResult = false;
|
||||||
|
|
||||||
|
if(controller->data.touched && (btns & VPAD_TOUCH) && controller->data.validPointer && controller->lastData.touched && controller->lastData.validPointer)
|
||||||
|
{
|
||||||
|
bResult = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(controller->data.buttons_h & btns)
|
||||||
|
{
|
||||||
|
bResult = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GuiTrigger::released(const GuiController *controller) const
|
||||||
|
{
|
||||||
|
if((controller->chan & chan) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(clicked(controller) || held(controller))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool bResult = false;
|
||||||
|
|
||||||
|
if(!controller->data.touched && (btns & VPAD_TOUCH) && controller->lastData.touched && controller->lastData.validPointer)
|
||||||
|
{
|
||||||
|
bResult = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(controller->data.buttons_r & btns)
|
||||||
|
{
|
||||||
|
bResult = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bResult;
|
||||||
|
}
|
||||||
|
|
106
source/gui/GuiTrigger.h
Normal file
106
source/gui/GuiTrigger.h
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef GUI_TRIGGER_H_
|
||||||
|
#define GUI_TRIGGER_H_
|
||||||
|
|
||||||
|
#include <dynamic_libs/os_functions.h>
|
||||||
|
|
||||||
|
|
||||||
|
//!Menu input trigger management. Determine if action is neccessary based on input data by comparing controller input data to a specific trigger element.
|
||||||
|
class GuiTrigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum eClicked{
|
||||||
|
CLICKED_NONE = 0x00,
|
||||||
|
CLICKED_TOUCH = 0x01,
|
||||||
|
CLICKED_BUTTON = 0x02,
|
||||||
|
};
|
||||||
|
enum eChannels {
|
||||||
|
CHANNEL_1 = 0x01,
|
||||||
|
CHANNEL_2 = 0x02,
|
||||||
|
CHANNEL_3 = 0x04,
|
||||||
|
CHANNEL_4 = 0x08,
|
||||||
|
CHANNEL_5 = 0x10,
|
||||||
|
CHANNEL_ALL = 0xFF
|
||||||
|
};
|
||||||
|
enum eButtons {
|
||||||
|
BUTTON_NONE = 0x0000,
|
||||||
|
VPAD_TOUCH = 0x80000000,
|
||||||
|
BUTTON_Z = 0x20000,
|
||||||
|
BUTTON_C = 0x10000,
|
||||||
|
BUTTON_A = 0x8000,
|
||||||
|
BUTTON_B = 0x4000,
|
||||||
|
BUTTON_X = 0x2000,
|
||||||
|
BUTTON_Y = 0x1000,
|
||||||
|
BUTTON_1 = BUTTON_Y,
|
||||||
|
BUTTON_2 = BUTTON_X,
|
||||||
|
BUTTON_LEFT = 0x0800,
|
||||||
|
BUTTON_RIGHT = 0x0400,
|
||||||
|
BUTTON_UP = 0x0200,
|
||||||
|
BUTTON_DOWN = 0x0100,
|
||||||
|
BUTTON_ZL = 0x0080,
|
||||||
|
BUTTON_ZR = 0x0040,
|
||||||
|
BUTTON_L = 0x0020,
|
||||||
|
BUTTON_R = 0x0010,
|
||||||
|
BUTTON_PLUS = 0x0008,
|
||||||
|
BUTTON_MINUS = 0x0004,
|
||||||
|
BUTTON_HOME = 0x0002,
|
||||||
|
BUTTON_SYNC = 0x0001,
|
||||||
|
STICK_R_LEFT = 0x04000000,
|
||||||
|
STICK_R_RIGHT = 0x02000000,
|
||||||
|
STICK_R_UP = 0x01000000,
|
||||||
|
STICK_R_DOWN = 0x00800000,
|
||||||
|
STICK_L_LEFT = 0x40000000,
|
||||||
|
STICK_L_RIGHT = 0x20000000,
|
||||||
|
STICK_L_UP = 0x10000000,
|
||||||
|
STICK_L_DOWN = 0x08000000
|
||||||
|
};
|
||||||
|
|
||||||
|
//!Constructor
|
||||||
|
GuiTrigger();
|
||||||
|
//!Constructor
|
||||||
|
GuiTrigger(u32 ch, u32 btns, bool clickEverywhere = false, bool holdEverywhere = false, bool selectionClickEverywhere = false);
|
||||||
|
//!Destructor
|
||||||
|
virtual ~GuiTrigger();
|
||||||
|
//!Sets a simple trigger. Requires: element is selected, and trigger button is pressed
|
||||||
|
void setTrigger(u32 ch, u32 btns);
|
||||||
|
|
||||||
|
void setClickEverywhere(bool b) { bClickEverywhere = b; }
|
||||||
|
void setHoldOnly(bool b) { bHoldEverywhere = b; }
|
||||||
|
void setSelectionClickEverywhere(bool b) { bSelectionClickEverywhere = b; }
|
||||||
|
|
||||||
|
bool isClickEverywhere() const { return bClickEverywhere; }
|
||||||
|
bool isHoldEverywhere() const { return bHoldEverywhere; }
|
||||||
|
bool isSelectionClickEverywhere() const { return bSelectionClickEverywhere; }
|
||||||
|
|
||||||
|
bool left(const GuiController *controller) const;
|
||||||
|
bool right(const GuiController *controller) const;
|
||||||
|
bool up(const GuiController *controller) const;
|
||||||
|
bool down(const GuiController *controller) const;
|
||||||
|
s32 clicked(const GuiController *controller) const;
|
||||||
|
bool held(const GuiController *controller) const;
|
||||||
|
bool released(const GuiController *controller) const;
|
||||||
|
private:
|
||||||
|
u32 chan;
|
||||||
|
u32 btns;
|
||||||
|
bool bClickEverywhere;
|
||||||
|
bool bHoldEverywhere;
|
||||||
|
bool bSelectionClickEverywhere;
|
||||||
|
bool bLastTouched;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
66
source/gui/VPadController.h
Normal file
66
source/gui/VPadController.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef VPAD_CONTROLLER_H_
|
||||||
|
#define VPAD_CONTROLLER_H_
|
||||||
|
|
||||||
|
#include "GuiController.h"
|
||||||
|
#include <dynamic_libs/vpad_functions.h>
|
||||||
|
|
||||||
|
class VPadController : public GuiController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//!Constructor
|
||||||
|
VPadController(s32 channel)
|
||||||
|
: GuiController(channel)
|
||||||
|
{
|
||||||
|
memset(&vpad, 0, sizeof(vpad));
|
||||||
|
}
|
||||||
|
|
||||||
|
//!Destructor
|
||||||
|
virtual ~VPadController() {}
|
||||||
|
|
||||||
|
bool update(s32 width, s32 height)
|
||||||
|
{
|
||||||
|
lastData = data;
|
||||||
|
|
||||||
|
s32 vpadError = -1;
|
||||||
|
VPADRead(0, &vpad, 1, &vpadError);
|
||||||
|
|
||||||
|
if(vpadError == 0){
|
||||||
|
data.buttons_r = vpad.btns_r;
|
||||||
|
data.buttons_h = vpad.btns_h;
|
||||||
|
data.buttons_d = vpad.btns_d;
|
||||||
|
data.validPointer = !vpad.tpdata.invalid;
|
||||||
|
data.touched = vpad.tpdata.touched;
|
||||||
|
|
||||||
|
VPADGetTPCalibratedPoint(0, &tpCalib, &vpad.tpdata1);
|
||||||
|
|
||||||
|
//! calculate the screen offsets
|
||||||
|
data.x = -(width >> 1) + (s32)(((float)tpCalib.x / 1280.0f) * (float)width);
|
||||||
|
data.y = -(height >> 1) + (s32)(float)height - (((float)tpCalib.y / 720.0f) * (float)height);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
VPADData vpad;
|
||||||
|
VPADTPData tpCalib;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
179
source/gui/WPadController.h
Normal file
179
source/gui/WPadController.h
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef WPAD_CONTROLLER_H_
|
||||||
|
#define WPAD_CONTROLLER_H_
|
||||||
|
|
||||||
|
#include "GuiController.h"
|
||||||
|
#include <dynamic_libs/padscore_functions.h>
|
||||||
|
|
||||||
|
class WPadController : public GuiController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//!Constructor
|
||||||
|
WPadController(s32 channel)
|
||||||
|
: GuiController(channel)
|
||||||
|
{
|
||||||
|
memset(&kpadData, 0, sizeof(kpadData));
|
||||||
|
}
|
||||||
|
|
||||||
|
//!Destructor
|
||||||
|
virtual ~WPadController() {}
|
||||||
|
|
||||||
|
u32 remapWiiMoteButtons(u32 buttons)
|
||||||
|
{
|
||||||
|
u32 conv_buttons = 0;
|
||||||
|
|
||||||
|
if(buttons & WPAD_BUTTON_LEFT)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_LEFT;
|
||||||
|
|
||||||
|
if(buttons & WPAD_BUTTON_RIGHT)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_RIGHT;
|
||||||
|
|
||||||
|
if(buttons & WPAD_BUTTON_DOWN)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_DOWN;
|
||||||
|
|
||||||
|
if(buttons & WPAD_BUTTON_UP)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_UP;
|
||||||
|
|
||||||
|
if(buttons & WPAD_BUTTON_PLUS)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_PLUS;
|
||||||
|
|
||||||
|
if(buttons & WPAD_BUTTON_2)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_2;
|
||||||
|
|
||||||
|
if(buttons & WPAD_BUTTON_1)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_1;
|
||||||
|
|
||||||
|
if(buttons & WPAD_BUTTON_B)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_B;
|
||||||
|
|
||||||
|
if(buttons & WPAD_BUTTON_A)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_A;
|
||||||
|
|
||||||
|
if(buttons & WPAD_BUTTON_MINUS)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_MINUS;
|
||||||
|
|
||||||
|
if(buttons & WPAD_BUTTON_Z)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_Z;
|
||||||
|
|
||||||
|
if(buttons & WPAD_BUTTON_C)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_C;
|
||||||
|
|
||||||
|
if(buttons & WPAD_BUTTON_HOME)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_HOME;
|
||||||
|
|
||||||
|
return conv_buttons;
|
||||||
|
}
|
||||||
|
u32 remapClassicButtons(u32 buttons)
|
||||||
|
{
|
||||||
|
u32 conv_buttons = 0;
|
||||||
|
|
||||||
|
if(buttons & WPAD_CLASSIC_BUTTON_LEFT)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_LEFT;
|
||||||
|
|
||||||
|
if(buttons & WPAD_CLASSIC_BUTTON_RIGHT)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_RIGHT;
|
||||||
|
|
||||||
|
if(buttons & WPAD_CLASSIC_BUTTON_DOWN)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_DOWN;
|
||||||
|
|
||||||
|
if(buttons & WPAD_CLASSIC_BUTTON_UP)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_UP;
|
||||||
|
|
||||||
|
if(buttons & WPAD_CLASSIC_BUTTON_PLUS)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_PLUS;
|
||||||
|
|
||||||
|
if(buttons & WPAD_CLASSIC_BUTTON_X)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_X;
|
||||||
|
|
||||||
|
if(buttons & WPAD_CLASSIC_BUTTON_Y)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_Y;
|
||||||
|
|
||||||
|
if(buttons & WPAD_CLASSIC_BUTTON_B)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_B;
|
||||||
|
|
||||||
|
if(buttons & WPAD_CLASSIC_BUTTON_A)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_A;
|
||||||
|
|
||||||
|
if(buttons & WPAD_CLASSIC_BUTTON_MINUS)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_MINUS;
|
||||||
|
|
||||||
|
if(buttons & WPAD_CLASSIC_BUTTON_HOME)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_HOME;
|
||||||
|
|
||||||
|
if(buttons & WPAD_CLASSIC_BUTTON_ZR)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_ZR;
|
||||||
|
|
||||||
|
if(buttons & WPAD_CLASSIC_BUTTON_ZL)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_ZL;
|
||||||
|
|
||||||
|
if(buttons & WPAD_CLASSIC_BUTTON_R)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_R;
|
||||||
|
|
||||||
|
if(buttons & WPAD_CLASSIC_BUTTON_L)
|
||||||
|
conv_buttons |= GuiTrigger::BUTTON_L;
|
||||||
|
|
||||||
|
return conv_buttons;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool update(s32 width, s32 height)
|
||||||
|
{
|
||||||
|
lastData = data;
|
||||||
|
|
||||||
|
u32 controller_type;
|
||||||
|
|
||||||
|
//! check if the controller is connected
|
||||||
|
if(WPADProbe(chanIdx-1, &controller_type) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
KPADRead(chanIdx-1, &kpadData, 1);
|
||||||
|
|
||||||
|
if(kpadData.device_type <= 1)
|
||||||
|
{
|
||||||
|
data.buttons_r = remapWiiMoteButtons(kpadData.btns_r);
|
||||||
|
data.buttons_h = remapWiiMoteButtons(kpadData.btns_h);
|
||||||
|
data.buttons_d = remapWiiMoteButtons(kpadData.btns_d);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data.buttons_r = remapClassicButtons(kpadData.classic.btns_r);
|
||||||
|
data.buttons_h = remapClassicButtons(kpadData.classic.btns_h);
|
||||||
|
data.buttons_d = remapClassicButtons(kpadData.classic.btns_d);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.validPointer = (kpadData.pos_valid == 1 || kpadData.pos_valid == 2) && (kpadData.pos_x >= -1.0f && kpadData.pos_x <= 1.0f) && (kpadData.pos_y >= -1.0f && kpadData.pos_y <= 1.0f);
|
||||||
|
//! calculate the screen offsets if pointer is valid else leave old value
|
||||||
|
if(data.validPointer)
|
||||||
|
{
|
||||||
|
data.x = (width >> 1) * kpadData.pos_x;
|
||||||
|
data.y = (height >> 1) * (-kpadData.pos_y);
|
||||||
|
|
||||||
|
if(kpadData.angle_y > 0.0f)
|
||||||
|
data.pointerAngle = (-kpadData.angle_x + 1.0f) * 0.5f * 180.0f;
|
||||||
|
else
|
||||||
|
data.pointerAngle = (kpadData.angle_x + 1.0f) * 0.5f * 180.0f - 180.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
KPADData kpadData;
|
||||||
|
u32 lastButtons;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
2731
source/gui/sigslot.h
Normal file
2731
source/gui/sigslot.h
Normal file
File diff suppressed because it is too large
Load Diff
208
source/resources/Resources.cpp
Normal file
208
source/resources/Resources.cpp
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "Resources.h"
|
||||||
|
#include "filelist.h"
|
||||||
|
#include <system/AsyncDeleter.h>
|
||||||
|
#include <fs/FSUtils.h>
|
||||||
|
#include "gui/GuiImageAsync.h"
|
||||||
|
#include "gui/GuiSound.h"
|
||||||
|
#include "utils/logger.h"
|
||||||
|
|
||||||
|
Resources * Resources::instance = NULL;
|
||||||
|
|
||||||
|
void Resources::Clear(){
|
||||||
|
ResourceFile * ResourceList = getResourceList();
|
||||||
|
if(ResourceList == NULL) return;
|
||||||
|
|
||||||
|
for(s32 i = 0; ResourceList[i].filename != NULL; ++i)
|
||||||
|
{
|
||||||
|
if(ResourceList[i].CustomFile)
|
||||||
|
{
|
||||||
|
free(ResourceList[i].CustomFile);
|
||||||
|
ResourceList[i].CustomFile = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ResourceList[i].CustomFileSize != 0)
|
||||||
|
ResourceList[i].CustomFileSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(instance)
|
||||||
|
delete instance;
|
||||||
|
|
||||||
|
instance = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Resources::LoadFiles(const char * path)
|
||||||
|
{
|
||||||
|
if(!path)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
Clear();
|
||||||
|
|
||||||
|
ResourceFile * ResourceList = getResourceList();
|
||||||
|
if(ResourceList == NULL) return false;
|
||||||
|
|
||||||
|
for(s32 i = 0; ResourceList[i].filename != NULL; ++i)
|
||||||
|
{
|
||||||
|
std::string fullpath(path);
|
||||||
|
fullpath += "/";
|
||||||
|
fullpath += ResourceList[i].filename;
|
||||||
|
|
||||||
|
u8 * buffer = NULL;
|
||||||
|
u32 filesize = 0;
|
||||||
|
|
||||||
|
FSUtils::LoadFileToMem(fullpath.c_str(), &buffer, &filesize);
|
||||||
|
|
||||||
|
ResourceList[i].CustomFile = buffer;
|
||||||
|
ResourceList[i].CustomFileSize = (u32) filesize;
|
||||||
|
result |= (buffer != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u8 * Resources::GetFile(const char * filename)
|
||||||
|
{
|
||||||
|
DEBUG_FUNCTION_LINE(".\n");
|
||||||
|
ResourceFile * ResourceList = getResourceList();
|
||||||
|
if(ResourceList == NULL) return NULL;
|
||||||
|
|
||||||
|
for(s32 i = 0; ResourceList[i].filename != NULL; ++i)
|
||||||
|
{
|
||||||
|
if(strcasecmp(filename, ResourceList[i].filename) == 0)
|
||||||
|
{
|
||||||
|
return (ResourceList[i].CustomFile ? ResourceList[i].CustomFile : ResourceList[i].DefaultFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 Resources::GetFileSize(const char * filename)
|
||||||
|
{
|
||||||
|
ResourceFile * ResourceList = getResourceList();
|
||||||
|
if(ResourceList == NULL) return 0;
|
||||||
|
|
||||||
|
for(s32 i = 0; ResourceList[i].filename != NULL; ++i)
|
||||||
|
{
|
||||||
|
if(strcasecmp(filename, ResourceList[i].filename) == 0)
|
||||||
|
{
|
||||||
|
return (ResourceList[i].CustomFile ? ResourceList[i].CustomFileSize : ResourceList[i].DefaultFileSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiImageData * Resources::GetImageData(const char * filename)
|
||||||
|
{
|
||||||
|
if(!instance)
|
||||||
|
instance = new Resources;
|
||||||
|
|
||||||
|
ResourceFile * ResourceList = getResourceList();
|
||||||
|
if(ResourceList == NULL) return NULL;
|
||||||
|
|
||||||
|
std::map<std::string, std::pair<u32, GuiImageData *> >::iterator itr = instance->imageDataMap.find(std::string(filename));
|
||||||
|
if(itr != instance->imageDataMap.end())
|
||||||
|
{
|
||||||
|
itr->second.first++;
|
||||||
|
return itr->second.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(s32 i = 0; ResourceList[i].filename != NULL; ++i)
|
||||||
|
{
|
||||||
|
if(strcasecmp(filename, ResourceList[i].filename) == 0)
|
||||||
|
{
|
||||||
|
const u8 * buff = ResourceList[i].CustomFile ? ResourceList[i].CustomFile : ResourceList[i].DefaultFile;
|
||||||
|
const u32 size = ResourceList[i].CustomFile ? ResourceList[i].CustomFileSize : ResourceList[i].DefaultFileSize;
|
||||||
|
|
||||||
|
if(buff == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
GuiImageData * image = new GuiImageData(buff, size);
|
||||||
|
instance->imageDataMap[std::string(filename)].first = 1;
|
||||||
|
instance->imageDataMap[std::string(filename)].second = image;
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Resources::RemoveImageData(GuiImageData * image)
|
||||||
|
{
|
||||||
|
std::map<std::string, std::pair<u32, GuiImageData *> >::iterator itr;
|
||||||
|
|
||||||
|
for(itr = instance->imageDataMap.begin(); itr != instance->imageDataMap.end(); itr++)
|
||||||
|
{
|
||||||
|
if(itr->second.second == image)
|
||||||
|
{
|
||||||
|
itr->second.first--;
|
||||||
|
|
||||||
|
if(itr->second.first == 0)
|
||||||
|
{
|
||||||
|
AsyncDeleter::pushForDelete( itr->second.second );
|
||||||
|
instance->imageDataMap.erase(itr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiSound * Resources::GetSound(const char * filename)
|
||||||
|
{
|
||||||
|
if(!instance)
|
||||||
|
instance = new Resources;
|
||||||
|
|
||||||
|
std::map<std::string, std::pair<u32, GuiSound *> >::iterator itr = instance->soundDataMap.find(std::string(filename));
|
||||||
|
if(itr != instance->soundDataMap.end())
|
||||||
|
{
|
||||||
|
itr->second.first++;
|
||||||
|
return itr->second.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceFile * ResourceList = getResourceList();
|
||||||
|
if(ResourceList == NULL) return NULL;
|
||||||
|
|
||||||
|
for(s32 i = 0; ResourceList[i].filename != NULL; ++i)
|
||||||
|
{
|
||||||
|
if(strcasecmp(filename, ResourceList[i].filename) == 0)
|
||||||
|
{
|
||||||
|
const u8 * buff = ResourceList[i].CustomFile ? ResourceList[i].CustomFile : ResourceList[i].DefaultFile;
|
||||||
|
const u32 size = ResourceList[i].CustomFile ? ResourceList[i].CustomFileSize : ResourceList[i].DefaultFileSize;
|
||||||
|
|
||||||
|
if(buff == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
GuiSound * sound = new GuiSound(buff, size);
|
||||||
|
instance->soundDataMap[std::string(filename)].first = 1;
|
||||||
|
instance->soundDataMap[std::string(filename)].second = sound;
|
||||||
|
|
||||||
|
return sound;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Resources::RemoveSound(GuiSound * sound)
|
||||||
|
{
|
||||||
|
std::map<std::string, std::pair<u32, GuiSound *> >::iterator itr;
|
||||||
|
|
||||||
|
for(itr = instance->soundDataMap.begin(); itr != instance->soundDataMap.end(); itr++)
|
||||||
|
{
|
||||||
|
if(itr->second.second == sound)
|
||||||
|
{
|
||||||
|
itr->second.first--;
|
||||||
|
|
||||||
|
if(itr->second.first == 0)
|
||||||
|
{
|
||||||
|
AsyncDeleter::pushForDelete( itr->second.second );
|
||||||
|
instance->soundDataMap.erase(itr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
source/resources/Resources.h
Normal file
34
source/resources/Resources.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef RECOURCES_H_
|
||||||
|
#define RECOURCES_H_
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <dynamic_libs/os_types.h>
|
||||||
|
|
||||||
|
//! forward declaration
|
||||||
|
class GuiImageData;
|
||||||
|
class GuiSound;
|
||||||
|
|
||||||
|
class Resources
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void Clear();
|
||||||
|
static bool LoadFiles(const char * path);
|
||||||
|
static const u8 * GetFile(const char * filename);
|
||||||
|
static u32 GetFileSize(const char * filename);
|
||||||
|
|
||||||
|
static GuiImageData * GetImageData(const char * filename);
|
||||||
|
static void RemoveImageData(GuiImageData * image);
|
||||||
|
|
||||||
|
static GuiSound * GetSound(const char * filename);
|
||||||
|
static void RemoveSound(GuiSound * sound);
|
||||||
|
private:
|
||||||
|
static Resources *instance;
|
||||||
|
|
||||||
|
Resources() {}
|
||||||
|
~Resources() {}
|
||||||
|
|
||||||
|
std::map<std::string, std::pair<u32, GuiImageData *> > imageDataMap;
|
||||||
|
std::map<std::string, std::pair<u32, GuiSound *> > soundDataMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
16
source/resources/filelist.h
Normal file
16
source/resources/filelist.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef _FILELIST_H_
|
||||||
|
#define _FILELIST_H_
|
||||||
|
#include <dynamic_libs/os_types.h>
|
||||||
|
|
||||||
|
typedef struct _ResourceFile
|
||||||
|
{
|
||||||
|
const char *filename;
|
||||||
|
const u8 *DefaultFile;
|
||||||
|
const u32 &DefaultFileSize;
|
||||||
|
u8 *CustomFile;
|
||||||
|
u32 CustomFileSize;
|
||||||
|
} ResourceFile;
|
||||||
|
|
||||||
|
ResourceFile * getResourceList();
|
||||||
|
|
||||||
|
#endif
|
142
source/sounds/BufferCircle.cpp
Normal file
142
source/sounds/BufferCircle.cpp
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010
|
||||||
|
* by Dimok
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* for WiiXplorer 2010
|
||||||
|
***************************************************************************/
|
||||||
|
#include <malloc.h>
|
||||||
|
#include "utils/utils.h"
|
||||||
|
#include "BufferCircle.hpp"
|
||||||
|
|
||||||
|
BufferCircle::BufferCircle()
|
||||||
|
{
|
||||||
|
which = 0;
|
||||||
|
BufferBlockSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferCircle::~BufferCircle()
|
||||||
|
{
|
||||||
|
FreeBuffer();
|
||||||
|
SoundBuffer.clear();
|
||||||
|
BufferSize.clear();
|
||||||
|
BufferReady.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BufferCircle::SetBufferBlockSize(s32 size)
|
||||||
|
{
|
||||||
|
if(size < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BufferBlockSize = size;
|
||||||
|
|
||||||
|
for(s32 i = 0; i < Size(); i++)
|
||||||
|
{
|
||||||
|
if(SoundBuffer[i] != NULL)
|
||||||
|
free(SoundBuffer[i]);
|
||||||
|
|
||||||
|
SoundBuffer[i] = (u8 *) memalign(32, ALIGN32(BufferBlockSize));
|
||||||
|
BufferSize[i] = 0;
|
||||||
|
BufferReady[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BufferCircle::Resize(s32 size)
|
||||||
|
{
|
||||||
|
while(size < Size())
|
||||||
|
RemoveBuffer(Size()-1);
|
||||||
|
|
||||||
|
s32 oldSize = Size();
|
||||||
|
|
||||||
|
SoundBuffer.resize(size);
|
||||||
|
BufferSize.resize(size);
|
||||||
|
BufferReady.resize(size);
|
||||||
|
|
||||||
|
for(s32 i = oldSize; i < Size(); i++)
|
||||||
|
{
|
||||||
|
if(BufferBlockSize > 0)
|
||||||
|
SoundBuffer[i] = (u8 *) memalign(32, ALIGN32(BufferBlockSize));
|
||||||
|
else
|
||||||
|
SoundBuffer[i] = NULL;
|
||||||
|
BufferSize[i] = 0;
|
||||||
|
BufferReady[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BufferCircle::RemoveBuffer(s32 pos)
|
||||||
|
{
|
||||||
|
if(!Valid(pos))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(SoundBuffer[pos] != NULL)
|
||||||
|
free(SoundBuffer[pos]);
|
||||||
|
|
||||||
|
SoundBuffer.erase(SoundBuffer.begin()+pos);
|
||||||
|
BufferSize.erase(BufferSize.begin()+pos);
|
||||||
|
BufferReady.erase(BufferReady.begin()+pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BufferCircle::ClearBuffer()
|
||||||
|
{
|
||||||
|
for(s32 i = 0; i < Size(); i++)
|
||||||
|
{
|
||||||
|
BufferSize[i] = 0;
|
||||||
|
BufferReady[i] = false;
|
||||||
|
}
|
||||||
|
which = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BufferCircle::FreeBuffer()
|
||||||
|
{
|
||||||
|
for(s32 i = 0; i < Size(); i++)
|
||||||
|
{
|
||||||
|
if(SoundBuffer[i] != NULL)
|
||||||
|
free(SoundBuffer[i]);
|
||||||
|
|
||||||
|
SoundBuffer[i] = NULL;
|
||||||
|
BufferSize[i] = 0;
|
||||||
|
BufferReady[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BufferCircle::LoadNext()
|
||||||
|
{
|
||||||
|
BufferReady[which] = false;
|
||||||
|
BufferSize[which] = 0;
|
||||||
|
|
||||||
|
which = Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BufferCircle::SetBufferReady(s32 pos, bool state)
|
||||||
|
{
|
||||||
|
if(!Valid(pos))
|
||||||
|
return;
|
||||||
|
|
||||||
|
BufferReady[pos] = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BufferCircle::SetBufferSize(s32 pos, s32 size)
|
||||||
|
{
|
||||||
|
if(!Valid(pos))
|
||||||
|
return;
|
||||||
|
|
||||||
|
BufferSize[pos] = size;
|
||||||
|
}
|
86
source/sounds/BufferCircle.hpp
Normal file
86
source/sounds/BufferCircle.hpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010
|
||||||
|
* by Dimok
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* for WiiXplorer 2010
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef BUFFER_CIRCLE_HPP_
|
||||||
|
#define BUFFER_CIRCLE_HPP_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <dynamic_libs/os_types.h>
|
||||||
|
|
||||||
|
class BufferCircle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//!> Constructor
|
||||||
|
BufferCircle();
|
||||||
|
//!> Destructor
|
||||||
|
~BufferCircle();
|
||||||
|
//!> Set circle size
|
||||||
|
void Resize(s32 size);
|
||||||
|
//!> Get the circle size
|
||||||
|
s32 Size() { return SoundBuffer.size(); };
|
||||||
|
//!> Set/resize the buffer size
|
||||||
|
void SetBufferBlockSize(s32 size);
|
||||||
|
//!> Remove a buffer
|
||||||
|
void RemoveBuffer(s32 pos);
|
||||||
|
//!> Set all buffers clear
|
||||||
|
void ClearBuffer();
|
||||||
|
//!> Free all buffers
|
||||||
|
void FreeBuffer();
|
||||||
|
//!> Switch to next buffer
|
||||||
|
void LoadNext();
|
||||||
|
//!> Get the current buffer
|
||||||
|
u8 * GetBuffer() { return GetBuffer(which); };
|
||||||
|
//!> Get a buffer at a position
|
||||||
|
u8 * GetBuffer(s32 pos) { if(!Valid(pos)) return NULL; else return SoundBuffer[pos]; };
|
||||||
|
//!> Get current buffer size
|
||||||
|
u32 GetBufferSize() { return GetBufferSize(which); };
|
||||||
|
//!> Get buffer size at position
|
||||||
|
u32 GetBufferSize(s32 pos) { if(!Valid(pos)) return 0; else return BufferSize[pos]; };
|
||||||
|
//!> Is current buffer ready
|
||||||
|
bool IsBufferReady() { return IsBufferReady(which); };
|
||||||
|
//!> Is a buffer at a position ready
|
||||||
|
bool IsBufferReady(s32 pos) { if(!Valid(pos)) return false; else return BufferReady[pos]; };
|
||||||
|
//!> Set a buffer at a position to a ready state
|
||||||
|
void SetBufferReady(s32 pos, bool st);
|
||||||
|
//!> Set the buffersize at a position
|
||||||
|
void SetBufferSize(s32 pos, s32 size);
|
||||||
|
//!> Get the current position in the circle
|
||||||
|
u16 Which() { return which; };
|
||||||
|
|
||||||
|
//!> Get the next location
|
||||||
|
inline u16 Next() { return (which+1 >= Size()) ? 0 : which+1; }
|
||||||
|
inline u16 Prev() { if(Size() == 0) return 0; else return ((s32)which-1 < 0) ? Size()-1 : which-1; }
|
||||||
|
protected:
|
||||||
|
//!> Check if the position is a valid position in the vector
|
||||||
|
bool Valid(s32 pos) { return !(pos < 0 || pos >= Size()); };
|
||||||
|
|
||||||
|
u16 which;
|
||||||
|
u32 BufferBlockSize;
|
||||||
|
std::vector<u8 *> SoundBuffer;
|
||||||
|
std::vector<u32> BufferSize;
|
||||||
|
std::vector<bool> BufferReady;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
217
source/sounds/Mp3Decoder.cpp
Normal file
217
source/sounds/Mp3Decoder.cpp
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010
|
||||||
|
* by Dimok
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* for WiiXplorer 2010
|
||||||
|
***************************************************************************/
|
||||||
|
#include <string>
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <dynamic_libs/os_functions.h>
|
||||||
|
#include "Mp3Decoder.hpp"
|
||||||
|
|
||||||
|
Mp3Decoder::Mp3Decoder(const char * filepath)
|
||||||
|
: SoundDecoder(filepath)
|
||||||
|
{
|
||||||
|
SoundType = SOUND_MP3;
|
||||||
|
ReadBuffer = NULL;
|
||||||
|
mad_timer_reset(&Timer);
|
||||||
|
mad_stream_init(&Stream);
|
||||||
|
mad_frame_init(&Frame);
|
||||||
|
mad_synth_init(&Synth);
|
||||||
|
|
||||||
|
if(!file_fd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
OpenFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
Mp3Decoder::Mp3Decoder(const u8 * snd, s32 len)
|
||||||
|
: SoundDecoder(snd, len)
|
||||||
|
{
|
||||||
|
SoundType = SOUND_MP3;
|
||||||
|
ReadBuffer = NULL;
|
||||||
|
mad_timer_reset(&Timer);
|
||||||
|
mad_stream_init(&Stream);
|
||||||
|
mad_frame_init(&Frame);
|
||||||
|
mad_synth_init(&Synth);
|
||||||
|
|
||||||
|
if(!file_fd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
OpenFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
Mp3Decoder::~Mp3Decoder()
|
||||||
|
{
|
||||||
|
ExitRequested = true;
|
||||||
|
while(Decoding)
|
||||||
|
os_usleep(100);
|
||||||
|
|
||||||
|
mad_synth_finish(&Synth);
|
||||||
|
mad_frame_finish(&Frame);
|
||||||
|
mad_stream_finish(&Stream);
|
||||||
|
|
||||||
|
if(ReadBuffer)
|
||||||
|
free(ReadBuffer);
|
||||||
|
ReadBuffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mp3Decoder::OpenFile()
|
||||||
|
{
|
||||||
|
GuardPtr = NULL;
|
||||||
|
ReadBuffer = (u8 *) memalign(32, SoundBlockSize*SoundBlocks);
|
||||||
|
if(!ReadBuffer)
|
||||||
|
{
|
||||||
|
if(file_fd)
|
||||||
|
delete file_fd;
|
||||||
|
file_fd = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 dummybuff[4096];
|
||||||
|
s32 ret = Read(dummybuff, 4096, 0);
|
||||||
|
if(ret <= 0)
|
||||||
|
{
|
||||||
|
if(file_fd)
|
||||||
|
delete file_fd;
|
||||||
|
file_fd = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SampleRate = (u32) Frame.header.samplerate;
|
||||||
|
Format = ((MAD_NCHANNELS(&Frame.header) == 2) ? (FORMAT_PCM_16_BIT | CHANNELS_STEREO) : (FORMAT_PCM_16_BIT | CHANNELS_MONO));
|
||||||
|
Rewind();
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Mp3Decoder::Rewind()
|
||||||
|
{
|
||||||
|
mad_synth_finish(&Synth);
|
||||||
|
mad_frame_finish(&Frame);
|
||||||
|
mad_stream_finish(&Stream);
|
||||||
|
mad_timer_reset(&Timer);
|
||||||
|
mad_stream_init(&Stream);
|
||||||
|
mad_frame_init(&Frame);
|
||||||
|
mad_synth_init(&Synth);
|
||||||
|
SynthPos = 0;
|
||||||
|
GuardPtr = NULL;
|
||||||
|
|
||||||
|
if(!file_fd)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return SoundDecoder::Rewind();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline s16 FixedToShort(mad_fixed_t Fixed)
|
||||||
|
{
|
||||||
|
/* Clipping */
|
||||||
|
if(Fixed>=MAD_F_ONE)
|
||||||
|
return(SHRT_MAX);
|
||||||
|
if(Fixed<=-MAD_F_ONE)
|
||||||
|
return(-SHRT_MAX);
|
||||||
|
|
||||||
|
Fixed=Fixed>>(MAD_F_FRACBITS-15);
|
||||||
|
return((s16)Fixed);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Mp3Decoder::Read(u8 * buffer, s32 buffer_size, s32 pos)
|
||||||
|
{
|
||||||
|
if(!file_fd)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(Format == (FORMAT_PCM_16_BIT | CHANNELS_STEREO))
|
||||||
|
buffer_size &= ~0x0003;
|
||||||
|
else
|
||||||
|
buffer_size &= ~0x0001;
|
||||||
|
|
||||||
|
u8 * write_pos = buffer;
|
||||||
|
u8 * write_end = buffer+buffer_size;
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
while(SynthPos < Synth.pcm.length)
|
||||||
|
{
|
||||||
|
if(write_pos >= write_end)
|
||||||
|
return write_pos-buffer;
|
||||||
|
|
||||||
|
*((s16 *) write_pos) = FixedToShort(Synth.pcm.samples[0][SynthPos]);
|
||||||
|
write_pos += 2;
|
||||||
|
|
||||||
|
if(MAD_NCHANNELS(&Frame.header) == 2)
|
||||||
|
{
|
||||||
|
*((s16 *) write_pos) = FixedToShort(Synth.pcm.samples[1][SynthPos]);
|
||||||
|
write_pos += 2;
|
||||||
|
}
|
||||||
|
SynthPos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Stream.buffer == NULL || Stream.error == MAD_ERROR_BUFLEN)
|
||||||
|
{
|
||||||
|
u8 * ReadStart = ReadBuffer;
|
||||||
|
s32 ReadSize = SoundBlockSize*SoundBlocks;
|
||||||
|
s32 Remaining = 0;
|
||||||
|
|
||||||
|
if(Stream.next_frame != NULL)
|
||||||
|
{
|
||||||
|
Remaining = Stream.bufend - Stream.next_frame;
|
||||||
|
memmove(ReadBuffer, Stream.next_frame, Remaining);
|
||||||
|
ReadStart += Remaining;
|
||||||
|
ReadSize -= Remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadSize = file_fd->read(ReadStart, ReadSize);
|
||||||
|
if(ReadSize <= 0)
|
||||||
|
{
|
||||||
|
GuardPtr = ReadStart;
|
||||||
|
memset(GuardPtr, 0, MAD_BUFFER_GUARD);
|
||||||
|
ReadSize = MAD_BUFFER_GUARD;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurPos += ReadSize;
|
||||||
|
mad_stream_buffer(&Stream, ReadBuffer, Remaining+ReadSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mad_frame_decode(&Frame,&Stream))
|
||||||
|
{
|
||||||
|
if(MAD_RECOVERABLE(Stream.error))
|
||||||
|
{
|
||||||
|
if(Stream.error != MAD_ERROR_LOSTSYNC || !GuardPtr)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(Stream.error != MAD_ERROR_BUFLEN)
|
||||||
|
return -1;
|
||||||
|
else if(Stream.error == MAD_ERROR_BUFLEN && GuardPtr)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mad_timer_add(&Timer,Frame.header.duration);
|
||||||
|
mad_synth_frame(&Synth,&Frame);
|
||||||
|
SynthPos = 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
47
source/sounds/Mp3Decoder.hpp
Normal file
47
source/sounds/Mp3Decoder.hpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010
|
||||||
|
* by Dimok
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* for WiiXplorer 2010
|
||||||
|
***************************************************************************/
|
||||||
|
#include <mad.h>
|
||||||
|
|
||||||
|
#include "SoundDecoder.hpp"
|
||||||
|
|
||||||
|
class Mp3Decoder : public SoundDecoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Mp3Decoder(const char * filepath);
|
||||||
|
Mp3Decoder(const u8 * sound, s32 len);
|
||||||
|
virtual ~Mp3Decoder();
|
||||||
|
s32 Rewind();
|
||||||
|
s32 Read(u8 * buffer, s32 buffer_size, s32 pos);
|
||||||
|
protected:
|
||||||
|
void OpenFile();
|
||||||
|
struct mad_stream Stream;
|
||||||
|
struct mad_frame Frame;
|
||||||
|
struct mad_synth Synth;
|
||||||
|
mad_timer_t Timer;
|
||||||
|
u8 * GuardPtr;
|
||||||
|
u8 * ReadBuffer;
|
||||||
|
u32 SynthPos;
|
||||||
|
};
|
138
source/sounds/OggDecoder.cpp
Normal file
138
source/sounds/OggDecoder.cpp
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010
|
||||||
|
* by Dimok
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* for WiiXplorer 2010
|
||||||
|
***************************************************************************/
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <dynamic_libs/os_functions.h>
|
||||||
|
#include "OggDecoder.hpp"
|
||||||
|
|
||||||
|
static int ogg_read(void * punt, int bytes, int blocks, int *f)
|
||||||
|
{
|
||||||
|
return ((CFile *) f)->read((u8 *) punt, bytes*blocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ogg_seek(int *f, ogg_int64_t offset, int mode)
|
||||||
|
{
|
||||||
|
return ((CFile *) f)->seek((u64) offset, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ogg_close(int *f)
|
||||||
|
{
|
||||||
|
((CFile *) f)->close();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long ogg_tell(int *f)
|
||||||
|
{
|
||||||
|
return (long) ((CFile *) f)->tell();
|
||||||
|
}
|
||||||
|
|
||||||
|
static ov_callbacks callbacks = {
|
||||||
|
(size_t (*)(void *, size_t, size_t, void *)) ogg_read,
|
||||||
|
(int (*)(void *, ogg_int64_t, int)) ogg_seek,
|
||||||
|
(int (*)(void *)) ogg_close,
|
||||||
|
(long (*)(void *)) ogg_tell
|
||||||
|
};
|
||||||
|
|
||||||
|
OggDecoder::OggDecoder(const char * filepath)
|
||||||
|
: SoundDecoder(filepath)
|
||||||
|
{
|
||||||
|
SoundType = SOUND_OGG;
|
||||||
|
|
||||||
|
if(!file_fd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
OpenFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
OggDecoder::OggDecoder(const u8 * snd, s32 len)
|
||||||
|
: SoundDecoder(snd, len)
|
||||||
|
{
|
||||||
|
SoundType = SOUND_OGG;
|
||||||
|
|
||||||
|
if(!file_fd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
OpenFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
OggDecoder::~OggDecoder()
|
||||||
|
{
|
||||||
|
ExitRequested = true;
|
||||||
|
while(Decoding)
|
||||||
|
os_usleep(100);
|
||||||
|
|
||||||
|
if(file_fd)
|
||||||
|
ov_clear(&ogg_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OggDecoder::OpenFile()
|
||||||
|
{
|
||||||
|
if (ov_open_callbacks(file_fd, &ogg_file, NULL, 0, callbacks) < 0)
|
||||||
|
{
|
||||||
|
delete file_fd;
|
||||||
|
file_fd = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ogg_info = ov_info(&ogg_file, -1);
|
||||||
|
if(!ogg_info)
|
||||||
|
{
|
||||||
|
ov_clear(&ogg_file);
|
||||||
|
delete file_fd;
|
||||||
|
file_fd = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Format = ((ogg_info->channels == 2) ? (FORMAT_PCM_16_BIT | CHANNELS_STEREO) : (FORMAT_PCM_16_BIT | CHANNELS_MONO));
|
||||||
|
SampleRate = ogg_info->rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 OggDecoder::Rewind()
|
||||||
|
{
|
||||||
|
if(!file_fd)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
s32 ret = ov_time_seek(&ogg_file, 0);
|
||||||
|
CurPos = 0;
|
||||||
|
EndOfFile = false;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 OggDecoder::Read(u8 * buffer, s32 buffer_size, s32 pos)
|
||||||
|
{
|
||||||
|
if(!file_fd)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
s32 bitstream = 0;
|
||||||
|
|
||||||
|
s32 read = (s32) ov_read(&ogg_file, (char *) buffer, (int) buffer_size, (int *)&bitstream);
|
||||||
|
|
||||||
|
if(read > 0)
|
||||||
|
CurPos += read;
|
||||||
|
|
||||||
|
return read;
|
||||||
|
}
|
43
source/sounds/OggDecoder.hpp
Normal file
43
source/sounds/OggDecoder.hpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010
|
||||||
|
* by Dimok
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* for WiiXplorer 2010
|
||||||
|
***************************************************************************/
|
||||||
|
#include <tremor/ivorbiscodec.h>
|
||||||
|
#include <tremor/ivorbisfile.h>
|
||||||
|
|
||||||
|
#include "SoundDecoder.hpp"
|
||||||
|
|
||||||
|
class OggDecoder : public SoundDecoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OggDecoder(const char * filepath);
|
||||||
|
OggDecoder(const u8 * snd, s32 len);
|
||||||
|
virtual ~OggDecoder();
|
||||||
|
s32 Rewind();
|
||||||
|
s32 Read(u8 * buffer, s32 buffer_size, s32 pos);
|
||||||
|
protected:
|
||||||
|
void OpenFile();
|
||||||
|
OggVorbis_File ogg_file;
|
||||||
|
vorbis_info *ogg_info;
|
||||||
|
};
|
225
source/sounds/SoundDecoder.cpp
Normal file
225
source/sounds/SoundDecoder.cpp
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2009-2013 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dynamic_libs/os_functions.h>
|
||||||
|
#include "SoundDecoder.hpp"
|
||||||
|
|
||||||
|
static const u32 FixedPointShift = 15;
|
||||||
|
static const u32 FixedPointScale = 1 << FixedPointShift;
|
||||||
|
|
||||||
|
SoundDecoder::SoundDecoder()
|
||||||
|
{
|
||||||
|
file_fd = NULL;
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundDecoder::SoundDecoder(const std::string & filepath)
|
||||||
|
{
|
||||||
|
file_fd = new CFile(filepath, CFile::ReadOnly);
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundDecoder::SoundDecoder(const u8 * buffer, s32 size)
|
||||||
|
{
|
||||||
|
file_fd = new CFile(buffer, size);
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundDecoder::~SoundDecoder()
|
||||||
|
{
|
||||||
|
ExitRequested = true;
|
||||||
|
while(Decoding)
|
||||||
|
os_usleep(1000);
|
||||||
|
|
||||||
|
//! lock unlock once to make sure it's really not decoding
|
||||||
|
Lock();
|
||||||
|
Unlock();
|
||||||
|
|
||||||
|
if(file_fd)
|
||||||
|
delete file_fd;
|
||||||
|
file_fd = NULL;
|
||||||
|
|
||||||
|
if(ResampleBuffer)
|
||||||
|
free(ResampleBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundDecoder::Init()
|
||||||
|
{
|
||||||
|
SoundType = SOUND_RAW;
|
||||||
|
SoundBlocks = 8;
|
||||||
|
SoundBlockSize = 0x4000;
|
||||||
|
ResampleTo48kHz = false;
|
||||||
|
CurPos = 0;
|
||||||
|
whichLoad = 0;
|
||||||
|
Loop = false;
|
||||||
|
EndOfFile = false;
|
||||||
|
Decoding = false;
|
||||||
|
ExitRequested = false;
|
||||||
|
SoundBuffer.SetBufferBlockSize(SoundBlockSize);
|
||||||
|
SoundBuffer.Resize(SoundBlocks);
|
||||||
|
ResampleBuffer = NULL;
|
||||||
|
ResampleRatio = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 SoundDecoder::Rewind()
|
||||||
|
{
|
||||||
|
CurPos = 0;
|
||||||
|
EndOfFile = false;
|
||||||
|
file_fd->rewind();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 SoundDecoder::Read(u8 * buffer, s32 buffer_size, s32 pos)
|
||||||
|
{
|
||||||
|
s32 ret = file_fd->read(buffer, buffer_size);
|
||||||
|
CurPos += ret;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundDecoder::EnableUpsample(void)
|
||||||
|
{
|
||||||
|
if( (ResampleBuffer == NULL)
|
||||||
|
&& IsStereo() && Is16Bit()
|
||||||
|
&& SampleRate != 32000
|
||||||
|
&& SampleRate != 48000)
|
||||||
|
{
|
||||||
|
ResampleBuffer = (u8*)memalign(32, SoundBlockSize);
|
||||||
|
ResampleRatio = ( FixedPointScale * SampleRate ) / 48000;
|
||||||
|
SoundBlockSize = ( SoundBlockSize * ResampleRatio ) / FixedPointScale;
|
||||||
|
SoundBlockSize &= ~0x03;
|
||||||
|
// set new sample rate
|
||||||
|
SampleRate = 48000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundDecoder::Upsample(s16 *src, s16 *dst, u32 nr_src_samples, u32 nr_dst_samples)
|
||||||
|
{
|
||||||
|
s32 timer = 0;
|
||||||
|
|
||||||
|
for(u32 i = 0, n = 0; i < nr_dst_samples; i += 2)
|
||||||
|
{
|
||||||
|
if((n+3) < nr_src_samples) {
|
||||||
|
// simple fixed point linear interpolation
|
||||||
|
dst[i] = src[n] + ( ((src[n+2] - src[n] ) * timer) >> FixedPointShift );
|
||||||
|
dst[i+1] = src[n+1] + ( ((src[n+3] - src[n+1]) * timer) >> FixedPointShift );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dst[i] = src[n];
|
||||||
|
dst[i+1] = src[n+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
timer += ResampleRatio;
|
||||||
|
|
||||||
|
if(timer >= (s32)FixedPointScale) {
|
||||||
|
n += 2;
|
||||||
|
timer -= FixedPointScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundDecoder::Decode()
|
||||||
|
{
|
||||||
|
if(!file_fd || ExitRequested || EndOfFile)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// check if we are not at the pre-last buffer (last buffer is playing)
|
||||||
|
u16 whichPlaying = SoundBuffer.Which();
|
||||||
|
if( ((whichPlaying == 0) && (whichLoad == SoundBuffer.Size()-2))
|
||||||
|
|| ((whichPlaying == 1) && (whichLoad == SoundBuffer.Size()-1))
|
||||||
|
|| (whichLoad == (whichPlaying-2)))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Decoding = true;
|
||||||
|
|
||||||
|
s32 done = 0;
|
||||||
|
u8 * write_buf = SoundBuffer.GetBuffer(whichLoad);
|
||||||
|
if(!write_buf)
|
||||||
|
{
|
||||||
|
ExitRequested = true;
|
||||||
|
Decoding = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ResampleTo48kHz && !ResampleBuffer)
|
||||||
|
EnableUpsample();
|
||||||
|
|
||||||
|
while(done < SoundBlockSize)
|
||||||
|
{
|
||||||
|
s32 ret = Read(&write_buf[done], SoundBlockSize-done, Tell());
|
||||||
|
|
||||||
|
if(ret <= 0)
|
||||||
|
{
|
||||||
|
if(Loop)
|
||||||
|
{
|
||||||
|
Rewind();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EndOfFile = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done += ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(done > 0)
|
||||||
|
{
|
||||||
|
// check if we need to resample
|
||||||
|
if(ResampleBuffer && ResampleRatio)
|
||||||
|
{
|
||||||
|
memcpy(ResampleBuffer, write_buf, done);
|
||||||
|
|
||||||
|
s32 src_samples = done >> 1;
|
||||||
|
s32 dest_samples = ( src_samples * FixedPointScale ) / ResampleRatio;
|
||||||
|
dest_samples &= ~0x01;
|
||||||
|
Upsample((s16*)ResampleBuffer, (s16*)write_buf, src_samples, dest_samples);
|
||||||
|
done = dest_samples << 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! TODO: remove this later and add STEREO support with two voices, for now we convert to MONO
|
||||||
|
if(IsStereo())
|
||||||
|
{
|
||||||
|
s16* monoBuf = (s16*)write_buf;
|
||||||
|
done = done >> 1;
|
||||||
|
|
||||||
|
for(s32 i = 0; i < done; i++)
|
||||||
|
monoBuf[i] = monoBuf[i << 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
DCFlushRange(write_buf, done);
|
||||||
|
SoundBuffer.SetBufferSize(whichLoad, done);
|
||||||
|
SoundBuffer.SetBufferReady(whichLoad, true);
|
||||||
|
if(++whichLoad >= SoundBuffer.Size())
|
||||||
|
whichLoad = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if next in queue needs to be filled as well and do so
|
||||||
|
if(!SoundBuffer.IsBufferReady(whichLoad))
|
||||||
|
Decode();
|
||||||
|
|
||||||
|
Decoding = false;
|
||||||
|
}
|
||||||
|
|
105
source/sounds/SoundDecoder.hpp
Normal file
105
source/sounds/SoundDecoder.hpp
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010
|
||||||
|
* by Dimok
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* for WiiXplorer 2010
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef SOUND_DECODER_HPP
|
||||||
|
#define SOUND_DECODER_HPP
|
||||||
|
|
||||||
|
#include <fs/CFile.hpp>
|
||||||
|
#include <system/CMutex.h>
|
||||||
|
#include "BufferCircle.hpp"
|
||||||
|
|
||||||
|
class SoundDecoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SoundDecoder();
|
||||||
|
SoundDecoder(const std::string & filepath);
|
||||||
|
SoundDecoder(const u8 * buffer, s32 size);
|
||||||
|
virtual ~SoundDecoder();
|
||||||
|
virtual void Lock() { mutex.lock(); }
|
||||||
|
virtual void Unlock() { mutex.unlock(); }
|
||||||
|
virtual s32 Read(u8 * buffer, s32 buffer_size, s32 pos);
|
||||||
|
virtual s32 Tell() { return CurPos; }
|
||||||
|
virtual s32 Seek(s32 pos) { CurPos = pos; return file_fd->seek(CurPos, SEEK_SET); }
|
||||||
|
virtual s32 Rewind();
|
||||||
|
virtual u16 GetFormat() { return Format; }
|
||||||
|
virtual u16 GetSampleRate() { return SampleRate; }
|
||||||
|
virtual void Decode();
|
||||||
|
virtual bool IsBufferReady() { return SoundBuffer.IsBufferReady(); }
|
||||||
|
virtual u8 * GetBuffer() { return SoundBuffer.GetBuffer(); }
|
||||||
|
virtual u32 GetBufferSize() { return SoundBuffer.GetBufferSize(); }
|
||||||
|
virtual void LoadNext() { SoundBuffer.LoadNext(); }
|
||||||
|
virtual bool IsEOF() { return EndOfFile; }
|
||||||
|
virtual void SetLoop(bool l) { Loop = l; EndOfFile = false; }
|
||||||
|
virtual u8 GetSoundType() { return SoundType; }
|
||||||
|
virtual void ClearBuffer() { SoundBuffer.ClearBuffer(); whichLoad = 0; }
|
||||||
|
virtual bool IsStereo() { return (GetFormat() & CHANNELS_STEREO) != 0; }
|
||||||
|
virtual bool Is16Bit() { return ((GetFormat() & 0xFF) == FORMAT_PCM_16_BIT); }
|
||||||
|
virtual bool IsDecoding() { return Decoding; }
|
||||||
|
|
||||||
|
void EnableUpsample(void);
|
||||||
|
|
||||||
|
enum SoundFormats
|
||||||
|
{
|
||||||
|
FORMAT_PCM_16_BIT = 0x0A,
|
||||||
|
FORMAT_PCM_8_BIT = 0x19,
|
||||||
|
};
|
||||||
|
enum SoundChannels
|
||||||
|
{
|
||||||
|
CHANNELS_MONO = 0x100,
|
||||||
|
CHANNELS_STEREO = 0x200
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SoundType
|
||||||
|
{
|
||||||
|
SOUND_RAW = 0,
|
||||||
|
SOUND_MP3,
|
||||||
|
SOUND_OGG,
|
||||||
|
SOUND_WAV
|
||||||
|
};
|
||||||
|
protected:
|
||||||
|
void Init();
|
||||||
|
void Upsample(s16 *src, s16 *dst, u32 nr_src_samples, u32 nr_dst_samples);
|
||||||
|
|
||||||
|
CFile * file_fd;
|
||||||
|
BufferCircle SoundBuffer;
|
||||||
|
u8 SoundType;
|
||||||
|
u16 whichLoad;
|
||||||
|
u16 SoundBlocks;
|
||||||
|
s32 SoundBlockSize;
|
||||||
|
s32 CurPos;
|
||||||
|
bool ResampleTo48kHz;
|
||||||
|
bool Loop;
|
||||||
|
bool EndOfFile;
|
||||||
|
bool Decoding;
|
||||||
|
bool ExitRequested;
|
||||||
|
u16 Format;
|
||||||
|
u16 SampleRate;
|
||||||
|
u8 *ResampleBuffer;
|
||||||
|
u32 ResampleRatio;
|
||||||
|
CMutex mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
351
source/sounds/SoundHandler.cpp
Normal file
351
source/sounds/SoundHandler.cpp
Normal file
@ -0,0 +1,351 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010
|
||||||
|
* by Dimok
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* for WiiXplorer 2010
|
||||||
|
***************************************************************************/
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
//#include "common/common.h"
|
||||||
|
#include <dynamic_libs/ax_functions.h>
|
||||||
|
#include "fs/CFile.hpp"
|
||||||
|
#include "SoundHandler.hpp"
|
||||||
|
#include "WavDecoder.hpp"
|
||||||
|
#include "Mp3Decoder.hpp"
|
||||||
|
#include "OggDecoder.hpp"
|
||||||
|
|
||||||
|
SoundHandler * SoundHandler::handlerInstance = NULL;
|
||||||
|
|
||||||
|
SoundHandler::SoundHandler()
|
||||||
|
: CThread(CThread::eAttributeAffCore1 | CThread::eAttributePinnedAff, 0, 0x8000)
|
||||||
|
{
|
||||||
|
Decoding = false;
|
||||||
|
ExitRequested = false;
|
||||||
|
for(u32 i = 0; i < MAX_DECODERS; ++i)
|
||||||
|
{
|
||||||
|
DecoderList[i] = NULL;
|
||||||
|
voiceList[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
resumeThread();
|
||||||
|
|
||||||
|
//! wait for initialization
|
||||||
|
while(!isThreadSuspended())
|
||||||
|
os_usleep(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundHandler::~SoundHandler()
|
||||||
|
{
|
||||||
|
ExitRequested = true;
|
||||||
|
ThreadSignal();
|
||||||
|
|
||||||
|
ClearDecoderList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundHandler::AddDecoder(s32 voice, const char * filepath)
|
||||||
|
{
|
||||||
|
if(voice < 0 || voice >= MAX_DECODERS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(DecoderList[voice] != NULL)
|
||||||
|
RemoveDecoder(voice);
|
||||||
|
|
||||||
|
DecoderList[voice] = GetSoundDecoder(filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundHandler::AddDecoder(s32 voice, const u8 * snd, s32 len)
|
||||||
|
{
|
||||||
|
if(voice < 0 || voice >= MAX_DECODERS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(DecoderList[voice] != NULL)
|
||||||
|
RemoveDecoder(voice);
|
||||||
|
|
||||||
|
DecoderList[voice] = GetSoundDecoder(snd, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundHandler::RemoveDecoder(s32 voice)
|
||||||
|
{
|
||||||
|
if(voice < 0 || voice >= MAX_DECODERS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(DecoderList[voice] != NULL)
|
||||||
|
{
|
||||||
|
if(voiceList[voice] && voiceList[voice]->getState() != Voice::STATE_STOPPED)
|
||||||
|
{
|
||||||
|
if(voiceList[voice]->getState() != Voice::STATE_STOP)
|
||||||
|
voiceList[voice]->setState(Voice::STATE_STOP);
|
||||||
|
|
||||||
|
while(voiceList[voice]->getState() != Voice::STATE_STOPPED)
|
||||||
|
os_usleep(1000);
|
||||||
|
}
|
||||||
|
SoundDecoder *decoder = DecoderList[voice];
|
||||||
|
decoder->Lock();
|
||||||
|
DecoderList[voice] = NULL;
|
||||||
|
decoder->Unlock();
|
||||||
|
delete decoder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundHandler::ClearDecoderList()
|
||||||
|
{
|
||||||
|
for(u32 i = 0; i < MAX_DECODERS; ++i)
|
||||||
|
RemoveDecoder(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool CheckMP3Signature(const u8 * buffer)
|
||||||
|
{
|
||||||
|
const char MP3_Magic[][3] =
|
||||||
|
{
|
||||||
|
{'I', 'D', '3'}, //'ID3'
|
||||||
|
{0xff, 0xfe}, //'MPEG ADTS, layer III, v1.0 [protected]', 'mp3', 'audio/mpeg'),
|
||||||
|
{0xff, 0xff}, //'MPEG ADTS, layer III, v1.0', 'mp3', 'audio/mpeg'),
|
||||||
|
{0xff, 0xfa}, //'MPEG ADTS, layer III, v1.0 [protected]', 'mp3', 'audio/mpeg'),
|
||||||
|
{0xff, 0xfb}, //'MPEG ADTS, layer III, v1.0', 'mp3', 'audio/mpeg'),
|
||||||
|
{0xff, 0xf2}, //'MPEG ADTS, layer III, v2.0 [protected]', 'mp3', 'audio/mpeg'),
|
||||||
|
{0xff, 0xf3}, //'MPEG ADTS, layer III, v2.0', 'mp3', 'audio/mpeg'),
|
||||||
|
{0xff, 0xf4}, //'MPEG ADTS, layer III, v2.0 [protected]', 'mp3', 'audio/mpeg'),
|
||||||
|
{0xff, 0xf5}, //'MPEG ADTS, layer III, v2.0', 'mp3', 'audio/mpeg'),
|
||||||
|
{0xff, 0xf6}, //'MPEG ADTS, layer III, v2.0 [protected]', 'mp3', 'audio/mpeg'),
|
||||||
|
{0xff, 0xf7}, //'MPEG ADTS, layer III, v2.0', 'mp3', 'audio/mpeg'),
|
||||||
|
{0xff, 0xe2}, //'MPEG ADTS, layer III, v2.5 [protected]', 'mp3', 'audio/mpeg'),
|
||||||
|
{0xff, 0xe3}, //'MPEG ADTS, layer III, v2.5', 'mp3', 'audio/mpeg'),
|
||||||
|
};
|
||||||
|
|
||||||
|
if(buffer[0] == MP3_Magic[0][0] && buffer[1] == MP3_Magic[0][1] &&
|
||||||
|
buffer[2] == MP3_Magic[0][2])
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(s32 i = 1; i < 13; i++)
|
||||||
|
{
|
||||||
|
if(buffer[0] == MP3_Magic[i][0] && buffer[1] == MP3_Magic[i][1])
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundDecoder * SoundHandler::GetSoundDecoder(const char * filepath)
|
||||||
|
{
|
||||||
|
u32 magic;
|
||||||
|
CFile f(filepath, CFile::ReadOnly);
|
||||||
|
if(f.size() == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
f.read((u8 *) &magic, 1);
|
||||||
|
}
|
||||||
|
while(((u8 *) &magic)[0] == 0 && f.tell() < f.size());
|
||||||
|
|
||||||
|
if(f.tell() == f.size())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
f.seek(f.tell()-1, SEEK_SET);
|
||||||
|
f.read((u8 *) &magic, 4);
|
||||||
|
f.close();
|
||||||
|
|
||||||
|
if(magic == 0x4f676753) // 'OggS'
|
||||||
|
{
|
||||||
|
return new OggDecoder(filepath);
|
||||||
|
}
|
||||||
|
else if(magic == 0x52494646) // 'RIFF'
|
||||||
|
{
|
||||||
|
return new WavDecoder(filepath);
|
||||||
|
}
|
||||||
|
else if(CheckMP3Signature((u8 *) &magic) == true)
|
||||||
|
{
|
||||||
|
return new Mp3Decoder(filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SoundDecoder(filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundDecoder * SoundHandler::GetSoundDecoder(const u8 * sound, s32 length)
|
||||||
|
{
|
||||||
|
const u8 * check = sound;
|
||||||
|
s32 counter = 0;
|
||||||
|
|
||||||
|
while(check[0] == 0 && counter < length)
|
||||||
|
{
|
||||||
|
check++;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(counter >= length)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
u32 * magic = (u32 *) check;
|
||||||
|
|
||||||
|
if(magic[0] == 0x4f676753) // 'OggS'
|
||||||
|
{
|
||||||
|
return new OggDecoder(sound, length);
|
||||||
|
}
|
||||||
|
else if(magic[0] == 0x52494646) // 'RIFF'
|
||||||
|
{
|
||||||
|
return new WavDecoder(sound, length);
|
||||||
|
}
|
||||||
|
else if(CheckMP3Signature(check) == true)
|
||||||
|
{
|
||||||
|
return new Mp3Decoder(sound, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SoundDecoder(sound, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundHandler::executeThread()
|
||||||
|
{
|
||||||
|
// v2 sound lib can not properly end transition audio on old firmwares
|
||||||
|
if (OS_FIRMWARE >= 400 && OS_FIRMWARE <= 410)
|
||||||
|
{
|
||||||
|
ProperlyEndTransitionAudio();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! initialize 48 kHz renderer
|
||||||
|
u32 params[3] = { 1, 0, 0 };
|
||||||
|
|
||||||
|
if(AXInitWithParams != 0)
|
||||||
|
AXInitWithParams(params);
|
||||||
|
else
|
||||||
|
AXInit();
|
||||||
|
|
||||||
|
// The problem with last voice on 500 was caused by it having priority 0
|
||||||
|
// We would need to change this priority distribution if for some reason
|
||||||
|
// we would need MAX_DECODERS > Voice::PRIO_MAX
|
||||||
|
for(u32 i = 0; i < MAX_DECODERS; ++i)
|
||||||
|
{
|
||||||
|
s32 priority = (MAX_DECODERS - i) * Voice::PRIO_MAX / MAX_DECODERS;
|
||||||
|
voiceList[i] = new Voice(priority); // allocate voice 0 with highest priority
|
||||||
|
}
|
||||||
|
|
||||||
|
AXRegisterFrameCallback((void*)&axFrameCallback);
|
||||||
|
|
||||||
|
|
||||||
|
u16 i = 0;
|
||||||
|
while (!ExitRequested)
|
||||||
|
{
|
||||||
|
suspendThread();
|
||||||
|
|
||||||
|
for(i = 0; i < MAX_DECODERS; ++i)
|
||||||
|
{
|
||||||
|
if(DecoderList[i] == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Decoding = true;
|
||||||
|
if(DecoderList[i])
|
||||||
|
DecoderList[i]->Lock();
|
||||||
|
if(DecoderList[i])
|
||||||
|
DecoderList[i]->Decode();
|
||||||
|
if(DecoderList[i])
|
||||||
|
DecoderList[i]->Unlock();
|
||||||
|
}
|
||||||
|
Decoding = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(u32 i = 0; i < MAX_DECODERS; ++i)
|
||||||
|
voiceList[i]->stop();
|
||||||
|
|
||||||
|
AXRegisterFrameCallback(NULL);
|
||||||
|
AXQuit();
|
||||||
|
|
||||||
|
for(u32 i = 0; i < MAX_DECODERS; ++i)
|
||||||
|
{
|
||||||
|
delete voiceList[i];
|
||||||
|
voiceList[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundHandler::axFrameCallback(void)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < MAX_DECODERS; i++)
|
||||||
|
{
|
||||||
|
Voice *voice = handlerInstance->getVoice(i);
|
||||||
|
|
||||||
|
switch (voice->getState())
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case Voice::STATE_STOPPED:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Voice::STATE_START: {
|
||||||
|
SoundDecoder * decoder = handlerInstance->getDecoder(i);
|
||||||
|
decoder->Lock();
|
||||||
|
if(decoder->IsBufferReady())
|
||||||
|
{
|
||||||
|
const u8 *buffer = decoder->GetBuffer();
|
||||||
|
const u32 bufferSize = decoder->GetBufferSize();
|
||||||
|
decoder->LoadNext();
|
||||||
|
|
||||||
|
const u8 *nextBuffer = NULL;
|
||||||
|
u32 nextBufferSize = 0;
|
||||||
|
|
||||||
|
if(decoder->IsBufferReady())
|
||||||
|
{
|
||||||
|
nextBuffer = decoder->GetBuffer();
|
||||||
|
nextBufferSize = decoder->GetBufferSize();
|
||||||
|
decoder->LoadNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
voice->play(buffer, bufferSize, nextBuffer, nextBufferSize, decoder->GetFormat() & 0xff, decoder->GetSampleRate());
|
||||||
|
|
||||||
|
handlerInstance->ThreadSignal();
|
||||||
|
|
||||||
|
voice->setState(Voice::STATE_PLAYING);
|
||||||
|
}
|
||||||
|
decoder->Unlock();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Voice::STATE_PLAYING:
|
||||||
|
if(voice->getInternState() == 1)
|
||||||
|
{
|
||||||
|
if(voice->isBufferSwitched())
|
||||||
|
{
|
||||||
|
SoundDecoder * decoder = handlerInstance->getDecoder(i);
|
||||||
|
decoder->Lock();
|
||||||
|
if(decoder->IsBufferReady())
|
||||||
|
{
|
||||||
|
voice->setNextBuffer(decoder->GetBuffer(), decoder->GetBufferSize());
|
||||||
|
decoder->LoadNext();
|
||||||
|
handlerInstance->ThreadSignal();
|
||||||
|
}
|
||||||
|
else if(decoder->IsEOF())
|
||||||
|
{
|
||||||
|
voice->setState(Voice::STATE_STOP);
|
||||||
|
}
|
||||||
|
decoder->Unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
voice->setState(Voice::STATE_STOPPED);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Voice::STATE_STOP:
|
||||||
|
if(voice->getInternState() != 0)
|
||||||
|
voice->stop();
|
||||||
|
voice->setState(Voice::STATE_STOPPED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
78
source/sounds/SoundHandler.hpp
Normal file
78
source/sounds/SoundHandler.hpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010
|
||||||
|
* by Dimok
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* for WiiXplorer 2010
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef SOUNDHANDLER_H_
|
||||||
|
#define SOUNDHANDLER_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <system/CThread.h>
|
||||||
|
#include "SoundDecoder.hpp"
|
||||||
|
#include "Voice.h"
|
||||||
|
|
||||||
|
#define MAX_DECODERS 16 // can be increased up to 96
|
||||||
|
|
||||||
|
class SoundHandler : public CThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static SoundHandler * instance() {
|
||||||
|
if (!handlerInstance)
|
||||||
|
handlerInstance = new SoundHandler();
|
||||||
|
return handlerInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DestroyInstance() { delete handlerInstance; handlerInstance = NULL; }
|
||||||
|
|
||||||
|
void AddDecoder(s32 voice, const char * filepath);
|
||||||
|
void AddDecoder(s32 voice, const u8 * snd, s32 len);
|
||||||
|
void RemoveDecoder(s32 voice);
|
||||||
|
|
||||||
|
SoundDecoder * getDecoder(s32 i) { return ((i < 0 || i >= MAX_DECODERS) ? NULL : DecoderList[i]); };
|
||||||
|
Voice * getVoice(s32 i) { return ((i < 0 || i >= MAX_DECODERS) ? NULL : voiceList[i]); };
|
||||||
|
|
||||||
|
void ThreadSignal() { resumeThread(); };
|
||||||
|
bool IsDecoding() { return Decoding; };
|
||||||
|
protected:
|
||||||
|
SoundHandler();
|
||||||
|
~SoundHandler();
|
||||||
|
|
||||||
|
static void axFrameCallback(void);
|
||||||
|
|
||||||
|
void executeThread(void);
|
||||||
|
void ClearDecoderList();
|
||||||
|
|
||||||
|
SoundDecoder * GetSoundDecoder(const char * filepath);
|
||||||
|
SoundDecoder * GetSoundDecoder(const u8 * sound, s32 length);
|
||||||
|
|
||||||
|
static SoundHandler * handlerInstance;
|
||||||
|
|
||||||
|
bool Decoding;
|
||||||
|
bool ExitRequested;
|
||||||
|
|
||||||
|
Voice * voiceList[MAX_DECODERS];
|
||||||
|
SoundDecoder * DecoderList[MAX_DECODERS];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
170
source/sounds/Voice.h
Normal file
170
source/sounds/Voice.h
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef _AXSOUND_H_
|
||||||
|
#define _AXSOUND_H_
|
||||||
|
|
||||||
|
#include <dynamic_libs/os_functions.h>
|
||||||
|
#include <dynamic_libs/ax_functions.h>
|
||||||
|
|
||||||
|
class Voice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum VoicePriorities
|
||||||
|
{
|
||||||
|
PRIO_MIN = 1,
|
||||||
|
PRIO_MAX = 31
|
||||||
|
};
|
||||||
|
|
||||||
|
enum VoiceStates
|
||||||
|
{
|
||||||
|
STATE_STOPPED,
|
||||||
|
STATE_START,
|
||||||
|
STATE_PLAYING,
|
||||||
|
STATE_STOP,
|
||||||
|
};
|
||||||
|
|
||||||
|
Voice(s32 prio)
|
||||||
|
: state(STATE_STOPPED)
|
||||||
|
{
|
||||||
|
lastLoopCounter = 0;
|
||||||
|
nextBufferSize = 0;
|
||||||
|
|
||||||
|
voice = AXAcquireVoice(prio, 0, 0);
|
||||||
|
if(voice)
|
||||||
|
{
|
||||||
|
AXVoiceBegin(voice);
|
||||||
|
AXSetVoiceType(voice, 0);
|
||||||
|
setVolume(0x80000000);
|
||||||
|
|
||||||
|
u32 mix[24];
|
||||||
|
memset(mix, 0, sizeof(mix));
|
||||||
|
mix[0] = 0x80000000;
|
||||||
|
mix[4] = 0x80000000;
|
||||||
|
|
||||||
|
AXSetVoiceDeviceMix(voice, 0, 0, mix);
|
||||||
|
AXSetVoiceDeviceMix(voice, 1, 0, mix);
|
||||||
|
|
||||||
|
AXVoiceEnd(voice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~Voice()
|
||||||
|
{
|
||||||
|
if(voice)
|
||||||
|
{
|
||||||
|
AXFreeVoice(voice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void play(const u8 *buffer, u32 bufferSize, const u8 *nextBuffer, u32 nextBufSize, u16 format, u32 sampleRate)
|
||||||
|
{
|
||||||
|
if(!voice)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memset(&voiceBuffer, 0, sizeof(voiceBuffer));
|
||||||
|
|
||||||
|
voiceBuffer.samples = buffer;
|
||||||
|
voiceBuffer.format = format;
|
||||||
|
voiceBuffer.loop = (nextBuffer == NULL) ? 0 : 1;
|
||||||
|
voiceBuffer.cur_pos = 0;
|
||||||
|
voiceBuffer.end_pos = bufferSize >> 1;
|
||||||
|
voiceBuffer.loop_offset = ((nextBuffer - buffer) >> 1);
|
||||||
|
nextBufferSize = nextBufSize;
|
||||||
|
|
||||||
|
u32 samplesPerSec = (AXGetInputSamplesPerSec != 0) ? AXGetInputSamplesPerSec() : 32000;
|
||||||
|
|
||||||
|
ratioBits[0] = (u32)(0x00010000 * ((f32)sampleRate / (f32)samplesPerSec));
|
||||||
|
ratioBits[1] = 0;
|
||||||
|
ratioBits[2] = 0;
|
||||||
|
ratioBits[3] = 0;
|
||||||
|
|
||||||
|
AXSetVoiceOffsets(voice, &voiceBuffer);
|
||||||
|
AXSetVoiceSrc(voice, ratioBits);
|
||||||
|
AXSetVoiceSrcType(voice, 1);
|
||||||
|
AXSetVoiceState(voice, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop()
|
||||||
|
{
|
||||||
|
if(voice)
|
||||||
|
AXSetVoiceState(voice, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setVolume(u32 vol)
|
||||||
|
{
|
||||||
|
if(voice)
|
||||||
|
AXSetVoiceVe(voice, &vol);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void setNextBuffer(const u8 *buffer, u32 bufferSize)
|
||||||
|
{
|
||||||
|
voiceBuffer.loop_offset = ((buffer - voiceBuffer.samples) >> 1);
|
||||||
|
nextBufferSize = bufferSize;
|
||||||
|
|
||||||
|
AXSetVoiceLoopOffset(voice, voiceBuffer.loop_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isBufferSwitched()
|
||||||
|
{
|
||||||
|
u32 loopCounter = AXGetVoiceLoopCount(voice);
|
||||||
|
if(lastLoopCounter != loopCounter)
|
||||||
|
{
|
||||||
|
lastLoopCounter = loopCounter;
|
||||||
|
AXSetVoiceEndOffset(voice, voiceBuffer.loop_offset + (nextBufferSize >> 1));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 getInternState() const {
|
||||||
|
if(voice)
|
||||||
|
return ((u32 *)voice)[1];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
u32 getState() const {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
void setState(u32 s) {
|
||||||
|
state = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void * getVoice() const {
|
||||||
|
return voice;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void *voice;
|
||||||
|
u32 ratioBits[4];
|
||||||
|
|
||||||
|
typedef struct _ax_buffer_t {
|
||||||
|
u16 format;
|
||||||
|
u16 loop;
|
||||||
|
u32 loop_offset;
|
||||||
|
u32 end_pos;
|
||||||
|
u32 cur_pos;
|
||||||
|
const unsigned char *samples;
|
||||||
|
} ax_buffer_t;
|
||||||
|
|
||||||
|
ax_buffer_t voiceBuffer;
|
||||||
|
u32 state;
|
||||||
|
u32 nextBufferSize;
|
||||||
|
u32 lastLoopCounter;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _AXSOUND_H_
|
154
source/sounds/WavDecoder.cpp
Normal file
154
source/sounds/WavDecoder.cpp
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010
|
||||||
|
* by Dimok
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* for WiiXplorer 2010
|
||||||
|
***************************************************************************/
|
||||||
|
#include <string.h>
|
||||||
|
#include "WavDecoder.hpp"
|
||||||
|
#include "utils/utils.h"
|
||||||
|
|
||||||
|
WavDecoder::WavDecoder(const char * filepath)
|
||||||
|
: SoundDecoder(filepath)
|
||||||
|
{
|
||||||
|
SoundType = SOUND_WAV;
|
||||||
|
SampleRate = 48000;
|
||||||
|
Format = CHANNELS_STEREO | FORMAT_PCM_16_BIT;
|
||||||
|
|
||||||
|
if(!file_fd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
OpenFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
WavDecoder::WavDecoder(const u8 * snd, s32 len)
|
||||||
|
: SoundDecoder(snd, len)
|
||||||
|
{
|
||||||
|
SoundType = SOUND_WAV;
|
||||||
|
SampleRate = 48000;
|
||||||
|
Format = CHANNELS_STEREO | FORMAT_PCM_16_BIT;
|
||||||
|
|
||||||
|
if(!file_fd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
OpenFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
WavDecoder::~WavDecoder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WavDecoder::OpenFile()
|
||||||
|
{
|
||||||
|
SWaveHdr Header;
|
||||||
|
SWaveFmtChunk FmtChunk;
|
||||||
|
memset(&Header, 0, sizeof(SWaveHdr));
|
||||||
|
memset(&FmtChunk, 0, sizeof(SWaveFmtChunk));
|
||||||
|
|
||||||
|
file_fd->read((u8 *) &Header, sizeof(SWaveHdr));
|
||||||
|
file_fd->read((u8 *) &FmtChunk, sizeof(SWaveFmtChunk));
|
||||||
|
|
||||||
|
if (Header.magicRIFF != 0x52494646) // 'RIFF'
|
||||||
|
{
|
||||||
|
CloseFile();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(Header.magicWAVE != 0x57415645) // 'WAVE'
|
||||||
|
{
|
||||||
|
CloseFile();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(FmtChunk.magicFMT != 0x666d7420) // 'fmt '
|
||||||
|
{
|
||||||
|
CloseFile();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataOffset = sizeof(SWaveHdr)+le32(FmtChunk.size)+8;
|
||||||
|
file_fd->seek(DataOffset, SEEK_SET);
|
||||||
|
SWaveChunk DataChunk;
|
||||||
|
file_fd->read((u8 *) &DataChunk, sizeof(SWaveChunk));
|
||||||
|
|
||||||
|
while(DataChunk.magicDATA != 0x64617461) // 'data'
|
||||||
|
{
|
||||||
|
DataOffset += 8+le32(DataChunk.size);
|
||||||
|
file_fd->seek(DataOffset, SEEK_SET);
|
||||||
|
s32 ret = file_fd->read((u8 *) &DataChunk, sizeof(SWaveChunk));
|
||||||
|
if(ret <= 0)
|
||||||
|
{
|
||||||
|
CloseFile();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataOffset += 8;
|
||||||
|
DataSize = le32(DataChunk.size);
|
||||||
|
Is16Bit = (le16(FmtChunk.bps) == 16);
|
||||||
|
SampleRate = le32(FmtChunk.freq);
|
||||||
|
|
||||||
|
if (le16(FmtChunk.channels) == 1 && le16(FmtChunk.bps) == 8 && le16(FmtChunk.alignment) <= 1)
|
||||||
|
Format = CHANNELS_MONO | FORMAT_PCM_8_BIT;
|
||||||
|
else if (le16(FmtChunk.channels) == 1 && le16(FmtChunk.bps) == 16 && le16(FmtChunk.alignment) <= 2)
|
||||||
|
Format = CHANNELS_MONO | FORMAT_PCM_16_BIT;
|
||||||
|
else if (le16(FmtChunk.channels) == 2 && le16(FmtChunk.bps) == 8 && le16(FmtChunk.alignment) <= 2)
|
||||||
|
Format = CHANNELS_STEREO | FORMAT_PCM_8_BIT;
|
||||||
|
else if (le16(FmtChunk.channels) == 2 && le16(FmtChunk.bps) == 16 && le16(FmtChunk.alignment) <= 4)
|
||||||
|
Format = CHANNELS_STEREO | FORMAT_PCM_16_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WavDecoder::CloseFile()
|
||||||
|
{
|
||||||
|
if(file_fd)
|
||||||
|
delete file_fd;
|
||||||
|
|
||||||
|
file_fd = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 WavDecoder::Read(u8 * buffer, s32 buffer_size, s32 pos)
|
||||||
|
{
|
||||||
|
if(!file_fd)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(CurPos >= (s32) DataSize)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
file_fd->seek(DataOffset+CurPos, SEEK_SET);
|
||||||
|
|
||||||
|
if(buffer_size > (s32) DataSize-CurPos)
|
||||||
|
buffer_size = DataSize-CurPos;
|
||||||
|
|
||||||
|
s32 read = file_fd->read(buffer, buffer_size);
|
||||||
|
if(read > 0)
|
||||||
|
{
|
||||||
|
if (Is16Bit)
|
||||||
|
{
|
||||||
|
read &= ~0x0001;
|
||||||
|
|
||||||
|
for (u32 i = 0; i < (u32) (read / sizeof (u16)); ++i)
|
||||||
|
((u16 *) buffer)[i] = le16(((u16 *) buffer)[i]);
|
||||||
|
}
|
||||||
|
CurPos += read;
|
||||||
|
}
|
||||||
|
|
||||||
|
return read;
|
||||||
|
}
|
71
source/sounds/WavDecoder.hpp
Normal file
71
source/sounds/WavDecoder.hpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010
|
||||||
|
* by Dimok
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* for WiiXplorer 2010
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef WAVDECODER_HPP_
|
||||||
|
#define WAVDECODER_HPP_
|
||||||
|
|
||||||
|
#include "SoundDecoder.hpp"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u32 magicRIFF;
|
||||||
|
u32 size;
|
||||||
|
u32 magicWAVE;
|
||||||
|
} SWaveHdr;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u32 magicFMT;
|
||||||
|
u32 size;
|
||||||
|
u16 format;
|
||||||
|
u16 channels;
|
||||||
|
u32 freq;
|
||||||
|
u32 avgBps;
|
||||||
|
u16 alignment;
|
||||||
|
u16 bps;
|
||||||
|
} SWaveFmtChunk;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u32 magicDATA;
|
||||||
|
u32 size;
|
||||||
|
} SWaveChunk;
|
||||||
|
|
||||||
|
class WavDecoder : public SoundDecoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WavDecoder(const char * filepath);
|
||||||
|
WavDecoder(const u8 * snd, s32 len);
|
||||||
|
virtual ~WavDecoder();
|
||||||
|
s32 Read(u8 * buffer, s32 buffer_size, s32 pos);
|
||||||
|
protected:
|
||||||
|
void OpenFile();
|
||||||
|
void CloseFile();
|
||||||
|
u32 DataOffset;
|
||||||
|
u32 DataSize;
|
||||||
|
bool Is16Bit;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
290
source/video/CVideo.cpp
Normal file
290
source/video/CVideo.cpp
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "CVideo.h"
|
||||||
|
#include <system/memory.h>
|
||||||
|
#include "shaders/Texture2DShader.h"
|
||||||
|
#include "shaders/ColorShader.h"
|
||||||
|
#include "shaders/Shader3D.h"
|
||||||
|
#include "shaders/ShaderFractalColor.h"
|
||||||
|
#include "shaders/FXAAShader.h"
|
||||||
|
#include <dynamic_libs/os_functions.h>
|
||||||
|
|
||||||
|
CVideo::CVideo(s32 forceTvScanMode, s32 forceDrcScanMode)
|
||||||
|
{
|
||||||
|
tvEnabled = false;
|
||||||
|
drcEnabled = false;
|
||||||
|
|
||||||
|
//! allocate MEM2 command buffer memory
|
||||||
|
gx2CommandBuffer = MEM2_alloc(GX2_COMMAND_BUFFER_SIZE, 0x40);
|
||||||
|
|
||||||
|
//! initialize GX2 command buffer
|
||||||
|
u32 gx2_init_attributes[9];
|
||||||
|
gx2_init_attributes[0] = GX2_INIT_ATTRIB_CB_BASE;
|
||||||
|
gx2_init_attributes[1] = (u32)gx2CommandBuffer;
|
||||||
|
gx2_init_attributes[2] = GX2_INIT_ATTRIB_CB_SIZE;
|
||||||
|
gx2_init_attributes[3] = GX2_COMMAND_BUFFER_SIZE;
|
||||||
|
gx2_init_attributes[4] = GX2_INIT_ATTRIB_ARGC;
|
||||||
|
gx2_init_attributes[5] = 0;
|
||||||
|
gx2_init_attributes[6] = GX2_INIT_ATTRIB_ARGV;
|
||||||
|
gx2_init_attributes[7] = 0;
|
||||||
|
gx2_init_attributes[8] = GX2_INIT_ATTRIB_NULL;
|
||||||
|
GX2Init(gx2_init_attributes);
|
||||||
|
|
||||||
|
//! GX2 resources are not used in this application but if needed, the allocator is setup
|
||||||
|
GX2RSetAllocator(&CVideo::GX2RAlloc, &CVideo::GX2RFree);
|
||||||
|
|
||||||
|
u32 scanBufferSize = 0;
|
||||||
|
s32 scaleNeeded = 0;
|
||||||
|
|
||||||
|
s32 tvScanMode = (forceTvScanMode >= 0) ? forceTvScanMode : GX2GetSystemTVScanMode();
|
||||||
|
s32 drcScanMode = (forceDrcScanMode >= 0) ? forceDrcScanMode : GX2GetSystemDRCScanMode();
|
||||||
|
|
||||||
|
s32 tvRenderMode;
|
||||||
|
u32 tvWidth = 0;
|
||||||
|
u32 tvHeight = 0;
|
||||||
|
|
||||||
|
switch(tvScanMode)
|
||||||
|
{
|
||||||
|
case GX2_TV_SCAN_MODE_480I:
|
||||||
|
case GX2_TV_SCAN_MODE_480P:
|
||||||
|
tvWidth = 854;
|
||||||
|
tvHeight = 480;
|
||||||
|
tvRenderMode = GX2_TV_RENDER_480_WIDE;
|
||||||
|
break;
|
||||||
|
case GX2_TV_SCAN_MODE_1080I:
|
||||||
|
case GX2_TV_SCAN_MODE_1080P:
|
||||||
|
tvWidth = 1920;
|
||||||
|
tvHeight = 1080;
|
||||||
|
tvRenderMode = GX2_TV_RENDER_1080;
|
||||||
|
break;
|
||||||
|
case GX2_TV_SCAN_MODE_720P:
|
||||||
|
default:
|
||||||
|
tvWidth = 1280;
|
||||||
|
tvHeight = 720;
|
||||||
|
tvRenderMode = GX2_TV_RENDER_720;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 tvAAMode = GX2_AA_MODE_1X;
|
||||||
|
s32 drcAAMode = GX2_AA_MODE_4X;
|
||||||
|
|
||||||
|
//! calculate the scale factor for later texture resize
|
||||||
|
widthScaleFactor = 1.0f / (f32)tvWidth;
|
||||||
|
heightScaleFactor = 1.0f / (f32)tvHeight;
|
||||||
|
depthScaleFactor = widthScaleFactor;
|
||||||
|
|
||||||
|
//! calculate the size needed for the TV scan buffer and allocate the buffer from bucket memory
|
||||||
|
GX2CalcTVSize(tvRenderMode, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, GX2_BUFFERING_DOUBLE, &scanBufferSize, &scaleNeeded);
|
||||||
|
tvScanBuffer = MEMBucket_alloc(scanBufferSize, GX2_SCAN_BUFFER_ALIGNMENT);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU, tvScanBuffer, scanBufferSize);
|
||||||
|
GX2SetTVBuffer(tvScanBuffer, scanBufferSize, tvRenderMode, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, GX2_BUFFERING_DOUBLE);
|
||||||
|
|
||||||
|
//! calculate the size needed for the DRC scan buffer and allocate the buffer from bucket memory
|
||||||
|
GX2CalcDRCSize(drcScanMode, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, GX2_BUFFERING_DOUBLE, &scanBufferSize, &scaleNeeded);
|
||||||
|
drcScanBuffer = MEMBucket_alloc(scanBufferSize, GX2_SCAN_BUFFER_ALIGNMENT);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU, drcScanBuffer, scanBufferSize);
|
||||||
|
GX2SetDRCBuffer(drcScanBuffer, scanBufferSize, drcScanMode, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, GX2_BUFFERING_DOUBLE);
|
||||||
|
|
||||||
|
//! Setup color buffer for TV rendering
|
||||||
|
GX2InitColorBuffer(&tvColorBuffer, GX2_SURFACE_DIM_2D, tvWidth, tvHeight, 1, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, tvAAMode);
|
||||||
|
tvColorBuffer.surface.image_data = MEM1_alloc(tvColorBuffer.surface.image_size, tvColorBuffer.surface.align);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU, tvColorBuffer.surface.image_data, tvColorBuffer.surface.image_size);
|
||||||
|
|
||||||
|
//! due to AA we can only use 16 bit depth buffer in MEM1 otherwise we would have to switch to mem2 for depth buffer
|
||||||
|
//! this should be ok for our purpose i guess
|
||||||
|
|
||||||
|
//! Setup TV depth buffer (can be the same for both if rendered one after another)
|
||||||
|
u32 size, align;
|
||||||
|
GX2InitDepthBuffer(&tvDepthBuffer, GX2_SURFACE_DIM_2D, tvColorBuffer.surface.width, tvColorBuffer.surface.height, 1, GX2_SURFACE_FORMAT_TCD_R32_FLOAT, tvAAMode);
|
||||||
|
tvDepthBuffer.surface.image_data = MEM1_alloc(tvDepthBuffer.surface.image_size, tvDepthBuffer.surface.align);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU, tvDepthBuffer.surface.image_data, tvDepthBuffer.surface.image_size);
|
||||||
|
|
||||||
|
//! Setup TV HiZ buffer
|
||||||
|
GX2CalcDepthBufferHiZInfo(&tvDepthBuffer, &size, &align);
|
||||||
|
tvDepthBuffer.hiZ_data = MEM1_alloc(size, align);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU, tvDepthBuffer.hiZ_data, size);
|
||||||
|
GX2InitDepthBufferHiZEnable(&tvDepthBuffer, GX2_ENABLE);
|
||||||
|
|
||||||
|
//! Setup color buffer for DRC rendering
|
||||||
|
GX2InitColorBuffer(&drcColorBuffer, GX2_SURFACE_DIM_2D, 854, 480, 1, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, drcAAMode);
|
||||||
|
drcColorBuffer.surface.image_data = MEM1_alloc(drcColorBuffer.surface.image_size, drcColorBuffer.surface.align);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU, drcColorBuffer.surface.image_data, drcColorBuffer.surface.image_size);
|
||||||
|
|
||||||
|
//! Setup DRC depth buffer (can be the same for both if rendered one after another)
|
||||||
|
GX2InitDepthBuffer(&drcDepthBuffer, GX2_SURFACE_DIM_2D, drcColorBuffer.surface.width, drcColorBuffer.surface.height, 1, GX2_SURFACE_FORMAT_TCD_R32_FLOAT, drcAAMode);
|
||||||
|
drcDepthBuffer.surface.image_data = MEM1_alloc(drcDepthBuffer.surface.image_size, drcDepthBuffer.surface.align);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU, drcDepthBuffer.surface.image_data, drcDepthBuffer.surface.image_size);
|
||||||
|
|
||||||
|
//! Setup DRC HiZ buffer
|
||||||
|
GX2CalcDepthBufferHiZInfo(&drcDepthBuffer, &size, &align);
|
||||||
|
drcDepthBuffer.hiZ_data = MEM1_alloc(size, align);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU, drcDepthBuffer.hiZ_data, size);
|
||||||
|
GX2InitDepthBufferHiZEnable(&drcDepthBuffer, GX2_ENABLE);
|
||||||
|
|
||||||
|
|
||||||
|
//! allocate auxilary buffer last as there might not be enough MEM1 left for other stuff after that
|
||||||
|
if (tvColorBuffer.surface.aa)
|
||||||
|
{
|
||||||
|
u32 auxSize, auxAlign;
|
||||||
|
GX2CalcColorBufferAuxInfo(&tvColorBuffer, &auxSize, &auxAlign);
|
||||||
|
tvColorBuffer.aux_data = MEM1_alloc(auxSize, auxAlign);
|
||||||
|
if(!tvColorBuffer.aux_data)
|
||||||
|
tvColorBuffer.aux_data = MEM2_alloc(auxSize, auxAlign);
|
||||||
|
|
||||||
|
tvColorBuffer.aux_size = auxSize;
|
||||||
|
memset(tvColorBuffer.aux_data, GX2_AUX_BUFFER_CLEAR_VALUE, auxSize);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU, tvColorBuffer.aux_data, auxSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drcColorBuffer.surface.aa)
|
||||||
|
{
|
||||||
|
u32 auxSize, auxAlign;
|
||||||
|
GX2CalcColorBufferAuxInfo(&drcColorBuffer, &auxSize, &auxAlign);
|
||||||
|
drcColorBuffer.aux_data = MEM1_alloc(auxSize, auxAlign);
|
||||||
|
if(!drcColorBuffer.aux_data)
|
||||||
|
drcColorBuffer.aux_data = MEM2_alloc(auxSize, auxAlign);
|
||||||
|
drcColorBuffer.aux_size = auxSize;
|
||||||
|
memset(drcColorBuffer.aux_data, GX2_AUX_BUFFER_CLEAR_VALUE, auxSize);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU, drcColorBuffer.aux_data, auxSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
//! allocate memory and setup context state TV
|
||||||
|
tvContextState = (GX2ContextState*)MEM2_alloc(sizeof(GX2ContextState), GX2_CONTEXT_STATE_ALIGNMENT);
|
||||||
|
GX2SetupContextStateEx(tvContextState, GX2_TRUE);
|
||||||
|
|
||||||
|
//! allocate memory and setup context state DRC
|
||||||
|
drcContextState = (GX2ContextState*)MEM2_alloc(sizeof(GX2ContextState), GX2_CONTEXT_STATE_ALIGNMENT);
|
||||||
|
GX2SetupContextStateEx(drcContextState, GX2_TRUE);
|
||||||
|
|
||||||
|
//! set initial context state and render buffers
|
||||||
|
GX2SetContextState(tvContextState);
|
||||||
|
GX2SetColorBuffer(&tvColorBuffer, GX2_RENDER_TARGET_0);
|
||||||
|
GX2SetDepthBuffer(&tvDepthBuffer);
|
||||||
|
|
||||||
|
GX2SetContextState(drcContextState);
|
||||||
|
GX2SetColorBuffer(&drcColorBuffer, GX2_RENDER_TARGET_0);
|
||||||
|
GX2SetDepthBuffer(&drcDepthBuffer);
|
||||||
|
|
||||||
|
//! set initial viewport
|
||||||
|
GX2SetViewport(0.0f, 0.0f, tvColorBuffer.surface.width, tvColorBuffer.surface.height, 0.0f, 1.0f);
|
||||||
|
GX2SetScissor(0, 0, tvColorBuffer.surface.width, tvColorBuffer.surface.height);
|
||||||
|
|
||||||
|
//! this is not necessary but can be used for swap counting and vsyncs
|
||||||
|
GX2SetSwapInterval(1);
|
||||||
|
|
||||||
|
//GX2SetTVGamma(0.8f);
|
||||||
|
//GX2SetDRCGamma(0.8f);
|
||||||
|
|
||||||
|
//! initialize perspective matrix
|
||||||
|
const float cam_X_rot = 25.0f;
|
||||||
|
|
||||||
|
projectionMtx = glm::perspective(45.0f, 1.0f, 0.1f, 100.0f);
|
||||||
|
|
||||||
|
viewMtx = glm::mat4(1.0f);
|
||||||
|
viewMtx = glm::translate(viewMtx, glm::vec3(0.0f, 0.0f, -2.5f));
|
||||||
|
viewMtx = glm::rotate(viewMtx, DegToRad(cam_X_rot), glm::vec3(1.0f, 0.0f, 0.0f));
|
||||||
|
|
||||||
|
GX2InitSampler(&aaSampler, GX2_TEX_CLAMP_CLAMP, GX2_TEX_XY_FILTER_BILINEAR);
|
||||||
|
GX2InitTexture(&tvAaTexture, tvColorBuffer.surface.width, tvColorBuffer.surface.height, 1, 0, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, GX2_SURFACE_DIM_2D, GX2_TILE_MODE_DEFAULT);
|
||||||
|
tvAaTexture.surface.image_data = tvColorBuffer.surface.image_data;
|
||||||
|
tvAaTexture.surface.image_size = tvColorBuffer.surface.image_size;
|
||||||
|
tvAaTexture.surface.mip_data = tvColorBuffer.surface.mip_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
CVideo::~CVideo()
|
||||||
|
{
|
||||||
|
//! flush buffers
|
||||||
|
GX2Flush();
|
||||||
|
GX2DrawDone();
|
||||||
|
//! shutdown
|
||||||
|
GX2Shutdown();
|
||||||
|
//! free command buffer memory
|
||||||
|
MEM2_free(gx2CommandBuffer);
|
||||||
|
//! free scan buffers
|
||||||
|
MEMBucket_free(tvScanBuffer);
|
||||||
|
MEMBucket_free(drcScanBuffer);
|
||||||
|
//! free color buffers
|
||||||
|
MEM1_free(tvColorBuffer.surface.image_data);
|
||||||
|
MEM1_free(drcColorBuffer.surface.image_data);
|
||||||
|
//! free depth buffers
|
||||||
|
MEM1_free(tvDepthBuffer.surface.image_data);
|
||||||
|
MEM1_free(tvDepthBuffer.hiZ_data);
|
||||||
|
MEM1_free(drcDepthBuffer.surface.image_data);
|
||||||
|
MEM1_free(drcDepthBuffer.hiZ_data);
|
||||||
|
//! free context buffers
|
||||||
|
MEM2_free(tvContextState);
|
||||||
|
MEM2_free(drcContextState);
|
||||||
|
//! free aux buffer
|
||||||
|
if(tvColorBuffer.aux_data)
|
||||||
|
{
|
||||||
|
if(((u32)tvColorBuffer.aux_data & 0xF0000000) == 0xF0000000)
|
||||||
|
MEM1_free(tvColorBuffer.aux_data);
|
||||||
|
else
|
||||||
|
MEM2_free(tvColorBuffer.aux_data);
|
||||||
|
}
|
||||||
|
if(drcColorBuffer.aux_data)
|
||||||
|
{
|
||||||
|
if(((u32)drcColorBuffer.aux_data & 0xF0000000) == 0xF0000000)
|
||||||
|
MEM1_free(drcColorBuffer.aux_data);
|
||||||
|
else
|
||||||
|
MEM2_free(drcColorBuffer.aux_data);
|
||||||
|
}
|
||||||
|
//! destroy shaders
|
||||||
|
ColorShader::destroyInstance();
|
||||||
|
FXAAShader::destroyInstance();
|
||||||
|
Shader3D::destroyInstance();
|
||||||
|
ShaderFractalColor::destroyInstance();
|
||||||
|
Texture2DShader::destroyInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVideo::renderFXAA(const GX2Texture * texture, const GX2Sampler *sampler)
|
||||||
|
{
|
||||||
|
resolution[0] = texture->surface.width;
|
||||||
|
resolution[1] = texture->surface.height;
|
||||||
|
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_COLOR_BUFFER | GX2_INVALIDATE_TEXTURE, texture->surface.image_data, texture->surface.image_size);
|
||||||
|
|
||||||
|
GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_ALWAYS);
|
||||||
|
FXAAShader::instance()->setShaders();
|
||||||
|
FXAAShader::instance()->setAttributeBuffer();
|
||||||
|
FXAAShader::instance()->setResolution(resolution);
|
||||||
|
FXAAShader::instance()->setTextureAndSampler(texture, sampler);
|
||||||
|
FXAAShader::instance()->draw();
|
||||||
|
GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_LEQUAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* CVideo::GX2RAlloc(u32 flags, u32 size, u32 align)
|
||||||
|
{
|
||||||
|
//! min. alignment
|
||||||
|
if (align < 4)
|
||||||
|
align = 4;
|
||||||
|
|
||||||
|
if ((flags & 0x2040E) && !(flags & 0x40000))
|
||||||
|
return MEM1_alloc(size, align);
|
||||||
|
else
|
||||||
|
return MEM2_alloc(size, align);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVideo::GX2RFree(u32 flags, void* p)
|
||||||
|
{
|
||||||
|
if ((flags & 0x2040E) && !(flags & 0x40000))
|
||||||
|
MEM1_free(p);
|
||||||
|
else
|
||||||
|
MEM2_free(p);
|
||||||
|
}
|
202
source/video/CVideo.h
Normal file
202
source/video/CVideo.h
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef __CVIDEO_H_
|
||||||
|
#define __CVIDEO_H_
|
||||||
|
|
||||||
|
#include <dynamic_libs/gx2_functions.h>
|
||||||
|
#include "shaders/Shader.h"
|
||||||
|
|
||||||
|
class CVideo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CVideo(s32 forceTvScanMode = -1, s32 forceDrcScanMode = -1);
|
||||||
|
virtual ~CVideo();
|
||||||
|
|
||||||
|
void prepareTvRendering(void) {
|
||||||
|
currContextState = tvContextState;
|
||||||
|
currColorBuffer = &tvColorBuffer;
|
||||||
|
currDepthBuffer = &tvDepthBuffer;
|
||||||
|
prepareRendering();
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepareDrcRendering(void) {
|
||||||
|
currContextState = drcContextState;
|
||||||
|
currColorBuffer = &drcColorBuffer;
|
||||||
|
currDepthBuffer = &drcDepthBuffer;
|
||||||
|
prepareRendering();
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepareRendering(void) {
|
||||||
|
GX2ClearColor(currColorBuffer, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
GX2ClearDepthStencilEx(currDepthBuffer, currDepthBuffer->clear_depth, currDepthBuffer->clear_stencil, GX2_CLEAR_BOTH);
|
||||||
|
|
||||||
|
GX2SetContextState(currContextState);
|
||||||
|
GX2SetViewport(0.0f, 0.0f, currColorBuffer->surface.width, currColorBuffer->surface.height, 0.0f, 1.0f);
|
||||||
|
GX2SetScissor(0, 0, currColorBuffer->surface.width, currColorBuffer->surface.height);
|
||||||
|
|
||||||
|
GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_LEQUAL);
|
||||||
|
GX2SetColorControl(GX2_LOGIC_OP_COPY, 1, GX2_DISABLE, GX2_ENABLE);
|
||||||
|
GX2SetBlendControl(GX2_RENDER_TARGET_0, GX2_BLEND_SRC_ALPHA, GX2_BLEND_ONE_MINUS_SRC_ALPHA, GX2_BLEND_COMBINE_ADD, GX2_ENABLE, GX2_BLEND_SRC_ALPHA, GX2_BLEND_ONE_MINUS_SRC_ALPHA, GX2_BLEND_COMBINE_ADD);
|
||||||
|
GX2SetCullOnlyControl(GX2_FRONT_FACE_CCW, GX2_DISABLE, GX2_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setStencilRender(bool bEnable)
|
||||||
|
{
|
||||||
|
if(bEnable)
|
||||||
|
{
|
||||||
|
GX2SetStencilMask(0xff, 0xff, 0x01, 0xff, 0xff, 0x01);
|
||||||
|
GX2SetDepthStencilControl(GX2_DISABLE, GX2_DISABLE, GX2_COMPARE_LEQUAL, GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_ALWAYS, GX2_STENCIL_KEEP, GX2_STENCIL_KEEP, GX2_STENCIL_REPLACE,
|
||||||
|
GX2_COMPARE_ALWAYS, GX2_STENCIL_KEEP, GX2_STENCIL_KEEP, GX2_STENCIL_REPLACE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GX2SetStencilMask(0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
|
||||||
|
GX2SetDepthStencilControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_LEQUAL, GX2_DISABLE, GX2_DISABLE, GX2_COMPARE_NEVER, GX2_STENCIL_KEEP, GX2_STENCIL_KEEP, GX2_STENCIL_KEEP,
|
||||||
|
GX2_COMPARE_NEVER, GX2_STENCIL_KEEP, GX2_STENCIL_KEEP, GX2_STENCIL_KEEP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drcDrawDone(void) {
|
||||||
|
//! on DRC we do a hardware AA because FXAA does not look good
|
||||||
|
//renderFXAA(&drcAaTexture, &aaSampler);
|
||||||
|
GX2CopyColorBufferToScanBuffer(&drcColorBuffer, GX2_SCAN_TARGET_DRC_FIRST);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tvDrawDone(void) {
|
||||||
|
renderFXAA(&tvAaTexture, &aaSampler);
|
||||||
|
GX2CopyColorBufferToScanBuffer(&tvColorBuffer, GX2_SCAN_TARGET_TV);
|
||||||
|
GX2SwapScanBuffers();
|
||||||
|
GX2Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void waitForVSync(void) {
|
||||||
|
GX2WaitForVsync();
|
||||||
|
frameCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tvEnable(bool bEnable) {
|
||||||
|
if(tvEnabled != bEnable)
|
||||||
|
{
|
||||||
|
GX2SetTVEnable(bEnable ? GX2_ENABLE : GX2_DISABLE);
|
||||||
|
tvEnabled = bEnable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void drcEnable(bool bEnable) {
|
||||||
|
if(drcEnabled != bEnable)
|
||||||
|
{
|
||||||
|
GX2SetDRCEnable(bEnable ? GX2_ENABLE : GX2_DISABLE);
|
||||||
|
drcEnabled = bEnable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 getFrameCount(void) const {
|
||||||
|
return frameCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 getTvWidth(void) const {
|
||||||
|
return tvColorBuffer.surface.width;
|
||||||
|
}
|
||||||
|
u32 getTvHeight(void) const {
|
||||||
|
return tvColorBuffer.surface.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 getDrcWidth(void) const {
|
||||||
|
return drcColorBuffer.surface.width;
|
||||||
|
}
|
||||||
|
u32 getDrcHeight(void) const {
|
||||||
|
return drcColorBuffer.surface.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::mat4 & getProjectionMtx(void) const {
|
||||||
|
return projectionMtx;
|
||||||
|
}
|
||||||
|
const glm::mat4 & getViewMtx(void) const {
|
||||||
|
return viewMtx;
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 getWidthScaleFactor(void) const {
|
||||||
|
return widthScaleFactor;
|
||||||
|
}
|
||||||
|
f32 getHeightScaleFactor(void) const {
|
||||||
|
return heightScaleFactor;
|
||||||
|
}
|
||||||
|
f32 getDepthScaleFactor(void) const {
|
||||||
|
return depthScaleFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void screenPosToWorldRay(f32 posX, f32 posY, glm::vec3 & rayOrigin, glm::vec3 & rayDirection)
|
||||||
|
{
|
||||||
|
//! normalize positions
|
||||||
|
posX = 2.0f * posX * getWidthScaleFactor();
|
||||||
|
posY = 2.0f * posY * getHeightScaleFactor();
|
||||||
|
|
||||||
|
glm::vec4 rayStart(posX, posY, 0.0f, 1.0f);
|
||||||
|
glm::vec4 rayEnd(posX, posY, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
glm::mat4 IMV = glm::inverse(projectionMtx * viewMtx);
|
||||||
|
glm::vec4 rayStartWorld = IMV * rayStart;
|
||||||
|
rayStartWorld /= rayStartWorld.w;
|
||||||
|
|
||||||
|
glm::vec4 rayEndWorld = IMV * rayEnd;
|
||||||
|
rayEndWorld /= rayEndWorld.w;
|
||||||
|
|
||||||
|
glm::vec3 rayDirectionWorld(rayEndWorld - rayStartWorld);
|
||||||
|
rayDirectionWorld = glm::normalize(rayDirectionWorld);
|
||||||
|
|
||||||
|
rayOrigin = glm::vec3(rayStartWorld);
|
||||||
|
rayDirection = glm::normalize(rayDirectionWorld);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
static void *GX2RAlloc(u32 flags, u32 size, u32 align);
|
||||||
|
static void GX2RFree(u32 flags, void* p);
|
||||||
|
|
||||||
|
void renderFXAA(const GX2Texture * texture, const GX2Sampler *sampler);
|
||||||
|
|
||||||
|
void *gx2CommandBuffer;
|
||||||
|
|
||||||
|
void *tvScanBuffer;
|
||||||
|
void *drcScanBuffer;
|
||||||
|
|
||||||
|
u32 frameCount;
|
||||||
|
f32 widthScaleFactor;
|
||||||
|
f32 heightScaleFactor;
|
||||||
|
f32 depthScaleFactor;
|
||||||
|
|
||||||
|
bool tvEnabled;
|
||||||
|
bool drcEnabled;
|
||||||
|
|
||||||
|
GX2ColorBuffer tvColorBuffer;
|
||||||
|
GX2DepthBuffer tvDepthBuffer;
|
||||||
|
GX2ColorBuffer drcColorBuffer;
|
||||||
|
GX2DepthBuffer drcDepthBuffer;
|
||||||
|
|
||||||
|
GX2ContextState *tvContextState;
|
||||||
|
GX2ContextState *drcContextState;
|
||||||
|
|
||||||
|
GX2ContextState *currContextState;
|
||||||
|
GX2ColorBuffer *currColorBuffer;
|
||||||
|
GX2DepthBuffer *currDepthBuffer;
|
||||||
|
|
||||||
|
GX2Texture tvAaTexture;
|
||||||
|
GX2Sampler aaSampler;
|
||||||
|
|
||||||
|
glm::mat4 projectionMtx;
|
||||||
|
glm::mat4 viewMtx;
|
||||||
|
glm::vec2 resolution;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __GX2_VIDEO_H_
|
88
source/video/CursorDrawer.cpp
Normal file
88
source/video/CursorDrawer.cpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2016,2017 Maschell
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <dynamic_libs/gx2_functions.h>
|
||||||
|
#include "video/shaders/ColorShader.h"
|
||||||
|
#include "video/shaders/FXAAShader.h"
|
||||||
|
#include "video/shaders/Shader3D.h"
|
||||||
|
#include "video/shaders/ShaderFractalColor.h"
|
||||||
|
#include "video/shaders/Texture2DShader.h"
|
||||||
|
#include "CursorDrawer.h"
|
||||||
|
|
||||||
|
CursorDrawer *CursorDrawer::instance = NULL;
|
||||||
|
|
||||||
|
CursorDrawer::CursorDrawer()
|
||||||
|
{
|
||||||
|
init_colorVtxs();
|
||||||
|
}
|
||||||
|
|
||||||
|
CursorDrawer::~CursorDrawer()
|
||||||
|
{
|
||||||
|
//! destroy shaders
|
||||||
|
ColorShader::destroyInstance();
|
||||||
|
FXAAShader::destroyInstance();
|
||||||
|
Shader3D::destroyInstance();
|
||||||
|
ShaderFractalColor::destroyInstance();
|
||||||
|
Texture2DShader::destroyInstance();
|
||||||
|
if(this->colorVtxs){
|
||||||
|
free(this->colorVtxs);
|
||||||
|
this->colorVtxs = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CursorDrawer::init_colorVtxs(){
|
||||||
|
if(!this->colorVtxs){
|
||||||
|
this->colorVtxs = (u8*)memalign(0x40, sizeof(u8) * 16);
|
||||||
|
if(this->colorVtxs == NULL) return;
|
||||||
|
|
||||||
|
}
|
||||||
|
memset(this->colorVtxs,0xFF,16*sizeof(u8));
|
||||||
|
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, this->colorVtxs, 16 * sizeof(u8));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Could be improved. It be more generic.
|
||||||
|
void CursorDrawer::draw_Cursor(f32 x,f32 y)
|
||||||
|
{
|
||||||
|
if(this->colorVtxs == NULL){
|
||||||
|
init_colorVtxs();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 widthScaleFactor = 1.0f / (f32)1280;
|
||||||
|
f32 heightScaleFactor = 1.0f / (f32)720;
|
||||||
|
|
||||||
|
s32 width = 20;
|
||||||
|
|
||||||
|
glm::vec3 positionOffsets = glm::vec3(0.0f);
|
||||||
|
|
||||||
|
positionOffsets[0] = (x-((1280)/2)+(width/2)) * widthScaleFactor * 2.0f;
|
||||||
|
positionOffsets[1] = -(y-((720)/2)+(width/2)) * heightScaleFactor * 2.0f;
|
||||||
|
|
||||||
|
glm::vec3 scale(width*widthScaleFactor,width*heightScaleFactor,1.0f);
|
||||||
|
|
||||||
|
ColorShader::instance()->setShaders();
|
||||||
|
ColorShader::instance()->setAttributeBuffer(this->colorVtxs, NULL, 4);
|
||||||
|
ColorShader::instance()->setAngle(0);
|
||||||
|
ColorShader::instance()->setOffset(positionOffsets);
|
||||||
|
ColorShader::instance()->setScale(scale);
|
||||||
|
ColorShader::instance()->setColorIntensity(glm::vec4(1.0f));
|
||||||
|
ColorShader::instance()->draw(GX2_PRIMITIVE_QUADS, 4);
|
||||||
|
}
|
62
source/video/CursorDrawer.h
Normal file
62
source/video/CursorDrawer.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2016,2017 Maschell
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef _CursorDrawer_H_
|
||||||
|
#define _CursorDrawer_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <dynamic_libs/gx2_types.h>
|
||||||
|
|
||||||
|
class CursorDrawer
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
static CursorDrawer *getInstance() {
|
||||||
|
if(!instance)
|
||||||
|
instance = new CursorDrawer();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroyInstance() {
|
||||||
|
if(instance){
|
||||||
|
delete instance;
|
||||||
|
instance = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw(f32 x, f32 y)
|
||||||
|
{
|
||||||
|
CursorDrawer * cur_instance = getInstance();
|
||||||
|
if(cur_instance == NULL) return;
|
||||||
|
cur_instance->draw_Cursor(x,y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//!Constructor
|
||||||
|
CursorDrawer();
|
||||||
|
//!Destructor
|
||||||
|
~CursorDrawer();
|
||||||
|
static CursorDrawer *instance;
|
||||||
|
void draw_Cursor(f32 x, f32 y);
|
||||||
|
void init_colorVtxs();
|
||||||
|
|
||||||
|
u8 * colorVtxs = NULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
167
source/video/shaders/ColorShader.cpp
Normal file
167
source/video/shaders/ColorShader.cpp
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "ColorShader.h"
|
||||||
|
|
||||||
|
static const u32 cpVertexShaderProgram[] =
|
||||||
|
{
|
||||||
|
0x00000000,0x00008009,0x20000000,0x000078a0,
|
||||||
|
0x3c200000,0x88060094,0x00c00000,0x88062014,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00a11f00,0xfc00620f,0x02490001,0x80000040,
|
||||||
|
0xfd041f80,0x900c0060,0x83f9223e,0x0000803f,
|
||||||
|
0xfe282001,0x10000040,0xfe001f80,0x00080060,
|
||||||
|
0xfeac9f80,0xfd00624f,0xdb0f49c0,0xdb0fc940,
|
||||||
|
0xfea81f80,0x9000e02f,0x83f9223e,0x00000000,
|
||||||
|
0xfe041f80,0x00370000,0xffa01f00,0x80000000,
|
||||||
|
0xff101f00,0x800c0020,0x7f041f80,0x80370000,
|
||||||
|
0x0000103f,0x00000000,0x02c51f00,0x80000000,
|
||||||
|
0xfea41f00,0x80000020,0xffa09f00,0x80000040,
|
||||||
|
0xff001f80,0x800c0060,0x398ee33f,0x0000103f,
|
||||||
|
0x02c41f00,0x9000e00f,0x02c59f01,0x80000020,
|
||||||
|
0xfea81f00,0x80000040,0x02c19f80,0x9000e06f,
|
||||||
|
0x398ee33f,0x00000000,0x02c11f01,0x80000000,
|
||||||
|
0x02c49f80,0x80000060,0x02e08f01,0xfe0c620f,
|
||||||
|
0x02c01f80,0x7f00622f,0xfe242000,0x10000000,
|
||||||
|
0xfe20a080,0x10000020,0xf2178647,0x49c0e9fb,
|
||||||
|
0xfbbdb2ab,0x768ac733
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u32 cpVertexShaderRegs[] = {
|
||||||
|
0x00000103,0x00000000,0x00000000,0x00000001,
|
||||||
|
0xffffff00,0xffffffff,0xffffffff,0xffffffff,
|
||||||
|
0xffffffff,0xffffffff,0xffffffff,0xffffffff,
|
||||||
|
0xffffffff,0xffffffff,0x00000000,0xfffffffc,
|
||||||
|
0x00000002,0x00000001,0x00000000,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x00000000,0x0000000e,0x00000010
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u32 cpPixelShaderProgram[] =
|
||||||
|
{
|
||||||
|
0x20000000,0x00000ca0,0x00000000,0x88062094,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00002000,0x90000000,0x0004a000,0x90000020,
|
||||||
|
0x00082001,0x90000040,0x000ca081,0x90000060,
|
||||||
|
0xbb7dd898,0x9746c59c,0xc69b00e7,0x03c36218
|
||||||
|
};
|
||||||
|
static const u32 cpPixelShaderRegs[] = {
|
||||||
|
0x00000001,0x00000002,0x14000001,0x00000000,
|
||||||
|
0x00000001,0x00000100,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x0000000f,0x00000001,0x00000010,
|
||||||
|
0x00000000
|
||||||
|
};
|
||||||
|
|
||||||
|
ColorShader * ColorShader::shaderInstance = NULL;
|
||||||
|
|
||||||
|
ColorShader::ColorShader()
|
||||||
|
: vertexShader(cuAttributeCount)
|
||||||
|
{
|
||||||
|
//! create pixel shader
|
||||||
|
pixelShader.setProgram(cpPixelShaderProgram, sizeof(cpPixelShaderProgram), cpPixelShaderRegs, sizeof(cpPixelShaderRegs));
|
||||||
|
|
||||||
|
colorIntensityLocation = 0;
|
||||||
|
pixelShader.addUniformVar((GX2UniformVar){ "unf_color_intensity", GX2_VAR_TYPE_VEC4, 1, colorIntensityLocation, 0xffffffff });
|
||||||
|
|
||||||
|
//! create vertex shader
|
||||||
|
vertexShader.setProgram(cpVertexShaderProgram, sizeof(cpVertexShaderProgram), cpVertexShaderRegs, sizeof(cpVertexShaderRegs));
|
||||||
|
|
||||||
|
angleLocation = 0;
|
||||||
|
offsetLocation = 4;
|
||||||
|
scaleLocation = 8;
|
||||||
|
vertexShader.addUniformVar((GX2UniformVar){ "unf_angle", GX2_VAR_TYPE_FLOAT, 1, angleLocation, 0xffffffff });
|
||||||
|
vertexShader.addUniformVar((GX2UniformVar){ "unf_offset", GX2_VAR_TYPE_VEC3, 1, offsetLocation, 0xffffffff });
|
||||||
|
vertexShader.addUniformVar((GX2UniformVar){ "unf_scale", GX2_VAR_TYPE_VEC3, 1, scaleLocation, 0xffffffff });
|
||||||
|
|
||||||
|
colorLocation = 1;
|
||||||
|
positionLocation = 0;
|
||||||
|
vertexShader.addAttribVar((GX2AttribVar){ "attr_color", GX2_VAR_TYPE_VEC4, 0, colorLocation });
|
||||||
|
vertexShader.addAttribVar((GX2AttribVar){ "attr_position", GX2_VAR_TYPE_VEC3, 0, positionLocation });
|
||||||
|
|
||||||
|
//! setup attribute streams
|
||||||
|
GX2InitAttribStream(vertexShader.getAttributeBuffer(0), positionLocation, 0, 0, GX2_ATTRIB_FORMAT_32_32_32_FLOAT);
|
||||||
|
GX2InitAttribStream(vertexShader.getAttributeBuffer(1), colorLocation, 1, 0, GX2_ATTRIB_FORMAT_8_8_8_8_UNORM);
|
||||||
|
|
||||||
|
//! create fetch shader
|
||||||
|
fetchShader = new FetchShader(vertexShader.getAttributeBuffer(), vertexShader.getAttributesCount());
|
||||||
|
|
||||||
|
//! model vertex has to be align and cannot be in unknown regions for GX2 like 0xBCAE1000
|
||||||
|
positionVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, cuPositionVtxsSize);
|
||||||
|
if(positionVtxs)
|
||||||
|
{
|
||||||
|
//! position vertex structure
|
||||||
|
s32 i = 0;
|
||||||
|
positionVtxs[i++] = -1.0f; positionVtxs[i++] = -1.0f; positionVtxs[i++] = 0.0f;
|
||||||
|
positionVtxs[i++] = 1.0f; positionVtxs[i++] = -1.0f; positionVtxs[i++] = 0.0f;
|
||||||
|
positionVtxs[i++] = 1.0f; positionVtxs[i++] = 1.0f; positionVtxs[i++] = 0.0f;
|
||||||
|
positionVtxs[i++] = -1.0f; positionVtxs[i++] = 1.0f; positionVtxs[i++] = 0.0f;
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, positionVtxs, cuPositionVtxsSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorShader::~ColorShader()
|
||||||
|
{
|
||||||
|
if(positionVtxs)
|
||||||
|
{
|
||||||
|
free(positionVtxs);
|
||||||
|
positionVtxs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete fetchShader;
|
||||||
|
fetchShader = NULL;
|
||||||
|
}
|
100
source/video/shaders/ColorShader.h
Normal file
100
source/video/shaders/ColorShader.h
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef __COLOR_SHADER_H_
|
||||||
|
#define __COLOR_SHADER_H_
|
||||||
|
|
||||||
|
#include "VertexShader.h"
|
||||||
|
#include "PixelShader.h"
|
||||||
|
#include "FetchShader.h"
|
||||||
|
|
||||||
|
class ColorShader : public Shader
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ColorShader();
|
||||||
|
virtual ~ColorShader();
|
||||||
|
|
||||||
|
static const u32 cuAttributeCount = 2;
|
||||||
|
static const u32 cuPositionVtxsSize = 4 * cuVertexAttrSize;
|
||||||
|
|
||||||
|
static ColorShader *shaderInstance;
|
||||||
|
|
||||||
|
FetchShader *fetchShader;
|
||||||
|
VertexShader vertexShader;
|
||||||
|
PixelShader pixelShader;
|
||||||
|
|
||||||
|
f32 *positionVtxs;
|
||||||
|
|
||||||
|
u32 angleLocation;
|
||||||
|
u32 offsetLocation;
|
||||||
|
u32 scaleLocation;
|
||||||
|
u32 colorLocation;
|
||||||
|
u32 colorIntensityLocation;
|
||||||
|
u32 positionLocation;
|
||||||
|
public:
|
||||||
|
static const u32 cuColorVtxsSize = 4 * cuColorAttrSize;
|
||||||
|
|
||||||
|
static ColorShader *instance() {
|
||||||
|
if(!shaderInstance) {
|
||||||
|
shaderInstance = new ColorShader();
|
||||||
|
}
|
||||||
|
return shaderInstance;
|
||||||
|
}
|
||||||
|
static void destroyInstance() {
|
||||||
|
if(shaderInstance) {
|
||||||
|
delete shaderInstance;
|
||||||
|
shaderInstance = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setShaders(void) const
|
||||||
|
{
|
||||||
|
fetchShader->setShader();
|
||||||
|
vertexShader.setShader();
|
||||||
|
pixelShader.setShader();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAttributeBuffer(const u8 * colorAttr, const f32 * posVtxs_in = NULL, const u32 & vtxCount = 0) const
|
||||||
|
{
|
||||||
|
if(posVtxs_in && vtxCount) {
|
||||||
|
VertexShader::setAttributeBuffer(0, vtxCount * cuVertexAttrSize, cuVertexAttrSize, posVtxs_in);
|
||||||
|
VertexShader::setAttributeBuffer(1, vtxCount * cuColorAttrSize, cuColorAttrSize, colorAttr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
VertexShader::setAttributeBuffer(0, cuPositionVtxsSize, cuVertexAttrSize, positionVtxs);
|
||||||
|
VertexShader::setAttributeBuffer(1, cuColorVtxsSize, cuColorAttrSize, colorAttr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAngle(const float & val)
|
||||||
|
{
|
||||||
|
VertexShader::setUniformReg(angleLocation, 4, &val);
|
||||||
|
}
|
||||||
|
void setOffset(const glm::vec3 & vec)
|
||||||
|
{
|
||||||
|
VertexShader::setUniformReg(offsetLocation, 4, &vec[0]);
|
||||||
|
}
|
||||||
|
void setScale(const glm::vec3 & vec)
|
||||||
|
{
|
||||||
|
VertexShader::setUniformReg(scaleLocation, 4, &vec[0]);
|
||||||
|
}
|
||||||
|
void setColorIntensity(const glm::vec4 & vec)
|
||||||
|
{
|
||||||
|
PixelShader::setUniformReg(colorIntensityLocation, 4, &vec[0]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __COLOR_SHADER_H_
|
230
source/video/shaders/FXAAShader.cpp
Normal file
230
source/video/shaders/FXAAShader.cpp
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "FXAAShader.h"
|
||||||
|
|
||||||
|
static const u32 cpVertexShaderProgram[] =
|
||||||
|
{
|
||||||
|
0x00000000,0x00008009,0x20000000,0x000004a0,
|
||||||
|
0x3ca00000,0x88060094,0x00400000,0xff0f2094,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0xfd001f80,0x900c2060,0x0000803f,0x00000000,
|
||||||
|
0xc1a229f5,0xd0eddc33,0x426618fd,0x8509cfe7
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u32 cpVertexShaderRegs[] = {
|
||||||
|
0x00000102,0x00000000,0x00000000,0x00000001,
|
||||||
|
0xffffffff,0xffffffff,0xffffffff,0xffffffff,
|
||||||
|
0xffffffff,0xffffffff,0xffffffff,0xffffffff,
|
||||||
|
0xffffffff,0xffffffff,0x00000000,0xfffffffe,
|
||||||
|
0x00000001,0x00000000,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x00000000,0x0000000e,0x00000010
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u32 cpPixelShaderProgram[] =
|
||||||
|
{
|
||||||
|
0x20000000,0x00003ca0,0xa0000000,0x000c8080,
|
||||||
|
0x30000000,0x000010a1,0xa8000000,0x0010c080,
|
||||||
|
0x75000000,0x000088a0,0x00800100,0x88062094,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00241f02,0x1000e00f,0x00241f00,0x1000e02f,
|
||||||
|
0x00201f02,0x00000040,0x00201f00,0x00000060,
|
||||||
|
0x00011f80,0x10332060,0xff000000,0xff102200,
|
||||||
|
0xfd001f00,0x900cc020,0xffc09f01,0x90004040,
|
||||||
|
0xffc01f01,0x90000060,0x00051f80,0x1033a040,
|
||||||
|
0x0000803f,0x00000000,0xffe00f00,0x90004000,
|
||||||
|
0xff008000,0xff102220,0xffe08f00,0x90000440,
|
||||||
|
0x010c0000,0x010c4660,0xff008080,0xff004220,
|
||||||
|
0x01a01f00,0x00280000,0x01a49f00,0x00280020,
|
||||||
|
0x01a81f01,0x00280040,0xfd0c1f00,0x1028e06f,
|
||||||
|
0x00208081,0x90002000,0x8716993e,0xa245163f,
|
||||||
|
0xd578e93d,0x00000080,0x03a01f00,0x00280000,
|
||||||
|
0x03a49f00,0x00280020,0x03a81f01,0x1028e04f,
|
||||||
|
0xfd0c1f00,0x00280060,0x00a40081,0x90002020,
|
||||||
|
0x8716993e,0xa245163f,0xd578e93d,0x00000080,
|
||||||
|
0x04a01f00,0x00280000,0x04a49f00,0x1028a02f,
|
||||||
|
0x04a81f01,0x00280040,0xfd0c1f00,0x00280060,
|
||||||
|
0x7fcc1f80,0x1000c02f,0x8716993e,0xa245163f,
|
||||||
|
0xd578e93d,0x00000080,0x02a01f00,0x1028e00f,
|
||||||
|
0x02a49f00,0x00280020,0x02a81f01,0x00280040,
|
||||||
|
0xfd0c1f00,0x00280060,0x7fcc1f80,0x1000e02f,
|
||||||
|
0x8716993e,0xa245163f,0xd578e93d,0x00000080,
|
||||||
|
0x7dc41f00,0x00020000,0x7fec0f01,0x00020020,
|
||||||
|
0x7fc81f00,0x00000040,0x7dc41f00,0x00000060,
|
||||||
|
0x7fec0f81,0x9001802f,0xfef88f00,0x1000e00f,
|
||||||
|
0xfedc8f00,0x00000420,0x7de40f00,0x80010040,
|
||||||
|
0x7ec49f01,0x00001060,0xfec41f80,0x10024060,
|
||||||
|
0xfed49f00,0x80020000,0xfe141f00,0x900c802f,
|
||||||
|
0xfeac1f00,0x80000040,0xfec01f02,0x80020060,
|
||||||
|
0x7cc41f81,0x90010060,0x0000003d,0x00000000,
|
||||||
|
0xfd001f00,0x900c6000,0xfea89f00,0x80010020,
|
||||||
|
0xfec09f81,0x00020040,0x0000803f,0x0000003e,
|
||||||
|
0xfec41f81,0x00000020,0xfe041f80,0x00330000,
|
||||||
|
0x7fe01f00,0x80000040,0x7ce41f80,0x80000060,
|
||||||
|
0xfea81f00,0x80010000,0xfeac1f80,0x80010020,
|
||||||
|
0x000000c1,0x00000000,0xfea01f00,0x00020040,
|
||||||
|
0xfea41f80,0x00020060,0x00000041,0x00000000,
|
||||||
|
0x05c81f01,0x9000e00f,0x01cc9f81,0x9000e06f,
|
||||||
|
0xfeac1f00,0x01004200,0xfea01f00,0x01044220,
|
||||||
|
0xfeac9f00,0x01002240,0xfea09f00,0x01042260,
|
||||||
|
0xfe8c1f80,0x01008600,0xacaa2a3e,0xaaaa2abe,
|
||||||
|
0x7f9c1f00,0x0100a200,0x7f801f00,0x01048220,
|
||||||
|
0x7f901f80,0x0104a240,0x02080001,0x7000a00f,
|
||||||
|
0x02000000,0x7000c04f,0x02048000,0x7000e06f,
|
||||||
|
0x01a81f80,0x9000e00f,0xd578e93d,0x00000000,
|
||||||
|
0x04a80001,0x1000c00f,0x04a48000,0x00000020,
|
||||||
|
0x04a00000,0x00000040,0xfe081f00,0xe00c0060,
|
||||||
|
0xfe0c1f80,0xe00c0000,0x01a41f00,0x7f00620f,
|
||||||
|
0xfea89f00,0xfe0c822f,0xfea49f00,0xff00a24f,
|
||||||
|
0x7d001f80,0xe00c0060,0xa245163f,0x0000803e,
|
||||||
|
0x7ea01f00,0xfe0ce20f,0x01a09f80,0xfe006a4f,
|
||||||
|
0x0000803e,0x8716993e,0xfe088001,0x9001c00f,
|
||||||
|
0xfe488001,0x1002e44f,0xfea01f80,0x80000000,
|
||||||
|
0xd578e93d,0x00000000,0x7ca41f00,0x00280000,
|
||||||
|
0x7da89f00,0x00280020,0xff201f00,0x00280040,
|
||||||
|
0xfd081f80,0x00280060,0x8716993e,0xa245163f,
|
||||||
|
0x00000080,0x00000000,0x7fc81f00,0x80060000,
|
||||||
|
0xfec00f80,0x80060060,0xfec09f81,0xfb80634f,
|
||||||
|
0xfe888f00,0x7e886300,0xfea80f01,0x7f8c6320,
|
||||||
|
0xfee80f00,0x7d806340,0xfe680080,0x06846f60,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x10000100,0x01101df0,0x00008010,0xecdfea0d,
|
||||||
|
0x10000200,0x03101df0,0x00002050,0xecdfea0d,
|
||||||
|
0x10000000,0x04101df0,0x00003071,0xecdfea0d,
|
||||||
|
0x10000200,0x02101df0,0x0000b070,0xecdfea0d,
|
||||||
|
0x10000200,0x02101df0,0x00008010,0xecdfea0d,
|
||||||
|
0x10000100,0x00101df0,0x0000a051,0xecdfea0d,
|
||||||
|
0x10000400,0x04101df0,0x00008010,0xecdfea0d,
|
||||||
|
0x10000500,0x05101df0,0x00000011,0xecdfea0d,
|
||||||
|
0x10000100,0x01101df0,0x00008010,0xecdfea0d,
|
||||||
|
0xfe2e963a,0x0269a9a3,0x38f88096,0x400cf48b
|
||||||
|
};
|
||||||
|
static const u32 cpPixelShaderRegs[] = {
|
||||||
|
0x00000007,0x00000002,0x04000101,0x00000000,
|
||||||
|
0x00000001,0x00000100,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x0000000f,0x00000001,0x00000010,
|
||||||
|
0x00000000
|
||||||
|
};
|
||||||
|
|
||||||
|
FXAAShader * FXAAShader::shaderInstance = NULL;
|
||||||
|
|
||||||
|
FXAAShader::FXAAShader()
|
||||||
|
: vertexShader(cuAttributeCount)
|
||||||
|
{
|
||||||
|
//! create pixel shader
|
||||||
|
pixelShader.setProgram(cpPixelShaderProgram, sizeof(cpPixelShaderProgram), cpPixelShaderRegs, sizeof(cpPixelShaderRegs));
|
||||||
|
|
||||||
|
resolutionLocation = 0;
|
||||||
|
pixelShader.addUniformVar((GX2UniformVar){ "unf_resolution", GX2_VAR_TYPE_VEC2, 1, resolutionLocation, 0xffffffff });
|
||||||
|
|
||||||
|
samplerLocation = 0;
|
||||||
|
pixelShader.addSamplerVar((GX2SamplerVar){ "sampl_texture", GX2_SAMPLER_TYPE_2D, samplerLocation });
|
||||||
|
|
||||||
|
//! create vertex shader
|
||||||
|
vertexShader.setProgram(cpVertexShaderProgram, sizeof(cpVertexShaderProgram), cpVertexShaderRegs, sizeof(cpVertexShaderRegs));
|
||||||
|
|
||||||
|
positionLocation = 0;
|
||||||
|
texCoordLocation = 1;
|
||||||
|
vertexShader.addAttribVar((GX2AttribVar){ "attr_position", GX2_VAR_TYPE_VEC3, 0, positionLocation });
|
||||||
|
vertexShader.addAttribVar((GX2AttribVar){ "attr_texture_coord", GX2_VAR_TYPE_VEC2, 0, texCoordLocation });
|
||||||
|
|
||||||
|
//! setup attribute streams
|
||||||
|
GX2InitAttribStream(vertexShader.getAttributeBuffer(0), positionLocation, 0, 0, GX2_ATTRIB_FORMAT_32_32_32_FLOAT);
|
||||||
|
GX2InitAttribStream(vertexShader.getAttributeBuffer(1), texCoordLocation, 1, 0, GX2_ATTRIB_FORMAT_32_32_FLOAT);
|
||||||
|
|
||||||
|
//! create fetch shader
|
||||||
|
fetchShader = new FetchShader(vertexShader.getAttributeBuffer(), vertexShader.getAttributesCount());
|
||||||
|
|
||||||
|
//! model vertex has to be align and cannot be in unknown regions for GX2 like 0xBCAE1000
|
||||||
|
posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciPositionVtxsSize);
|
||||||
|
texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciTexCoordsVtxsSize);
|
||||||
|
|
||||||
|
//! position vertex structure and texture coordinate vertex structure
|
||||||
|
s32 i = 0;
|
||||||
|
posVtxs[i++] = -1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f;
|
||||||
|
posVtxs[i++] = 1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f;
|
||||||
|
posVtxs[i++] = 1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f;
|
||||||
|
posVtxs[i++] = -1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f;
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, posVtxs, ciPositionVtxsSize);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
texCoords[i++] = 0.0f; texCoords[i++] = 1.0f;
|
||||||
|
texCoords[i++] = 1.0f; texCoords[i++] = 1.0f;
|
||||||
|
texCoords[i++] = 1.0f; texCoords[i++] = 0.0f;
|
||||||
|
texCoords[i++] = 0.0f; texCoords[i++] = 0.0f;
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, texCoords, ciTexCoordsVtxsSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
FXAAShader::~FXAAShader()
|
||||||
|
{
|
||||||
|
if(posVtxs)
|
||||||
|
{
|
||||||
|
free(posVtxs);
|
||||||
|
posVtxs = NULL;
|
||||||
|
}
|
||||||
|
if(texCoords)
|
||||||
|
{
|
||||||
|
free(texCoords);
|
||||||
|
texCoords = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete fetchShader;
|
||||||
|
fetchShader = NULL;
|
||||||
|
}
|
86
source/video/shaders/FXAAShader.h
Normal file
86
source/video/shaders/FXAAShader.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef __FXAA_SHADER_H_
|
||||||
|
#define __FXAA_SHADER_H_
|
||||||
|
|
||||||
|
#include "VertexShader.h"
|
||||||
|
#include "PixelShader.h"
|
||||||
|
#include "FetchShader.h"
|
||||||
|
|
||||||
|
class FXAAShader : public Shader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static FXAAShader *instance() {
|
||||||
|
if(!shaderInstance) {
|
||||||
|
shaderInstance = new FXAAShader();
|
||||||
|
}
|
||||||
|
return shaderInstance;
|
||||||
|
}
|
||||||
|
static void destroyInstance() {
|
||||||
|
if(shaderInstance) {
|
||||||
|
delete shaderInstance;
|
||||||
|
shaderInstance = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setShaders(void) const
|
||||||
|
{
|
||||||
|
fetchShader->setShader();
|
||||||
|
vertexShader.setShader();
|
||||||
|
pixelShader.setShader();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAttributeBuffer() const
|
||||||
|
{
|
||||||
|
VertexShader::setAttributeBuffer(0, ciPositionVtxsSize, cuVertexAttrSize, posVtxs);
|
||||||
|
VertexShader::setAttributeBuffer(1, ciTexCoordsVtxsSize, cuTexCoordAttrSize, texCoords);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setResolution(const glm::vec2 & vec)
|
||||||
|
{
|
||||||
|
PixelShader::setUniformReg(resolutionLocation, 4, &vec[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTextureAndSampler(const GX2Texture *texture, const GX2Sampler *sampler) const {
|
||||||
|
GX2SetPixelTexture(texture, samplerLocation);
|
||||||
|
GX2SetPixelSampler(sampler, samplerLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FXAAShader();
|
||||||
|
virtual ~FXAAShader();
|
||||||
|
|
||||||
|
static const u32 cuAttributeCount = 2;
|
||||||
|
static const u32 ciPositionVtxsSize = 4 * cuVertexAttrSize;
|
||||||
|
static const u32 ciTexCoordsVtxsSize = 4 * cuTexCoordAttrSize;
|
||||||
|
|
||||||
|
static FXAAShader *shaderInstance;
|
||||||
|
|
||||||
|
FetchShader *fetchShader;
|
||||||
|
VertexShader vertexShader;
|
||||||
|
PixelShader pixelShader;
|
||||||
|
|
||||||
|
f32 *posVtxs;
|
||||||
|
f32 *texCoords;
|
||||||
|
|
||||||
|
u32 samplerLocation;
|
||||||
|
u32 positionLocation;
|
||||||
|
u32 texCoordLocation;
|
||||||
|
u32 resolutionLocation;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __FXAA_SHADER_H_
|
58
source/video/shaders/FetchShader.h
Normal file
58
source/video/shaders/FetchShader.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef FETCH_SHADER_H
|
||||||
|
#define FETCH_SHADER_H
|
||||||
|
|
||||||
|
#include "Shader.h"
|
||||||
|
|
||||||
|
class FetchShader : public Shader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FetchShader(GX2AttribStream * attributes, u32 attrCount, s32 type = GX2_FETCH_SHADER_TESSELATION_NONE, s32 tess = GX2_TESSELLATION_MODE_DISCRETE)
|
||||||
|
: fetchShader(NULL)
|
||||||
|
, fetchShaderProgramm(NULL)
|
||||||
|
{
|
||||||
|
u32 shaderSize = GX2CalcFetchShaderSizeEx(attrCount, type, tess);
|
||||||
|
fetchShaderProgramm = memalign(GX2_SHADER_ALIGNMENT, shaderSize);
|
||||||
|
if(fetchShaderProgramm)
|
||||||
|
{
|
||||||
|
fetchShader = new GX2FetchShader;
|
||||||
|
GX2InitFetchShaderEx(fetchShader, fetchShaderProgramm, attrCount, attributes, type, tess);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_SHADER, fetchShaderProgramm, shaderSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual ~FetchShader() {
|
||||||
|
if(fetchShaderProgramm)
|
||||||
|
free(fetchShaderProgramm);
|
||||||
|
if(fetchShader)
|
||||||
|
delete fetchShader;
|
||||||
|
}
|
||||||
|
|
||||||
|
GX2FetchShader *getFetchShader() const {
|
||||||
|
return fetchShader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setShader(void) const {
|
||||||
|
GX2SetFetchShader(fetchShader);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
GX2FetchShader *fetchShader;
|
||||||
|
void *fetchShaderProgramm;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FETCH_SHADER_H
|
150
source/video/shaders/PixelShader.h
Normal file
150
source/video/shaders/PixelShader.h
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef PIXEL_SHADER_H
|
||||||
|
#define PIXEL_SHADER_H
|
||||||
|
|
||||||
|
#include "Shader.h"
|
||||||
|
|
||||||
|
class PixelShader : public Shader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PixelShader()
|
||||||
|
: pixelShader((GX2PixelShader*) memalign(0x40, sizeof(GX2PixelShader)))
|
||||||
|
{
|
||||||
|
if(pixelShader)
|
||||||
|
{
|
||||||
|
memset(pixelShader, 0, sizeof(GX2PixelShader));
|
||||||
|
pixelShader->shader_mode = GX2_SHADER_MODE_UNIFORM_REGISTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual ~PixelShader()
|
||||||
|
{
|
||||||
|
if(pixelShader)
|
||||||
|
{
|
||||||
|
if(pixelShader->shader_data)
|
||||||
|
free(pixelShader->shader_data);
|
||||||
|
|
||||||
|
for(u32 i = 0; i < pixelShader->uniform_blocks_count; i++)
|
||||||
|
free((void*)pixelShader->uniform_block[i].name);
|
||||||
|
|
||||||
|
if(pixelShader->uniform_block)
|
||||||
|
free((void*)pixelShader->uniform_block);
|
||||||
|
|
||||||
|
for(u32 i = 0; i < pixelShader->uniform_vars_count; i++)
|
||||||
|
free((void*)pixelShader->uniform_var[i].name);
|
||||||
|
|
||||||
|
if(pixelShader->uniform_var)
|
||||||
|
free((void*)pixelShader->uniform_var);
|
||||||
|
|
||||||
|
if(pixelShader->initial_value)
|
||||||
|
free((void*)pixelShader->initial_value);
|
||||||
|
|
||||||
|
for(u32 i = 0; i < pixelShader->sampler_vars_count; i++)
|
||||||
|
free((void*)pixelShader->sampler_var[i].name);
|
||||||
|
|
||||||
|
if(pixelShader->sampler_var)
|
||||||
|
free((void*)pixelShader->sampler_var);
|
||||||
|
|
||||||
|
if(pixelShader->loops_data)
|
||||||
|
free((void*)pixelShader->loops_data);
|
||||||
|
|
||||||
|
free(pixelShader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setProgram(const u32 * program, const u32 & programSize, const u32 * regs, const u32 & regsSize)
|
||||||
|
{
|
||||||
|
if(!pixelShader)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//! this must be moved into an area where the graphic engine has access to and must be aligned to 0x100
|
||||||
|
pixelShader->shader_size = programSize;
|
||||||
|
pixelShader->shader_data = memalign(GX2_SHADER_ALIGNMENT, pixelShader->shader_size);
|
||||||
|
if(pixelShader->shader_data)
|
||||||
|
{
|
||||||
|
memcpy(pixelShader->shader_data, program, pixelShader->shader_size);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_SHADER, pixelShader->shader_data, pixelShader->shader_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(pixelShader->regs, regs, regsSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addUniformVar(const GX2UniformVar & var)
|
||||||
|
{
|
||||||
|
if(!pixelShader)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u32 idx = pixelShader->uniform_vars_count;
|
||||||
|
|
||||||
|
GX2UniformVar* newVar = (GX2UniformVar*) malloc((pixelShader->uniform_vars_count + 1) * sizeof(GX2UniformVar));
|
||||||
|
if(newVar)
|
||||||
|
{
|
||||||
|
if(pixelShader->uniform_var)
|
||||||
|
{
|
||||||
|
memcpy(newVar, pixelShader->uniform_var, pixelShader->uniform_vars_count * sizeof(GX2UniformVar));
|
||||||
|
free(pixelShader->uniform_var);
|
||||||
|
}
|
||||||
|
pixelShader->uniform_var = newVar;
|
||||||
|
|
||||||
|
memcpy(pixelShader->uniform_var + idx, &var, sizeof(GX2UniformVar));
|
||||||
|
pixelShader->uniform_var[idx].name = (char*) malloc(strlen(var.name) + 1);
|
||||||
|
strcpy((char*)pixelShader->uniform_var[idx].name, var.name);
|
||||||
|
|
||||||
|
pixelShader->uniform_vars_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addSamplerVar(const GX2SamplerVar & var)
|
||||||
|
{
|
||||||
|
if(!pixelShader)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u32 idx = pixelShader->sampler_vars_count;
|
||||||
|
|
||||||
|
GX2SamplerVar* newVar = (GX2SamplerVar*) malloc((pixelShader->sampler_vars_count + 1) * sizeof(GX2SamplerVar));
|
||||||
|
if(newVar)
|
||||||
|
{
|
||||||
|
if(pixelShader->sampler_var)
|
||||||
|
{
|
||||||
|
memcpy(newVar, pixelShader->sampler_var, pixelShader->sampler_vars_count * sizeof(GX2SamplerVar));
|
||||||
|
free(pixelShader->sampler_var);
|
||||||
|
}
|
||||||
|
pixelShader->sampler_var = newVar;
|
||||||
|
|
||||||
|
memcpy(pixelShader->sampler_var + idx, &var, sizeof(GX2SamplerVar));
|
||||||
|
pixelShader->sampler_var[idx].name = (char*) malloc(strlen(var.name) + 1);
|
||||||
|
strcpy((char*)pixelShader->sampler_var[idx].name, var.name);
|
||||||
|
|
||||||
|
pixelShader->sampler_vars_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GX2PixelShader * getPixelShader() const {
|
||||||
|
return pixelShader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setShader(void) const {
|
||||||
|
GX2SetPixelShader(pixelShader);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void setUniformReg(u32 location, u32 size, const void * reg) {
|
||||||
|
GX2SetPixelUniformReg(location, size, reg);
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
GX2PixelShader *pixelShader;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PIXEL_SHADER_H
|
74
source/video/shaders/Shader.h
Normal file
74
source/video/shaders/Shader.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef SHADER_H_
|
||||||
|
#define SHADER_H_
|
||||||
|
|
||||||
|
#include "glm/glm.hpp"
|
||||||
|
#include "glm/gtc/matrix_transform.hpp"
|
||||||
|
#include <dynamic_libs/gx2_functions.h>
|
||||||
|
#include <utils/utils.h>
|
||||||
|
|
||||||
|
class Shader
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
Shader() {}
|
||||||
|
virtual ~Shader() {}
|
||||||
|
public:
|
||||||
|
static const u16 cuVertexAttrSize = sizeof(f32) * 3;
|
||||||
|
static const u16 cuTexCoordAttrSize = sizeof(f32) * 2;
|
||||||
|
static const u16 cuColorAttrSize = sizeof(u8) * 4;
|
||||||
|
|
||||||
|
static void setLineWidth(const f32 & width) {
|
||||||
|
GX2SetLineWidth(width);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw(s32 primitive = GX2_PRIMITIVE_QUADS, u32 vtxCount = 4)
|
||||||
|
{
|
||||||
|
switch(primitive)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case GX2_PRIMITIVE_QUADS:
|
||||||
|
{
|
||||||
|
GX2DrawEx(GX2_PRIMITIVE_QUADS, vtxCount, 0, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GX2_PRIMITIVE_TRIANGLES:
|
||||||
|
{
|
||||||
|
GX2DrawEx(GX2_PRIMITIVE_TRIANGLES, vtxCount, 0, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GX2_PRIMITIVE_TRIANGLE_FAN:
|
||||||
|
{
|
||||||
|
GX2DrawEx(GX2_PRIMITIVE_TRIANGLE_FAN, vtxCount, 0, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GX2_PRIMITIVE_LINES:
|
||||||
|
{
|
||||||
|
GX2DrawEx(GX2_PRIMITIVE_LINES, vtxCount, 0, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GX2_PRIMITIVE_LINE_STRIP:
|
||||||
|
{
|
||||||
|
GX2DrawEx(GX2_PRIMITIVE_LINE_STRIP, vtxCount, 0, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//! TODO: add other primitives later
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHADER_H_
|
266
source/video/shaders/Shader3D.cpp
Normal file
266
source/video/shaders/Shader3D.cpp
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "Shader3D.h"
|
||||||
|
|
||||||
|
static const u32 cpVertexShaderProgram[] =
|
||||||
|
{
|
||||||
|
0x00000000,0x00008009,0x20000000,0x0000e4a1,
|
||||||
|
0x00c00100,0x88048093,0x01c00300,0x98060014,
|
||||||
|
0x9a000000,0x000058a0,0x3c200200,0x88062094,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x0765a101,0x9000e00f,0x0761a101,0x9000e02f,
|
||||||
|
0x01081f00,0x900ce040,0x01041f00,0x900ce060,
|
||||||
|
0x01001f80,0x900ce000,0x02001f00,0x900c6000,
|
||||||
|
0x02041f00,0x900c6020,0x076da101,0x9000e04f,
|
||||||
|
0x0769a181,0x9000e06f,0x0745a101,0x9000c00f,
|
||||||
|
0x0741a181,0x9000c02f,0x074da101,0x9000c04f,
|
||||||
|
0x0749a181,0x9000c06f,0x0bc9a000,0x7f00e20f,
|
||||||
|
0x0bc92080,0x7f04e22f,0x0bc9a001,0x7f08e24f,
|
||||||
|
0x0bc92081,0x7f0ce26f,0x0725a101,0x9000a00f,
|
||||||
|
0x0721a181,0x9000a02f,0x072da101,0x9000a04f,
|
||||||
|
0x0729a181,0x9000a06f,0x0ac9a000,0x7e00c20f,
|
||||||
|
0x0ac92080,0x7e04c22f,0x0ac9a001,0x7e08c24f,
|
||||||
|
0x0ac92081,0x7e0cc26f,0x0ba5a000,0x7f00e20f,
|
||||||
|
0x0ba52080,0x7f04e22f,0x0ba5a001,0x7f08e24f,
|
||||||
|
0x0ba52081,0x7f0ce26f,0x08eda000,0x9000800f,
|
||||||
|
0x08ed2080,0x9000802f,0x08eda001,0x9000804f,
|
||||||
|
0x08ed2081,0x9000806f,0x09c9a000,0x7d00a20f,
|
||||||
|
0x09c92080,0x7d04a22f,0x09c9a001,0x7d08a24f,
|
||||||
|
0x09c92081,0x7d0ca26f,0x0aa5a000,0x7e00c20f,
|
||||||
|
0x0aa52080,0x7e04c22f,0x0aa5a001,0x7e08c24f,
|
||||||
|
0x0aa52081,0x7e0cc26f,0x0b81a000,0x7f004200,
|
||||||
|
0x0b812080,0x7f044220,0x0b81a001,0x7f082240,
|
||||||
|
0x0b812081,0x7f0c0260,0x08c9a000,0x7c00820f,
|
||||||
|
0x08c92080,0x7c04822f,0x08c9a001,0x7c08824f,
|
||||||
|
0x08c92081,0x7c0c826f,0x09a5a000,0x7d00a20f,
|
||||||
|
0x09a52080,0x7d04a22f,0x09a5a001,0x7d08a24f,
|
||||||
|
0x09a52081,0x7d0ca26f,0x0a81a000,0x7e000200,
|
||||||
|
0x0a812080,0x7e040220,0x0a81a001,0x7e080240,
|
||||||
|
0x0a812081,0x7e0c2260,0x0240a001,0x9000c00f,
|
||||||
|
0x0244a001,0x9000c02f,0x0148a001,0x9000c04f,
|
||||||
|
0x004ca001,0x9000c06f,0x0264a081,0x9000e02f,
|
||||||
|
0x0260a001,0x9000e00f,0x0224a001,0x90002020,
|
||||||
|
0x0168a001,0x9000e04f,0x006ca001,0x9000e06f,
|
||||||
|
0x0220a081,0x90002000,0x08a5a000,0x7c00820f,
|
||||||
|
0x08a52080,0x7c04822f,0x08a5a001,0x7c08824f,
|
||||||
|
0x08a52081,0x7c0c826f,0x0981a000,0x7d008200,
|
||||||
|
0x09812080,0x7d048220,0x0981a001,0x7d084240,
|
||||||
|
0x09812081,0x7d0c4260,0x02090000,0x7e00c20f,
|
||||||
|
0x02098000,0x7e04c22f,0x0128a001,0x9000a04f,
|
||||||
|
0x002ca001,0x9000c06f,0x02298081,0x7e0caa6f,
|
||||||
|
0x03090000,0x7f00e20f,0x03098000,0x7f04e22f,
|
||||||
|
0x02090001,0x7e08f64f,0x03298001,0x7f0ce26f,
|
||||||
|
0x03090081,0x7f08ca4f,0x0881a000,0x7c00c200,
|
||||||
|
0x08812080,0x7c04e220,0x0881a001,0x7c08a240,
|
||||||
|
0x08812081,0x7c0c8260,0x0200a001,0x9000800f,
|
||||||
|
0x0204a001,0x9000802f,0x0108a001,0x9000804f,
|
||||||
|
0x000ca001,0x9000806f,0x01098080,0x0104aa2f,
|
||||||
|
0x01090000,0x0100a20f,0x02858000,0x7e04c22f,
|
||||||
|
0x01090001,0x7d08a24f,0x01298081,0x7e0cc26f,
|
||||||
|
0x02850000,0x7e00f60f,0x03858000,0x7f04622f,
|
||||||
|
0x02450001,0x7f08e24f,0x02458001,0x7d0ca26f,
|
||||||
|
0x03850080,0x7f00ca0f,0x00090000,0x7c004200,
|
||||||
|
0x00098000,0x7c04b220,0x03450001,0x7e08c24f,
|
||||||
|
0x03458001,0x7f0ce26f,0x03e18080,0xfe042620,
|
||||||
|
0x01850000,0x7d00a200,0x01858000,0x7d04622f,
|
||||||
|
0x00090001,0x7c086240,0x00298081,0x7c0c0260,
|
||||||
|
0x02c10000,0x7f000200,0x02e18000,0x7e040620,
|
||||||
|
0x01450001,0x7d088240,0x01458001,0x7e0c6260,
|
||||||
|
0x01e18080,0xfe04c620,0x03c10000,0x7e002200,
|
||||||
|
0x03818001,0x7f0c4220,0x02a10001,0x7f081640,
|
||||||
|
0x02818001,0x7d0c3660,0x03a10081,0x7e082a40,
|
||||||
|
0x07080000,0x0100c20f,0x07088000,0x0104622f,
|
||||||
|
0x00458001,0x000cea4f,0x07288081,0x0204f66f,
|
||||||
|
0x00850000,0x0200620f,0x00858000,0x05046a2f,
|
||||||
|
0x07080001,0x0108c24f,0x01818001,0x030c726f,
|
||||||
|
0x07cc8080,0xfe04c22f,0x01c10000,0x0500660f,
|
||||||
|
0x00e18000,0xfe04622f,0x00450001,0x0308624f,
|
||||||
|
0x07cc9f01,0x7f0ce26f,0x00c10080,0xfe00e60f,
|
||||||
|
0x07cc1f00,0x7e00660f,0x00a10001,0xfe08c22f,
|
||||||
|
0x01a10001,0x0408624f,0x00818001,0x7f086a6f,
|
||||||
|
0x07c09f80,0x7e048200,0x07e00f00,0xfe008220,
|
||||||
|
0x07cc1f01,0x7e086a4f,0x07c09f81,0x7f0c8240,
|
||||||
|
0x07c08f80,0xfe088260,0x2c34800d,0xe3b4f15e,
|
||||||
|
0x7642ed30,0x7408600d
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u32 cpVertexShaderRegs[] = {
|
||||||
|
0x00000108,0x00000000,0x00000002,0x00000001,
|
||||||
|
0xffff0001,0xffffffff,0xffffffff,0xffffffff,
|
||||||
|
0xffffffff,0xffffffff,0xffffffff,0xffffffff,
|
||||||
|
0xffffffff,0xffffffff,0x00000000,0xfffffffc,
|
||||||
|
0x00000002,0x00000000,0x00000001,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x00000000,0x0000000e,0x00000010
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u32 cPixelShaderProgram[] =
|
||||||
|
{
|
||||||
|
0x20000000,0x000008a4,0x03000000,0x01004085,
|
||||||
|
0x23000000,0x000044a8,0x35000000,0x000000a4,
|
||||||
|
0x06000000,0x01004085,0x36000000,0x00002ca8,
|
||||||
|
0x50000000,0x0000c080,0x42000000,0x00001ca0,
|
||||||
|
0x00800000,0x88062094,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0xfd001f80,0x900c0060,0x0000803f,0x00000000,
|
||||||
|
0x02011f80,0x8c110000,0xf8402000,0x9006a00f,
|
||||||
|
0x02552001,0x00000020,0x01248082,0x80020060,
|
||||||
|
0xfe3c1f00,0x1000e04f,0xfe041f80,0x1033c00f,
|
||||||
|
0xfe482081,0x80060020,0xfee40f81,0x0289e30f,
|
||||||
|
0x02c51f80,0x80060060,0xfeec0f80,0x0285634f,
|
||||||
|
0xfec80f80,0x80000060,0xfe4ca081,0x9000e04f,
|
||||||
|
0xfe281f00,0x80060000,0xf8c01f81,0x9006e02f,
|
||||||
|
0xfee00f81,0xfd80636f,0x0000803f,0x00000000,
|
||||||
|
0x7fc49f81,0xf880e34f,0xfe381f80,0x00000000,
|
||||||
|
0x7de00f81,0xfe800360,0x01011f80,0x8c100000,
|
||||||
|
0x00a81f00,0x9000e02f,0x00000082,0x80020060,
|
||||||
|
0x00002040,0x00000000,0xfeac9f80,0xfd00624f,
|
||||||
|
0x3333333f,0x00002040,0xfee88f80,0x0101620f,
|
||||||
|
0x00cc1f80,0x9000e06f,0xf8c09f01,0x80060020,
|
||||||
|
0xfe2c1f80,0x9006e04f,0xfee48f81,0xf880630f,
|
||||||
|
0x7fc81f80,0xfd800360,0x0000803f,0x00000000,
|
||||||
|
0x000ca001,0x80000000,0x00091f00,0x800c0020,
|
||||||
|
0x00051f00,0x800c0040,0x00011f80,0x800c0060,
|
||||||
|
0xfe2c0000,0x90002000,0xfe288000,0x90002020,
|
||||||
|
0xfe240001,0x90002040,0xfe208081,0x90002060,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x10000100,0x01100df0,0x00008010,0xecdfea0d,
|
||||||
|
0x99720984,0x041cab0d,0xa28a9ccd,0x95d199a5
|
||||||
|
};
|
||||||
|
static const u32 cPixelShaderRegs[] = {
|
||||||
|
0x00000102,0x00000002,0x14000002,0x00000000,
|
||||||
|
0x00000002,0x00000100,0x00000101,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x0000000f,0x00000001,0x00000010,
|
||||||
|
0x00000000
|
||||||
|
};
|
||||||
|
|
||||||
|
Shader3D * Shader3D::shaderInstance = NULL;
|
||||||
|
|
||||||
|
Shader3D::Shader3D()
|
||||||
|
: vertexShader(cuAttributeCount)
|
||||||
|
{
|
||||||
|
//! create pixel shader
|
||||||
|
pixelShader.setProgram(cPixelShaderProgram, sizeof(cPixelShaderProgram), cPixelShaderRegs, sizeof(cPixelShaderRegs));
|
||||||
|
|
||||||
|
colorIntensityLocation = 0;
|
||||||
|
fadeDistanceLocation = 4;
|
||||||
|
fadeOutLocation = 8;
|
||||||
|
pixelShader.addUniformVar((GX2UniformVar){ "unf_color_intensity", GX2_VAR_TYPE_VEC4, 1, colorIntensityLocation, 0xffffffff });
|
||||||
|
pixelShader.addUniformVar((GX2UniformVar){ "unf_fade_distance", GX2_VAR_TYPE_FLOAT, 1, fadeDistanceLocation, 0xffffffff });
|
||||||
|
pixelShader.addUniformVar((GX2UniformVar){ "unf_fade_out_alpha", GX2_VAR_TYPE_VEC4, 1, fadeOutLocation, 0xffffffff });
|
||||||
|
|
||||||
|
samplerLocation = 0;
|
||||||
|
pixelShader.addSamplerVar((GX2SamplerVar){ "sampl_texture", GX2_SAMPLER_TYPE_2D, samplerLocation });
|
||||||
|
|
||||||
|
//! create vertex shader
|
||||||
|
vertexShader.setProgram(cpVertexShaderProgram, sizeof(cpVertexShaderProgram), cpVertexShaderRegs, sizeof(cpVertexShaderRegs));
|
||||||
|
|
||||||
|
modelMatrixLocation = 0;
|
||||||
|
projectionMatrixLocation = 16;
|
||||||
|
viewMatrixLocation = 32;
|
||||||
|
vertexShader.addUniformVar((GX2UniformVar){ "modelMatrix", GX2_VAR_TYPE_MAT4, 1, modelMatrixLocation, 0xffffffff });
|
||||||
|
vertexShader.addUniformVar((GX2UniformVar){ "viewMatrix", GX2_VAR_TYPE_MAT4, 1, projectionMatrixLocation, 0xffffffff });
|
||||||
|
vertexShader.addUniformVar((GX2UniformVar){ "projectionMatrix", GX2_VAR_TYPE_MAT4, 1, viewMatrixLocation, 0xffffffff });
|
||||||
|
|
||||||
|
positionLocation = 0;
|
||||||
|
texCoordLocation = 1;
|
||||||
|
vertexShader.addAttribVar((GX2AttribVar){ "attr_position", GX2_VAR_TYPE_VEC3, 0, positionLocation });
|
||||||
|
vertexShader.addAttribVar((GX2AttribVar){ "attr_texture_coord", GX2_VAR_TYPE_VEC2, 0, texCoordLocation });
|
||||||
|
|
||||||
|
//! setup attribute streams
|
||||||
|
GX2InitAttribStream(vertexShader.getAttributeBuffer(0), positionLocation, 0, 0, GX2_ATTRIB_FORMAT_32_32_32_FLOAT);
|
||||||
|
GX2InitAttribStream(vertexShader.getAttributeBuffer(1), texCoordLocation, 1, 0, GX2_ATTRIB_FORMAT_32_32_FLOAT);
|
||||||
|
|
||||||
|
//! create fetch shader
|
||||||
|
fetchShader = new FetchShader(vertexShader.getAttributeBuffer(), vertexShader.getAttributesCount());
|
||||||
|
|
||||||
|
//! initialize default quad texture vertexes as those are very commonly used
|
||||||
|
//! model vertex has to be align and cannot be in unknown regions for GX2 like 0xBCAE1000
|
||||||
|
posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciPositionVtxsSize);
|
||||||
|
texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciTexCoordsVtxsSize);
|
||||||
|
|
||||||
|
//! position vertex structure and texture coordinate vertex structure
|
||||||
|
s32 i = 0;
|
||||||
|
posVtxs[i++] = -1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f;
|
||||||
|
posVtxs[i++] = 1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f;
|
||||||
|
posVtxs[i++] = 1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f;
|
||||||
|
posVtxs[i++] = -1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f;
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, posVtxs, ciPositionVtxsSize);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
texCoords[i++] = 0.0f; texCoords[i++] = 1.0f;
|
||||||
|
texCoords[i++] = 1.0f; texCoords[i++] = 1.0f;
|
||||||
|
texCoords[i++] = 1.0f; texCoords[i++] = 0.0f;
|
||||||
|
texCoords[i++] = 0.0f; texCoords[i++] = 0.0f;
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, texCoords, ciTexCoordsVtxsSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader3D::~Shader3D()
|
||||||
|
{
|
||||||
|
if(posVtxs)
|
||||||
|
{
|
||||||
|
free(posVtxs);
|
||||||
|
posVtxs = NULL;
|
||||||
|
}
|
||||||
|
if(texCoords)
|
||||||
|
{
|
||||||
|
free(texCoords);
|
||||||
|
texCoords = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete fetchShader;
|
||||||
|
fetchShader = NULL;
|
||||||
|
}
|
119
source/video/shaders/Shader3D.h
Normal file
119
source/video/shaders/Shader3D.h
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef SHADER_3D_H_
|
||||||
|
#define SHADER_3D_H_
|
||||||
|
|
||||||
|
#include "VertexShader.h"
|
||||||
|
#include "PixelShader.h"
|
||||||
|
#include "FetchShader.h"
|
||||||
|
|
||||||
|
class Shader3D : public Shader
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Shader3D();
|
||||||
|
virtual ~Shader3D();
|
||||||
|
|
||||||
|
static Shader3D * shaderInstance;
|
||||||
|
|
||||||
|
static const unsigned char cuAttributeCount = 2;
|
||||||
|
static const u32 ciPositionVtxsSize = 4 * cuVertexAttrSize;
|
||||||
|
static const u32 ciTexCoordsVtxsSize = 4 * cuTexCoordAttrSize;
|
||||||
|
|
||||||
|
FetchShader *fetchShader;
|
||||||
|
VertexShader vertexShader;
|
||||||
|
PixelShader pixelShader;
|
||||||
|
|
||||||
|
f32 *posVtxs;
|
||||||
|
f32 *texCoords;
|
||||||
|
|
||||||
|
u32 modelMatrixLocation;
|
||||||
|
u32 viewMatrixLocation;
|
||||||
|
u32 projectionMatrixLocation;
|
||||||
|
u32 positionLocation;
|
||||||
|
u32 texCoordLocation;
|
||||||
|
|
||||||
|
u32 colorIntensityLocation;
|
||||||
|
u32 fadeDistanceLocation;
|
||||||
|
u32 fadeOutLocation;
|
||||||
|
u32 samplerLocation;
|
||||||
|
public:
|
||||||
|
static Shader3D *instance() {
|
||||||
|
if(!shaderInstance) {
|
||||||
|
shaderInstance = new Shader3D();
|
||||||
|
}
|
||||||
|
return shaderInstance;
|
||||||
|
}
|
||||||
|
static void destroyInstance() {
|
||||||
|
if(shaderInstance) {
|
||||||
|
delete shaderInstance;
|
||||||
|
shaderInstance = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setShaders(void) const
|
||||||
|
{
|
||||||
|
fetchShader->setShader();
|
||||||
|
vertexShader.setShader();
|
||||||
|
pixelShader.setShader();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAttributeBuffer(const u32 & vtxCount = 0, const f32 * posVtxs_in = NULL, const f32 * texCoords_in = NULL) const
|
||||||
|
{
|
||||||
|
if(posVtxs_in && texCoords_in && vtxCount)
|
||||||
|
{
|
||||||
|
VertexShader::setAttributeBuffer(0, vtxCount * cuVertexAttrSize, cuVertexAttrSize, posVtxs_in);
|
||||||
|
VertexShader::setAttributeBuffer(1, vtxCount * cuTexCoordAttrSize, cuTexCoordAttrSize, texCoords_in);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//! use default quad vertex and texture coordinates if nothing is passed
|
||||||
|
VertexShader::setAttributeBuffer(0, ciPositionVtxsSize, cuVertexAttrSize, posVtxs);
|
||||||
|
VertexShader::setAttributeBuffer(1, ciTexCoordsVtxsSize, cuTexCoordAttrSize, texCoords);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setProjectionMtx(const glm::mat4 & mtx)
|
||||||
|
{
|
||||||
|
VertexShader::setUniformReg(projectionMatrixLocation, 16, &mtx[0][0]);
|
||||||
|
}
|
||||||
|
void setViewMtx(const glm::mat4 & mtx)
|
||||||
|
{
|
||||||
|
VertexShader::setUniformReg(viewMatrixLocation, 16, &mtx[0][0]);
|
||||||
|
}
|
||||||
|
void setModelViewMtx(const glm::mat4 & mtx)
|
||||||
|
{
|
||||||
|
VertexShader::setUniformReg(modelMatrixLocation, 16, &mtx[0][0]);
|
||||||
|
}
|
||||||
|
void setColorIntensity(const glm::vec4 & vec)
|
||||||
|
{
|
||||||
|
PixelShader::setUniformReg(colorIntensityLocation, 4, &vec[0]);
|
||||||
|
}
|
||||||
|
void setAlphaFadeOut(const glm::vec4 & vec)
|
||||||
|
{
|
||||||
|
PixelShader::setUniformReg(fadeOutLocation, 4, &vec[0]);
|
||||||
|
}
|
||||||
|
void setDistanceFadeOut(const float & value)
|
||||||
|
{
|
||||||
|
PixelShader::setUniformReg(fadeDistanceLocation, 4, &value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTextureAndSampler(const GX2Texture *texture, const GX2Sampler *sampler) const {
|
||||||
|
GX2SetPixelTexture(texture, samplerLocation);
|
||||||
|
GX2SetPixelSampler(sampler, samplerLocation);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHADER_3D_H_
|
373
source/video/shaders/ShaderFractalColor.cpp
Normal file
373
source/video/shaders/ShaderFractalColor.cpp
Normal file
@ -0,0 +1,373 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "ShaderFractalColor.h"
|
||||||
|
|
||||||
|
static const u32 cpVertexShaderProgram[] =
|
||||||
|
{
|
||||||
|
0x00000000,0x00008009,0x20000000,0x0000eca1,
|
||||||
|
0x00c00000,0x88068093,0x01400200,0x9a048013,
|
||||||
|
0x9c000000,0x000044a0,0x3c200000,0x88060094,
|
||||||
|
0x02400000,0x88062014,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x0765a101,0x9000e00f,0x0761a101,0x9000e02f,
|
||||||
|
0x03001f00,0x900c8040,0x03041f80,0x900c8060,
|
||||||
|
0x076da101,0x9000e04f,0x0769a181,0x9000e06f,
|
||||||
|
0x0745a101,0x9000c00f,0x0741a181,0x9000c02f,
|
||||||
|
0x074da101,0x9000c04f,0x0749a181,0x9000c06f,
|
||||||
|
0x0bc9a000,0x7f00e20f,0x0bc92080,0x7f04e22f,
|
||||||
|
0x0bc9a001,0x7f08e24f,0x0bc92081,0x7f0ce26f,
|
||||||
|
0x0725a101,0x9000a00f,0x0721a181,0x9000a02f,
|
||||||
|
0x072da101,0x9000a04f,0x0729a181,0x9000a06f,
|
||||||
|
0x0ac9a000,0x7e00c20f,0x0ac92080,0x7e04c22f,
|
||||||
|
0x0ac9a001,0x7e08c24f,0x0ac92081,0x7e0cc26f,
|
||||||
|
0x0ba5a000,0x7f00e20f,0x0ba52080,0x7f04e22f,
|
||||||
|
0x0ba5a001,0x7f08e24f,0x0ba52081,0x7f0ce26f,
|
||||||
|
0x08eda000,0x9000800f,0x08ed2080,0x9000802f,
|
||||||
|
0x08eda001,0x9000804f,0x08ed2081,0x9000806f,
|
||||||
|
0x09c9a000,0x7d00a20f,0x09c92080,0x7d04a22f,
|
||||||
|
0x09c9a001,0x7d08a24f,0x09c92081,0x7d0ca26f,
|
||||||
|
0x0aa5a000,0x7e00c20f,0x0aa52080,0x7e04c22f,
|
||||||
|
0x0aa5a001,0x7e08c24f,0x0aa52081,0x7e0cc26f,
|
||||||
|
0x0b81a000,0x7f006200,0x0b812080,0x7f046220,
|
||||||
|
0x0b81a001,0x7f080240,0x0b812081,0x7f0c0260,
|
||||||
|
0x08c9a000,0x7c00820f,0x08c92080,0x7c04822f,
|
||||||
|
0x08c9a001,0x7c08824f,0x08c92081,0x7c0c826f,
|
||||||
|
0x09a5a000,0x7d00a20f,0x09a52080,0x7d04a22f,
|
||||||
|
0x09a5a001,0x7d08a24f,0x09a52081,0x7d0ca26f,
|
||||||
|
0x0a81a000,0x7e008200,0x0a812080,0x7e048220,
|
||||||
|
0x0a81a001,0x7e086240,0x0a812081,0x7e0c4260,
|
||||||
|
0x0340a001,0x9000c00f,0x0344a001,0x9000c02f,
|
||||||
|
0x0048a001,0x9000c04f,0x004ca001,0x9000c06f,
|
||||||
|
0x0364a081,0x9000e02f,0x0360a001,0x9000e00f,
|
||||||
|
0x0324a001,0x90000020,0x0068a001,0x9000e04f,
|
||||||
|
0x006ca001,0x9000e06f,0x0320a081,0x90000000,
|
||||||
|
0x08a5a000,0x7c00820f,0x08a52080,0x7c04822f,
|
||||||
|
0x08a5a001,0x7c08824f,0x08a52081,0x7c0c826f,
|
||||||
|
0x0981a000,0x7d00a200,0x09812080,0x7d04a220,
|
||||||
|
0x0981a001,0x7d08a240,0x09812081,0x7d0c6260,
|
||||||
|
0x02890000,0x7e00c20f,0x02898000,0x7e04c22f,
|
||||||
|
0x0028a001,0x9000a04f,0x002ca001,0x9000c06f,
|
||||||
|
0x02498081,0x7e0caa6f,0x03890000,0x7f00e20f,
|
||||||
|
0x03898000,0x7f04e22f,0x02690001,0x7e08f64f,
|
||||||
|
0x03498001,0x7f0ce26f,0x03690081,0x7f08ca4f,
|
||||||
|
0x0881a000,0x7c00c200,0x08812080,0x7c04c220,
|
||||||
|
0x0881a001,0x7c08e240,0x08812081,0x7c0ca260,
|
||||||
|
0x0300a001,0x9000800f,0x0304a001,0x9000802f,
|
||||||
|
0x0008a001,0x9000804f,0x000ca001,0x9000806f,
|
||||||
|
0x01898080,0x0004aa2f,0x01890000,0x0000a20f,
|
||||||
|
0x02a58000,0x7e04c22f,0x01690001,0x7d08a24f,
|
||||||
|
0x01498081,0x7e0cc26f,0x02a50000,0x7e00f60f,
|
||||||
|
0x03a58000,0x7f04622f,0x02a50001,0x7f08e24f,
|
||||||
|
0x02658001,0x7d0ca26f,0x03a50080,0x7f00ca0f,
|
||||||
|
0x00890000,0x7c00820f,0x00898000,0x7c049220,
|
||||||
|
0x03a50001,0x7e08c24f,0x03658001,0x7f0ce26f,
|
||||||
|
0x03c18080,0xfe04862f,0x01a50000,0x7d008200,
|
||||||
|
0x01a58000,0x7d04622f,0x00690001,0x7c086240,
|
||||||
|
0x00498081,0x7c0c4260,0x02c10000,0x7f00e20f,
|
||||||
|
0x02c18000,0x7e04c62f,0x01a50001,0x7d080240,
|
||||||
|
0x01658001,0x7e0c0260,0x01c18080,0xfe040620,
|
||||||
|
0x03c10000,0x7e00620f,0x03a18001,0x7f0c622f,
|
||||||
|
0x02e10001,0x7f08764f,0x02a18001,0x7d0c766f,
|
||||||
|
0x03e10081,0x7e084a0f,0x02e80f00,0xfe000e00,
|
||||||
|
0x02c88f00,0x7c046220,0x02c81f01,0xff00c240,
|
||||||
|
0x02c89f01,0xfe04c260,0x00a50080,0x7c00aa00,
|
||||||
|
0x01c10000,0x0400760f,0x00a58000,0x0404622f,
|
||||||
|
0x00a50001,0x0308e24f,0x00658001,0x020c626f,
|
||||||
|
0x00c10080,0x0500ea0f,0x02c41f00,0x0000620f,
|
||||||
|
0x00c18000,0xfe04c22f,0x01e10001,0x0008624f,
|
||||||
|
0x01a18001,0x000c666f,0x00a18081,0xfe0ce66f,
|
||||||
|
0x00e10001,0x7f08620f,0x02048000,0x03046a2f,
|
||||||
|
0x02c41f01,0x06086a4f,0x02c49f01,0x060c6a6f,
|
||||||
|
0x02e00f80,0xfe000220,0x02c08f00,0xfe040200,
|
||||||
|
0x02e08f01,0xfe0c0240,0x02c01f80,0xfe080260,
|
||||||
|
0x8aa480ad,0x2bfc5ca6,0xb5e05b5b,0xd48dc71c
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u32 cpVertexShaderRegs[] = {
|
||||||
|
0x00000108,0x00000000,0x00000004,0x00000001,
|
||||||
|
0xff000201,0xffffffff,0xffffffff,0xffffffff,
|
||||||
|
0xffffffff,0xffffffff,0xffffffff,0xffffffff,
|
||||||
|
0xffffffff,0xffffffff,0x00000000,0xfffffff8,
|
||||||
|
0x00000003,0x00000001,0x00000000,0x00000002,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x00000000,0x0000000e,0x00000010
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u32 cpPixelShaderProgram[] =
|
||||||
|
{
|
||||||
|
0x20000000,0x000008a4,0x04000000,0x01004085,
|
||||||
|
0x23000000,0x0000eca1,0x9f000000,0x0000e0a8,
|
||||||
|
0xd8000000,0x000000a4,0x07000000,0x01004085,
|
||||||
|
0xd9000000,0x000048a8,0xec000000,0x000000a4,
|
||||||
|
0x0a000000,0x01004085,0xed000000,0x000050a8,
|
||||||
|
0x02010000,0x000030a0,0x00000000,0x88062094,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0xfd001f80,0x900c0060,0x0000803f,0x00000000,
|
||||||
|
0x03011f80,0x8c210000,0xfd001f00,0x900c0000,
|
||||||
|
0xfd001f00,0x900ca02f,0x00000002,0x80020040,
|
||||||
|
0x00048002,0x80020060,0xf8001f80,0x900cc04f,
|
||||||
|
0x0000803f,0x00000000,0xfea81f00,0x9000e00f,
|
||||||
|
0xfeac1f00,0x9000e02f,0xf8001f00,0x900c804f,
|
||||||
|
0xf8001f80,0x900ca06f,0x00000040,0x00000000,
|
||||||
|
0xfea01f00,0x00280000,0xfea41f00,0x00280020,
|
||||||
|
0xfe041f00,0x00280040,0xfd041f80,0x00280060,
|
||||||
|
0xaf67bb3e,0x00000080,0x7fc41f00,0x00000000,
|
||||||
|
0x7fc01f80,0x00000020,0xfe041f00,0x100ac00f,
|
||||||
|
0xfe001f80,0x100ac02f,0xfea01f00,0x00280000,
|
||||||
|
0xfea41f00,0x00280020,0xfe041f00,0x00280040,
|
||||||
|
0xfd041f00,0x1028e06f,0x7fc01f82,0x00000000,
|
||||||
|
0x8c65583e,0x00000080,0x7ea41f00,0x80000000,
|
||||||
|
0x7ea01f00,0x80000020,0xfee01f00,0x10006040,
|
||||||
|
0x7fc48f82,0x00000860,0xa7c4623b,0x00000000,
|
||||||
|
0xfea81f00,0x1000e00f,0x7fcc9f01,0x10006020,
|
||||||
|
0xfe001f00,0x000a0040,0xfe041f00,0x000a0060,
|
||||||
|
0xfea89f80,0x10008040,0x8c65583e,0x3acd13bf,
|
||||||
|
0xfeb81f00,0x7e04c20f,0xfebc1f00,0x7e00822f,
|
||||||
|
0x03c89f00,0x80060040,0xfea49f00,0x1000e06f,
|
||||||
|
0xfea41f81,0x10006060,0x00809043,0x8c65583e,
|
||||||
|
0x3acd13bf,0x00000000,0xfea81f00,0xf880a30f,
|
||||||
|
0xfe001f00,0x900ca02f,0x7dc41f00,0x1000e04f,
|
||||||
|
0xfe081f00,0xfd80636f,0x04081f80,0x900c800f,
|
||||||
|
0x0000803f,0x00000000,0xfea81f00,0xf900620f,
|
||||||
|
0xfea41f00,0xf900622f,0xfe0c1f00,0x900ca04f,
|
||||||
|
0xfec00f00,0x1000c46f,0xfefc0f80,0x10006000,
|
||||||
|
0x00000842,0x00000000,0xfeac1f00,0xf900620f,
|
||||||
|
0x7fc81f00,0x9000c02f,0x7dc49f00,0x9000e04f,
|
||||||
|
0x7df08f01,0x10008060,0x030c1f80,0x900ca02f,
|
||||||
|
0x00000842,0x00000000,0xfea41f00,0x80000000,
|
||||||
|
0x7ecc1f00,0x9000e02f,0x7e688000,0x80000040,
|
||||||
|
0xfea81f00,0x80000060,0x7d6c8081,0x80000000,
|
||||||
|
0xa7c4623b,0x00000000,0xfe001f00,0x000a0000,
|
||||||
|
0xfe0c1f00,0x000a0020,0xfea41f00,0x80000040,
|
||||||
|
0x03648000,0xfe08626f,0x7d648081,0xff00420f,
|
||||||
|
0xa7c4623b,0x00000000,0xfeb01f00,0x7e04620f,
|
||||||
|
0xfeb41f00,0x7f08662f,0x7c800001,0xff006e4f,
|
||||||
|
0xfe081f00,0x000a0060,0x03680081,0xfe0c4e0f,
|
||||||
|
0x00809043,0x00000000,0xfebc1f00,0x7f04620f,
|
||||||
|
0x7cc41f00,0x00000020,0x7cc49f00,0x1000e04f,
|
||||||
|
0xff901f00,0x00000060,0xfe981f80,0x00000000,
|
||||||
|
0x00809043,0x00000000,0xfea81f00,0xf900620f,
|
||||||
|
0x7cc41f00,0x00000020,0x00c09f00,0x1000c04f,
|
||||||
|
0xfe0c1f00,0x80010060,0xff001f80,0x80010000,
|
||||||
|
0x00000842,0x00000000,0xfea81f00,0xf900620f,
|
||||||
|
0xfecc9f01,0x80000020,0x7fc81f00,0x9000e04f,
|
||||||
|
0x7dc89f00,0x1000c86f,0xffe01f80,0x80000000,
|
||||||
|
0x00000842,0x00000000,0xfeac1f00,0xf900620f,
|
||||||
|
0x7ec81f00,0x9000802f,0xfec49f00,0x9000a040,
|
||||||
|
0xfea89f00,0x80000060,0xffe01f80,0x9000a060,
|
||||||
|
0x00000842,0xa7c4623b,0xfea41f00,0x80000000,
|
||||||
|
0x7ecc1f00,0x9000e02f,0xfe0c1f00,0x000a0040,
|
||||||
|
0x7c888081,0x80000000,0xa7c4623b,0x00000000,
|
||||||
|
0xfe001f00,0x000a0000,0xfeb81f00,0x7f08622f,
|
||||||
|
0xfea49f00,0x80000040,0x048c8081,0xff00420f,
|
||||||
|
0x00809043,0xa7c4623b,0xfeb01f00,0x7c04620f,
|
||||||
|
0x03600000,0xff00622f,0xfea49f00,0x80000040,
|
||||||
|
0xfe081f80,0x000a0060,0x00809043,0x0ccec73c,
|
||||||
|
0xfebc1f00,0x7f040200,0xfea09f00,0x90000020,
|
||||||
|
0xfe941f00,0x10000040,0xfe081f80,0x30080060,
|
||||||
|
0x00809043,0x0ccec73c,0x00041f00,0x20080000,
|
||||||
|
0x00a01f00,0x80000020,0x002c1f02,0x1000e04f,
|
||||||
|
0x00081f80,0x80010060,0x0ccec73c,0x00000000,
|
||||||
|
0xfe201f02,0x1000800f,0xfec81f03,0x80020020,
|
||||||
|
0xfe041f00,0x20080040,0xfe881f00,0x00000060,
|
||||||
|
0xfecc9f81,0x9000a06f,0xfe0c1f00,0x000a0000,
|
||||||
|
0xfe801f00,0x00000020,0xfec01f02,0x80020040,
|
||||||
|
0xfe281f02,0x1000c06f,0xfe841f82,0x1000804f,
|
||||||
|
0xfe041f00,0x000a0000,0x7fc81f02,0x00000020,
|
||||||
|
0xfe8c1f00,0x00000040,0xfecc9f03,0x80020060,
|
||||||
|
0xfe881f82,0x1000a00f,0x7cc01f02,0x00000000,
|
||||||
|
0xfe8c1f02,0x1000e02f,0xfec49f00,0x80000040,
|
||||||
|
0xfe081f00,0x000a0060,0x03c89f80,0x9000e04f,
|
||||||
|
0x7ecc9f03,0x00000000,0xfec01f00,0x80000020,
|
||||||
|
0x04c81f00,0x80000040,0x7c880f01,0xfe086a6f,
|
||||||
|
0x7dac8f81,0x9000800f,0x7da00f00,0xfe04620f,
|
||||||
|
0xfec01f00,0x80000020,0x03c01f00,0x80000840,
|
||||||
|
0x03ac0f00,0xfe08c66f,0xfebc9f80,0xfd00420f,
|
||||||
|
0xe07be53f,0x5c8e5a3f,0xfeb09f00,0xfd00620f,
|
||||||
|
0x05e81f00,0x9000f02f,0x7fe48f00,0xfe04624f,
|
||||||
|
0x04ec8f00,0xfe08626f,0x03840f81,0x7f08a20f,
|
||||||
|
0xe07be53f,0x5c8e5a3f,0x7e0c1f00,0x900ce00f,
|
||||||
|
0xfe0c1f00,0x900c802f,0x05cc1f00,0x9000e84f,
|
||||||
|
0xfeb89f80,0xfd00626f,0xe07be53f,0x5c8e5a3f,
|
||||||
|
0x7cc09f81,0x80000020,0x7fa40f00,0x00280000,
|
||||||
|
0xfe848f00,0x00280020,0x7fe80f00,0x00280440,
|
||||||
|
0xfd001f80,0x00280060,0x00000080,0x00000000,
|
||||||
|
0xfdc01f80,0xf800620f,0x00000243,0x00000000,
|
||||||
|
0xfea01f80,0x90000060,0x5555d53f,0x00000000,
|
||||||
|
0x02011f80,0x8c110000,0x02448002,0x80020000,
|
||||||
|
0xf8402000,0x9006a02f,0x02552081,0x00000040,
|
||||||
|
0xfe301f00,0x1000e06f,0xfe081f80,0x1033c02f,
|
||||||
|
0xfe4c2081,0x80060040,0xfee88f81,0x0289e32f,
|
||||||
|
0x02c59f80,0x80060000,0xfee08f80,0x0285636f,
|
||||||
|
0xfecc8f80,0x80000000,0xfe40a081,0x80000060,
|
||||||
|
0x00cc9f81,0x9000e04f,0xfe281f00,0x80060000,
|
||||||
|
0xf8c01f81,0x9006c02f,0xfee00f81,0xfd80636f,
|
||||||
|
0x0000803f,0x00000000,0x7ec49f81,0xf880e34f,
|
||||||
|
0xfe381f80,0x00000000,0x7de40f81,0xfe800360,
|
||||||
|
0x00011f80,0x8c100000,0xf8001f00,0x900ce00f,
|
||||||
|
0x00311f00,0x1000e02f,0x02a41f00,0xf910624f,
|
||||||
|
0x02a01f00,0xf910626f,0x00011f80,0x1033e04f,
|
||||||
|
0x00000040,0x00000000,0xfecc9f03,0x80020000,
|
||||||
|
0xfec81f83,0x80020060,0x7fd49f01,0x00000020,
|
||||||
|
0x7fd41f80,0x00000040,0xfe081f00,0x80010000,
|
||||||
|
0xfe041f80,0x80010060,0xfee00f01,0x80000000,
|
||||||
|
0xfeec0f81,0x80000020,0xfec01f00,0x00280000,
|
||||||
|
0xfec49f00,0x00280020,0x7fe00f00,0x00280040,
|
||||||
|
0xfd001f80,0x00280060,0x00000080,0x00000000,
|
||||||
|
0xfe001f80,0x00350000,0x00ec1f82,0x000c0260,
|
||||||
|
0x01011f00,0x800c0000,0x01051f00,0x800c0020,
|
||||||
|
0x002c1f00,0x80060040,0xf8008001,0x9006e06f,
|
||||||
|
0x01091f80,0x800c0000,0x01c01f00,0x90000000,
|
||||||
|
0xfe088001,0xfd80632f,0x01e81f00,0x90000040,
|
||||||
|
0x01c49f80,0x90000020,0x0000803f,0x00000000,
|
||||||
|
0x7fcc9f80,0xf880630f,0xfe20a081,0x80000000,
|
||||||
|
0x01cc1f80,0x90000060,0xc21e82a7,0x62ccc547,
|
||||||
|
0x1708607c,0x73ea57a6
|
||||||
|
};
|
||||||
|
static const u32 cpPixelShaderRegs[] = {
|
||||||
|
0x00000106,0x00000002,0x14000003,0x00000000,
|
||||||
|
0x00000003,0x00000100,0x00000101,0x00000102,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x0000000f,0x00000001,0x00000010,
|
||||||
|
0x00000000
|
||||||
|
};
|
||||||
|
|
||||||
|
ShaderFractalColor * ShaderFractalColor::shaderInstance = NULL;
|
||||||
|
|
||||||
|
ShaderFractalColor::ShaderFractalColor()
|
||||||
|
: vertexShader(cuAttributeCount)
|
||||||
|
{
|
||||||
|
//! create pixel shader
|
||||||
|
pixelShader.setProgram(cpPixelShaderProgram, sizeof(cpPixelShaderProgram), cpPixelShaderRegs, sizeof(cpPixelShaderRegs));
|
||||||
|
|
||||||
|
blurLocation = 0;
|
||||||
|
colorIntensityLocation = 4;
|
||||||
|
fadeOutLocation = 8;
|
||||||
|
fractalLocation = 12;
|
||||||
|
pixelShader.addUniformVar((GX2UniformVar){ "unf_blur_border", GX2_VAR_TYPE_FLOAT, 1, blurLocation, 0xffffffff });
|
||||||
|
pixelShader.addUniformVar((GX2UniformVar){ "unf_color_intensity", GX2_VAR_TYPE_VEC4, 1, colorIntensityLocation, 0xffffffff });
|
||||||
|
pixelShader.addUniformVar((GX2UniformVar){ "unf_fade_out_alpha", GX2_VAR_TYPE_VEC4, 1, fadeOutLocation, 0xffffffff });
|
||||||
|
pixelShader.addUniformVar((GX2UniformVar){ "unf_fract_alpha", GX2_VAR_TYPE_INT, 1, fractalLocation, 0xffffffff });
|
||||||
|
|
||||||
|
//! create vertex shader
|
||||||
|
vertexShader.setProgram(cpVertexShaderProgram, sizeof(cpVertexShaderProgram), cpVertexShaderRegs, sizeof(cpVertexShaderRegs));
|
||||||
|
|
||||||
|
modelMatrixLocation = 0;
|
||||||
|
projectionMatrixLocation = 16;
|
||||||
|
viewMatrixLocation = 32;
|
||||||
|
vertexShader.addUniformVar((GX2UniformVar){ "modelMatrix", GX2_VAR_TYPE_MAT4, 1, modelMatrixLocation, 0xffffffff });
|
||||||
|
vertexShader.addUniformVar((GX2UniformVar){ "projectionMatrix", GX2_VAR_TYPE_MAT4, 1, projectionMatrixLocation, 0xffffffff });
|
||||||
|
vertexShader.addUniformVar((GX2UniformVar){ "viewMatrix", GX2_VAR_TYPE_MAT4, 1, viewMatrixLocation, 0xffffffff });
|
||||||
|
|
||||||
|
positionLocation = 0;
|
||||||
|
colorLocation = 1;
|
||||||
|
texCoordLocation = 2;
|
||||||
|
vertexShader.addAttribVar((GX2AttribVar){ "attr_colors", GX2_VAR_TYPE_VEC4, 0, colorLocation });
|
||||||
|
vertexShader.addAttribVar((GX2AttribVar){ "attr_position", GX2_VAR_TYPE_VEC3, 0, positionLocation });
|
||||||
|
vertexShader.addAttribVar((GX2AttribVar){ "attr_texture_coord", GX2_VAR_TYPE_VEC2, 0, texCoordLocation });
|
||||||
|
|
||||||
|
//! setup attribute streams
|
||||||
|
GX2InitAttribStream(vertexShader.getAttributeBuffer(0), positionLocation, 0, 0, GX2_ATTRIB_FORMAT_32_32_32_FLOAT);
|
||||||
|
GX2InitAttribStream(vertexShader.getAttributeBuffer(1), texCoordLocation, 1, 0, GX2_ATTRIB_FORMAT_32_32_FLOAT);
|
||||||
|
GX2InitAttribStream(vertexShader.getAttributeBuffer(2), colorLocation, 2, 0, GX2_ATTRIB_FORMAT_8_8_8_8_UNORM);
|
||||||
|
|
||||||
|
//! create fetch shader
|
||||||
|
fetchShader = new FetchShader(vertexShader.getAttributeBuffer(), vertexShader.getAttributesCount());
|
||||||
|
|
||||||
|
//! initialize default quad texture vertexes as those are very commonly used
|
||||||
|
//! model vertex has to be align and cannot be in unknown regions for GX2 like 0xBCAE1000
|
||||||
|
posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciPositionVtxsSize);
|
||||||
|
texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciTexCoordsVtxsSize);
|
||||||
|
colorVtxs = (u8*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciColorVtxsSize);
|
||||||
|
|
||||||
|
//! position vertex structure and texture coordinate vertex structure
|
||||||
|
s32 i = 0;
|
||||||
|
posVtxs[i++] = -1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f;
|
||||||
|
posVtxs[i++] = 1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f;
|
||||||
|
posVtxs[i++] = 1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f;
|
||||||
|
posVtxs[i++] = -1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f;
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, posVtxs, ciPositionVtxsSize);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
texCoords[i++] = 0.0f; texCoords[i++] = 1.0f;
|
||||||
|
texCoords[i++] = 1.0f; texCoords[i++] = 1.0f;
|
||||||
|
texCoords[i++] = 1.0f; texCoords[i++] = 0.0f;
|
||||||
|
texCoords[i++] = 0.0f; texCoords[i++] = 0.0f;
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, texCoords, ciTexCoordsVtxsSize);
|
||||||
|
|
||||||
|
|
||||||
|
for(i = 0; i < (s32)ciColorVtxsSize; i++)
|
||||||
|
colorVtxs[i] = 0xff;
|
||||||
|
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, colorVtxs, ciColorVtxsSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderFractalColor::~ShaderFractalColor()
|
||||||
|
{
|
||||||
|
if(posVtxs)
|
||||||
|
{
|
||||||
|
free(posVtxs);
|
||||||
|
posVtxs = NULL;
|
||||||
|
}
|
||||||
|
if(texCoords)
|
||||||
|
{
|
||||||
|
free(texCoords);
|
||||||
|
texCoords = NULL;
|
||||||
|
}
|
||||||
|
if(colorVtxs)
|
||||||
|
{
|
||||||
|
free(colorVtxs);
|
||||||
|
colorVtxs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete fetchShader;
|
||||||
|
fetchShader = NULL;
|
||||||
|
}
|
124
source/video/shaders/ShaderFractalColor.h
Normal file
124
source/video/shaders/ShaderFractalColor.h
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef SHADER_FRACTAL_COLOR_H_
|
||||||
|
#define SHADER_FRACTAL_COLOR_H_
|
||||||
|
|
||||||
|
#include "VertexShader.h"
|
||||||
|
#include "PixelShader.h"
|
||||||
|
#include "FetchShader.h"
|
||||||
|
|
||||||
|
class ShaderFractalColor : public Shader
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ShaderFractalColor();
|
||||||
|
virtual ~ShaderFractalColor();
|
||||||
|
|
||||||
|
static ShaderFractalColor * shaderInstance;
|
||||||
|
|
||||||
|
static const unsigned char cuAttributeCount = 3;
|
||||||
|
static const u32 ciPositionVtxsSize = 4 * cuVertexAttrSize;
|
||||||
|
static const u32 ciTexCoordsVtxsSize = 4 * cuTexCoordAttrSize;
|
||||||
|
static const u32 ciColorVtxsSize = 4 * cuColorAttrSize;
|
||||||
|
|
||||||
|
FetchShader *fetchShader;
|
||||||
|
VertexShader vertexShader;
|
||||||
|
PixelShader pixelShader;
|
||||||
|
|
||||||
|
f32 *posVtxs;
|
||||||
|
f32 *texCoords;
|
||||||
|
u8 *colorVtxs;
|
||||||
|
|
||||||
|
u32 modelMatrixLocation;
|
||||||
|
u32 viewMatrixLocation;
|
||||||
|
u32 projectionMatrixLocation;
|
||||||
|
u32 positionLocation;
|
||||||
|
u32 colorLocation;
|
||||||
|
u32 texCoordLocation;
|
||||||
|
|
||||||
|
u32 blurLocation;
|
||||||
|
u32 colorIntensityLocation;
|
||||||
|
u32 fadeOutLocation;
|
||||||
|
u32 fractalLocation;
|
||||||
|
public:
|
||||||
|
static ShaderFractalColor *instance() {
|
||||||
|
if(!shaderInstance) {
|
||||||
|
shaderInstance = new ShaderFractalColor();
|
||||||
|
}
|
||||||
|
return shaderInstance;
|
||||||
|
}
|
||||||
|
static void destroyInstance() {
|
||||||
|
if(shaderInstance) {
|
||||||
|
delete shaderInstance;
|
||||||
|
shaderInstance = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setShaders(void) const
|
||||||
|
{
|
||||||
|
fetchShader->setShader();
|
||||||
|
vertexShader.setShader();
|
||||||
|
pixelShader.setShader();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAttributeBuffer(const u32 & vtxCount = 0, const f32 * posVtxs_in = NULL, const f32 * texCoords_in = NULL, const u8 * colorVtxs_in = NULL) const
|
||||||
|
{
|
||||||
|
if(posVtxs_in && texCoords_in && vtxCount)
|
||||||
|
{
|
||||||
|
VertexShader::setAttributeBuffer(0, vtxCount * cuVertexAttrSize, cuVertexAttrSize, posVtxs_in);
|
||||||
|
VertexShader::setAttributeBuffer(1, vtxCount * cuTexCoordAttrSize, cuTexCoordAttrSize, texCoords_in);
|
||||||
|
VertexShader::setAttributeBuffer(2, vtxCount * cuColorAttrSize, cuColorAttrSize, colorVtxs_in);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//! use default quad vertex and texture coordinates if nothing is passed
|
||||||
|
VertexShader::setAttributeBuffer(0, ciPositionVtxsSize, cuVertexAttrSize, posVtxs);
|
||||||
|
VertexShader::setAttributeBuffer(1, ciTexCoordsVtxsSize, cuTexCoordAttrSize, texCoords);
|
||||||
|
VertexShader::setAttributeBuffer(2, ciColorVtxsSize, cuColorAttrSize, colorVtxs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setProjectionMtx(const glm::mat4 & mtx)
|
||||||
|
{
|
||||||
|
VertexShader::setUniformReg(projectionMatrixLocation, 16, &mtx[0][0]);
|
||||||
|
}
|
||||||
|
void setViewMtx(const glm::mat4 & mtx)
|
||||||
|
{
|
||||||
|
VertexShader::setUniformReg(viewMatrixLocation, 16, &mtx[0][0]);
|
||||||
|
}
|
||||||
|
void setModelViewMtx(const glm::mat4 & mtx)
|
||||||
|
{
|
||||||
|
VertexShader::setUniformReg(modelMatrixLocation, 16, &mtx[0][0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBlurBorder(const float & blurBorderSize)
|
||||||
|
{
|
||||||
|
PixelShader::setUniformReg(blurLocation, 4, &blurBorderSize);
|
||||||
|
}
|
||||||
|
void setColorIntensity(const glm::vec4 & vec)
|
||||||
|
{
|
||||||
|
PixelShader::setUniformReg(colorIntensityLocation, 4, &vec[0]);
|
||||||
|
}
|
||||||
|
void setAlphaFadeOut(const glm::vec4 & vec)
|
||||||
|
{
|
||||||
|
PixelShader::setUniformReg(fadeOutLocation, 4, &vec[0]);
|
||||||
|
}
|
||||||
|
void setFractalColor(const int & fractalColorEnable)
|
||||||
|
{
|
||||||
|
PixelShader::setUniformReg(fractalLocation, 4, &fractalColorEnable);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHADER_FRACTAL_COLOR_H_
|
271
source/video/shaders/Texture2DShader.cpp
Normal file
271
source/video/shaders/Texture2DShader.cpp
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "Texture2DShader.h"
|
||||||
|
|
||||||
|
static const u32 cpVertexShaderProgram[] =
|
||||||
|
{
|
||||||
|
0x00000000,0x00008009,0x20000000,0x000080a0,
|
||||||
|
0x3c200100,0x88060094,0x00400000,0x88042014,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x02290001,0x80000000,0x02041f00,0x900c0020,
|
||||||
|
0x00a11f00,0xfc00624f,0xfd041f00,0x900c4060,
|
||||||
|
0x02001f80,0x900c0000,0x83f9223e,0x0000803f,
|
||||||
|
0xfe081f00,0x00080020,0xfe202081,0x10004040,
|
||||||
|
0xfea49f80,0xfd00620f,0xdb0f49c0,0xdb0fc940,
|
||||||
|
0xfea01f80,0x9000e06f,0x83f9223e,0x00000000,
|
||||||
|
0xfe0c1f80,0x00370000,0xffa01f00,0x80000040,
|
||||||
|
0xff101f00,0x800c0060,0x7f0c1f80,0x80370040,
|
||||||
|
0x0000103f,0x00000000,0xffa01f00,0x80000000,
|
||||||
|
0xff001f00,0x800c0020,0x02c51f01,0x80000040,
|
||||||
|
0xfeac9f80,0x80000060,0x0000103f,0x398ee33f,
|
||||||
|
0xfea01f00,0x80000000,0x02c19f01,0x9000e02f,
|
||||||
|
0x01c41f01,0x9000e04f,0x02c59f80,0x80000060,
|
||||||
|
0x398ee33f,0x00000000,0x01c49f01,0x80000020,
|
||||||
|
0x02c11f80,0x80000040,0x01e08f00,0xfe04624f,
|
||||||
|
0x01c01f81,0x7f08626f,0xfe2c2000,0x10004000,
|
||||||
|
0xfe28a080,0x10004020,0xeb825790,0xb6f711be,
|
||||||
|
0x7c0e2df2,0x81173cfa
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u32 cpVertexShaderRegs[] = {
|
||||||
|
0x00000103,0x00000000,0x00000000,0x00000001,
|
||||||
|
0xffffff00,0xffffffff,0xffffffff,0xffffffff,
|
||||||
|
0xffffffff,0xffffffff,0xffffffff,0xffffffff,
|
||||||
|
0xffffffff,0xffffffff,0x00000000,0xfffffffc,
|
||||||
|
0x00000002,0x00000000,0x00000001,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x000000ff,0x000000ff,0x000000ff,
|
||||||
|
0x000000ff,0x00000000,0x0000000e,0x00000010
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u32 cPixelShaderProgram[] =
|
||||||
|
{
|
||||||
|
0x20000000,0x00000ca4,0x0b000000,0x00000085,
|
||||||
|
0x24000000,0x000050a0,0xb0000000,0x000cc080,
|
||||||
|
0x39000000,0x00005ca0,0xb8000000,0x000cc080,
|
||||||
|
0x51000000,0x000078a0,0xc0000000,0x000cc080,
|
||||||
|
0x70000000,0x000064a0,0xc8000000,0x0008c080,
|
||||||
|
0x8a000000,0x00005ca0,0x0e000000,0x01008086,
|
||||||
|
0xce000000,0x0000c080,0xa2000000,0x00000ca8,
|
||||||
|
0x00800000,0x88062094,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00051f00,0x80060000,0x00011f80,0x80060040,
|
||||||
|
0xfec81f80,0xfb802320,0x01041f80,0x8c220000,
|
||||||
|
0x00a41f00,0xfc10620f,0x010d1f00,0x900c0021,
|
||||||
|
0x00091f00,0x80060040,0x00a01f80,0xfc10626f,
|
||||||
|
0x00000040,0x00000000,0xfe080000,0xfe8cc300,
|
||||||
|
0xfe088080,0xfe80c320,0x00a11f00,0xfe000200,
|
||||||
|
0x00a51f00,0xfe040220,0x00a19f00,0xfe000240,
|
||||||
|
0x00a59f00,0xfe040260,0x00a11f81,0xfe002600,
|
||||||
|
0x4260e5bc,0xa69bc4bc,0x0ad7a3bc,0x00000000,
|
||||||
|
0x00a11f00,0x06004200,0x00a59f00,0x06042220,
|
||||||
|
0x00a51f00,0x06044240,0x00a11f01,0x06008260,
|
||||||
|
0x00a51f81,0x06048620,0x6f1283bc,0x0ad7a3bc,
|
||||||
|
0xa69b44bc,0x00000000,0x00a41f00,0x80000000,
|
||||||
|
0x00a01f00,0x80000020,0x00ac1f00,0x80000040,
|
||||||
|
0x00a81f00,0x80000060,0x00a19f80,0x06000600,
|
||||||
|
0xcac3123c,0x6f1203bc,0x03a41f00,0xfe00620f,
|
||||||
|
0x03a01f00,0xfe04622f,0x03ac1f00,0xfe08624f,
|
||||||
|
0x03a81f00,0xfe0c626f,0x00a59f80,0x06040620,
|
||||||
|
0xcc28913b,0x6f1203bc,0x01a41f00,0xfe00620f,
|
||||||
|
0x01a01f00,0xfe04622f,0x01ac1f00,0xfe08624f,
|
||||||
|
0x01a81f00,0xfe0c626f,0x00a19f80,0x06002600,
|
||||||
|
0xe8eab03c,0x6f1283bb,0x02ac1f00,0xfe084200,
|
||||||
|
0x02a81f00,0xfe0c4220,0x02a41f00,0xfe004240,
|
||||||
|
0x02a01f00,0xfe044260,0x00a59f80,0x06042620,
|
||||||
|
0x92bb353d,0x6f1283bb,0x04a81f00,0x0204620f,
|
||||||
|
0x04ac1f00,0x0200662f,0x04a41f00,0x0208624f,
|
||||||
|
0x04a01f00,0x020c626f,0x00a19f80,0x06004600,
|
||||||
|
0xc4139f3d,0x6f12833b,0x00a41f00,0xfe08620f,
|
||||||
|
0x00a01f00,0xfe0c622f,0x00ac1f00,0xfe04624f,
|
||||||
|
0x00a81f00,0xfe00626f,0x00a59f80,0x06044620,
|
||||||
|
0xb950ed3d,0x6f12833b,0x01a41f00,0xfe00620f,
|
||||||
|
0x01a01f00,0xfe04622f,0x01ac1f00,0xfe08624f,
|
||||||
|
0x01a81f00,0xfe0c626f,0x00a19f80,0x06002600,
|
||||||
|
0xecd7163e,0x6f12033c,0x03a41f00,0xfe000200,
|
||||||
|
0x03a01f00,0xfe040220,0x03ac1f00,0xfe082240,
|
||||||
|
0x03a81f00,0xfe0c2260,0x00a59f80,0x06042620,
|
||||||
|
0x2168233e,0x6f12033c,0x00a11f00,0x06006200,
|
||||||
|
0x00a51f00,0x06046220,0x00a19f00,0x06006240,
|
||||||
|
0x00a59f00,0x06046260,0x00a11f81,0x0600e600,
|
||||||
|
0xa69b443c,0x6f12833c,0x0ad7a33c,0x00000000,
|
||||||
|
0x02ac1f00,0x0108620f,0x02a81f00,0x010c622f,
|
||||||
|
0x02a41f00,0x0000624f,0x02a01f00,0x0004666f,
|
||||||
|
0x00a59f80,0x0604e620,0xecd7163e,0x0ad7a33c,
|
||||||
|
0x04a81f00,0xfe04620f,0x04ac1f00,0xfe00622f,
|
||||||
|
0x04a41f00,0xfe08624f,0x04a01f00,0xfe0c626f,
|
||||||
|
0x00a19f80,0x06008600,0xb950ed3d,0xa69bc43c,
|
||||||
|
0x05a41f00,0xfe08620f,0x05a01f00,0xfe0c622f,
|
||||||
|
0x05ac1f00,0xfe04624f,0x05a81f00,0xfe00626f,
|
||||||
|
0x00a59f80,0x06048620,0xc4139f3d,0xa69bc43c,
|
||||||
|
0x03a41f00,0xfe00a200,0x03a01f00,0xfe04a220,
|
||||||
|
0x03ac1f00,0xfe086240,0x03a81f00,0xfe0c6260,
|
||||||
|
0x00a19f80,0x06006600,0x92bb353d,0x4260e53c,
|
||||||
|
0x00a51f80,0x06046220,0x4260e53c,0x00000000,
|
||||||
|
0x07ac1f00,0x0308620f,0x07a81f00,0x030c622f,
|
||||||
|
0x07a41f00,0x0500624f,0x07a01f80,0x0504626f,
|
||||||
|
0xe8eab03c,0x00000000,0x04a81f00,0xfe04620f,
|
||||||
|
0x04ac1f00,0xfe00622f,0x04a41f00,0xfe08624f,
|
||||||
|
0x04a01f80,0xfe0c626f,0xcac3123c,0x00000000,
|
||||||
|
0x06a41f00,0xfe08620f,0x06a01f00,0xfe0c622f,
|
||||||
|
0x06ac1f00,0xfe04624f,0x06a81f80,0xfe00626f,
|
||||||
|
0xcc28913b,0x00000000,0xfe20a000,0x9000e00f,
|
||||||
|
0xfe242000,0x9000e02f,0xfe28a001,0x9000e04f,
|
||||||
|
0xfe2c2081,0x9000e06f,0xfe28a081,0x80060020,
|
||||||
|
0xfee48f00,0x7f842300,0xfee40f00,0x7f802320,
|
||||||
|
0xfee48f01,0x7f8c2340,0xfee40f81,0x08842b60,
|
||||||
|
0x00202000,0x90002000,0x0024a000,0x90002020,
|
||||||
|
0x00282001,0x90002040,0x002ca081,0x90002060,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x10000000,0x03100df0,0x00008010,0xecdfea0d,
|
||||||
|
0x10000000,0x00100df0,0x0000a051,0xecdfea0d,
|
||||||
|
0x10000100,0x01100df0,0x00008010,0xecdfea0d,
|
||||||
|
0x10000200,0x02100df0,0x00000011,0xecdfea0d,
|
||||||
|
0x10000400,0x04100df0,0x0000b070,0xecdfea0d,
|
||||||
|
0x10000000,0x00100df0,0x00008010,0xecdfea0d,
|
||||||
|
0x10000100,0x01100df0,0x00008010,0xecdfea0d,
|
||||||
|
0x10000600,0x03100df0,0x00008010,0xecdfea0d,
|
||||||
|
0x10000200,0x02100df0,0x00008010,0xecdfea0d,
|
||||||
|
0x10000100,0x04100df0,0x00008010,0xecdfea0d,
|
||||||
|
0x10000300,0x05100df0,0x00008010,0xecdfea0d,
|
||||||
|
0x10000300,0x03100df0,0x0000a051,0xecdfea0d,
|
||||||
|
0x10000700,0x07100df0,0x00008010,0xecdfea0d,
|
||||||
|
0x10000400,0x04100df0,0x00008010,0xecdfea0d,
|
||||||
|
0x10000300,0x06100df0,0x00008010,0xecdfea0d,
|
||||||
|
0x10000000,0x00100df0,0x00008010,0xecdfea0d,
|
||||||
|
0xc8581837,0x22740275,0x281eddcc,0xfa8b9b65
|
||||||
|
};
|
||||||
|
static const u32 cPixelShaderRegs[] = {
|
||||||
|
0x00000109,0x00000002,0x14000001,0x00000000,
|
||||||
|
0x00000001,0x00000100,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x00000000,0x00000000,0x00000000,
|
||||||
|
0x00000000,0x0000000f,0x00000001,0x00000010,
|
||||||
|
0x00000000
|
||||||
|
};
|
||||||
|
|
||||||
|
Texture2DShader * Texture2DShader::shaderInstance = NULL;
|
||||||
|
|
||||||
|
Texture2DShader::Texture2DShader()
|
||||||
|
: vertexShader(cuAttributeCount)
|
||||||
|
{
|
||||||
|
//! create pixel shader
|
||||||
|
pixelShader.setProgram(cPixelShaderProgram, sizeof(cPixelShaderProgram), cPixelShaderRegs, sizeof(cPixelShaderRegs));
|
||||||
|
|
||||||
|
blurLocation = 0;
|
||||||
|
colorIntensityLocation = 4;
|
||||||
|
pixelShader.addUniformVar((GX2UniformVar){ "unf_blur_texture_direction", GX2_VAR_TYPE_VEC3, 1, blurLocation, 0xffffffff });
|
||||||
|
pixelShader.addUniformVar((GX2UniformVar){ "unf_color_intensity", GX2_VAR_TYPE_VEC4, 1, colorIntensityLocation, 0xffffffff });
|
||||||
|
|
||||||
|
samplerLocation = 0;
|
||||||
|
pixelShader.addSamplerVar((GX2SamplerVar){ "sampl_texture", GX2_SAMPLER_TYPE_2D, samplerLocation });
|
||||||
|
|
||||||
|
//! create vertex shader
|
||||||
|
vertexShader.setProgram(cpVertexShaderProgram, sizeof(cpVertexShaderProgram), cpVertexShaderRegs, sizeof(cpVertexShaderRegs));
|
||||||
|
|
||||||
|
angleLocation = 0;
|
||||||
|
offsetLocation = 4;
|
||||||
|
scaleLocation = 8;
|
||||||
|
vertexShader.addUniformVar((GX2UniformVar){ "unf_angle", GX2_VAR_TYPE_FLOAT, 1, angleLocation, 0xffffffff });
|
||||||
|
vertexShader.addUniformVar((GX2UniformVar){ "unf_offset", GX2_VAR_TYPE_VEC3, 1, offsetLocation, 0xffffffff });
|
||||||
|
vertexShader.addUniformVar((GX2UniformVar){ "unf_scale", GX2_VAR_TYPE_VEC3, 1, scaleLocation, 0xffffffff });
|
||||||
|
|
||||||
|
positionLocation = 0;
|
||||||
|
texCoordLocation = 1;
|
||||||
|
vertexShader.addAttribVar((GX2AttribVar){ "attr_position", GX2_VAR_TYPE_VEC3, 0, positionLocation });
|
||||||
|
vertexShader.addAttribVar((GX2AttribVar){ "attr_texture_coord", GX2_VAR_TYPE_VEC2, 0, texCoordLocation });
|
||||||
|
|
||||||
|
//! setup attribute streams
|
||||||
|
GX2InitAttribStream(vertexShader.getAttributeBuffer(0), positionLocation, 0, 0, GX2_ATTRIB_FORMAT_32_32_32_FLOAT);
|
||||||
|
GX2InitAttribStream(vertexShader.getAttributeBuffer(1), texCoordLocation, 1, 0, GX2_ATTRIB_FORMAT_32_32_FLOAT);
|
||||||
|
|
||||||
|
//! create fetch shader
|
||||||
|
fetchShader = new FetchShader(vertexShader.getAttributeBuffer(), vertexShader.getAttributesCount());
|
||||||
|
|
||||||
|
//! model vertex has to be align and cannot be in unknown regions for GX2 like 0xBCAE1000
|
||||||
|
posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciPositionVtxsSize);
|
||||||
|
texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciTexCoordsVtxsSize);
|
||||||
|
|
||||||
|
//! defaults for normal square
|
||||||
|
//! position vertex structure and texture coordinate vertex structure
|
||||||
|
s32 i = 0;
|
||||||
|
posVtxs[i++] = -1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f;
|
||||||
|
posVtxs[i++] = 1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f;
|
||||||
|
posVtxs[i++] = 1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f;
|
||||||
|
posVtxs[i++] = -1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f;
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, posVtxs, ciPositionVtxsSize);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
texCoords[i++] = 0.0f; texCoords[i++] = 1.0f;
|
||||||
|
texCoords[i++] = 1.0f; texCoords[i++] = 1.0f;
|
||||||
|
texCoords[i++] = 1.0f; texCoords[i++] = 0.0f;
|
||||||
|
texCoords[i++] = 0.0f; texCoords[i++] = 0.0f;
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, texCoords, ciTexCoordsVtxsSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture2DShader::~Texture2DShader()
|
||||||
|
{
|
||||||
|
if(posVtxs)
|
||||||
|
{
|
||||||
|
free(posVtxs);
|
||||||
|
posVtxs = NULL;
|
||||||
|
}
|
||||||
|
if(texCoords)
|
||||||
|
{
|
||||||
|
free(texCoords);
|
||||||
|
texCoords = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete fetchShader;
|
||||||
|
fetchShader = NULL;
|
||||||
|
}
|
112
source/video/shaders/Texture2DShader.h
Normal file
112
source/video/shaders/Texture2DShader.h
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef __TEXTURE_2D_SHADER_H_
|
||||||
|
#define __TEXTURE_2D_SHADER_H_
|
||||||
|
|
||||||
|
#include "VertexShader.h"
|
||||||
|
#include "PixelShader.h"
|
||||||
|
#include "FetchShader.h"
|
||||||
|
|
||||||
|
class Texture2DShader : public Shader
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Texture2DShader();
|
||||||
|
virtual ~Texture2DShader();
|
||||||
|
|
||||||
|
static const u32 cuAttributeCount = 2;
|
||||||
|
static const u32 ciPositionVtxsSize = 4 * cuVertexAttrSize;
|
||||||
|
static const u32 ciTexCoordsVtxsSize = 4 * cuTexCoordAttrSize;
|
||||||
|
|
||||||
|
static Texture2DShader *shaderInstance;
|
||||||
|
|
||||||
|
FetchShader *fetchShader;
|
||||||
|
VertexShader vertexShader;
|
||||||
|
PixelShader pixelShader;
|
||||||
|
|
||||||
|
f32 *posVtxs;
|
||||||
|
f32 *texCoords;
|
||||||
|
|
||||||
|
u32 angleLocation;
|
||||||
|
u32 offsetLocation;
|
||||||
|
u32 scaleLocation;
|
||||||
|
u32 colorIntensityLocation;
|
||||||
|
u32 blurLocation;
|
||||||
|
u32 samplerLocation;
|
||||||
|
u32 positionLocation;
|
||||||
|
u32 texCoordLocation;
|
||||||
|
public:
|
||||||
|
static Texture2DShader *instance() {
|
||||||
|
if(!shaderInstance) {
|
||||||
|
shaderInstance = new Texture2DShader();
|
||||||
|
}
|
||||||
|
return shaderInstance;
|
||||||
|
}
|
||||||
|
static void destroyInstance() {
|
||||||
|
if(shaderInstance) {
|
||||||
|
delete shaderInstance;
|
||||||
|
shaderInstance = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setShaders(void) const
|
||||||
|
{
|
||||||
|
fetchShader->setShader();
|
||||||
|
vertexShader.setShader();
|
||||||
|
pixelShader.setShader();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAttributeBuffer(const f32 * texCoords_in = NULL, const f32 * posVtxs_in = NULL, const u32 & vtxCount = 0) const
|
||||||
|
{
|
||||||
|
if(posVtxs_in && texCoords_in && vtxCount)
|
||||||
|
{
|
||||||
|
VertexShader::setAttributeBuffer(0, vtxCount * cuVertexAttrSize, cuVertexAttrSize, posVtxs_in);
|
||||||
|
VertexShader::setAttributeBuffer(1, vtxCount * cuTexCoordAttrSize, cuTexCoordAttrSize, texCoords_in);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
VertexShader::setAttributeBuffer(0, ciPositionVtxsSize, cuVertexAttrSize, posVtxs);
|
||||||
|
VertexShader::setAttributeBuffer(1, ciTexCoordsVtxsSize, cuTexCoordAttrSize, texCoords);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAngle(const float & val)
|
||||||
|
{
|
||||||
|
VertexShader::setUniformReg(angleLocation, 4, &val);
|
||||||
|
}
|
||||||
|
void setOffset(const glm::vec3 & vec)
|
||||||
|
{
|
||||||
|
VertexShader::setUniformReg(offsetLocation, 4, &vec[0]);
|
||||||
|
}
|
||||||
|
void setScale(const glm::vec3 & vec)
|
||||||
|
{
|
||||||
|
VertexShader::setUniformReg(scaleLocation, 4, &vec[0]);
|
||||||
|
}
|
||||||
|
void setColorIntensity(const glm::vec4 & vec)
|
||||||
|
{
|
||||||
|
PixelShader::setUniformReg(colorIntensityLocation, 4, &vec[0]);
|
||||||
|
}
|
||||||
|
void setBlurring(const glm::vec3 & vec)
|
||||||
|
{
|
||||||
|
PixelShader::setUniformReg(blurLocation, 4, &vec[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTextureAndSampler(const GX2Texture *texture, const GX2Sampler *sampler) const {
|
||||||
|
GX2SetPixelTexture(texture, samplerLocation);
|
||||||
|
GX2SetPixelSampler(sampler, samplerLocation);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __TEXTURE_2D_SHADER_H_
|
178
source/video/shaders/VertexShader.h
Normal file
178
source/video/shaders/VertexShader.h
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2015 Dimok
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef VERTEX_SHADER_H
|
||||||
|
#define VERTEX_SHADER_H
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "Shader.h"
|
||||||
|
|
||||||
|
class VertexShader : public Shader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VertexShader(u32 numAttr)
|
||||||
|
: attributesCount( numAttr )
|
||||||
|
, attributes( new GX2AttribStream[attributesCount] )
|
||||||
|
, vertexShader( (GX2VertexShader*) memalign(0x40, sizeof(GX2VertexShader)) )
|
||||||
|
{
|
||||||
|
if(vertexShader)
|
||||||
|
{
|
||||||
|
memset(vertexShader, 0, sizeof(GX2VertexShader));
|
||||||
|
vertexShader->shader_mode = GX2_SHADER_MODE_UNIFORM_REGISTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~VertexShader() {
|
||||||
|
delete [] attributes;
|
||||||
|
|
||||||
|
if(vertexShader)
|
||||||
|
{
|
||||||
|
if(vertexShader->shader_data)
|
||||||
|
free(vertexShader->shader_data);
|
||||||
|
|
||||||
|
for(u32 i = 0; i < vertexShader->uniform_blocks_count; i++)
|
||||||
|
free((void*)vertexShader->uniform_block[i].name);
|
||||||
|
|
||||||
|
if(vertexShader->uniform_block)
|
||||||
|
free((void*)vertexShader->uniform_block);
|
||||||
|
|
||||||
|
for(u32 i = 0; i < vertexShader->uniform_vars_count; i++)
|
||||||
|
free((void*)vertexShader->uniform_var[i].name);
|
||||||
|
|
||||||
|
if(vertexShader->uniform_var)
|
||||||
|
free((void*)vertexShader->uniform_var);
|
||||||
|
|
||||||
|
if(vertexShader->initial_value)
|
||||||
|
free((void*)vertexShader->initial_value);
|
||||||
|
|
||||||
|
for(u32 i = 0; i < vertexShader->sampler_vars_count; i++)
|
||||||
|
free((void*)vertexShader->sampler_var[i].name);
|
||||||
|
|
||||||
|
if(vertexShader->sampler_var)
|
||||||
|
free((void*)vertexShader->sampler_var);
|
||||||
|
|
||||||
|
for(u32 i = 0; i < vertexShader->attribute_vars_count; i++)
|
||||||
|
free((void*)vertexShader->attribute_var[i].name);
|
||||||
|
|
||||||
|
if(vertexShader->attribute_var)
|
||||||
|
free((void*)vertexShader->attribute_var);
|
||||||
|
|
||||||
|
if(vertexShader->loops_data)
|
||||||
|
free((void*)vertexShader->loops_data);
|
||||||
|
|
||||||
|
free(vertexShader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setProgram(const u32 * program, const u32 & programSize, const u32 * regs, const u32 & regsSize)
|
||||||
|
{
|
||||||
|
if(!vertexShader)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//! this must be moved into an area where the graphic engine has access to and must be aligned to 0x100
|
||||||
|
vertexShader->shader_size = programSize;
|
||||||
|
vertexShader->shader_data = memalign(GX2_SHADER_ALIGNMENT, vertexShader->shader_size);
|
||||||
|
if(vertexShader->shader_data)
|
||||||
|
{
|
||||||
|
memcpy(vertexShader->shader_data, program, vertexShader->shader_size);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_CPU_SHADER, vertexShader->shader_data, vertexShader->shader_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(vertexShader->regs, regs, regsSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addUniformVar(const GX2UniformVar & var)
|
||||||
|
{
|
||||||
|
if(!vertexShader)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u32 idx = vertexShader->uniform_vars_count;
|
||||||
|
|
||||||
|
GX2UniformVar* newVar = (GX2UniformVar*) malloc((vertexShader->uniform_vars_count + 1) * sizeof(GX2UniformVar));
|
||||||
|
if(newVar)
|
||||||
|
{
|
||||||
|
if(vertexShader->uniform_vars_count > 0)
|
||||||
|
{
|
||||||
|
memcpy(newVar, vertexShader->uniform_var, vertexShader->uniform_vars_count * sizeof(GX2UniformVar));
|
||||||
|
free(vertexShader->uniform_var);
|
||||||
|
}
|
||||||
|
vertexShader->uniform_var = newVar;
|
||||||
|
|
||||||
|
memcpy(vertexShader->uniform_var + idx, &var, sizeof(GX2UniformVar));
|
||||||
|
vertexShader->uniform_var[idx].name = (char*) malloc(strlen(var.name) + 1);
|
||||||
|
strcpy((char*)vertexShader->uniform_var[idx].name, var.name);
|
||||||
|
|
||||||
|
vertexShader->uniform_vars_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addAttribVar(const GX2AttribVar & var)
|
||||||
|
{
|
||||||
|
if(!vertexShader)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u32 idx = vertexShader->attribute_vars_count;
|
||||||
|
|
||||||
|
GX2AttribVar* newVar = (GX2AttribVar*) malloc((vertexShader->attribute_vars_count + 1) * sizeof(GX2AttribVar));
|
||||||
|
if(newVar)
|
||||||
|
{
|
||||||
|
if(vertexShader->attribute_vars_count > 0)
|
||||||
|
{
|
||||||
|
memcpy(newVar, vertexShader->attribute_var, vertexShader->attribute_vars_count * sizeof(GX2AttribVar));
|
||||||
|
free(vertexShader->attribute_var);
|
||||||
|
}
|
||||||
|
vertexShader->attribute_var = newVar;
|
||||||
|
|
||||||
|
memcpy(vertexShader->attribute_var + idx, &var, sizeof(GX2AttribVar));
|
||||||
|
vertexShader->attribute_var[idx].name = (char*) malloc(strlen(var.name) + 1);
|
||||||
|
strcpy((char*)vertexShader->attribute_var[idx].name, var.name);
|
||||||
|
|
||||||
|
vertexShader->attribute_vars_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void setAttributeBuffer(u32 bufferIdx, u32 bufferSize, u32 stride, const void * buffer) {
|
||||||
|
GX2SetAttribBuffer(bufferIdx, bufferSize, stride, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
GX2VertexShader *getVertexShader() const {
|
||||||
|
return vertexShader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setShader(void) const {
|
||||||
|
GX2SetVertexShader(vertexShader);
|
||||||
|
}
|
||||||
|
|
||||||
|
GX2AttribStream * getAttributeBuffer(u32 idx = 0) const {
|
||||||
|
if(idx >= attributesCount) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return &attributes[idx];
|
||||||
|
}
|
||||||
|
u32 getAttributesCount() const {
|
||||||
|
return attributesCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setUniformReg(u32 location, u32 size, const void * reg) {
|
||||||
|
GX2SetVertexUniformReg(location, size, reg);
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
u32 attributesCount;
|
||||||
|
GX2AttribStream *attributes;
|
||||||
|
GX2VertexShader *vertexShader;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VERTEX_SHADER_H
|
Loading…
Reference in New Issue
Block a user