From a0fb7b7bc5c4e798e4ad548e0bef2440b0386f62 Mon Sep 17 00:00:00 2001 From: Nunuhara Cabbage Date: Fri, 11 Jun 2021 19:41:24 -0700 Subject: [PATCH] GoatGUIEngine: implement numeral parts --- src/hll/GoatGUIEngine.c | 174 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 164 insertions(+), 10 deletions(-) diff --git a/src/hll/GoatGUIEngine.c b/src/hll/GoatGUIEngine.c index 5f317dc..699197f 100644 --- a/src/hll/GoatGUIEngine.c +++ b/src/hll/GoatGUIEngine.c @@ -95,6 +95,7 @@ enum parts_type { PARTS_CG, PARTS_TEXT, PARTS_ANIMATION, + PARTS_NUMERAL, }; struct parts_cg { @@ -122,12 +123,20 @@ struct parts_animation { unsigned current_frame; }; +struct parts_numeral { + Texture texture; + Texture cg[12]; + int space; + int show_comma; +}; + struct parts_state { enum parts_type type; union { struct parts_cg cg; struct parts_text text; struct parts_animation anim; + struct parts_numeral num; }; }; @@ -199,7 +208,7 @@ static void parts_render(struct parts *parts, struct parts_render_params *parent switch (state->type) { case PARTS_CG: if (state->cg.texture.handle) - parts_render_cg(parts, &parts->states[parts->state].cg.texture, ¶ms); + parts_render_cg(parts, &state->cg.texture, ¶ms); break; case PARTS_TEXT: if (state->text.texture.handle) @@ -207,7 +216,13 @@ static void parts_render(struct parts *parts, struct parts_render_params *parent break; case PARTS_ANIMATION: if (state->anim.texture.handle) - parts_render_cg(parts, &parts->states[parts->state].anim.texture, ¶ms); + parts_render_cg(parts, &state->anim.texture, ¶ms); + break; + case PARTS_NUMERAL: + if (state->num.texture.handle) { + NOTICE("RENDERING NUMERAL"); + parts_render_cg(parts, &state->num.texture, ¶ms); + } break; } @@ -342,6 +357,12 @@ static void parts_state_free(struct parts_state *state) gfx_delete_texture(&state->anim.frames[i]); } break; + case PARTS_NUMERAL: + gfx_delete_texture(&state->num.texture); + for (int i = 0; i < 12; i++) { + gfx_delete_texture(&state->num.cg[i]); + } + break; } memset(state, 0, sizeof(struct parts_state)); } @@ -379,6 +400,15 @@ static struct parts_animation *parts_get_animation(struct parts *parts, int stat return &parts->states[state].anim; } +static struct parts_numeral *parts_get_numeral(struct parts *parts, int state) +{ + if (parts->states[state].type != PARTS_NUMERAL) { + NOTICE("RESET NUMERAL (%d)", parts->states[state].type); + parts_state_reset(&parts->states[state], PARTS_NUMERAL); + } + return &parts->states[state].num; +} + static struct parts_motion *parts_motion_alloc(enum parts_motion_type type, int begin_time, int end_time) { struct parts_motion *motion = xcalloc(1, sizeof(struct parts_motion)); @@ -566,6 +596,9 @@ static void parts_set_alpha(struct parts *parts, int alpha) s->anim.frames[i].alpha_mod = parts->alpha; } break; + case PARTS_NUMERAL: + s->num.texture.alpha_mod = parts->alpha; + break; } } parts_dirty(parts); @@ -794,6 +827,12 @@ static bool GoatGUIEngine_SetPartsCG(int parts_no, int cg_no, possibly_unused in } struct parts *parts = parts_get(parts_no); + if (!cg_no) { + parts_state_reset(&parts->states[state], PARTS_CG); + parts_dirty(parts); + return true; + } + struct cg *cg = asset_cg_load(cg_no); if (!cg) return false; @@ -1057,10 +1096,125 @@ bool GoatGUIEngine_SetHGaugeRate(int PartsNumber, int Numerator, int Denominator bool GoatGUIEngine_SetVGaugeCG(int PartsNumber, int CGNumber, int State); bool GoatGUIEngine_SetVGaugeRate(int PartsNumber, int Numerator, int Denominator, int State); bool GoatGUIEngine_SetNumeralCG(int PartsNumber, int CGNumber, int State); -bool GoatGUIEngine_SetNumeralLinkedCGNumberWidthWidthList(int PartsNumber, int CGNumber, int Width0, int Width1, int Width2, int Width3, int Width4, int Width5, int Width6, int Width7, int Width8, int Width9, int WidthMinus, int WidthComma, int State); -bool GoatGUIEngine_SetNumeralNumber(int PartsNumber, int Number, int State); -bool GoatGUIEngine_SetNumeralShowComma(int PartsNumber, bool ShowComma, int State); -bool GoatGUIEngine_SetNumeralSpace(int PartsNumber, int NumeralSpace, int State); + +bool GoatGUIEngine_SetNumeralLinkedCGNumberWidthWidthList(int parts_no, int cg_no, int w0, int w1, int w2, int w3, int w4, int w5, int w6, int w7, int w8, int w9, int w_minus, int w_comma, int state) +{ + // TODO? Create a generic numeral-font object that can be shared between parts. + // In the current implementation, each number stores a complete copy of + // its numeral font. + + state--; + if (state < 0 || state > PARTS_NR_STATES) + return false; + + struct cg *cg = asset_cg_load(cg_no); + if (!cg) + return false; + + int w[12] = { w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w_minus, w_comma }; + Texture t = {0}; + gfx_init_texture_with_cg(&t, cg); + cg_free(cg); + + int x = 0; + struct parts_numeral *n = parts_get_numeral(parts_get(parts_no), state); + for (int i = 0; i < 12; i++) { + gfx_delete_texture(&n->cg[i]); + if (w[i] <= 0) + continue; + + gfx_init_texture_blank(&n->cg[i], w[i], t.h); + gfx_copy_with_alpha_map(&n->cg[i], 0, 0, &t, x, 0, w[i], t.h); + x += w[i]; + } + + gfx_delete_texture(&t); + return true; +} + +bool GoatGUIEngine_SetNumeralNumber(int parts_no, int n, int state) +{ + state--; + if (state < 0 || state > PARTS_NR_STATES) + return false; + + struct parts *parts = parts_get(parts_no); + struct parts_numeral *num = parts_get_numeral(parts, state); + bool negative = n < 0; + if (negative) + n *= -1; + + // extract digits + int digits; + uint8_t d[32]; + for (digits = 0; n; digits++) { + d[digits] = n % 10; + n /= 10; + } + + // encode number as texture indices + int nr_chars = 0; + uint8_t chars[32]; + if (negative) { + chars[nr_chars++] = 10; + } + for (int i = 0; i < digits; i++) { + if (num->show_comma && i > 0 && i % 3 == 0) { + chars[nr_chars++] = 11; + } + chars[nr_chars++] = d[i]; + } + + // determine output dimensions + int w = 0, h = 0; + for (int i = nr_chars-1; i >= 0; i--) { + if (!num->cg[chars[i]].handle) + continue; + w += num->cg[chars[i]].w; + h = max(h, num->cg[chars[i]].h); + } + w += (nr_chars-1) * num->space; + + // copy chars to texture + gfx_delete_texture(&num->texture); + gfx_init_texture_rgba(&num->texture, w, h, (SDL_Color){0, 0, 0, 255}); + + int x = 0; + for (int i = nr_chars-1; i>= 0; i--) { + Texture *ch = &num->cg[chars[i]]; + if (!ch->handle) + continue; + gfx_copy_with_alpha_map(&num->texture, x, 0, ch, 0, 0, ch->w, ch->h); + x += ch->w + num->space; + } + + parts->rect.w = w; + parts->rect.h = h; + + parts_dirty(parts); + return true; +} + +bool GoatGUIEngine_SetNumeralShowComma(int parts_no, bool show_comma, int state) +{ + state--; + if (state < 0 || state > PARTS_NR_STATES) + return false; + + parts_get_numeral(parts_get(parts_no), state)->show_comma = show_comma; + return true; +} + +bool GoatGUIEngine_SetNumeralSpace(int parts_no, int space, int state) +{ + state--; + if (state < 0 || state > PARTS_NR_STATES) + return false; + + parts_get_numeral(parts_get(parts_no), state)->space = space; + return true; +} + bool GoatGUIEngine_SetPartsRectangleDetectionSize(int PartsNumber, int Width, int Height, int State); bool GoatGUIEngine_SetPartsFlash(int PartsNumber, struct string *pIFlashFileName, int State); bool GoatGUIEngine_IsPartsFlashEnd(int PartsNumber, int State); @@ -1428,10 +1582,10 @@ HLL_LIBRARY(GoatGUIEngine, HLL_TODO_EXPORT(SetVGaugeCG, GoatGUIEngine_SetVGaugeCG), HLL_TODO_EXPORT(SetVGaugeRate, GoatGUIEngine_SetVGaugeRate), HLL_TODO_EXPORT(SetNumeralCG, GoatGUIEngine_SetNumeralCG), - HLL_TODO_EXPORT(SetNumeralLinkedCGNumberWidthWidthList, GoatGUIEngine_SetNumeralLinkedCGNumberWidthWidthList), - HLL_TODO_EXPORT(SetNumeralNumber, GoatGUIEngine_SetNumeralNumber), - HLL_TODO_EXPORT(SetNumeralShowComma, GoatGUIEngine_SetNumeralShowComma), - HLL_TODO_EXPORT(SetNumeralSpace, GoatGUIEngine_SetNumeralSpace), + HLL_EXPORT(SetNumeralLinkedCGNumberWidthWidthList, GoatGUIEngine_SetNumeralLinkedCGNumberWidthWidthList), + HLL_EXPORT(SetNumeralNumber, GoatGUIEngine_SetNumeralNumber), + HLL_EXPORT(SetNumeralShowComma, GoatGUIEngine_SetNumeralShowComma), + HLL_EXPORT(SetNumeralSpace, GoatGUIEngine_SetNumeralSpace), HLL_TODO_EXPORT(SetPartsRectangleDetectionSize, GoatGUIEngine_SetPartsRectangleDetectionSize), HLL_TODO_EXPORT(SetPartsFlash, GoatGUIEngine_SetPartsFlash), HLL_TODO_EXPORT(IsPartsFlashEnd, GoatGUIEngine_IsPartsFlashEnd),