This repository has been archived on 2024-11-07. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Dawn-GB/src/conversation/textbox.c

177 lines
5.0 KiB
C

/**
* Copyright (c) 2022 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "textbox.h"
char TEXTBOX_TEXTS[TEXTBOX_SCROLL_ROWS_MAX * TEXTBOX_CHARS_PER_ROW];
uint8_t TEXTBOX_ROW_COUNT;
uint8_t TEXTBOX_ROW_CURRENT;
uint8_t TEXTBOX_STATE;
uint8_t TEXTBOX_SCROLL;
inline void conversationTextboxInit() {
uint8_t i;
uint8_t TEXTBOX_TILES[TEXTBOX_TILES_MAX];
// Reset textbox state
TEXTBOX_STATE = 0;
// Setup window data
move_win(7, SCREENHEIGHT - (TEXTBOX_HEIGHT_IN_TILES * 8));
set_win_data(FONT_DATA_POSITION, FONT_IMAGE_TILES, FONT_IMAGE);
set_win_data(BORDER_DATA_POSITION, BORDER_IMAGE_TILES, BORDER_IMAGE);
// Corners
TEXTBOX_TILES[0] = BORDER_TILE_TOP_LEFT;
TEXTBOX_TILES[TEXTBOX_WIDTH_IN_TILES-1] = BORDER_TILE_TOP_RIGHT;
TEXTBOX_TILES[TEXTBOX_TILES_MAX-1] = BORDER_TILE_BOTTOM_RIGHT;
TEXTBOX_TILES[TEXTBOX_TILES_MAX-TEXTBOX_WIDTH_IN_TILES] = BORDER_TILE_BOTTOM_LEFT;
// Edges
for(i = 1; i < TEXTBOX_WIDTH_IN_TILES - 1; i++) {
TEXTBOX_TILES[i] = BORDER_TILE_TOP_CENTER;
TEXTBOX_TILES[TEXTBOX_TILES_MAX - 1 - i] = BORDER_TILE_BOTTOM_CENTER;
}
for(i = 1; i < TEXTBOX_HEIGHT_IN_TILES - 1; i++) {
TEXTBOX_TILES[TEXTBOX_WIDTH_IN_TILES * i] = BORDER_TILE_CENTER_LEFT;
TEXTBOX_TILES[TEXTBOX_WIDTH_IN_TILES * (i+1) - 1] = BORDER_TILE_CENTER_RIGHT;
}
set_win_tiles(
0x00, 0x00,
TEXTBOX_WIDTH_IN_TILES, TEXTBOX_HEIGHT_IN_TILES,
TEXTBOX_TILES
);
}
void conversationTextboxSetText(char *text) {
uint8_t i, j, k, rowStart, stateFlags;
char c, c2;
// Begin by filling the textbox text chars with whitespace to begin.
// TODO: I'm pretty sure I can move this lower and optimize.
for(i = 0; i < TEXTBOX_SCROLL_ROWS_MAX * TEXTBOX_CHARS_PER_ROW; i++) {
TEXTBOX_TEXTS[i] = ' ';
}
// Reset textbox state
TEXTBOX_STATE = TEXTBOX_STATE_VISIBLE;
TEXTBOX_SCROLL = 0;
TEXTBOX_ROW_COUNT = 0;
TEXTBOX_ROW_CURRENT = 0;
TEXTBOX_ROW_COUNT = 1;
// Copy source text to buffer, also determine wordwrapping here.
i = 0, j = 0, rowStart = 0, stateFlags = 0;
while((c = text[i]) != '\0') {// "For each char in string"
if(c == ' ') {
// Scan ahead and look at how many chars remain to the next space.
k = i + 1;
while(
(c2 = text[k]) != '\0' &&
c2 != '\n' &&
c2 != ' ' &&
(k - rowStart) < TEXTBOX_CHARS_PER_ROW
) k++;
// IF that number is less than the remaining chars on the current row,
// then treat this space like a newline.
if(k >= (rowStart + TEXTBOX_CHARS_PER_ROW - 1)) {
stateFlags |= 1 << 0;
}
} else if(c == '\n') {
stateFlags |= 1 << 0;
}
// Do we need to insert newline where we are currently?
if((stateFlags & (1 << 0)) != 0) {
stateFlags &= ~(1 << 0);// Remove newline flag
i++;
rowStart = i;// Update the row start (Should this be i+1?)
//TODO: can I optimize the next line by using rowStart somehow?
j = ((j / TEXTBOX_CHARS_PER_ROW) + 1) * TEXTBOX_CHARS_PER_ROW;// Update destination character position.
TEXTBOX_ROW_COUNT++;
continue;
}
// Insert the character
TEXTBOX_TEXTS[j] = c;
i++;
j++;
}
// Now we have organized the string nicely we can prep for rendering. Fill the
// tiles with blank chars.
textboxFillBlank();
// Show the window layer.
SHOW_WIN;
}
inline void textboxFillBlank() {
uint8_t i, j;
uint8_t TEXTBOX_TILES[TEXTBOX_CHAR_ROWS * TEXTBOX_CHARS_PER_ROW];
for(j = 0; j < TEXTBOX_CHAR_ROWS; j++) {
for(i = 0; i < TEXTBOX_CHARS_PER_ROW ; i++) {
TEXTBOX_TILES[i + (j * TEXTBOX_CHARS_PER_ROW)] = TEXTBOX_TILE_BLANK;
}
}
set_win_tiles(
0x01, 0x01,
TEXTBOX_WIDTH_IN_TILES - 0x02, TEXTBOX_HEIGHT_IN_TILES - 0x02,
TEXTBOX_TILES
);
}
inline void conversationTextboxUpdate() {
uint8_t i;
char c;
uint8_t tiles[1];
// Is the textbox visible?
if((TEXTBOX_STATE & TEXTBOX_STATE_VISIBLE) == 0) return;
// Have we finished scrolling?
if(TEXTBOX_STATE & TEXTBOX_STATE_SCROLLED) {
// Is the user trying to go to the next line?
if(INPUT_STATE & J_A) {
// First, lets figure out if there's any more text to reveal or not.
if((TEXTBOX_ROW_COUNT - TEXTBOX_ROW_CURRENT) < TEXTBOX_TILES_ROWS) {
TEXTBOX_STATE &= ~TEXTBOX_STATE_VISIBLE;
HIDE_WIN;
conversationQueueNext();
return;
}
TEXTBOX_STATE &= ~TEXTBOX_STATE_SCROLLED;
TEXTBOX_SCROLL = 0;
TEXTBOX_ROW_CURRENT += TEXTBOX_TILES_ROWS;
textboxFillBlank();
}
return;
}
// Move to the next character.
i = TEXTBOX_ROW_CURRENT * TEXTBOX_CHARS_PER_ROW;
c = TEXTBOX_TEXTS[i+TEXTBOX_SCROLL];
if(TEXTBOX_SCROLL == TEXTBOX_CHARS_MAX) {
TEXTBOX_STATE |= TEXTBOX_STATE_SCROLLED;
} else {
tiles[0] = c - TEXTBOX_FONT_START + FONT_DATA_POSITION;
set_win_tiles(
0x01 + (TEXTBOX_SCROLL % TEXTBOX_CHARS_PER_ROW),
0x01 + (TEXTBOX_SCROLL / TEXTBOX_CHARS_PER_ROW),
1, 1,
tiles
);
TEXTBOX_SCROLL++;
}
}