From e011b37c9e05009d5895ceec80983ec66fa042b7 Mon Sep 17 00:00:00 2001 From: Brandon Date: Wed, 15 Jun 2016 02:28:41 -0700 Subject: [PATCH] Switch to flarn2006's bmpfont library, Enable romfs (not working though), Scene clean up, and replays work on any setting --- bottomless-block-barrage.layout | 214 +++++++-------- resources/template.rsf | 4 +- romfs/font/Arial Black.bff | Bin 0 -> 65812 bytes source/main.cpp | 7 +- source/moves_recorder.cpp | 11 +- source/moves_recorder.hpp | 2 + source/scenes/endless_config_scene.cpp | 9 +- source/scenes/endless_config_scene.hpp | 3 +- source/scenes/endless_scene.cpp | 22 +- source/scenes/endless_scene.hpp | 3 +- source/scenes/puzzle_select_scene.cpp | 9 +- source/scenes/puzzle_select_scene.hpp | 3 +- source/scenes/replay_scene.cpp | 21 +- source/scenes/replay_scene.hpp | 5 +- source/scenes/replay_select_scene.cpp | 13 +- source/scenes/replay_select_scene.hpp | 3 +- source/scenes/scene.hpp | 6 +- source/scenes/title_scene.cpp | 7 +- source/scenes/title_scene.hpp | 3 +- source/util/BmpFont.cpp | 357 +++++++++++++++++++++++++ source/util/BmpFont.h | 62 +++++ source/util/font.cpp | 27 +- source/util/font.hpp | 23 +- source/util/slider.cpp | 2 +- source/util/text.cpp | 2 +- source/util/window.cpp | 2 +- source/util/window.hpp | 1 + source/windows/info_window.cpp | 4 +- 28 files changed, 596 insertions(+), 229 deletions(-) create mode 100644 romfs/font/Arial Black.bff create mode 100644 source/util/BmpFont.cpp create mode 100644 source/util/BmpFont.h diff --git a/bottomless-block-barrage.layout b/bottomless-block-barrage.layout index 96bbbb8..cfeb8ca 100644 --- a/bottomless-block-barrage.layout +++ b/bottomless-block-barrage.layout @@ -1,150 +1,150 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -152,124 +152,124 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/resources/template.rsf b/resources/template.rsf index aad12d6..9cebd15 100644 --- a/resources/template.rsf +++ b/resources/template.rsf @@ -3,9 +3,9 @@ BasicInfo: ProductCode : $(APP_PRODUCT_CODE) Logo : Nintendo # Nintendo / Licensed / Distributed / iQue / iQueForSystem -#RomFs: +RomFs: # Specifies the root path of the read only file system to include in the ROM. - #RootPath : $(APP_ROMFS) + RootPath : $(APP_ROMFS) TitleInfo: Category : Application diff --git a/romfs/font/Arial Black.bff b/romfs/font/Arial Black.bff new file mode 100644 index 0000000000000000000000000000000000000000..bb9e14cab348fe48c634da060b4a86585a744733 GIT binary patch literal 65812 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 font; int main() { + romfsInit(); sf2d_init(); sf2d_set_clear_color(RGBA8(0x0, 0x0, 0x0, 0xFF)); sf2d_set_3D(0); - font.reset(new Font(font_gfx, FONT_GFX_WIDTH, FONT_GFX_HEIGHT, 16, 16, TEXFMT_RGBA8, SF2D_PLACE_RAM)); - Window::set_skin(windowskin, TEXFMT_RGBA8, SF2D_PLACE_RAM); + font.reset(new Font("/Arial Black.bff")); + if (font->valid()) + Window::set_skin(windowskin, TEXFMT_RGBA8, SF2D_PLACE_RAM); std::unique_ptr scene; current_scene = new TitleScene(); @@ -44,5 +46,6 @@ int main() } sf2d_fini(); + romfsExit(); return 0; } diff --git a/source/moves_recorder.cpp b/source/moves_recorder.cpp index d3995ef..a0a4742 100644 --- a/source/moves_recorder.cpp +++ b/source/moves_recorder.cpp @@ -10,10 +10,12 @@ const std::string generate_filename() { char buffer[128]; - time_t now = time(0); + /*time_t now = time(0); struct tm tstruct = *localtime(&now); - strftime(buffer, sizeof(buffer), "/bbb-moves/%Y-%m-%d-%X", &tstruct); + strftime(buffer, sizeof(buffer), "/bbb-moves/%Y-%m-%d-%X", &tstruct);*/ + sprintf(buffer, "/bbb-moves/%ld", osGetTime()); return buffer; + } void MovesRecorder::clear() @@ -45,6 +47,8 @@ bool MovesRecorder::save(const std::string& specific_filename) file.write(reinterpret_cast(&size), sizeof(size)); file.write(reinterpret_cast(&seed), sizeof(seed)); + file.write(reinterpret_cast(&difficulty), sizeof(difficulty)); + file.write(reinterpret_cast(&level), sizeof(level)); for (u32 i = 0; i < moves.size(); i++) { const Move& move = moves[i]; @@ -66,6 +70,8 @@ bool MovesRecorder::load(const std::string& filename) u32 size = 0; file.read(reinterpret_cast(&size), sizeof(size)); file.read(reinterpret_cast(&seed), sizeof(seed)); + file.read(reinterpret_cast(&difficulty), sizeof(difficulty)); + file.read(reinterpret_cast(&level), sizeof(level)); for (u32 i = 0; i < size; i++) { Move move; @@ -76,6 +82,7 @@ bool MovesRecorder::load(const std::string& filename) moves.push_back(move); } file.close(); + return true; } void MovesRecorder::keys(u32& trigger, u32& held) diff --git a/source/moves_recorder.hpp b/source/moves_recorder.hpp index a2cfd33..7e6366e 100644 --- a/source/moves_recorder.hpp +++ b/source/moves_recorder.hpp @@ -28,6 +28,8 @@ class MovesRecorder u32 seed; + u32 difficulty = 0; + u32 level = 1; private: std::vector moves; u32 frame = 0; diff --git a/source/scenes/endless_config_scene.cpp b/source/scenes/endless_config_scene.cpp index 2b20adf..8167720 100644 --- a/source/scenes/endless_config_scene.cpp +++ b/source/scenes/endless_config_scene.cpp @@ -64,14 +64,7 @@ void EndlessConfigScene::update_level_select() } } -void EndlessConfigScene::draw_top_left() -{ - difficulty_choices.draw(); - level_text.draw(); - level_slider.draw(); -} - -void EndlessConfigScene::draw_top_right() +void EndlessConfigScene::draw_top() { difficulty_choices.draw(); level_text.draw(); diff --git a/source/scenes/endless_config_scene.hpp b/source/scenes/endless_config_scene.hpp index ec2d093..4b1769d 100644 --- a/source/scenes/endless_config_scene.hpp +++ b/source/scenes/endless_config_scene.hpp @@ -15,8 +15,7 @@ class EndlessConfigScene : public Scene void initialize(); void update(); protected: - void draw_top_left(); - void draw_top_right(); + void draw_top(); void draw_bottom(); private: void update_difficulty_select(); diff --git a/source/scenes/endless_scene.cpp b/source/scenes/endless_scene.cpp index 4b9c79b..65f8a85 100644 --- a/source/scenes/endless_scene.cpp +++ b/source/scenes/endless_scene.cpp @@ -19,6 +19,8 @@ EndlessScene::EndlessScene(const Config& c) : config(c), level(c.level) void EndlessScene::initialize() { recorder.seed = (unsigned int) time(NULL); + recorder.difficulty = config.difficulty; + recorder.level = config.level; srand(recorder.seed); switch (config.difficulty) @@ -172,7 +174,7 @@ void EndlessScene::update_gameover() if (trigger & KEY_A) { if (save_replay_command.selection() == 0) - recorder.save("/bbb-moves/test"); + recorder.save(); save_replay_command.set_active(false); save_replay_command.set_hidden(true); @@ -198,23 +200,7 @@ void EndlessScene::update_gameover() } } -void EndlessScene::draw_top_left() -{ - if (panel_table.is_gameover()) - { - game_over.draw(); - try_again.draw(); - save_replay_command.draw(); - try_again_command.draw(); - } - else - { - info.draw(); - ccc_stats.draw(); - } -} - -void EndlessScene::draw_top_right() +void EndlessScene::draw_top() { if (panel_table.is_gameover()) { diff --git a/source/scenes/endless_scene.hpp b/source/scenes/endless_scene.hpp index 855d656..0cce1f0 100644 --- a/source/scenes/endless_scene.hpp +++ b/source/scenes/endless_scene.hpp @@ -25,8 +25,7 @@ class EndlessScene : public Scene void update(); protected: - void draw_top_left(); - void draw_top_right(); + void draw_top(); void draw_bottom(); void draw_selector(); diff --git a/source/scenes/puzzle_select_scene.cpp b/source/scenes/puzzle_select_scene.cpp index f29290b..21f740f 100644 --- a/source/scenes/puzzle_select_scene.cpp +++ b/source/scenes/puzzle_select_scene.cpp @@ -112,14 +112,7 @@ void PuzzleSelectScene::update_level_select() } } -void PuzzleSelectScene::draw_top_left() -{ - set_choices.draw(); - stage_choices.draw(); - level_choices.draw(); -} - -void PuzzleSelectScene::draw_top_right() +void PuzzleSelectScene::draw_top() { set_choices.draw(); stage_choices.draw(); diff --git a/source/scenes/puzzle_select_scene.hpp b/source/scenes/puzzle_select_scene.hpp index cf4ce85..393c444 100644 --- a/source/scenes/puzzle_select_scene.hpp +++ b/source/scenes/puzzle_select_scene.hpp @@ -11,8 +11,7 @@ class PuzzleSelectScene : public Scene void initialize(); void update(); protected: - void draw_top_left(); - void draw_top_right(); + void draw_top(); void draw_bottom(); private: void update_set_select(); diff --git a/source/scenes/replay_scene.cpp b/source/scenes/replay_scene.cpp index dcc491d..2d6ef5c 100644 --- a/source/scenes/replay_scene.cpp +++ b/source/scenes/replay_scene.cpp @@ -10,7 +10,7 @@ #include "selector_gfx.h" #include "debug_text.h" -ReplayScene::ReplayScene(const Config& c) : config(c), level(c.level) +ReplayScene::ReplayScene(const Config& c) : config(c) { } @@ -18,9 +18,10 @@ ReplayScene::ReplayScene(const Config& c) : config(c), level(c.level) void ReplayScene::initialize() { recorder.load(config.replay_filename); + level = recorder.level; srand(recorder.seed); - switch (config.difficulty) + switch (recorder.difficulty) { case EASY: panel_table.create(11, 6, 5, easy_speed_settings); @@ -33,8 +34,8 @@ void ReplayScene::initialize() break; } - info.set_level(config.level); - info.set_difficulty(config.difficulty); + info.set_level(level); + info.set_difficulty(static_cast(recorder.difficulty)); panels.create(panels_gfx, PANELS_GFX_WIDTH, PANELS_GFX_HEIGHT, TEXFMT_RGBA8, SF2D_PLACE_RAM); selector.create(selector_gfx, SELECTOR_GFX_WIDTH, SELECTOR_GFX_HEIGHT, TEXFMT_RGBA8, SF2D_PLACE_RAM); @@ -90,7 +91,7 @@ void ReplayScene::update() if (last_match.is_timeout()) { int timeout = calculate_timeout(last_match.combo, last_match.cascade + 1, - 3 - (int)config.difficulty, panel_table.is_danger()); + 3 - (int)recorder.difficulty, panel_table.is_danger()); panel_table.set_timeout(timeout); info.set_timeout(timeout); } @@ -118,7 +119,7 @@ void ReplayScene::update() if (minfo.is_timeout()) { int timeout = calculate_timeout(minfo.combo, minfo.cascade + 1, - 3 - (int)config.difficulty, panel_table.is_danger()); + 3 - (int)recorder.difficulty, panel_table.is_danger()); info.set_timeout(timeout); } last_match = minfo; @@ -130,13 +131,7 @@ void ReplayScene::update() frame++; } -void ReplayScene::draw_top_left() -{ - info.draw(); - ccc_stats.draw(); -} - -void ReplayScene::draw_top_right() +void ReplayScene::draw_top() { info.draw(); ccc_stats.draw(); diff --git a/source/scenes/replay_scene.hpp b/source/scenes/replay_scene.hpp index 8e092b0..6215f60 100644 --- a/source/scenes/replay_scene.hpp +++ b/source/scenes/replay_scene.hpp @@ -16,8 +16,6 @@ class ReplayScene : public Scene struct Config { std::string replay_filename; - Difficulty difficulty; - int level; }; ReplayScene(const Config& config); ~ReplayScene() {} @@ -25,8 +23,7 @@ class ReplayScene : public Scene void update(); protected: - void draw_top_left(); - void draw_top_right(); + void draw_top(); void draw_bottom(); void draw_selector(); diff --git a/source/scenes/replay_select_scene.cpp b/source/scenes/replay_select_scene.cpp index f29d6b8..c513eda 100644 --- a/source/scenes/replay_select_scene.cpp +++ b/source/scenes/replay_select_scene.cpp @@ -28,7 +28,7 @@ std::vector get_replays() void ReplaySelectScene::initialize() { - replays.create(0, 0, TOP_SCREEN_WIDTH / 3 - 2 * WINDOW_BORDER_SIZE, 16, 3, get_replays()); + replays.create(0, 0, TOP_SCREEN_WIDTH - 2 * WINDOW_BORDER_SIZE, 16, 1, get_replays()); replays.set_active(true); } @@ -40,11 +40,9 @@ void ReplaySelectScene::update() if (trigger & KEY_A) { std::string choice = replays.choice(); - choice = "/bbb-moves/test";// + choice; + choice = "/bbb-moves/" + choice; ReplayScene::Config config; config.replay_filename = choice; - config.level = 1; - config.difficulty = EASY; current_scene = new ReplayScene(config); } else if (trigger & KEY_B || (trigger == 0 && replays.empty())) @@ -54,12 +52,7 @@ void ReplaySelectScene::update() } -void ReplaySelectScene::draw_top_left() -{ - replays.draw(); -} - -void ReplaySelectScene::draw_top_right() +void ReplaySelectScene::draw_top() { replays.draw(); } diff --git a/source/scenes/replay_select_scene.hpp b/source/scenes/replay_select_scene.hpp index 512b0aa..fcb4b9c 100644 --- a/source/scenes/replay_select_scene.hpp +++ b/source/scenes/replay_select_scene.hpp @@ -13,8 +13,7 @@ class ReplaySelectScene : public Scene void initialize(); void update(); protected: - void draw_top_left(); - void draw_top_right(); + void draw_top(); void draw_bottom(); private: CommandWindow replays; diff --git a/source/scenes/scene.hpp b/source/scenes/scene.hpp index a98ca9f..cbd816b 100644 --- a/source/scenes/scene.hpp +++ b/source/scenes/scene.hpp @@ -21,8 +21,10 @@ class Scene virtual void update() {} void draw(); protected: - virtual void draw_top_left() {} - virtual void draw_top_right() {} + virtual void draw_top_left() {draw_top();} + virtual void draw_top_right() {draw_top();} + + virtual void draw_top() {} virtual void draw_bottom() {} KeyRepeatStore repeat; }; diff --git a/source/scenes/title_scene.cpp b/source/scenes/title_scene.cpp index 3af1d6e..146fbc7 100644 --- a/source/scenes/title_scene.cpp +++ b/source/scenes/title_scene.cpp @@ -48,12 +48,7 @@ void TitleScene::update() current_scene = NULL; } -void TitleScene::draw_top_left() -{ - background.draw(); -} - -void TitleScene::draw_top_right() +void TitleScene::draw_top() { background.draw(); } diff --git a/source/scenes/title_scene.hpp b/source/scenes/title_scene.hpp index 60e6883..41623a6 100644 --- a/source/scenes/title_scene.hpp +++ b/source/scenes/title_scene.hpp @@ -20,8 +20,7 @@ class TitleScene : public Scene void initialize(); void update(); protected: - void draw_top_left(); - void draw_top_right(); + void draw_top(); void draw_bottom(); private: Texture background; diff --git a/source/util/BmpFont.cpp b/source/util/BmpFont.cpp new file mode 100644 index 0000000..3437d12 --- /dev/null +++ b/source/util/BmpFont.cpp @@ -0,0 +1,357 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016 Michael Norton + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include +#include +#include "BmpFont.h" + +BmpFont::BmpFont() +{ + texture = nullptr; + unclip(); +} + +BmpFont::BmpFont(const char *filename) + : BmpFont() +{ + load(filename); +} + +BmpFont::~BmpFont() +{ + if (texture != nullptr) free(); +} + +bool BmpFont::load(const char *filename) +{ + if (texture != nullptr) free(); + + std::FILE *fp = std::fopen(filename, "rb"); + + if (fp) { + u8 temp[2]; + std::fread(temp, 1, 2, fp); + + if (temp[0] != 0xBF || temp[1] != 0xF2) { + std::fclose(fp); + return false; + } + + std::fread(&imgWidth, 4, 1, fp); + std::fread(&imgHeight, 4, 1, fp); + std::fread(&cellWidth, 4, 1, fp); + std::fread(&cellHeight, 4, 1, fp); + + u8 bitCount; + std::fread(&bitCount, 1, 1, fp); + + std::fread(&baseChar, 1, 1, fp); + std::fread(charWidths, 1, 256, fp); + + std::size_t byteCount = 4 * imgWidth * imgHeight; + u8 *data = new u8[byteCount]; + + if (bitCount == 8) { + u8 *ptr = data; + for (std::size_t i=0; i clipRight) + width = clipRight - x; + if (y + height > clipBottom) + height = clipBottom - y; + } + + if (width > 0 && height > 0) + sf2d_draw_texture_part_blend(texture, x, y, tx, ty, width, height, color); + + return charWidths[uc]; + } else { + return 0; + } +} + +void BmpFont::splitToLines(const std::string &str, std::vector &lines, int wrapWidth) const +{ + lines.clear(); + if (wrapWidth == 0) { + // No wrapping + std::stringstream curLine; + for (const auto &ch : str) { + if (ch == '\n') { + lines.push_back(curLine.str()); + curLine.str(""); + } else { + curLine << ch; + } + } + lines.push_back(curLine.str()); + } else if (wrapWidth > 0) { + // Word wrap + std::vector words; + std::stringstream curWord; + u32 curX = 0; + + for (const auto &ch : str) { + u8 curCharWidth = charWidths[(unsigned char)ch]; + bool ignoreWhitespace = false; + + if (curX + curCharWidth > (unsigned)wrapWidth) { + words.push_back(curWord.str()); + curWord.str(""); + curX = 0; + ignoreWhitespace = true; + } + + if ((!ignoreWhitespace || ch != ' ') && ch != '\n') { + curWord << ch; + curX += curCharWidth; + } + + if (ch == ' ' || ch == '\n' || ch == '-') { + words.push_back(curWord.str()); + curWord.str(""); + curX = 0; + if (ch == '\n') + words.push_back("\n"); + } + } + + std::string lastWord = curWord.str(); + if (!lastWord.empty()) + words.push_back(lastWord); + + std::stringstream curLine; + curX = 0; + + for (const auto &word : words) { + u32 curWidth = getLineWidth(word); + + if (curX + curWidth > (unsigned)wrapWidth || word[0] == '\n') { + lines.push_back(curLine.str()); + curLine.str(""); + curX = 0; + } + + if (word[0] != '\n') { + curLine << word; + curX += curWidth; + } + } + + std::string lastLine = curLine.str(); + if (!lastLine.empty()) + lines.push_back(lastLine); + } else { + // Character wrap + wrapWidth = -wrapWidth; + std::stringstream curLine; + u32 curX = 0; + + for (const auto &ch : str) { + unsigned char uc = ch; + if (ch == '\n' || curX + charWidths[uc] > (unsigned)wrapWidth) { + lines.push_back(curLine.str()); + curLine.str(""); + curX = 0; + } + if (ch != '\n') { + curLine << ch; + curX += charWidths[uc]; + } + } + + lines.push_back(curLine.str()); + } +} + +u32 BmpFont::drawStrInternal(const std::string &str, int x, int y, u32 color) const +{ + u32 curX = 0; + u32 width = 0; + + if (alignment == ALIGN_RIGHT) { + x -= getTextWidth(str); + } else if (alignment == ALIGN_CENTER) { + x -= getTextWidth(str) / 2; + } + + for (const auto &ch : str) { + curX += drawChar(ch, x + curX, y, color); + if (curX > width) width = curX; + } + return width; +} + +u32 BmpFont::drawStr(const std::string &str, int x, int y, u32 color) const +{ + std::vector lines; + splitToLines(str, lines, 0); + + u32 width = 0; + for (std::size_t i=0; i width) + width = curWidth; + } + + return width; +} + +u32 BmpFont::drawStrWrap(const std::string &str, int x, int y, int wrapWidth, u32 color) const +{ + std::vector lines; + splitToLines(str, lines, wrapWidth); + + for (std::size_t i=0; i lines; + splitToLines(str, lines, wrapWidth); + + width = 0; + for (const auto &line : lines) { + u32 curWidth = getLineWidth(line); + if (curWidth > width) + width = curWidth; + } + + height = lines.size() * cellHeight; +} + +u32 BmpFont::getTextWidth(const std::string &str, int wrapWidth) const +{ + u32 width, height; + getTextDims(str, width, height, wrapWidth); + return width; +} + +u32 BmpFont::getTextHeight(const std::string &str, int wrapWidth) const +{ + u32 width, height; + getTextDims(str, width, height, wrapWidth); + return height; +} + +void BmpFont::free() +{ + sf2d_free_texture(texture); + texture = nullptr; +} + +BmpFont &BmpFont::align(TextAlignment alignment) +{ + this->alignment = alignment; + return *this; +} + +BmpFont &BmpFont::clip(int left, int top, int right, int bottom) +{ + if (left > right) + std::swap(left, right); + if (top > bottom) + std::swap(top, bottom); + + clipLeft = left; + clipTop = top; + clipRight = right; + clipBottom = bottom; + + return *this; +} + +BmpFont &BmpFont::unclip() +{ + clipLeft = clipTop = clipRight = clipBottom = 0; + return *this; +} + +bool BmpFont::isClipped() const +{ + return (clipLeft != 0) || (clipTop != 0) || (clipRight != 0) || (clipBottom != 0); +} + +BmpFont::operator bool() const +{ + return (texture != nullptr); +} + +u32 BmpFont::height() const +{ + return cellHeight; +} diff --git a/source/util/BmpFont.h b/source/util/BmpFont.h new file mode 100644 index 0000000..645fbbb --- /dev/null +++ b/source/util/BmpFont.h @@ -0,0 +1,62 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016 Michael Norton + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#pragma once +#include +#include +#include + +enum TextAlignment { ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT }; + +class BmpFont +{ +private: + sf2d_texture *texture; + u32 imgWidth, imgHeight; + u32 cellWidth, cellHeight; + unsigned char baseChar; + TextAlignment alignment; + int clipLeft, clipTop, clipRight, clipBottom; + u8 charWidths[256]; + + static constexpr u32 WHITE = RGBA8(0xFF, 0xFF, 0xFF, 0xFF); + + void splitToLines(const std::string &str, std::vector &lines, int wrapWidth) const; + u32 drawStrInternal(const std::string &str, int x, int y, u32 color) const; + u32 getLineWidth(const std::string &line) const; + +public: + BmpFont(); + BmpFont(const char *filename); + ~BmpFont(); + + bool load(const char *filename); + u8 drawChar(char ch, int x, int y, u32 color = WHITE) const; + u32 drawStr(const std::string &str, int x, int y, u32 color = WHITE) const; + u32 drawStrWrap(const std::string &str, int x, int y, int wrapWidth, u32 color = WHITE) const; + void getTextDims(const std::string &str, u32 &width, u32 &height, int wrapWidth = 0) const; + u32 getTextWidth(const std::string &str, int wrapWidth = 0) const; + u32 getTextHeight(const std::string &str, int wrapWidth = 0) const; + void free(); + + BmpFont &align(TextAlignment alignment); + + BmpFont &clip(int left, int top, int right, int bottom); + BmpFont &unclip(); + bool isClipped() const; + + operator bool() const; + u32 height() const; + + BmpFont(const BmpFont &other) = delete; + const BmpFont &operator=(const BmpFont &other) = delete; +}; \ No newline at end of file diff --git a/source/util/font.cpp b/source/util/font.cpp index 11e71e0..0f81c4a 100644 --- a/source/util/font.cpp +++ b/source/util/font.cpp @@ -1,29 +1,20 @@ #include "font.hpp" +#include -Font::Font(const void *src_buffer, int sw, int sh, int cw, int ch, sf2d_texfmt pixel_format, sf2d_place place) : - texture(sf2d_create_texture_mem_RGBA8(src_buffer, sw, sh, pixel_format, place)), text_width(cw), text_height(ch), - chars_per_row(sw / cw), blend_color(0xFFFFFFFF) +void Font::draw(const std::string& str, int x, int y, u32 color) { + impl.drawStr(str, x, y, color); } -Font::~Font() +void Font::draw(int val, int x, int y, u32 color) { - if (texture) - sf2d_free_texture(texture); - texture = NULL; + std::stringstream str; + str << val; + impl.drawStr(str.str(), x, y, color); } -void Font::draw(int x, int y, const std::string& str) +void Font::draw(const std::string& str, int x, int y, int w, int h, u32 color) { - if (!valid()) return; - for (unsigned int i = 0; i < str.size(); i++) - draw(x + text_width * i, y, str[i]); -} -void Font::draw(int x, int y, char ch) -{ - if (!valid()) return; - int tx = ch % chars_per_row; - int ty = ch / chars_per_row; - sf2d_draw_texture_part_blend(texture, x, y, tx * text_width, ty * text_height, text_width, text_height, blend_color); } + diff --git a/source/util/font.hpp b/source/util/font.hpp index cd84597..6c97963 100644 --- a/source/util/font.hpp +++ b/source/util/font.hpp @@ -3,26 +3,21 @@ #include #include +#include "BmpFont.h" class Font { public: - Font(const void *src_buffer, int sw, int sh, int cw, int ch, sf2d_texfmt pixel_format, sf2d_place place); - ~Font(); - bool valid() const {return texture;} - int char_width() const {return text_width;} - int char_height() const {return text_height;} - void draw(int x, int y, const std::string& str); - void draw(int x, int y, char ch); - void set_blend_color(u32 color) {blend_color = color;} - u32 get_blend_color() const {return blend_color;} + Font(const std::string& filename) : impl(filename.c_str()) {} + ~Font() {} + void load(const std::string& filename) {impl.load(filename.c_str());} + bool valid() const {return impl;} + void draw(const std::string& str, int x, int y, u32 color = 0xFFFFFFFF); + void draw(int value, int x, int y, u32 color = 0xFFFFFFFF); + void draw(const std::string& str, int x, int y, int w, int h, u32 color = 0xFFFFFFFF); private: - sf2d_texture* texture; - int text_width; - int text_height; - int chars_per_row; - u32 blend_color; + BmpFont impl; Font(const Font&) = delete; Font(Font&&) = delete; Font& operator=(const Font&) = delete; diff --git a/source/util/slider.cpp b/source/util/slider.cpp index 6231bfc..04d0039 100644 --- a/source/util/slider.cpp +++ b/source/util/slider.cpp @@ -48,5 +48,5 @@ void Slider::draw() sf2d_draw_rectangle(x + percent - 2, y - 6 + height / 2, 5, 12, RGBA8(0x60, 0x60, 0x60, 255)); sf2d_draw_rectangle(x + percent - 2 + 1, y - 6 + height / 2 + 1, 3, 10, !is_active() ? color.start() : color.color()); if (style & LABELS) - font->draw(x + width, y, value); + font->draw(value, x + width, y); } diff --git a/source/util/text.cpp b/source/util/text.cpp index fb139d2..6dcd971 100644 --- a/source/util/text.cpp +++ b/source/util/text.cpp @@ -18,5 +18,5 @@ void Text::create(int x, int y, const std::string& str) void Text::draw() { if (is_hidden()) return; - font->draw(x, y, text); + font->draw(text, x, y); } diff --git a/source/util/window.cpp b/source/util/window.cpp index 40f0669..fb8086a 100644 --- a/source/util/window.cpp +++ b/source/util/window.cpp @@ -46,7 +46,7 @@ void Window::draw() void Window::draw_text(int wx, int wy, const std::string& str) { - font->draw(x + wx + WINDOW_BORDER_SIZE, y + wy + WINDOW_BORDER_SIZE, str); + font->draw(str, x + wx + WINDOW_BORDER_SIZE, y + wy + WINDOW_BORDER_SIZE); } void Window::set_skin(const void *src_buffer, sf2d_texfmt pixel_format, sf2d_place place) diff --git a/source/util/window.hpp b/source/util/window.hpp index 7895adc..b0bc342 100644 --- a/source/util/window.hpp +++ b/source/util/window.hpp @@ -46,6 +46,7 @@ class WindowSkin private: Texture skin; }; + class Window : public Widget { public: diff --git a/source/windows/info_window.cpp b/source/windows/info_window.cpp index 7419560..e4bfb43 100644 --- a/source/windows/info_window.cpp +++ b/source/windows/info_window.cpp @@ -4,8 +4,8 @@ #include // for TOP_SCREEN_HEIGHT InfoWindow::InfoWindow() : Window(0, 0, 8 * 16, TOP_SCREEN_HEIGHT - WINDOW_BORDER_SIZE * 2), -speed_exp_bar(0, 100, 24 - WINDOW_BORDER_SIZE, 96, 6 * 16, 6, 0xFF809018, 0xFF101010), -time_left_bar(0, 1, 24 - WINDOW_BORDER_SIZE, 152, 6 * 16, 6, 0xFF000080, 0xFF101010), +speed_exp_bar(0, 100, 24 - WINDOW_BORDER_SIZE, 96 + WINDOW_BORDER_SIZE, 6 * 16, 6, 0xFF809018, 0xFF101010), +time_left_bar(0, 1, 24 - WINDOW_BORDER_SIZE, 152 + WINDOW_BORDER_SIZE, 6 * 16, 6, 0xFF000080, 0xFF101010), last_update(0), timeout(0), timeout_started(false), score(0) { start_time = osGetTime();