Dreamcast: Initial WIP on showing on-screen keyboard when no keyboard connected

This commit is contained in:
UnknownShadow200 2024-04-11 20:16:40 +10:00
parent 4d8cd3e49e
commit 8bd5e66f46
5 changed files with 118 additions and 38 deletions

View File

@ -303,7 +303,7 @@ static Png_RowExpander Png_GetExpander(cc_uint8 col, cc_uint8 bitsPerSample) {
return NULL;
}
/* Sets alpha to 0 for any pixels in the bitmap whose RGB is same as col */
/* Sets alpha to 0 for any pixels in the bitmap whose RGB is same as colorspace */
static void ComputeTransparency(struct Bitmap* bmp, BitmapCol col) {
BitmapCol trnsRGB = col & BITMAPCOLOR_RGB_MASK;
int x, y, width = bmp->width, height = bmp->height;
@ -324,27 +324,27 @@ cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) {
/* header variables */
static const cc_uint8 samplesPerPixel[] = { 1, 0, 3, 1, 2, 0, 4 };
cc_uint8 col, bitsPerSample, bytesPerPixel = 0;
cc_uint8 colorspace, bitsPerSample, bytesPerPixel = 0;
Png_RowExpander rowExpander = NULL;
cc_uint32 scanlineSize = 0, scanlineBytes = 0;
/* palette data */
BitmapCol trnsCol;
BitmapCol trnsColor;
BitmapCol palette[PNG_PALETTE];
cc_uint32 i;
/* idat state */
cc_uint32 begY, rowY = 0, endY;
cc_uint8 buffer[PNG_PALETTE * 3];
cc_uint32 bufferIdx, bufferLen;
cc_uint32 read, left;
cc_uint32 read, bufferIdx = 0;
cc_uint32 left, bufferLen = 0;
int curY;
/* idat decompressor */
struct InflateState inflate;
struct Stream compStream, datStream;
struct ZLibHeader zlibHeader;
cc_uint8* data;
cc_uint8* data = NULL;
bmp->width = 0; bmp->height = 0;
bmp->scan0 = NULL;
@ -353,8 +353,8 @@ cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) {
if (res) return res;
if (!Png_Detect(tmp, PNG_SIG_SIZE)) return PNG_ERR_INVALID_SIG;
col = 0xFF; /* Unknown colour space */
trnsCol = BITMAPCOLOR_BLACK;
colorspace = 0xFF; /* Unknown colour space */
trnsColor = BITMAPCOLOR_BLACK;
for (i = 0; i < PNG_PALETTE; i++) { palette[i] = BITMAPCOLOR_BLACK; }
Inflate_MakeStream2(&compStream, &inflate, stream);
@ -378,25 +378,24 @@ cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) {
if (bmp->width < 0 || bmp->width > PNG_MAX_DIMS) return PNG_ERR_TOO_WIDE;
if (bmp->height < 0 || bmp->height > PNG_MAX_DIMS) return PNG_ERR_TOO_TALL;
bitsPerSample = tmp[8]; col = tmp[9];
bitsPerSample = tmp[8]; colorspace = tmp[9];
if (bitsPerSample == 16) return PNG_ERR_16BITSAMPLES;
rowExpander = Png_GetExpander(col, bitsPerSample);
rowExpander = Png_GetExpander(colorspace, bitsPerSample);
if (!rowExpander) return PNG_ERR_INVALID_COL_BPP;
if (tmp[10] != 0) return PNG_ERR_COMP_METHOD;
if (tmp[11] != 0) return PNG_ERR_FILTER;
if (tmp[12] != 0) return PNG_ERR_INTERLACED;
bytesPerPixel = ((samplesPerPixel[col] * bitsPerSample) + 7) >> 3;
scanlineSize = ((samplesPerPixel[col] * bitsPerSample * bmp->width) + 7) >> 3;
bytesPerPixel = ((samplesPerPixel[colorspace] * bitsPerSample) + 7) >> 3;
scanlineSize = ((samplesPerPixel[colorspace] * bitsPerSample * bmp->width) + 7) >> 3;
scanlineBytes = scanlineSize + 1; /* Add 1 byte for filter byte of each scanline */
data = Mem_TryAlloc(bmp->height, max(scanlineBytes, bmp->width * 4));
bmp->scan0 = (BitmapCol*)data;
if (!bmp->scan0) return ERR_OUT_OF_MEMORY;
bufferIdx = 0;
bufferLen = bmp->height * scanlineBytes;
} break;
@ -418,15 +417,15 @@ cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) {
/* 11.3.2.1 tRNS Transparency */
case PNG_FourCC('t','R','N','S'): {
if (col == PNG_COLOR_GRAYSCALE) {
if (colorspace == PNG_COLOR_GRAYSCALE) {
if (dataSize != 2) return PNG_ERR_TRANS_COUNT;
res = Stream_Read(stream, buffer, dataSize);
if (res) return res;
/* RGB is always two bytes */
trnsCol = BitmapCol_Make(buffer[1], buffer[1], buffer[1], 0);
} else if (col == PNG_COLOR_INDEXED) {
trnsColor = BitmapCol_Make(buffer[1], buffer[1], buffer[1], 0);
} else if (colorspace == PNG_COLOR_INDEXED) {
if (dataSize > PNG_PALETTE) return PNG_ERR_TRANS_COUNT;
res = Stream_Read(stream, buffer, dataSize);
@ -437,14 +436,14 @@ cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) {
palette[i] &= BITMAPCOLOR_RGB_MASK; /* set A to 0 */
palette[i] |= buffer[i] << BITMAPCOLOR_A_SHIFT;
}
} else if (col == PNG_COLOR_RGB) {
} else if (colorspace == PNG_COLOR_RGB) {
if (dataSize != 6) return PNG_ERR_TRANS_COUNT;
res = Stream_Read(stream, buffer, dataSize);
if (res) return res;
/* R,G,B are always two bytes */
trnsCol = BitmapCol_Make(buffer[1], buffer[3], buffer[5], 0);
trnsColor = BitmapCol_Make(buffer[1], buffer[3], buffer[5], 0);
} else {
return PNG_ERR_TRANS_INVALID;
}
@ -488,7 +487,7 @@ cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) {
/* With the RGBA colourspace, each scanline is (1 + width*4) bytes wide */
/* Therefore once a row has been reconstructed, the prior row can be converted */
/* immediately into the destination colour format */
if (col == PNG_COLOR_RGB_A) {
if (colorspace == PNG_COLOR_RGB_A) {
/* Prior line is no longer needed and can be overwritten now */
rowExpander(bmp->width, palette, &prior[1], Bitmap_GetRow(bmp, rowY - 1));
/* Current line is also no longer needed and can be overwritten now */
@ -505,14 +504,14 @@ cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) {
/* Therefore image expansion can only be done after all the rows have been reconstructed, and must */
/* be done backwards to avoid overwriting any source data that has yet to be processed */
/* This is slightly slower, but the majority of images ClassiCube encounters are RGBA anyways */
if (col != PNG_COLOR_RGB_A) {
if (colorspace != PNG_COLOR_RGB_A) {
for (curY = bmp->height - 1; curY >= 0; curY--) {
cc_uint8* scanline = &data[curY * scanlineBytes];
rowExpander(bmp->width, palette, &scanline[1], Bitmap_GetRow(bmp, curY));
}
}
if (!BitmapCol_A(trnsCol)) ComputeTransparency(bmp, trnsCol);
if (!BitmapCol_A(trnsColor)) ComputeTransparency(bmp, trnsColor);
return 0;
} break;

View File

@ -187,6 +187,8 @@ static cc_bool IsShutdown(int key) {
}
static void OnInputDown(void* obj, int key, cc_bool was) {
if (Window_Main.SoftKeyboardFocus) return;
if (IsShutdown(key)) Launcher_ShouldExit = true;
Launcher_Active->KeyDown(Launcher_Active, key, was);
}

View File

@ -1,16 +1,22 @@
#include "Core.h"
#include "Drawer2D.h"
#include "Funcs.h"
#include "Drawer2D.h"
#include "Event.h"
#include "ExtMath.h"
#include "String.h"
#include "Input.h"
#include "Utils.h"
#include "LBackend.h"
#include "Window.h"
static cc_bool kb_inited, kb_showing, kb_shift;
static cc_bool kb_inited, kb_showing, kb_shift, kb_needsHook;
static struct FontDesc kb_font;
static int kb_selected;
static const char** kb_table;
static float kb_padXAcc, kb_padYAcc;
static char kb_buffer[512];
static cc_string kb_str = String_FromArray(kb_buffer);
static void (*KB_MarkDirty)(void);
#define KB_CELLS_PER_ROW 13
#define KB_LAST_CELL (KB_CELLS_PER_ROW - 1)
@ -24,15 +30,15 @@ static cc_string kb_str = String_FromArray(kb_buffer);
static const char* kb_table_lower[] =
{
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", "\x11 BSP",
"q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "(", ")", "& ",
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", "Backspace",
"q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "(", ")", "& ",
"a", "s", "d", "f", "g", "h", "j", "k", "l", "?", ";", "'", "Enter",
"z", "x", "c", "v", "b", "n", "m", ".", ",","\\", "!", "@", "/ ",
"Caps", "Shift", "Space"
};
static const char* kb_table_upper[] =
{
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", "< BSP",
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", "Backspace",
"Q", "W", "E", "R", "T", "Y", "U", "I", "o", "p", "(", ")", "& ",
"A", "S", "D", "F", "G", "H", "J", "K", "L", "?", ";", "'", "Enter",
"Z", "X", "C", "V", "B", "N", "M", ".", ",","\\", "!", "@", "/ ",
@ -49,7 +55,7 @@ static void VirtualKeyboard_Init(void) {
}
static int VirtualKeyboard_Width(void) {
return (KB_CELLS_PER_ROW + 4) * KB_TILE_SIZE;
return (KB_CELLS_PER_ROW + 3) * KB_TILE_SIZE;
}
static int VirtualKeyboard_Height(void) {
@ -57,6 +63,7 @@ static int VirtualKeyboard_Height(void) {
}
static void VirtualKeyboard_Close(void);
static void VirtualKeyboard_Hook(void);
#define KB_NORMAL_COLOR BitmapCol_Make(0x7F, 0x7F, 0x7F, 0x90)
@ -69,6 +76,7 @@ static void VirtualKeyboard_Draw(struct Context2D* ctx) {
int row, cell;
int i, x, y, w, h, dx, dy;
Drawer2D.Colors['f'] = Drawer2D.Colors['0'];
if (kb_needsHook) VirtualKeyboard_Hook();
for (row = 0, y = 0; row < KB_TOTAL_ROWS; row++)
{
@ -103,15 +111,16 @@ static void VirtualKeyboard_Scroll(int delta) {
kb_selected += delta;
if (kb_selected < 0) kb_selected += KB_TOTAL_CHARS;
Math_Clamp(kb_selected, 0, KB_TOTAL_CHARS - 1);
KB_MarkDirty();
}
static void VirtualKeyboard_ToggleTable(void) {
kb_table = kb_table == kb_table_lower ? kb_table_upper : kb_table_lower;
KB_MarkDirty();
}
static void VirtualKeyboard_AppendChar(char c) {
String_Append(&kb_str, c);
Platform_Log1("%s", &kb_str);
Event_RaiseString(&InputEvents.TextChanged, &kb_str);
if (kb_shift) { VirtualKeyboard_ToggleTable(); kb_shift = false; }
@ -125,8 +134,10 @@ static void VirtualKeyboard_ClickSelected(void) {
case KB_INDEX(KB_LAST_CELL, 0):
if (kb_str.length) kb_str.length--;
Event_RaiseString(&InputEvents.TextChanged, &kb_str);
KB_MarkDirty();
break;
case KB_INDEX(KB_LAST_CELL, 2):
KB_MarkDirty();
Window_CloseKeyboard();
Input_SetPressed(CCKEY_ENTER);
Input_SetReleased(CCKEY_ENTER);
@ -158,8 +169,10 @@ static void VirtualKeyboard_ProcessDown(void* obj, int key, cc_bool was) {
VirtualKeyboard_Scroll(-KB_CELLS_PER_ROW);
} else if (Input_IsDownButton(key)) {
VirtualKeyboard_Scroll(+KB_CELLS_PER_ROW);
} else if (Input_IsEnterButton(key) || key == CCPAD_A) {
} else if (Input_IsEnterButton(key) || key == CCPAD_A) {
VirtualKeyboard_ClickSelected();
} else if (Input_IsEscapeButton(key) || key == CCPAD_B) {
VirtualKeyboard_Close();
}
}
@ -174,10 +187,28 @@ static void VirtualKeyboard_PadAxis(void* obj, int axis, float x, float y) {
}
static void VirtualKeyboard_Display(struct OpenKeyboardArgs* args) {
static void VirtualKeyboard_MarkDirty2D(void) {
LBackend_Redraw();
}
static void VirtualKeyboard_MarkDirty3D(void) {
/* TODO */
}
static void VirtualKeyboard_Hook(void) {
/* Don't hook immediately into events, otherwise the initial up/down press that opened */
/* the virtual keyboard in the first place gets mistakenly processed */
kb_needsHook = false;
Event_Register_(&InputEvents.Down, NULL, VirtualKeyboard_ProcessDown);
Event_Register_(&ControllerEvents.AxisUpdate, NULL, VirtualKeyboard_PadAxis);
}
static void VirtualKeyboard_Open(struct OpenKeyboardArgs* args, cc_bool launcher) {
VirtualKeyboard_Close();
VirtualKeyboard_Init();
kb_showing = true;
kb_showing = true;
kb_needsHook = true;
kb_table = kb_table_lower;
kb_selected = -1;
@ -187,9 +218,14 @@ static void VirtualKeyboard_Display(struct OpenKeyboardArgs* args) {
kb_str.length = 0;
if (args) String_AppendConst(&kb_str, args->placeholder);
Event_Register_(&InputEvents.Down, NULL, VirtualKeyboard_ProcessDown);
Event_Register_(&ControllerEvents.AxisUpdate, NULL, VirtualKeyboard_PadAxis);
if (launcher) {
KB_MarkDirty = VirtualKeyboard_MarkDirty2D;
} else {
KB_MarkDirty = VirtualKeyboard_MarkDirty3D;
}
Window_Main.SoftKeyboardFocus = true;
}
static void VirtualKeyboard_SetText(const cc_string* text) {
@ -197,7 +233,34 @@ static void VirtualKeyboard_SetText(const cc_string* text) {
}
static void VirtualKeyboard_Close(void) {
if (KB_MarkDirty) KB_MarkDirty();
Event_Unregister_(&InputEvents.Down, NULL, VirtualKeyboard_ProcessDown);
Event_Unregister_(&ControllerEvents.AxisUpdate, NULL, VirtualKeyboard_PadAxis);
kb_showing = false;
Window_Main.SoftKeyboardFocus = false;
KB_MarkDirty = NULL;
kb_showing = false;
kb_needsHook = false;
}
static void VirtualKeyboard_Display2D(Rect2D* r, struct Bitmap* bmp) {
struct Context2D ctx;
struct Bitmap copy = *bmp;
int x, y;
/* Mark entire framebuffer as needing to be redrawn */
r->x = 0; r->width = bmp->width;
r->y = 0; r->height = bmp->height;
/* Draw virtual keyboard at centre of window bottom */
y = bmp->height - 1 - VirtualKeyboard_Height();
y = max(y, 0);
copy.scan0 = Bitmap_GetRow(bmp, y);
x = (bmp->width - VirtualKeyboard_Width()) / 2;
x = max(x, 0);
copy.scan0 += x;
Context2D_Wrap(&ctx, &copy);
VirtualKeyboard_Draw(&ctx);
}

View File

@ -84,6 +84,8 @@ struct _WindowData {
/* Whether this window is backgrounded / inactivated */
/* (rendering is not performed when window is inactive) */
cc_bool Inactive;
/* Whether input should be ignored due to soft keyboard being open */
cc_bool SoftKeyboardFocus;
};
/* Data for the game/launcher window */

View File

@ -10,6 +10,7 @@
#include "Bitmap.h"
#include "Errors.h"
#include "ExtMath.h"
#include "VirtualKeyboard.h"
#include <kos.h>
static cc_bool launcherMode;
cc_bool window_inited;
@ -31,6 +32,7 @@ void Window_Init(void) {
Input.Sources = INPUT_SOURCE_GAMEPAD;
DisplayInfo.ContentOffsetX = 10;
DisplayInfo.ContentOffsetY = 20;
Window_Main.SoftKeyboard = SOFT_KEYBOARD_VIRTUAL;
vid_set_mode(DEFAULT_VID_MODE, DEFAULT_PIXEL_MODE);
vid_flip(0);
@ -262,6 +264,7 @@ void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) {
// https://dcemulation.org/phpBB/viewtopic.php?t=99999
// https://dcemulation.org/phpBB/viewtopic.php?t=43214
vid_waitvbl();
if (kb_showing) VirtualKeyboard_Display2D(&r, bmp);
for (int y = r.y; y < r.y + r.height; y++)
{
@ -285,9 +288,20 @@ void Window_FreeFramebuffer(struct Bitmap* bmp) {
/*########################################################################################################################*
*------------------------------------------------------Soft keyboard------------------------------------------------------*
*#########################################################################################################################*/
void Window_OpenKeyboard(struct OpenKeyboardArgs* args) { /* TODO implement */ }
void Window_SetKeyboardText(const cc_string* text) { }
void Window_CloseKeyboard(void) { /* TODO implement */ }
void Window_OpenKeyboard(struct OpenKeyboardArgs* args) {
if (Input.Sources & INPUT_SOURCE_NORMAL) return;
VirtualKeyboard_Open(args, launcherMode);
}
void Window_SetKeyboardText(const cc_string* text) {
if (!kb_showing) return;
VirtualKeyboard_SetText(text);
}
void Window_CloseKeyboard(void) {
if (Input.Sources & INPUT_SOURCE_NORMAL) return;
VirtualKeyboard_Close();
}
/*########################################################################################################################*