From ad6e5c4d2db862c7c9abe567d1e497e3680b2683 Mon Sep 17 00:00:00 2001 From: Pk11 Date: Wed, 25 Aug 2021 16:41:16 -0500 Subject: [PATCH] Bring closer to U-C 3DS --- include/font.hpp | 14 +- include/gui.hpp | 229 ++++++++++++++++++++++++++---- include/screenCommon.hpp | 42 ++++++ source/font.cpp | 11 +- source/gui.cpp | 291 ++++++++++++++++++++++++++++++++++++--- source/image.cpp | 22 ++- 6 files changed, 542 insertions(+), 67 deletions(-) create mode 100644 include/screenCommon.hpp diff --git a/include/font.hpp b/include/font.hpp index 76c5d87..e23bb6b 100644 --- a/include/font.hpp +++ b/include/font.hpp @@ -69,7 +69,7 @@ private: u16 charIndex(char16_t c); - void DrawString(std::u16string_view text, int x, int y, Alignment align, Palette palette, int maxWidth, float scaleX, float scaleY, bool rtl, Sprite *sprite); + void print(std::u16string_view text, int x, int y, Alignment align, Palette palette, int maxWidth, float scaleX, float scaleY, bool rtl, Sprite *sprite); public: /** @@ -118,7 +118,7 @@ public: * @param scaleX (Optional) The scale on the X axis * @param scaleY (Optional) The scale on the Y axis */ - void DrawString(int x, int y, int value, Alignment align = Alignment::left, Palette palette = Palette::UNIVCORE_TEXT_DEFAULT_PALETTE, int maxWidth = 0, float scaleX = 1.0f, float scaleY = 1.0f) { DrawString(utf8to16(std::to_string(value)), x, y, align, palette, maxWidth, scaleX, scaleY, false, nullptr); } + void print(int x, int y, int value, Alignment align = Alignment::left, Palette palette = Palette::UNIVCORE_TEXT_DEFAULT_PALETTE, int maxWidth = 0, float scaleX = 1.0f, float scaleY = 1.0f) { print(utf8to16(std::to_string(value)), x, y, align, palette, maxWidth, scaleX, scaleY, false, nullptr); } /** * @brief Prints a string to a background layer @@ -131,8 +131,8 @@ public: * @param scaleX (Optional) The scale on the X axis * @param scaleY (Optional) The scale on the Y axis */ - void DrawString(int x, int y, std::string_view text, Alignment align = Alignment::left, Palette palette = Palette::UNIVCORE_TEXT_DEFAULT_PALETTE, int maxWidth = 0, float scaleX = 1.0f, float scaleY = 1.0f) { DrawString(utf8to16(text), x, y, align, palette, maxWidth, scaleX, scaleY, false, nullptr); } - void DrawString(int x, int y, std::u16string_view text, Alignment align = Alignment::left, Palette palette = Palette::UNIVCORE_TEXT_DEFAULT_PALETTE, int maxWidth = 0, float scaleX = 1.0f, float scaleY = 1.0f) { DrawString(text, x, y, align, palette, maxWidth, scaleX, scaleY, false, nullptr); } + void print(int x, int y, std::string_view text, Alignment align = Alignment::left, Palette palette = Palette::UNIVCORE_TEXT_DEFAULT_PALETTE, int maxWidth = 0, float scaleX = 1.0f, float scaleY = 1.0f) { print(utf8to16(text), x, y, align, palette, maxWidth, scaleX, scaleY, false, nullptr); } + void print(int x, int y, std::u16string_view text, Alignment align = Alignment::left, Palette palette = Palette::UNIVCORE_TEXT_DEFAULT_PALETTE, int maxWidth = 0, float scaleX = 1.0f, float scaleY = 1.0f) { print(text, x, y, align, palette, maxWidth, scaleX, scaleY, false, nullptr); } /** * @brief Prints an integer value to a sprite @@ -146,7 +146,7 @@ public: * @param scaleX (Optional) The scale on the X axis * @param scaleY (Optional) The scale on the Y axis */ - void DrawString(int x, int y, int value, Sprite &sprite, Alignment align = Alignment::left, Palette palette = Palette::UNIVCORE_TEXT_DEFAULT_PALETTE, int maxWidth = 0, float scaleX = 1.0f, float scaleY = 1.0f) { DrawString(utf8to16(std::to_string(value)), x, y, align, palette, maxWidth, scaleX, scaleY, false, nullptr); } + void print(int x, int y, int value, Sprite &sprite, Alignment align = Alignment::left, Palette palette = Palette::UNIVCORE_TEXT_DEFAULT_PALETTE, int maxWidth = 0, float scaleX = 1.0f, float scaleY = 1.0f) { print(utf8to16(std::to_string(value)), x, y, align, palette, maxWidth, scaleX, scaleY, false, nullptr); } /** * @brief Prints a string to a sprite @@ -160,8 +160,8 @@ public: * @param scaleX (Optional) The scale on the X axis * @param scaleY (Optional) The scale on the Y axis */ - void DrawString(int x, int y, std::string_view text, Sprite &sprite, Alignment align = Alignment::left, Palette palette = Palette::UNIVCORE_TEXT_DEFAULT_PALETTE, int maxWidth = 0, float scaleX = 1.0f, float scaleY = 1.0f) { DrawString(utf8to16(text), x, y, align, palette, maxWidth, scaleX, scaleY, false, &sprite); } - void DrawString(int x, int y, std::u16string_view text, Sprite &sprite, Alignment align = Alignment::left, Palette palette = Palette::UNIVCORE_TEXT_DEFAULT_PALETTE, int maxWidth = 0, float scaleX = 1.0f, float scaleY = 1.0f) { DrawString(text, x, y, align, palette, maxWidth, scaleX, scaleY, false, &sprite); } + void print(int x, int y, std::string_view text, Sprite &sprite, Alignment align = Alignment::left, Palette palette = Palette::UNIVCORE_TEXT_DEFAULT_PALETTE, int maxWidth = 0, float scaleX = 1.0f, float scaleY = 1.0f) { print(utf8to16(text), x, y, align, palette, maxWidth, scaleX, scaleY, false, &sprite); } + void print(int x, int y, std::u16string_view text, Sprite &sprite, Alignment align = Alignment::left, Palette palette = Palette::UNIVCORE_TEXT_DEFAULT_PALETTE, int maxWidth = 0, float scaleX = 1.0f, float scaleY = 1.0f) { print(text, x, y, align, palette, maxWidth, scaleX, scaleY, false, &sprite); } #ifdef UNIVCORE_TEXT_BUFFERED /** diff --git a/include/gui.hpp b/include/gui.hpp index 6392cf7..2722c04 100644 --- a/include/gui.hpp +++ b/include/gui.hpp @@ -34,43 +34,224 @@ #include +#include "UNIVCORE_CONFIG.h" + #ifdef UNIVCORE_3DS_SIZE #define SCALE_3DS(Pos) Pos = (Pos * 4 / 5) #else #define SCALE_3DS(Pos) #endif +// TODO: Maybe change these, they need to be C2D's flags atm to be compatible with 3DS Universal-Core +enum { + C2D_AtBaseline = BIT(0), ///< Matches the Y coordinate with the baseline of the font. + C2D_WithColor = BIT(1), ///< Draws text with color. Requires a u32 color value. + C2D_AlignLeft = 0 << 2, ///< Draws text aligned to the left. This is the default. + C2D_AlignRight = 1 << 2, ///< Draws text aligned to the right. + C2D_AlignCenter = 2 << 2, ///< Draws text centered. + C2D_AlignJustified = 3 << 2, ///< Draws text justified. When C2D_WordWrap is not specified, right edge is x + scaleX*text->width. Otherwise, right edge is x + the width specified for those values. + C2D_AlignMask = 3 << 2, ///< Bitmask for alignment values. + C2D_WordWrap = BIT(4), ///< Draws text with wrapping of full words before specified width. Requires a float value, passed after color if C2D_WithColor is specified. +}; + namespace Gui { - extern int bg3Main, bg2Main, bg3Sub, bg2Sub; - extern bool widescreen; - extern bool top; + /* + Clear the Text Buffer. + */ + void clearTextBufs(void); - /** - * @brief Initializes the screens for drawing - */ - void init(void); + /* + Clear the screen. + */ + void clearScreen(bool top); - /** - * @brief Clears the given screen - * @param top The screen to clear - */ - void clear(bool top); + /* + Load an image (TODO: spritesheets?). - /** - * @brief Changes which screen to draw to - * @param top The screen to draw to - */ - void ScreenDraw(bool top); + Path: Path to the image file. (GFX) + sheet: Reference to the Image declaration. + */ + bool loadSheet(const char *Path, Image &image); - /** - * @brief Draws a rectangle of a given size at a given position - * @param x The X position - * @param y The Y position - * @param w The Width - * @param h The Height - * @param color The index of the color to use + /* + Draw an image. + image: The image which should be used. + imgIndex: For compatibility with 3DS, unused. + x: The X Position where the sprite should be drawn. + y: The Y Position where the sprite should be drawn. + ScaleX: The X-Scale for the sprite. (Optional!) + ScaleY: The Y-Scale for the sprite. (Optional!) + */ + void DrawSprite(Image image, size_t imgindex, int x, int y, float ScaleX = 1.0f, float ScaleY = 1.0f); + + /* + Initialize the GUI. + Call this when initializing. + + FontPath: The font to use. + */ + bool init(const char *FontPath = nullptr); + + /* + Load a Font. (NFTR) + + fnt: The Font variable which should be initialized. + Path: Path to the NFTR file. + if you're unsure, just call 'Gui::init();' and it will load the default font. + */ + bool loadFont(Font &fnt, const char *Path = nullptr); + + /* + Reinit the GUI. + + FontPath: The font to use. + */ + bool reinit(const char *FontPath = nullptr); + + /* + Draws a centered String. + x: The X Offset from center. (Center: 200 px on top, 160 px on Bottom.) + y: The Y Position of the Text. + size: The size of the Text. + palette: The palette of the Text. + Text: The Text which should be displayed. + maxWidth: The maxWidth for the Text. (Optional!) + maxHeight: The maxHeight of the Text. (Optional!) + fnt: The Font which should be used. Uses default font by default. (Optional!) + int flags: C2D text flags to use. (Optional!) + */ + void DrawStringCentered(int x, int y, float size, Palette palette, const std::string &Text, int maxWidth = 0, int maxHeight = 0, Font *fnt = nullptr, int flags = 0); + + /* + Draws a String. + + x: The X Position where the Text should be drawn. + y: The Y Position where the Text should be drawn. + size: The size of the Text. + palette: The palette of the Text. + Text: The Text which should be displayed. + maxWidth: The maxWidth for the Text. (Optional!) + maxHeight: The maxHeight of the Text. (Optional!) + fnt: The Font which should be used. Uses default font by default. (Optional!) + flags: C2D text flags to use. + */ + void DrawString(int x, int y, float size, Palette palette, const std::string &Text, int maxWidth = 0, int maxHeight = 0, Font *fnt = nullptr, int flags = 0); + + /* + Get the width of a String. + + size: The size of the Text. + Text: The Text where the width should be getted from. + fnt: The Font which should be used. Uses default font by default. (Optional!) + */ + int GetStringWidth(float size, const std::string &Text, Font *fnt = nullptr); + + /* + Get the height of a String. + + size: The size of the Text. + Text: The Text where the height should be getted from. + fnt: The Font which should be used. Uses default font by default. (Optional!) + */ + int GetStringHeight(float size, const std::string &Text, Font *fnt = nullptr); + + + /* + Get the size of a String. + + size: The size of the Text. + width: The width of the Text. + height: The height of the Text. + Text: The Text where the size should be getted from. + fnt: The Font which should be used. Uses default font by default. (Optional!) + */ + void GetStringSize(float size, int *width, int *height, const std::string &Text, Font *fnt = nullptr); + + /* + Draw a Rectangle. + + x: X Position of the Rectangle. + y: Y Position of the Rectangle. + w: The width of the rectangle. + h: The height of the rectangle. + color: The color of the rectangle. */ void Draw_Rect(int x, int y, int w, int h, u8 color); + + /* + Used for the current Screen's Draw. (Optional!) + stack: Is it the stack variant? + */ + void DrawScreen(bool stack = false); + + /* + Used for the current Screen's Logic. (Optional!) + + hDown: the hidKeysDown() variable. + hHeld: the HidKeysHeld() variable. + touch: The TouchPosition variable. + waitFade: Wheter to wait until the fade ends. + stack: Is it the stack variant? + */ + void ScreenLogic(u32 hDown, u32 hHeld, touchPosition touch, bool waitFade = true, bool stack = false); + + /* + Transfer the Temp Screen to the used one. (Optional!) + + stack: Is it the stack variant? + It will check, if the tempScreen variable is not nullptr, so don't worry. + */ + void transferScreen(bool stack = false); + + /* + Set a specific Screen with switch function. (Optional!) + + screen: unique_ptr of the screen. (Optional by using the screen class.) + screenSwitch: Wheter to switch to the current screen. + stack: Is it the stack variant? + */ + void setScreen(std::unique_ptr screen, bool fade = false, bool stack = false); + + /* + Fades into screens and calls the constructor after it. (Optional!) + fadeoutFrames: Amount of frames for fadeout. + fadeinFrames: Amount of frames for fadein. + stack: Is it the stack variant? + */ + void fadeEffects(int fadeoutFrames = 6, int fadeinFrames = 6, bool stack = false); + + void screenBack(bool fade = false); // Goes a screen back. (Set!) (Stack only!) + void screenBack2(); // Goes a screen back.(Action!) (Stack only!) + + /* + Set on which screen to draw. + + top: Whether to draw on the top. (3DS Universal-Core compatible targets are inside the screenCommon.hpp file.) + */ + void ScreenDraw(bool top); + + /* + Draws a grid. + xPos: X Position of the grid. + yPos: Y Position of the grid. + Width: Width of the grid. + Height: Height of the grid. + color: Color of the grid. + bgColor: The BG Color from the grid. (Optional! It's transparent by default.) + */ + void drawGrid(int xPos, int yPos, int Width, int Height, u8 color, u8 bgColor = 0); + + /* + Draws an animated selector. + xPos: X Position of the selector. + yPos: Y Position of the Selector. + Width: Width of the Selector. + Height: Height of the Selector. + speed: The speed of the animation. (Use .030f or something by default.) + SelectorColor: The Color of the Selector outline. + bgColor: The BG Color from the selector. (Optional! It's transparent by default.) + */ + void drawAnimatedSelector(int xPos, int yPos, int Width, int Height, int speed, u16 SelectorColor, u8 bgColor = 0); } #endif \ No newline at end of file diff --git a/include/screenCommon.hpp b/include/screenCommon.hpp new file mode 100644 index 0000000..e08b8b4 --- /dev/null +++ b/include/screenCommon.hpp @@ -0,0 +1,42 @@ +/* +* This file is part of Universal-Core +* Copyright (C) 2020-2021 Universal-Team +* +* 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 . +* +* Additional Terms 7.b and 7.c of GPLv3 apply to this file: +* * Requiring preservation of specified reasonable legal notices or +* author attributions in that material or in the Appropriate Legal +* Notices displayed by works containing it. +* * Prohibiting misrepresentation of the origin of that material, +* or requiring that modified versions of such material be marked in +* reasonable ways as different from the original version. +*/ + +#ifndef _UNIVERSAL_CORE_SCREENCOMMON_HPP +#define _UNIVERSAL_CORE_SCREENCOMMON_HPP + +#include "gui.hpp" +#include "structs.hpp" + +// Screens +#define Top 1 +#define TopRight 1 +#define Bottom 0 + +extern bool currentScreen; +extern bool fadeout, fadein, fadeout2, fadein2; +extern int fadealpha, fadecolor; + +#endif \ No newline at end of file diff --git a/source/font.cpp b/source/font.cpp index 1b33632..77602c5 100644 --- a/source/font.cpp +++ b/source/font.cpp @@ -26,7 +26,7 @@ #include "font.hpp" -#include "gui.hpp" +#include "screenCommon.hpp" #include "tonccpy.h" #ifdef UNIVCORE_TEXT_BUFFERED @@ -34,6 +34,7 @@ u8 Font::textBuf[2][256 * 192]; #endif Font::Font(const std::vector &paths) { + FILE *file = nullptr; for(const auto &path : paths) { file = fopen(path.c_str(), "rb"); @@ -183,7 +184,7 @@ int Font::calcWidth(std::u16string_view text) { return x; } -ITCM_CODE void Font::DrawString(std::u16string_view text, int x, int y, Alignment align, Palette palette, +ITCM_CODE void Font::print(std::u16string_view text, int x, int y, Alignment align, Palette palette, int maxWidth, float scaleX, float scaleY, bool rtl, Sprite *sprite) { // If RTL isn't forced, check for RTL text for(const auto c : text) { @@ -202,7 +203,7 @@ ITCM_CODE void Font::DrawString(std::u16string_view text, int x, int y, Alignmen case Alignment::center: { size_t newline = text.find('\n'); while(newline != text.npos) { - DrawString(text.substr(0, newline), x, y, align, palette, maxWidth, scaleX, scaleY, rtl, sprite); + print(text.substr(0, newline), x, y, align, palette, maxWidth, scaleX, scaleY, rtl, sprite); text = text.substr(newline + 1); newline = text.find('\n'); y += tileHeight; @@ -214,7 +215,7 @@ ITCM_CODE void Font::DrawString(std::u16string_view text, int x, int y, Alignmen case Alignment::right: { size_t newline = text.find('\n'); while(newline != text.npos) { - DrawString(text.substr(0, newline), x - (calcWidth(text.substr(0, newline)) * scaleX), y, + print(text.substr(0, newline), x - (calcWidth(text.substr(0, newline)) * scaleX), y, Alignment::left, palette, maxWidth, scaleX, scaleY, rtl, sprite); text = text.substr(newline + 1); newline = text.find('\n'); @@ -350,7 +351,7 @@ ITCM_CODE void Font::DrawString(std::u16string_view text, int x, int y, Alignmen // Don't draw off screen chars if(x >= 0 && x + fontWidths[(index * 3) + 2] < 256 && y >= 0 && y + tileHeight < 192) { #ifdef UNIVCORE_TEXT_BUFFERED - u8 *dst = textBuf[Gui::top] + y * 256 + x + fontWidths[(index * 3)]; + u8 *dst = textBuf[currentScreen] + y * 256 + x + fontWidths[(index * 3)]; #else u8 *dst = (u8 *)bgGetGfxPtr(Gui::top ? 2 : 6) + y * 256 + x + fontWidths[(index * 3)]; #endif diff --git a/source/gui.cpp b/source/gui.cpp index 9f26794..b3b8525 100644 --- a/source/gui.cpp +++ b/source/gui.cpp @@ -25,17 +25,26 @@ */ #include "gui.hpp" -#include "gui.hpp" +#include "font.hpp" #include "tonccpy.h" +#include #include -int Gui::bg3Main, Gui::bg2Main, Gui::bg3Sub, Gui::bg2Sub; -bool Gui::widescreen = false; -bool Gui::top = false; +#define ANIMATED_SELECTOR_COLOR 0xFF -void Gui::init(void) { +std::unique_ptr DefaultFont; +std::unique_ptr usedScreen, tempScreen; // tempScreen used for "fade" effects. +std::stack> screens; +bool currentScreen = false; +bool fadeout = false, fadein = false, fadeout2 = false, fadein2 = false; +int fadealpha = 0; +int fadecolor = 0; +bool widescreen = false; +int selectorTimer = 0; + +bool Gui::init(const char *FontPath) { // Initialize video mode videoSetMode(MODE_5_2D); videoSetModeSub(MODE_5_2D); @@ -48,29 +57,104 @@ void Gui::init(void) { oamInit(&oamMain, SpriteMapping_Bmp_1D_128, false); // Init the backgrounds - bg3Main = bgInit(3, BgType_Bmp8, BgSize_B8_256x256, 0, 0); - bgSetPriority(bg3Main, 3); + bgInit(3, BgType_Bmp8, BgSize_B8_256x256, 0, 0); + bgSetPriority(3, 3); - bg2Main = bgInit(2, BgType_Bmp8, BgSize_B8_256x256, 3, 0); - bgSetPriority(bg2Main, 2); + bgInit(2, BgType_Bmp8, BgSize_B8_256x256, 3, 0); + bgSetPriority(2, 2); - bg3Sub = bgInitSub(3, BgType_Bmp8, BgSize_B8_256x256, 0, 0); - bgSetPriority(bg3Sub, 3); + bgInitSub(3, BgType_Bmp8, BgSize_B8_256x256, 0, 0); + bgSetPriority(7, 3); - bg2Sub = bgInitSub(2, BgType_Bmp8, BgSize_B8_256x256, 3, 0); - bgSetPriority(bg2Sub, 2); + bgInitSub(2, BgType_Bmp8, BgSize_B8_256x256, 3, 0); + bgSetPriority(6, 2); // Set main background as target for sprite transparency REG_BLDCNT = 1 << 11; REG_BLDCNT_SUB = 1 << 11; + + // Load the default font + DefaultFont = std::make_unique(std::vector({"sd:/_nds/Universal-Updater/font.nftr", "fat:/_nds/Universal-Updater/font.nftr", "nitro:/graphics/font/default.nftr"})); + + return true; } -void Gui::clear(bool top) { - toncset(bgGetGfxPtr(top ? bg3Main : bg3Sub), 0, 256 * 192); +void Gui::clearScreen(bool top) { + toncset(bgGetGfxPtr(currentScreen ? 3 : 7), 0, 256 * 192); } -void Gui::ScreenDraw(bool top) { - Gui::top = top; +void Gui::clearTextBufs(void) { + DefaultFont->clear(); +} + +void Gui::DrawSprite(Image image, size_t imgindex, int x, int y, float ScaleX, float ScaleY) { + image.drawSpecial(x, y, ScaleX, ScaleY); +} + +bool Gui::loadFont(Font &fnt, const char *Path) { + if(Path && access(Path, F_OK) == 0) // Only load if found. + fnt = Font(Path); + + return true; +} + +bool Gui::loadSheet(const char *Path, Image &image) { + if(Path && access(Path, F_OK) == 0) // Only load if found. + image = Image(Path); + + return true; +} + +/* + Reinitialize the GUI. + + fontRegion: The region to use for the system font. +*/ +bool Gui::reinit(const char *FontPath) { + return Gui::init(FontPath); +} + +void Gui::DrawStringCentered(int x, int y, float size, Palette palette, const std::string &Text, int maxWidth, int maxHeight, Font *fnt, int flags) { +#ifdef UNIVCORE_3DS_SIZE + Gui::DrawString(x, y, size, palette, Text, maxWidth, maxHeight, fnt, flags | C2D_AlignCenter); +#else + Gui::DrawString(x, y, size, palette, Text, maxWidth, maxHeight, fnt, flags | C2D_AlignCenter); +#endif +} + +void Gui::DrawString(int x, int y, float size, Palette palette, const std::string &Text, int maxWidth, int maxHeight, Font *fnt, int flags) { + float heightScale = maxHeight == 0 ? size : std::min(size, size * (maxHeight / Gui::GetStringHeight(size, Text, fnt))); + float widthScale = maxWidth == 0 ? size : std::min(size, size * (maxWidth / Gui::GetStringWidth(size, Text, fnt))); + + // TODO: Wrapping and such + if(fnt) + fnt->print(x, y, Text, flags & C2D_AlignCenter ? Alignment::center : (flags & C2D_AlignRight ? Alignment::right : Alignment::left), palette, maxWidth, widthScale, heightScale); + else + DefaultFont->print(x, y, Text, flags & C2D_AlignCenter ? Alignment::center : (flags & C2D_AlignRight ? Alignment::right : Alignment::left), palette, maxWidth, widthScale, heightScale); +} + +int Gui::GetStringWidth(float size, const std::string &Text, Font *fnt) { + if(fnt) + return fnt->calcWidth(Text) * size; + else + return DefaultFont->calcWidth(Text) * size; +} + +int Gui::GetStringHeight(float size, const std::string &Text, Font *fnt) { + const int lines = 1 + std::count(Text.begin(), Text.end(), '\n'); + + if(fnt) + return fnt->height() * lines * size; + else + return DefaultFont->height() * lines * size; +} + +void Gui::GetStringSize(float size, int *width, int *height, const std::string &Text, Font *fnt) { + if(width) + *width = GetStringWidth(size, Text, fnt); + + if(height) + *height = GetStringHeight(size, Text, fnt); } void Gui::Draw_Rect(int x, int y, int w, int h, u8 color) { @@ -79,8 +163,179 @@ void Gui::Draw_Rect(int x, int y, int w, int h, u8 color) { SCALE_3DS(w); SCALE_3DS(h); - u8 *dst = (u8 *)bgGetGfxPtr(top ? bg3Main : bg3Sub); + u8 *dst = (u8 *)bgGetGfxPtr(currentScreen ? 3 : 7); for(int i = 0; i < h; i++) { toncset(dst + ((y + i) * 256 + x), color, w); } +} + +void Gui::DrawScreen(bool stack) { + if(!stack) { + if(usedScreen) + usedScreen->Draw(); + + } else { + if(!screens.empty()) + screens.top()->Draw(); + } +} + +void Gui::ScreenLogic(u32 hDown, u32 hHeld, touchPosition touch, bool waitFade, bool stack) { + if(waitFade) { + if(!fadein && !fadeout && !fadein2 && !fadeout2) { + if(!stack) { + if(usedScreen) + usedScreen->Logic(hDown, hHeld, touch); + + } else { + if(!screens.empty()) + screens.top()->Logic(hDown, hHeld, touch); + } + } + + } else { + if(!stack) { + if(usedScreen) + usedScreen->Logic(hDown, hHeld, touch); + + } else { + if(!screens.empty()) + screens.top()->Logic(hDown, hHeld, touch); + } + } +} + +void Gui::transferScreen(bool stack) { + if(!stack) { + if(tempScreen) + usedScreen = std::move(tempScreen); + + } else { + if(tempScreen) + screens.push(std::move(tempScreen)); + } +} + +void Gui::setScreen(std::unique_ptr screen, bool fade, bool stack) { + tempScreen = std::move(screen); + + /* Switch screen without fade. */ + if(!fade) { + Gui::transferScreen(stack); + + } else { + /* Fade, then switch. */ + fadeout = true; + } +} + +void Gui::fadeEffects(int fadeoutFrames, int fadeinFrames, bool stack) { + // TODO! + if(fadein) { + fadealpha -= fadeinFrames; + + if(fadealpha < 0) { + fadealpha = 0; + fadecolor = 255; + fadein = false; + } + } + + if(stack) { + if(fadein2) { + fadealpha -= fadeinFrames; + + if(fadealpha < 0) { + fadealpha = 0; + fadecolor = 255; + fadein2 = false; + } + } + } + + if(fadeout) { + fadealpha += fadeoutFrames; + + if(fadealpha > 255) { + fadealpha = 255; + Gui::transferScreen(stack); // Transfer Temp screen to the stack / used one. + fadein = true; + fadeout = false; + } + } + + if(stack) { + if(fadeout2) { + fadealpha += fadeoutFrames; + + if(fadealpha > 255) { + fadealpha = 255; + Gui::screenBack2(); // Go screen back. + fadein2 = true; + fadeout2 = false; + } + } + } +} + +void Gui::screenBack(bool fade) { + if(!fade) { + if(screens.size() > 0) + screens.pop(); + + } else { + if(screens.size() > 0) + fadeout2 = true; + } +} + +void Gui::screenBack2() { + if(screens.size() > 0) + screens.pop(); +} + +void Gui::ScreenDraw(bool top) { + currentScreen = top; +} + +void Gui::drawGrid(int xPos, int yPos, int Width, int Height, u8 color, u8 bgColor) { + constexpr int w = 1; + + /* BG Color for the Grid. (Transparent by default.) */ + Gui::Draw_Rect(xPos, yPos, Width, Height, bgColor); + + /* Grid part, Top. */ + Gui::Draw_Rect(xPos, yPos, Width, w, color); + /* Left. */ + Gui::Draw_Rect(xPos, yPos + w, w, Height - 2 * w, color); + /* Right. */ + Gui::Draw_Rect(xPos + Width - w, yPos + w, w, Height - 2 * w, color); + /* Bottom. */ + Gui::Draw_Rect(xPos, yPos + Height - w, Width, w, color); +} + +void Gui::drawAnimatedSelector(int xPos, int yPos, int Width, int Height, int speed, u16 SelectorColor, u8 bgColor) { + constexpr int w = 2; + int highlight_multiplier = (selectorTimer % 0x3F > 0x1F) ? selectorTimer % 0x1F : 0x1F - (selectorTimer % 0x1F); + u8 r = SelectorColor & 0x1F; + u8 g = (SelectorColor >> 5) & 0x1F; + u8 b = (SelectorColor >> 10) & 0x1F; + u16 color = (r / highlight_multiplier) | (g / highlight_multiplier) << 5 | (b / highlight_multiplier) << 10 | BIT(15); + + BG_PALETTE[ANIMATED_SELECTOR_COLOR] = color; + BG_PALETTE_SUB[ANIMATED_SELECTOR_COLOR] = color; + + /* BG Color for the Selector. */ + Gui::Draw_Rect(xPos, yPos, Width, Height, bgColor); + + /* Selector part, Top. */ + Gui::Draw_Rect(xPos, yPos, Width, w, ANIMATED_SELECTOR_COLOR); + /* Left. */ + Gui::Draw_Rect(xPos, yPos + w, w, Height - 2 * w, ANIMATED_SELECTOR_COLOR); + /* Right. */ + Gui::Draw_Rect(xPos + Width - w, yPos + w, w, Height - 2 * w, ANIMATED_SELECTOR_COLOR); + /* Bottom. */ + Gui::Draw_Rect(xPos, yPos + Height - w, Width, w, ANIMATED_SELECTOR_COLOR); + + selectorTimer += speed; } \ No newline at end of file diff --git a/source/image.cpp b/source/image.cpp index 54b2a22..03565a0 100644 --- a/source/image.cpp +++ b/source/image.cpp @@ -26,7 +26,7 @@ #include "image.hpp" -#include "gui.hpp" +#include "screenCommon.hpp" #include "tonccpy.h" @@ -91,9 +91,9 @@ void Image::draw(int x, int y, bool copyPal) { SCALE_3DS(y); if(copyPal) - tonccpy((Gui::top ? BG_PALETTE : BG_PALETTE_SUB) + _palOfs, _palette.data(), _palette.size() * 2); + tonccpy((currentScreen ? BG_PALETTE : BG_PALETTE_SUB) + _palOfs, _palette.data(), _palette.size() * 2); - u8 *dst = (u8 *)bgGetGfxPtr(Gui::top ? 3 : 7) + y * 256 + x; + u8 *dst = (u8 *)bgGetGfxPtr(currentScreen ? 3 : 7) + y * 256 + x; // If full width and X is 0, copy it all in one go if(_width == 256 && x == 0) { @@ -111,16 +111,13 @@ void Image::drawSpecial(int x, int y, float scaleX, float scaleY, int paletteOff SCALE_3DS(y); if(copyPal) - tonccpy((Gui::top ? BG_PALETTE : BG_PALETTE_SUB) + _palOfs + paletteOffset, _palette.data(), _palette.size() * 2); + tonccpy((currentScreen ? BG_PALETTE : BG_PALETTE_SUB) + _palOfs + paletteOffset, _palette.data(), _palette.size() * 2); - u8 *dst = (u8 *)bgGetGfxPtr(Gui::top ? 3 : 7) + y * 256 + x; + u8 *dst = (u8 *)bgGetGfxPtr(currentScreen ? 3 : 7) + y * 256 + x; // If the scale is 1 use faster integer math - nocashMessage("a"); if(scaleX == 1.0f && scaleY == 1.0f) { - nocashMessage("b"); for(int i = 0; i < _height; i++) { - nocashMessage("d"); for(int j = 0; j < _width; j++) { u8 px = _bitmap[i * _width + j]; if(_palette[px - _palOfs] & 0x8000) @@ -128,7 +125,6 @@ void Image::drawSpecial(int x, int y, float scaleX, float scaleY, int paletteOff } } } else { - nocashMessage("c"); for(int i = 0; i < _height * scaleY; i++) { for(int j = 0; j < _width * scaleX; j++) { u8 px = _bitmap[int(i / scaleY) * _width + int(j / scaleX)]; @@ -144,10 +140,10 @@ void Image::drawSegment(int x, int y, int imageX, int imageY, int w, int h, bool SCALE_3DS(y); if(copyPal) - tonccpy((Gui::top ? BG_PALETTE : BG_PALETTE_SUB) + _palOfs, _palette.data(), _palette.size() * 2); + tonccpy((currentScreen ? BG_PALETTE : BG_PALETTE_SUB) + _palOfs, _palette.data(), _palette.size() * 2); for(int i = 0; i < h; i++) { - tonccpy((u8 *)bgGetGfxPtr(Gui::top ? 3 : 7) + (y + i) * 256 + x, + tonccpy((u8 *)bgGetGfxPtr(currentScreen ? 3 : 7) + (y + i) * 256 + x, _bitmap.data() + (imageY + i) * _width + imageX, w); } } @@ -158,9 +154,9 @@ void Image::drawSegmentSpecial(int x, int y, int imageX, int imageY, int w, int SCALE_3DS(y); if(copyPal) - tonccpy((Gui::top ? BG_PALETTE : BG_PALETTE_SUB) + _palOfs + paletteOffset, _palette.data(), _palette.size() * 2); + tonccpy((currentScreen ? BG_PALETTE : BG_PALETTE_SUB) + _palOfs + paletteOffset, _palette.data(), _palette.size() * 2); - u8 *dst = (u8 *)bgGetGfxPtr(Gui::top ? 3 : 7) + y * 256 + x; + u8 *dst = (u8 *)bgGetGfxPtr(currentScreen ? 3 : 7) + y * 256 + x; // If the scale is 1 use faster integer math if(scaleX == 1.0f && scaleY == 1.0f) {