#include "./hud.h" #include #include #include #include #include #include #include "util/glyphas/block.h" #include "util/glyphas/cache.h" #include "util/math/vector.h" #include "core/lochara/base.h" #include "core/locommon/easing.h" #include "core/locommon/screen.h" #include "core/locommon/ticker.h" #include "core/loplayer/player.h" #include "core/loresource/set.h" #include "core/loresource/text.h" #include "core/loshader/set.h" #define BAR_SPEED_ 5 #define STATUS_MAX_WIDTH_ .6f #define STATUS_FAITH_SIZE_ .8f #define EFFECT_TEXT_COLOR_ vec4(1, 1, 1, 1) #define EFFECT_FADE_SPEED_ 2 #define EFFECT_LINE_HEIGHT_ 1.2f #define BIOME_TEXT_COLOR_ vec4(1, 1, 1, 1) #define BIOME_TEXT_SEED_ 29 /* = prime number */ static void loui_hud_calculate_geometry_( loui_hud_t* hud, const locommon_screen_t* screen) { assert(hud != NULL); assert(locommon_screen_valid(screen)); typeof(hud->geo)* g = &hud->geo; # define inch2winpos_(winpos, inch) \ locommon_screen_calc_winpos_from_inch(screen, winpos, inch) inch2winpos_(&g->padding, &vec2(.3f, .3f)); inch2winpos_(&g->madness_sz, &vec2(3.f, .12f)); if (g->madness_sz.x > STATUS_MAX_WIDTH_) { vec2_muleq(&g->madness_sz, STATUS_MAX_WIDTH_/g->madness_sz.x); } vec2_mul(&g->faith_sz, &g->madness_sz, .5f); # undef inch2winpos_ g->madness_pos = vec2(-1, 1); g->madness_pos.x += g->madness_sz.x + g->padding.x; g->madness_pos.y -= g->madness_sz.y + g->padding.y; g->faith_pos = vec2(-1, 1); g->faith_pos.x += g->padding.x + g->faith_sz.x; g->faith_pos.y -= g->padding.y + g->madness_sz.y*2 + g->faith_sz.y; locommon_screen_calc_pixels_from_inch( screen, &g->effect_fontpx, &vec2(.4f, .4f)); locommon_screen_calc_winpos_from_pixels( screen, &g->effect_fontsz, &g->effect_fontpx); g->effect_sz.x = 3*screen->dpi.x/screen->resolution.x; g->effect_sz.y = 4/screen->resolution.y; g->effect_pos = vec2(1-g->padding.x, -1+g->padding.y); vec2_subeq(&g->effect_pos, &g->effect_sz); locommon_screen_calc_pixels_from_inch( screen, &g->biome_fontpx, &vec2(.3f, .3f)); locommon_screen_calc_winpos_from_pixels( screen, &g->biome_fontsz, &g->biome_fontpx); vec2_add(&g->biome_pos, &vec2(-1, -1), &g->padding); } static void loui_hud_draw_status_bars_(const loui_hud_t* hud) { assert(hud != NULL); loshader_hud_bar_drawer_add_instance( &hud->shaders->drawer.hud_bar, &(loshader_hud_bar_drawer_instance_t) { .pos = hud->geo.madness_pos, .size = hud->geo.madness_sz, .bgcolor = vec4(0, 0, 0, hud->alpha), .fgcolor = vec4(1, 1, 1, .9f*hud->alpha), .value = hud->player->entity->param.recipient.madness, .prev_value = hud->prev_madness, }); loshader_hud_bar_drawer_add_instance( &hud->shaders->drawer.hud_bar, &(loshader_hud_bar_drawer_instance_t) { .pos = hud->geo.faith_pos, .size = hud->geo.faith_sz, .bgcolor = vec4(0, 0, 0, hud->alpha), .fgcolor = vec4(.9f, .9f, .9f, .9f*hud->alpha), .value = hud->player->entity->param.recipient.faith, .prev_value = hud->prev_faith, }); } static void loui_hud_initialize_effect_( loui_hud_t* hud, loui_hud_effect_t* effect, const locommon_screen_t* screen, const char* name) { assert(hud != NULL); assert(effect != NULL); assert(name != NULL); assert(locommon_screen_valid(screen)); *effect = (typeof(*effect)) { .text = glyphas_block_new( GLYPHAS_ALIGNER_DIRECTION_HORIZONTAL, -hud->geo.effect_fontpx.y, INT32_MAX, 32), }; glyphas_block_add_characters( effect->text, hud->font.effect, &EFFECT_TEXT_COLOR_, name, strlen(name)); const vec2_t reso = screen->resolution; glyphas_block_scale(effect->text, &vec2(2/reso.x, 2/reso.y)); } static void loui_hud_deinitialize_effect_(loui_hud_effect_t* effect) { assert(effect != NULL); glyphas_block_delete(effect->text); } static void loui_hud_update_effect_bars_(loui_hud_t* hud) { assert(hud != NULL); const loeffect_recipient_t* r = &hud->player->entity->param.recipient; loui_hud_effect_set_t* e = &hud->effects.set; const uint64_t t = hud->ticker->time; const float dt = hud->ticker->delta_f; # define lasting_effect_(n) do { \ const bool active = \ r->effects.n.start <= t && \ t < r->effects.n.start + r->effects.n.duration; \ locommon_easing_smooth_float( \ &e->n.alpha, !!active, dt*EFFECT_FADE_SPEED_); \ if (active) { \ e->n.value = (t - r->effects.n.start)*1.f / r->effects.n.duration; \ } \ } while (0) lasting_effect_(amnesia); lasting_effect_(curse); # undef lasting_effect_ } static void loui_hud_draw_effect_bars_(const loui_hud_t* hud) { assert(hud != NULL); const typeof(hud->geo)* g = &hud->geo; float h = 0; for (size_t i = 0; i < LOUI_HUD_EFFECT_COUNT; ++i) { const loui_hud_effect_t* e = &hud->effects.arr[i]; if (e->alpha == 0) continue; const float a = e->alpha * hud->alpha; const float y = h*g->effect_fontsz.y + g->effect_pos.y; glyphas_block_set_origin(e->text, &vec2(1, -1)); glyphas_block_translate(e->text, &vec2(1-g->padding.x, y)); glyphas_block_set_alpha(e->text, powf(a, 2)); loshader_hud_text_drawer_add_block( &hud->shaders->drawer.hud_text, e->text); loshader_hud_bar_drawer_add_instance( &hud->shaders->drawer.hud_bar, &(loshader_hud_bar_drawer_instance_t) { .pos = vec2(g->effect_pos.x, y), .size = vec2(-g->effect_sz.x, g->effect_sz.y), .bgcolor = vec4(1, 1, 1, .2f*a), .fgcolor = vec4(1, 1, 1, .8f*a), .value = e->value, .prev_value = e->value, }); h += a*a*(3-2*a)*EFFECT_LINE_HEIGHT_; } } static glyphas_block_t* loui_hud_create_biome_text_( loui_hud_t* hud, const locommon_screen_t* screen, const char* text) { assert(hud != NULL); assert(text != NULL); assert(locommon_screen_valid(screen)); glyphas_block_t* b = glyphas_block_new( GLYPHAS_ALIGNER_DIRECTION_HORIZONTAL, -hud->geo.biome_fontpx.y, INT32_MAX, 32); glyphas_block_add_characters( b, hud->font.biome, &BIOME_TEXT_COLOR_, text, strlen(text)); const vec2_t reso = screen->resolution; glyphas_block_scale(b, &vec2(2/reso.x, 2/reso.y)); glyphas_block_set_origin(b, &vec2(0, -1)); glyphas_block_translate(b, &hud->geo.biome_pos); glyphas_block_make_glitched(b, text[0]*BIOME_TEXT_SEED_); return b; } static void loui_hud_draw_biome_text_(const loui_hud_t* hud) { assert(hud != NULL); loshader_hud_text_drawer_add_block( &hud->shaders->drawer.hud_text, hud->biomes[hud->current_biome]); } void loui_hud_initialize( loui_hud_t* hud, loresource_set_t* res, loshader_set_t* shaders, const locommon_screen_t* screen, const locommon_ticker_t* ticker, loplayer_t* player) { assert(hud != NULL); assert(res != NULL); assert(shaders != NULL); assert(ticker != NULL); assert(player != NULL); assert(locommon_screen_valid(screen)); *hud = (typeof(*hud)) { .shaders = shaders, .ticker = ticker, .player = player, }; loui_hud_calculate_geometry_(hud, screen); hud->font = (typeof(hud->font)) { .effect = glyphas_cache_new( shaders->tex.hud_text, &res->font.sans, hud->geo.effect_fontpx.x, hud->geo.effect_fontpx.y), .biome = glyphas_cache_new( shaders->tex.hud_text, &res->font.serif, hud->geo.biome_fontpx.x, hud->geo.biome_fontpx.y), }; # define text_(name) loresource_text_get(res->lang, name) loui_hud_effect_set_t* e = &hud->effects.set; loui_hud_initialize_effect_( hud, &e->amnesia, screen, text_("effect_amnesia")); loui_hud_initialize_effect_( hud, &e->curse, screen, text_("effect_curse")); # define each_(NAME, name) do { \ hud->biomes[LOWORLD_CHUNK_BIOME_##NAME] = \ loui_hud_create_biome_text_(hud, screen, text_("biome_"#name)); \ } while (0) LOWORLD_CHUNK_BIOME_EACH(each_); # undef each_ # undef text_ } void loui_hud_deinitialize(loui_hud_t* hud) { assert(hud != NULL); for (size_t i = 0; i < LOUI_HUD_EFFECT_COUNT; ++i) { loui_hud_deinitialize_effect_(&hud->effects.arr[i]); } for (size_t i = 0; i < LOWORLD_CHUNK_BIOME_COUNT; ++i) { glyphas_block_delete(hud->biomes[i]); } glyphas_cache_delete(hud->font.effect); glyphas_cache_delete(hud->font.biome); } void loui_hud_update(loui_hud_t* hud) { assert(hud != NULL); const float dt = hud->ticker->delta_f; locommon_easing_smooth_float( &hud->prev_madness, hud->player->entity->param.recipient.madness, dt*BAR_SPEED_); locommon_easing_smooth_float( &hud->prev_faith, hud->player->entity->param.recipient.faith, dt*BAR_SPEED_); loui_hud_update_effect_bars_(hud); } void loui_hud_draw(const loui_hud_t* hud) { assert(hud != NULL); hud->shaders->drawer.hud_text.alpha = hud->alpha; loui_hud_draw_status_bars_(hud); loui_hud_draw_effect_bars_(hud); loui_hud_draw_biome_text_(hud); }