[RELEASE] u22-v04
This version is submitted for U22 final presentation. (squashed 158 commits)
This commit is contained in:
19
core/loui/CMakeLists.txt
Normal file
19
core/loui/CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
add_library(loui
|
||||
combat.c
|
||||
event.c
|
||||
hud.c
|
||||
menu.c
|
||||
popup.c
|
||||
ui.c
|
||||
)
|
||||
target_link_libraries(loui
|
||||
glyphas
|
||||
math
|
||||
|
||||
lochara
|
||||
locommon
|
||||
loplayer
|
||||
loresource
|
||||
loshader
|
||||
loworld
|
||||
)
|
127
core/loui/combat.c
Normal file
127
core/loui/combat.c
Normal file
@@ -0,0 +1,127 @@
|
||||
#include "./combat.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "util/math/algorithm.h"
|
||||
#include "util/math/vector.h"
|
||||
|
||||
#include "core/locommon/easing.h"
|
||||
#include "core/locommon/ticker.h"
|
||||
#include "core/loplayer/player.h"
|
||||
#include "core/loshader/set.h"
|
||||
|
||||
#define FADE_SPEED_ 50
|
||||
|
||||
#define RING_ATTACK_RANGE_ .6f
|
||||
#define RING_GUARD_RANGE_ .8f
|
||||
|
||||
#define RING_BASE_COLOR_(a) vec4(0, 0, 0, (a)*.6f)
|
||||
#define RING_CLOCKHAND_COLOR_(a) vec4(1, 1, 1, (a))
|
||||
#define RING_ATTACK_COLOR_(a) vec4(1, 0, 0, (a))
|
||||
#define RING_GUARD_COLOR_(a) vec4(0, 0, 1, (a))
|
||||
|
||||
#define RING_TAIL_PADDING_ 500
|
||||
|
||||
void loui_combat_initialize(
|
||||
loui_combat_t* combat,
|
||||
loshader_set_t* shaders,
|
||||
const locommon_ticker_t* ticker,
|
||||
const loplayer_t* player) {
|
||||
assert(combat != NULL);
|
||||
assert(shaders != NULL);
|
||||
assert(ticker != NULL);
|
||||
assert(player != NULL);
|
||||
|
||||
*combat = (typeof(*combat)) {
|
||||
.shaders = shaders,
|
||||
.ticker = ticker,
|
||||
.player = player,
|
||||
};
|
||||
}
|
||||
|
||||
void loui_combat_deinitialize(loui_combat_t* combat) {
|
||||
assert(combat != NULL);
|
||||
|
||||
}
|
||||
|
||||
void loui_combat_update(loui_combat_t* combat) {
|
||||
assert(combat != NULL);
|
||||
|
||||
const float dt = combat->ticker->delta_f;
|
||||
|
||||
const loplayer_combat_attack_t* la = combat->player->combat.last_attack;
|
||||
locommon_easing_smooth_float(&combat->alpha, !!(la != NULL), dt*FADE_SPEED_);
|
||||
if (la == NULL) {
|
||||
if (combat->ring_end <= combat->ticker->time) {
|
||||
combat->ring_end = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (combat->ring_end <= combat->ring_start) {
|
||||
combat->ring_start = combat->ticker->time;
|
||||
}
|
||||
combat->ring_end = la->start + la->duration + RING_TAIL_PADDING_;
|
||||
}
|
||||
|
||||
void loui_combat_draw(const loui_combat_t* combat) {
|
||||
assert(combat != NULL);
|
||||
|
||||
if (combat->alpha <= 0) return;
|
||||
|
||||
loshader_combat_ring_drawer_add_instance(
|
||||
&combat->shaders->drawer.combat_ring,
|
||||
&(loshader_combat_ring_drawer_instance_t) {
|
||||
.range = -1, /* = base */
|
||||
.color = RING_BASE_COLOR_(combat->alpha),
|
||||
});
|
||||
|
||||
const uint64_t ring_st = combat->ring_start;
|
||||
const uint64_t ring_ed = combat->ring_end;
|
||||
if (ring_ed < ring_st) return;
|
||||
|
||||
const uint64_t t = combat->ticker->time;
|
||||
const uint64_t dur = ring_ed - ring_st;
|
||||
loshader_combat_ring_drawer_add_instance(
|
||||
&combat->shaders->drawer.combat_ring,
|
||||
&(loshader_combat_ring_drawer_instance_t) {
|
||||
.range = 0, /* = clockhand */
|
||||
.start = (t - ring_st)*1.f/dur,
|
||||
.color = RING_CLOCKHAND_COLOR_(combat->alpha),
|
||||
});
|
||||
|
||||
const loplayer_combat_t* pcombat = &combat->player->combat;
|
||||
for (size_t i = 0; i < LOPLAYER_COMBAT_RESERVE; ++i) {
|
||||
const loplayer_combat_attack_t* a = &pcombat->attacks[i];
|
||||
if (a->duration == 0) continue;
|
||||
|
||||
const uint64_t st = MATH_MAX(ring_st, a->start);
|
||||
const uint64_t ed = a->start+a->duration;
|
||||
|
||||
loshader_combat_ring_drawer_add_instance(
|
||||
&combat->shaders->drawer.combat_ring,
|
||||
&(loshader_combat_ring_drawer_instance_t) {
|
||||
.range = RING_ATTACK_RANGE_,
|
||||
.start = (st - ring_st)*1.f/dur,
|
||||
.end = (ed - ring_st)*1.f/dur,
|
||||
.color = RING_ATTACK_COLOR_(combat->alpha),
|
||||
});
|
||||
}
|
||||
|
||||
const uint64_t gst = MATH_MAX(ring_st, pcombat->last_guard_start);
|
||||
const uint64_t ged =
|
||||
pcombat->last_guard_start <= pcombat->last_guard_end?
|
||||
pcombat->last_guard_end: t;
|
||||
if (ring_st <= gst && gst < ged && ged < ring_ed) {
|
||||
loshader_combat_ring_drawer_add_instance(
|
||||
&combat->shaders->drawer.combat_ring,
|
||||
&(loshader_combat_ring_drawer_instance_t) {
|
||||
.range = RING_GUARD_RANGE_,
|
||||
.start = (gst - ring_st)*1.f/dur,
|
||||
.end = (ged - ring_st)*1.f/dur,
|
||||
.color = RING_GUARD_COLOR_(combat->alpha),
|
||||
});
|
||||
}
|
||||
}
|
41
core/loui/combat.h
Normal file
41
core/loui/combat.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "core/locommon/ticker.h"
|
||||
#include "core/loplayer/player.h"
|
||||
#include "core/loshader/set.h"
|
||||
|
||||
typedef struct {
|
||||
loshader_set_t* shaders;
|
||||
const locommon_ticker_t* ticker;
|
||||
const loplayer_t* player;
|
||||
|
||||
uint64_t ring_start;
|
||||
uint64_t ring_end;
|
||||
float clockhand;
|
||||
float alpha;
|
||||
} loui_combat_t;
|
||||
|
||||
void
|
||||
loui_combat_initialize(
|
||||
loui_combat_t* combat,
|
||||
loshader_set_t* shaders,
|
||||
const locommon_ticker_t* ticker,
|
||||
const loplayer_t* player
|
||||
);
|
||||
|
||||
void
|
||||
loui_combat_deinitialize(
|
||||
loui_combat_t* combat
|
||||
);
|
||||
|
||||
void
|
||||
loui_combat_update(
|
||||
loui_combat_t* combat
|
||||
);
|
||||
|
||||
void
|
||||
loui_combat_draw(
|
||||
const loui_combat_t* combat
|
||||
);
|
117
core/loui/event.c
Normal file
117
core/loui/event.c
Normal file
@@ -0,0 +1,117 @@
|
||||
#include "./event.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "util/math/vector.h"
|
||||
#include "util/glyphas/block.h"
|
||||
#include "util/glyphas/cache.h"
|
||||
|
||||
#include "core/locommon/easing.h"
|
||||
#include "core/locommon/screen.h"
|
||||
#include "core/locommon/ticker.h"
|
||||
#include "core/loplayer/event.h"
|
||||
#include "core/loplayer/player.h"
|
||||
#include "core/loresource/set.h"
|
||||
#include "core/loresource/text.h"
|
||||
#include "core/loshader/set.h"
|
||||
|
||||
#define LINE_MAX_CHARS_ 256
|
||||
|
||||
#define CINESCOPE_SIZE_ .23f
|
||||
#define LINE_COLOR_ vec4(1, 1, 1, 1)
|
||||
|
||||
static void loui_event_update_line_(loui_event_t* ev) {
|
||||
assert(ev != NULL);
|
||||
|
||||
if (ev->player->event.ctx.line.last_update <= ev->last_line_update) {
|
||||
return;
|
||||
}
|
||||
ev->last_line_update = ev->player->event.ctx.line.last_update;
|
||||
|
||||
const char* id = ev->player->event.ctx.line.text_id;
|
||||
const char* s = id == NULL? "": loresource_text_get(ev->res->lang, id);
|
||||
|
||||
glyphas_block_clear(ev->line);
|
||||
glyphas_block_add_characters(
|
||||
ev->line, ev->font, &LINE_COLOR_, s, strlen(s));
|
||||
|
||||
glyphas_block_scale(
|
||||
ev->line,
|
||||
&vec2(2/ev->screen->resolution.x, 2/ev->screen->resolution.y));
|
||||
glyphas_block_set_origin(ev->line, &vec2(.5f, -.5f));
|
||||
|
||||
vec2_t sz, offset;
|
||||
glyphas_block_calculate_geometry(ev->line, &sz, &offset);
|
||||
|
||||
const float y = -1 + CINESCOPE_SIZE_/2 + sz.y/2;
|
||||
glyphas_block_translate(ev->line, &vec2(0, y));
|
||||
}
|
||||
|
||||
void loui_event_initialize(
|
||||
loui_event_t* ev,
|
||||
loresource_set_t* res,
|
||||
loshader_set_t* shaders,
|
||||
const locommon_screen_t* screen,
|
||||
const locommon_ticker_t* ticker,
|
||||
loplayer_t* player) {
|
||||
assert(ev != NULL);
|
||||
assert(res != NULL);
|
||||
assert(shaders != NULL);
|
||||
assert(screen != NULL);
|
||||
assert(ticker != NULL);
|
||||
assert(player != NULL);
|
||||
|
||||
vec2_t fontpx;
|
||||
locommon_screen_calc_pixels_from_inch(screen, &fontpx, &vec2(.15f, .15f));
|
||||
|
||||
*ev = (typeof(*ev)) {
|
||||
.res = res,
|
||||
.shaders = shaders,
|
||||
.screen = screen,
|
||||
.ticker = ticker,
|
||||
.player = player,
|
||||
|
||||
.font = glyphas_cache_new(
|
||||
shaders->tex.event_line,
|
||||
&res->font.serif,
|
||||
fontpx.x,
|
||||
fontpx.y),
|
||||
.line = glyphas_block_new(
|
||||
GLYPHAS_ALIGNER_DIRECTION_HORIZONTAL,
|
||||
-fontpx.y,
|
||||
INT32_MAX,
|
||||
LINE_MAX_CHARS_),
|
||||
};
|
||||
}
|
||||
|
||||
void loui_event_deinitialize(loui_event_t* ev) {
|
||||
assert(ev != NULL);
|
||||
|
||||
glyphas_block_delete(ev->line);
|
||||
glyphas_cache_delete(ev->font);
|
||||
}
|
||||
|
||||
void loui_event_update(loui_event_t* ev) {
|
||||
assert(ev != NULL);
|
||||
|
||||
loui_event_update_line_(ev);
|
||||
|
||||
const float dt = ev->ticker->delta_f;
|
||||
locommon_easing_smooth_float(
|
||||
&ev->cinescope, ev->player->event.ctx.cinescope*CINESCOPE_SIZE_, dt);
|
||||
}
|
||||
|
||||
void loui_event_draw(const loui_event_t* ev) {
|
||||
assert(ev != NULL);
|
||||
|
||||
loshader_event_line_drawer_add_block(
|
||||
&ev->shaders->drawer.event_line, ev->line);
|
||||
|
||||
loshader_cinescope_drawer_set_param(
|
||||
&ev->shaders->drawer.cinescope,
|
||||
&(loshader_cinescope_drawer_param_t) {
|
||||
.size = ev->cinescope,
|
||||
.color = vec4(0, 0, 0, 1),
|
||||
});
|
||||
}
|
50
core/loui/event.h
Normal file
50
core/loui/event.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/glyphas/block.h"
|
||||
#include "util/glyphas/cache.h"
|
||||
|
||||
#include "core/locommon/screen.h"
|
||||
#include "core/locommon/ticker.h"
|
||||
#include "core/loplayer/player.h"
|
||||
#include "core/loresource/set.h"
|
||||
#include "core/loshader/set.h"
|
||||
|
||||
typedef struct {
|
||||
loresource_set_t* res;
|
||||
loshader_set_t* shaders;
|
||||
const locommon_screen_t* screen;
|
||||
const locommon_ticker_t* ticker;
|
||||
loplayer_t* player;
|
||||
|
||||
glyphas_cache_t* font;
|
||||
|
||||
float cinescope;
|
||||
|
||||
glyphas_block_t* line;
|
||||
uint64_t last_line_update;
|
||||
} loui_event_t;
|
||||
|
||||
void
|
||||
loui_event_initialize(
|
||||
loui_event_t* ev,
|
||||
loresource_set_t* res,
|
||||
loshader_set_t* shaders,
|
||||
const locommon_screen_t* screen,
|
||||
const locommon_ticker_t* ticker,
|
||||
loplayer_t* player
|
||||
);
|
||||
|
||||
void
|
||||
loui_event_deinitialize(
|
||||
loui_event_t* ev
|
||||
);
|
||||
|
||||
void
|
||||
loui_event_update(
|
||||
loui_event_t* ev
|
||||
);
|
||||
|
||||
void
|
||||
loui_event_draw(
|
||||
const loui_event_t* ev
|
||||
);
|
319
core/loui/hud.c
Normal file
319
core/loui/hud.c
Normal file
@@ -0,0 +1,319 @@
|
||||
#include "./hud.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
96
core/loui/hud.h
Normal file
96
core/loui/hud.h
Normal file
@@ -0,0 +1,96 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "util/glyphas/block.h"
|
||||
#include "util/glyphas/cache.h"
|
||||
#include "util/math/vector.h"
|
||||
|
||||
#include "core/locommon/screen.h"
|
||||
#include "core/locommon/ticker.h"
|
||||
#include "core/loplayer/player.h"
|
||||
#include "core/loresource/set.h"
|
||||
#include "core/loshader/set.h"
|
||||
#include "core/loworld/chunk.h"
|
||||
|
||||
typedef struct {
|
||||
glyphas_block_t* text;
|
||||
|
||||
float alpha;
|
||||
float value;
|
||||
} loui_hud_effect_t;
|
||||
|
||||
typedef struct {
|
||||
loui_hud_effect_t amnesia;
|
||||
loui_hud_effect_t curse;
|
||||
} loui_hud_effect_set_t;
|
||||
|
||||
#define LOUI_HUD_EFFECT_COUNT \
|
||||
(sizeof(loui_hud_effect_set_t)/sizeof(loui_hud_effect_t))
|
||||
|
||||
typedef struct {
|
||||
loshader_set_t* shaders;
|
||||
const locommon_ticker_t* ticker;
|
||||
loplayer_t* player;
|
||||
|
||||
struct {
|
||||
glyphas_cache_t* effect;
|
||||
glyphas_cache_t* biome;
|
||||
} font;
|
||||
|
||||
struct {
|
||||
vec2_t padding;
|
||||
|
||||
vec2_t madness_pos;
|
||||
vec2_t madness_sz;
|
||||
vec2_t faith_pos;
|
||||
vec2_t faith_sz;
|
||||
|
||||
vec2_t effect_fontpx;
|
||||
vec2_t effect_fontsz;
|
||||
vec2_t effect_pos;
|
||||
vec2_t effect_sz;
|
||||
|
||||
vec2_t biome_fontpx;
|
||||
vec2_t biome_fontsz;
|
||||
vec2_t biome_pos;
|
||||
} geo;
|
||||
|
||||
union {
|
||||
loui_hud_effect_set_t set;
|
||||
loui_hud_effect_t arr[LOUI_HUD_EFFECT_COUNT];
|
||||
} effects;
|
||||
|
||||
glyphas_block_t* biomes[LOWORLD_CHUNK_BIOME_COUNT];
|
||||
loworld_chunk_biome_t current_biome;
|
||||
|
||||
float prev_madness;
|
||||
float prev_faith;
|
||||
|
||||
float alpha;
|
||||
} loui_hud_t;
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
void
|
||||
loui_hud_deinitialize(
|
||||
loui_hud_t* hud
|
||||
);
|
||||
|
||||
void
|
||||
loui_hud_update(
|
||||
loui_hud_t* hud
|
||||
);
|
||||
|
||||
void
|
||||
loui_hud_draw(
|
||||
const loui_hud_t* hud
|
||||
);
|
366
core/loui/menu.c
Normal file
366
core/loui/menu.c
Normal file
@@ -0,0 +1,366 @@
|
||||
#include "./menu.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "util/glyphas/block.h"
|
||||
#include "util/glyphas/cache.h"
|
||||
#include "util/math/constant.h"
|
||||
#include "util/math/vector.h"
|
||||
|
||||
#include "core/locommon/easing.h"
|
||||
#include "core/locommon/input.h"
|
||||
#include "core/locommon/screen.h"
|
||||
#include "core/locommon/ticker.h"
|
||||
#include "core/loplayer/player.h"
|
||||
#include "core/loplayer/stance.h"
|
||||
#include "core/loresource/set.h"
|
||||
#include "core/loresource/text.h"
|
||||
#include "core/loshader/set.h"
|
||||
|
||||
#define FADE_SPEED_ 2
|
||||
|
||||
#define STANCE_TEXT_LINEHEIGHT_ 1.5f
|
||||
#define STANCE_TEXT_MAX_WIDTH_ 3.5f /* inch */
|
||||
|
||||
#define STANCE_NAME_RESERVE_ 32
|
||||
#define STANCE_DESC_RESERVE_ 256
|
||||
#define STANCE_NOTE_RESERVE_ 256
|
||||
|
||||
#define STANCE_NAME_COLOR_ vec4(1, 1, 1, 1)
|
||||
#define STANCE_DESC_COLOR_ vec4(1, 1, 1, 1)
|
||||
#define STANCE_NOTE_COLOR_ vec4(.8f, .8f, 0, 1)
|
||||
|
||||
#define STANCE_ICON_HIGHLIGHT_SPEED_ 5
|
||||
#define STANCE_ICON_HIGHLIGHT_SIZE_ .2f
|
||||
|
||||
static void loui_menu_calc_geometry_(
|
||||
loui_menu_t* menu, const locommon_screen_t* screen) {
|
||||
assert(menu != NULL);
|
||||
assert(locommon_screen_valid(screen));
|
||||
|
||||
typeof(menu->geo)* g = &menu->geo;
|
||||
|
||||
# define calc_font_geo_(name, sz) do { \
|
||||
locommon_screen_calc_pixels_from_inch( \
|
||||
screen, &g->name##_fontpx, sz); \
|
||||
locommon_screen_calc_winpos_from_pixels( \
|
||||
screen, &g->name##_fontsz, &g->big_fontpx); \
|
||||
} while (0)
|
||||
|
||||
calc_font_geo_(big, &vec2(.20f, .20f));
|
||||
calc_font_geo_(normal, &vec2(.16f, .16f));
|
||||
calc_font_geo_(small, &vec2(.12f, .12f));
|
||||
|
||||
# undef calc_font_geo_
|
||||
|
||||
locommon_screen_calc_winpos_from_inch(
|
||||
screen, &g->stance_icon_interval, &vec2(2, 2));
|
||||
locommon_screen_calc_winpos_from_inch(
|
||||
screen, &g->stance_iconsz, &vec2(.3f, .3f));
|
||||
}
|
||||
|
||||
static void loui_menu_initialize_stance_(
|
||||
loui_menu_t* menu,
|
||||
loui_menu_stance_t* stance,
|
||||
const locommon_screen_t* screen,
|
||||
const char* name,
|
||||
const char* desc,
|
||||
const char* note) {
|
||||
assert(menu != NULL);
|
||||
assert(stance != NULL);
|
||||
assert(name != NULL);
|
||||
assert(desc != NULL);
|
||||
assert(note != NULL);
|
||||
assert(locommon_screen_valid(screen));
|
||||
|
||||
*stance = (typeof(*stance)) {0};
|
||||
|
||||
const float theta =
|
||||
(stance - menu->stances)*1.f/LOPLAYER_STANCE_COUNT*2*MATH_PI +
|
||||
MATH_PI/2;
|
||||
stance->pos.x = cos(theta) * menu->geo.stance_icon_interval.x;
|
||||
stance->pos.y = sin(theta) * menu->geo.stance_icon_interval.y;
|
||||
|
||||
const float width = screen->dpi.x*STANCE_TEXT_MAX_WIDTH_;
|
||||
const vec2_t invreso = vec2(2/screen->resolution.x, 2/screen->resolution.y);
|
||||
|
||||
stance->name = glyphas_block_new(
|
||||
GLYPHAS_ALIGNER_DIRECTION_HORIZONTAL,
|
||||
-menu->geo.big_fontpx.y*STANCE_TEXT_LINEHEIGHT_,
|
||||
INT32_MAX,
|
||||
STANCE_NAME_RESERVE_);
|
||||
glyphas_block_add_characters(
|
||||
stance->name,
|
||||
menu->font.sans.big,
|
||||
&STANCE_NAME_COLOR_,
|
||||
name,
|
||||
strlen(name));
|
||||
glyphas_block_scale(stance->name, &invreso);
|
||||
|
||||
stance->desc = glyphas_block_new(
|
||||
GLYPHAS_ALIGNER_DIRECTION_HORIZONTAL,
|
||||
-menu->geo.normal_fontpx.y*STANCE_TEXT_LINEHEIGHT_,
|
||||
width,
|
||||
STANCE_DESC_RESERVE_);
|
||||
glyphas_block_add_characters(
|
||||
stance->desc,
|
||||
menu->font.sans.normal,
|
||||
&STANCE_DESC_COLOR_,
|
||||
desc,
|
||||
strlen(desc));
|
||||
glyphas_block_scale(stance->desc, &invreso);
|
||||
|
||||
stance->note = glyphas_block_new(
|
||||
GLYPHAS_ALIGNER_DIRECTION_HORIZONTAL,
|
||||
-menu->geo.small_fontpx.y,
|
||||
width,
|
||||
STANCE_NOTE_RESERVE_);
|
||||
glyphas_block_add_characters(
|
||||
stance->note,
|
||||
menu->font.serif.small,
|
||||
&STANCE_NOTE_COLOR_,
|
||||
note,
|
||||
strlen(note));
|
||||
glyphas_block_scale(stance->note, &invreso);
|
||||
|
||||
glyphas_block_set_origin(stance->name, &vec2(.5f, 0));
|
||||
glyphas_block_set_origin(stance->desc, &vec2(.5f, 0));
|
||||
glyphas_block_set_origin(stance->note, &vec2(.5f, 0));
|
||||
|
||||
vec2_t dummy;
|
||||
|
||||
vec2_t namesz;
|
||||
glyphas_block_calculate_geometry(stance->name, &dummy, &namesz);
|
||||
vec2_t descsz;
|
||||
glyphas_block_calculate_geometry(stance->desc, &dummy, &descsz);
|
||||
vec2_t notesz;
|
||||
glyphas_block_calculate_geometry(stance->note, &dummy, ¬esz);
|
||||
|
||||
const float note_padding = menu->geo.small_fontsz.y;
|
||||
|
||||
float y = (namesz.y + descsz.y + note_padding + notesz.y)/2;
|
||||
glyphas_block_translate(stance->name, &vec2(0, y));
|
||||
|
||||
y -= namesz.y;
|
||||
glyphas_block_translate(stance->desc, &vec2(0, y));
|
||||
|
||||
y -= descsz.y + note_padding;
|
||||
glyphas_block_translate(stance->note, &vec2(0, y));
|
||||
}
|
||||
|
||||
static void loui_menu_deinitialize_stance_(loui_menu_stance_t* stance) {
|
||||
assert(stance != NULL);
|
||||
|
||||
glyphas_block_delete(stance->name);
|
||||
glyphas_block_delete(stance->desc);
|
||||
glyphas_block_delete(stance->note);
|
||||
}
|
||||
|
||||
static glyphas_block_t* loui_menu_create_exit_text_(
|
||||
loui_menu_t* menu, const locommon_screen_t* screen, const char* text) {
|
||||
assert(menu != NULL);
|
||||
assert(screen != NULL);
|
||||
assert(text != NULL);
|
||||
|
||||
glyphas_block_t* b = glyphas_block_new(
|
||||
GLYPHAS_ALIGNER_DIRECTION_HORIZONTAL,
|
||||
-menu->geo.normal_fontpx.y,
|
||||
INT32_MAX,
|
||||
32);
|
||||
glyphas_block_add_characters(
|
||||
b, menu->font.sans.normal, &vec4(1, 1, 1, 1), text, strlen(text));
|
||||
|
||||
glyphas_block_scale(
|
||||
b, &vec2(2.f/screen->resolution.x, 2.f/screen->resolution.y));
|
||||
glyphas_block_set_origin(b, &vec2(.5f, -1));
|
||||
glyphas_block_translate(b, &vec2(0, -1));
|
||||
return b;
|
||||
}
|
||||
|
||||
static loui_menu_stance_t* loui_menu_find_stance_icon_at_(
|
||||
loui_menu_t* menu, const vec2_t* pos) {
|
||||
assert(menu != NULL);
|
||||
assert(vec2_valid(pos));
|
||||
|
||||
for (size_t i = 0; i < LOPLAYER_STANCE_COUNT; ++i) {
|
||||
vec2_t p;
|
||||
vec2_sub(&p, pos, &menu->stances[i].pos);
|
||||
p.x /= menu->geo.stance_iconsz.x;
|
||||
p.y /= menu->geo.stance_iconsz.y;
|
||||
if (fabsf(p.x) + fabsf(p.y) < 1) {
|
||||
return &menu->stances[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void loui_menu_update_stances_(
|
||||
loui_menu_t* menu, const locommon_input_t* input) {
|
||||
assert(menu != NULL);
|
||||
|
||||
const float dt = menu->ticker->delta_f;
|
||||
|
||||
menu->hovered_stance =
|
||||
input == NULL? NULL:
|
||||
loui_menu_find_stance_icon_at_(menu, &input->cursor);
|
||||
|
||||
for (size_t i = 0; i < LOPLAYER_STANCE_COUNT; ++i) {
|
||||
loui_menu_stance_t* s = &menu->stances[i];
|
||||
locommon_easing_linear_float(
|
||||
&s->highlight,
|
||||
s == menu->hovered_stance,
|
||||
dt*STANCE_ICON_HIGHLIGHT_SPEED_);
|
||||
}
|
||||
}
|
||||
|
||||
static void loui_menu_draw_stance_icons_(const loui_menu_t* menu) {
|
||||
assert(menu != NULL);
|
||||
|
||||
for (size_t i = 0; i < LOPLAYER_STANCE_COUNT; ++i) {
|
||||
const loui_menu_stance_t* s = &menu->stances[i];
|
||||
|
||||
const loshader_menu_stance_id_t id =
|
||||
loplayer_stance_set_has(&menu->player->stances, i)?
|
||||
loplayer_stance_get_menu_shader_id(i):
|
||||
LOSHADER_MENU_STANCE_ID_EMPTY;
|
||||
|
||||
vec2_t sz = menu->geo.stance_iconsz;
|
||||
vec2_muleq(&sz, 1+powf(s->highlight, 2.f)*STANCE_ICON_HIGHLIGHT_SIZE_);
|
||||
|
||||
loshader_menu_stance_drawer_add_instance(
|
||||
&menu->shaders->drawer.menu_stance,
|
||||
&(loshader_menu_stance_drawer_instance_t) {
|
||||
.id = id,
|
||||
.pos = s->pos,
|
||||
.size = sz,
|
||||
.alpha = menu->alpha,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void loui_menu_draw_stance_text_(const loui_menu_t* menu) {
|
||||
assert(menu != NULL);
|
||||
|
||||
if (menu->hovered_stance == NULL) return;
|
||||
|
||||
const size_t index = menu->hovered_stance - menu->stances;
|
||||
|
||||
const loui_menu_stance_t* s = menu->hovered_stance;
|
||||
if (!loplayer_stance_set_has(&menu->player->stances, index)) {
|
||||
s = &menu->stances[LOPLAYER_STANCE_COUNT];
|
||||
}
|
||||
|
||||
loshader_menu_text_drawer_add_block(
|
||||
&menu->shaders->drawer.menu_text, s->name);
|
||||
loshader_menu_text_drawer_add_block(
|
||||
&menu->shaders->drawer.menu_text, s->desc);
|
||||
loshader_menu_text_drawer_add_block(
|
||||
&menu->shaders->drawer.menu_text, s->note);
|
||||
}
|
||||
|
||||
void loui_menu_initialize(
|
||||
loui_menu_t* menu,
|
||||
loresource_set_t* res,
|
||||
loshader_set_t* shaders,
|
||||
const locommon_screen_t* screen,
|
||||
const locommon_ticker_t* ticker,
|
||||
loplayer_t* player) {
|
||||
assert(menu != NULL);
|
||||
assert(res != NULL);
|
||||
assert(shaders != NULL);
|
||||
assert(ticker != NULL);
|
||||
assert(player != NULL);
|
||||
assert(locommon_screen_valid(screen));
|
||||
|
||||
*menu = (typeof(*menu)) {
|
||||
.shaders = shaders,
|
||||
.ticker = ticker,
|
||||
.player = player,
|
||||
};
|
||||
loui_menu_calc_geometry_(menu, screen);
|
||||
|
||||
menu->font = (typeof(menu->font)) {
|
||||
.sans = {
|
||||
.big = glyphas_cache_new(
|
||||
shaders->tex.menu_text,
|
||||
&res->font.sans,
|
||||
menu->geo.big_fontpx.x,
|
||||
menu->geo.big_fontpx.y),
|
||||
.normal = glyphas_cache_new(
|
||||
shaders->tex.menu_text,
|
||||
&res->font.sans,
|
||||
menu->geo.normal_fontpx.x,
|
||||
menu->geo.normal_fontpx.y),
|
||||
},
|
||||
.serif = {
|
||||
.small = glyphas_cache_new(
|
||||
shaders->tex.menu_text,
|
||||
&res->font.serif,
|
||||
menu->geo.small_fontpx.x,
|
||||
menu->geo.small_fontpx.y),
|
||||
},
|
||||
};
|
||||
|
||||
# define text_(v) loresource_text_get(res->lang, v)
|
||||
|
||||
# define each_(NAME, name) \
|
||||
loui_menu_initialize_stance_( \
|
||||
menu, \
|
||||
&menu->stances[LOPLAYER_STANCE_##NAME], \
|
||||
screen, \
|
||||
text_("stance_"#name"_name"), \
|
||||
text_("stance_"#name"_desc"), \
|
||||
text_("stance_"#name"_note"))
|
||||
LOPLAYER_STANCE_EACH(each_);
|
||||
# undef each_
|
||||
|
||||
loui_menu_initialize_stance_(
|
||||
menu, &menu->stances[LOPLAYER_STANCE_COUNT],
|
||||
screen,
|
||||
text_("stance_unknown_name"),
|
||||
text_("stance_unknown_desc"),
|
||||
text_("stance_unknown_note"));
|
||||
menu->exit_text = loui_menu_create_exit_text_(
|
||||
menu, screen, text_("menu_exit"));
|
||||
|
||||
# undef text_
|
||||
}
|
||||
|
||||
void loui_menu_deinitialize(loui_menu_t* menu) {
|
||||
assert(menu != NULL);
|
||||
|
||||
for (size_t i = 0; i < LOPLAYER_STANCE_COUNT+1; ++i) {
|
||||
loui_menu_deinitialize_stance_(&menu->stances[i]);
|
||||
}
|
||||
glyphas_block_delete(menu->exit_text);
|
||||
glyphas_cache_delete(menu->font.sans.big);
|
||||
glyphas_cache_delete(menu->font.sans.normal);
|
||||
glyphas_cache_delete(menu->font.serif.small);
|
||||
}
|
||||
|
||||
void loui_menu_update(loui_menu_t* menu, const locommon_input_t* input) {
|
||||
assert(menu != NULL);
|
||||
|
||||
loui_menu_update_stances_(menu, input);
|
||||
|
||||
menu->request_exit =
|
||||
input != NULL &&
|
||||
input->buttons & LOCOMMON_INPUT_BUTTON_OK &&
|
||||
input->cursor.y < -1+menu->geo.normal_fontsz.y;
|
||||
}
|
||||
|
||||
void loui_menu_draw(const loui_menu_t* menu) {
|
||||
assert(menu != NULL);
|
||||
|
||||
if (menu->alpha <= 0) return;
|
||||
|
||||
menu->shaders->drawer.menu_text.alpha = menu->alpha;
|
||||
menu->shaders->drawer.menu_background.alpha = menu->alpha;
|
||||
|
||||
loui_menu_draw_stance_icons_(menu);
|
||||
loui_menu_draw_stance_text_(menu);
|
||||
|
||||
loshader_menu_text_drawer_add_block(
|
||||
&menu->shaders->drawer.menu_text, menu->exit_text);
|
||||
}
|
86
core/loui/menu.h
Normal file
86
core/loui/menu.h
Normal file
@@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/glyphas/block.h"
|
||||
#include "util/glyphas/cache.h"
|
||||
#include "util/math/vector.h"
|
||||
|
||||
#include "core/locommon/input.h"
|
||||
#include "core/locommon/screen.h"
|
||||
#include "core/locommon/ticker.h"
|
||||
#include "core/loplayer/player.h"
|
||||
#include "core/loplayer/stance.h"
|
||||
#include "core/loresource/set.h"
|
||||
#include "core/loshader/set.h"
|
||||
|
||||
typedef struct {
|
||||
glyphas_block_t* name;
|
||||
glyphas_block_t* desc;
|
||||
glyphas_block_t* note;
|
||||
|
||||
vec2_t pos;
|
||||
float highlight;
|
||||
} loui_menu_stance_t;
|
||||
|
||||
typedef struct {
|
||||
loshader_set_t* shaders;
|
||||
const locommon_ticker_t* ticker;
|
||||
loplayer_t* player;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
glyphas_cache_t* big;
|
||||
glyphas_cache_t* normal;
|
||||
} sans;
|
||||
struct {
|
||||
glyphas_cache_t* small;
|
||||
} serif;
|
||||
} font;
|
||||
|
||||
struct {
|
||||
vec2_t big_fontpx;
|
||||
vec2_t big_fontsz;
|
||||
|
||||
vec2_t normal_fontpx;
|
||||
vec2_t normal_fontsz;
|
||||
|
||||
vec2_t small_fontpx;
|
||||
vec2_t small_fontsz;
|
||||
|
||||
vec2_t stance_icon_interval;
|
||||
vec2_t stance_iconsz;
|
||||
} geo;
|
||||
|
||||
loui_menu_stance_t stances[LOPLAYER_STANCE_COUNT+1];
|
||||
loui_menu_stance_t* hovered_stance;
|
||||
|
||||
glyphas_block_t* exit_text;
|
||||
bool request_exit;
|
||||
|
||||
float alpha;
|
||||
} loui_menu_t;
|
||||
|
||||
void
|
||||
loui_menu_initialize(
|
||||
loui_menu_t* menu,
|
||||
loresource_set_t* res,
|
||||
loshader_set_t* shaders,
|
||||
const locommon_screen_t* screen,
|
||||
const locommon_ticker_t* ticker,
|
||||
loplayer_t* player
|
||||
);
|
||||
|
||||
void
|
||||
loui_menu_deinitialize(
|
||||
loui_menu_t* menu
|
||||
);
|
||||
|
||||
void
|
||||
loui_menu_update(
|
||||
loui_menu_t* menu,
|
||||
const locommon_input_t* input /* NULLABLE */
|
||||
);
|
||||
|
||||
void
|
||||
loui_menu_draw(
|
||||
const loui_menu_t* menu
|
||||
);
|
137
core/loui/popup.c
Normal file
137
core/loui/popup.c
Normal file
@@ -0,0 +1,137 @@
|
||||
#include "./popup.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util/glyphas/block.h"
|
||||
#include "util/glyphas/cache.h"
|
||||
#include "util/math/vector.h"
|
||||
|
||||
#include "core/locommon/easing.h"
|
||||
#include "core/locommon/screen.h"
|
||||
#include "core/locommon/ticker.h"
|
||||
#include "core/loplayer/player.h"
|
||||
#include "core/loplayer/popup.h"
|
||||
#include "core/loresource/set.h"
|
||||
#include "core/loresource/text.h"
|
||||
#include "core/loshader/set.h"
|
||||
|
||||
#define DURATION_ 4 /* [sec] */
|
||||
|
||||
#define HEAD_COLOR_ vec4(1, 1, 1, 1)
|
||||
|
||||
static void loui_popup_calculate_geometry_(
|
||||
loui_popup_t* popup, const locommon_screen_t* screen) {
|
||||
assert(popup != NULL);
|
||||
assert(screen != NULL);
|
||||
|
||||
typeof(popup->geo)* g = &popup->geo;
|
||||
|
||||
locommon_screen_calc_pixels_from_inch(
|
||||
screen, &g->big_fontpx, &vec2(.6f, .6f));
|
||||
locommon_screen_calc_winpos_from_pixels(
|
||||
screen, &g->big_fontsz, &g->big_fontpx);
|
||||
}
|
||||
|
||||
static glyphas_block_t* loui_popup_create_head_text_(
|
||||
loui_popup_t* popup, const locommon_screen_t* screen, const char* str) {
|
||||
assert(popup != NULL);
|
||||
assert(screen != NULL);
|
||||
assert(str != NULL);
|
||||
|
||||
glyphas_block_t* b = glyphas_block_new(
|
||||
GLYPHAS_ALIGNER_DIRECTION_HORIZONTAL,
|
||||
-popup->geo.big_fontpx.y,
|
||||
INT32_MAX,
|
||||
32);
|
||||
glyphas_block_add_characters(
|
||||
b,
|
||||
popup->font.serif.big,
|
||||
&HEAD_COLOR_,
|
||||
str,
|
||||
strlen(str));
|
||||
glyphas_block_scale(
|
||||
b, &vec2(2/screen->resolution.x, 2/screen->resolution.y));
|
||||
|
||||
glyphas_block_set_origin(b, &vec2(.5f, -1));
|
||||
return b;
|
||||
}
|
||||
|
||||
void loui_popup_initialize(
|
||||
loui_popup_t* popup,
|
||||
loresource_set_t* res,
|
||||
loshader_set_t* shaders,
|
||||
const locommon_screen_t* screen,
|
||||
const locommon_ticker_t* ticker,
|
||||
loplayer_t* player) {
|
||||
assert(popup != NULL);
|
||||
assert(res != NULL);
|
||||
assert(shaders != NULL);
|
||||
assert(screen != NULL);
|
||||
assert(ticker != NULL);
|
||||
assert(player != NULL);
|
||||
|
||||
*popup = (typeof(*popup)) {
|
||||
.shaders = shaders,
|
||||
.ticker = ticker,
|
||||
.player = player,
|
||||
};
|
||||
loui_popup_calculate_geometry_(popup, screen);
|
||||
|
||||
popup->font = (typeof(popup->font)) {
|
||||
.serif = {
|
||||
.big = glyphas_cache_new(
|
||||
shaders->tex.popup_text,
|
||||
&res->font.serif,
|
||||
popup->geo.big_fontpx.x,
|
||||
popup->geo.big_fontpx.y),
|
||||
},
|
||||
};
|
||||
|
||||
# define text_(v) loresource_text_get(res->lang, v)
|
||||
|
||||
popup->head = (typeof(popup->head)) {
|
||||
.new_stance = loui_popup_create_head_text_(
|
||||
popup, screen, text_("popup_new_stance_head")),
|
||||
};
|
||||
|
||||
# undef text_
|
||||
}
|
||||
|
||||
void loui_popup_deinitialize(loui_popup_t* popup) {
|
||||
assert(popup != NULL);
|
||||
|
||||
glyphas_block_delete(popup->head.new_stance);
|
||||
glyphas_cache_delete(popup->font.serif.big);
|
||||
}
|
||||
|
||||
void loui_popup_update(loui_popup_t* popup) {
|
||||
assert(popup != NULL);
|
||||
|
||||
const float dt = popup->ticker->delta_f;
|
||||
locommon_easing_linear_float(&popup->alpha, 0, dt/DURATION_);
|
||||
if (popup->alpha > 0) return;
|
||||
|
||||
const loplayer_popup_item_t* item =
|
||||
loplayer_popup_enqueue(&popup->player->popup);
|
||||
if (item == NULL) return;
|
||||
|
||||
popup->item = *item;
|
||||
popup->alpha = 1;
|
||||
}
|
||||
|
||||
void loui_popup_draw(const loui_popup_t* popup) {
|
||||
assert(popup != NULL);
|
||||
|
||||
if (popup->alpha <= 0) return;
|
||||
|
||||
popup->shaders->drawer.popup_text.alpha = popup->alpha;
|
||||
|
||||
switch (popup->item.type) {
|
||||
case LOPLAYER_POPUP_ITEM_TYPE_NEW_STANCE:
|
||||
loshader_popup_text_drawer_add_block(
|
||||
&popup->shaders->drawer.popup_text, popup->head.new_stance);
|
||||
break;
|
||||
}
|
||||
}
|
61
core/loui/popup.h
Normal file
61
core/loui/popup.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/glyphas/block.h"
|
||||
#include "util/glyphas/cache.h"
|
||||
#include "util/math/vector.h"
|
||||
|
||||
#include "core/locommon/screen.h"
|
||||
#include "core/locommon/ticker.h"
|
||||
#include "core/loplayer/player.h"
|
||||
#include "core/loplayer/popup.h"
|
||||
#include "core/loresource/set.h"
|
||||
#include "core/loshader/set.h"
|
||||
|
||||
typedef struct {
|
||||
loshader_set_t* shaders;
|
||||
const locommon_ticker_t* ticker;
|
||||
loplayer_t* player;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
glyphas_cache_t* big;
|
||||
} serif;
|
||||
} font;
|
||||
|
||||
struct {
|
||||
vec2_t big_fontpx;
|
||||
vec2_t big_fontsz;
|
||||
} geo;
|
||||
|
||||
float alpha;
|
||||
loplayer_popup_item_t item;
|
||||
|
||||
struct {
|
||||
glyphas_block_t* new_stance;
|
||||
} head;
|
||||
} loui_popup_t;
|
||||
|
||||
void
|
||||
loui_popup_initialize(
|
||||
loui_popup_t* popup,
|
||||
loresource_set_t* res,
|
||||
loshader_set_t* shaders,
|
||||
const locommon_screen_t* screen,
|
||||
const locommon_ticker_t* ticker,
|
||||
loplayer_t* player
|
||||
);
|
||||
|
||||
void
|
||||
loui_popup_deinitialize(
|
||||
loui_popup_t* popup
|
||||
);
|
||||
|
||||
void
|
||||
loui_popup_update(
|
||||
loui_popup_t* popup
|
||||
);
|
||||
|
||||
void
|
||||
loui_popup_draw(
|
||||
const loui_popup_t* popup
|
||||
);
|
130
core/loui/ui.c
Normal file
130
core/loui/ui.c
Normal file
@@ -0,0 +1,130 @@
|
||||
#include "./ui.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "core/locommon/easing.h"
|
||||
#include "core/locommon/input.h"
|
||||
#include "core/locommon/screen.h"
|
||||
#include "core/locommon/ticker.h"
|
||||
#include "core/loplayer/player.h"
|
||||
#include "core/loresource/set.h"
|
||||
#include "core/loshader/set.h"
|
||||
#include "core/loworld/chunk.h"
|
||||
#include "core/loworld/view.h"
|
||||
|
||||
#include "./combat.h"
|
||||
#include "./event.h"
|
||||
#include "./hud.h"
|
||||
#include "./menu.h"
|
||||
|
||||
#define FADE_SPEED_ 4
|
||||
|
||||
void loui_initialize(
|
||||
loui_t* ui,
|
||||
loresource_set_t* res,
|
||||
loshader_set_t* shaders,
|
||||
const locommon_screen_t* screen,
|
||||
const locommon_ticker_t* ticker,
|
||||
loplayer_t* player,
|
||||
const loworld_view_t* view) {
|
||||
assert(ui != NULL);
|
||||
assert(res != NULL);
|
||||
assert(shaders != NULL);
|
||||
assert(ticker != NULL);
|
||||
assert(player != NULL);
|
||||
assert(view != NULL);
|
||||
assert(locommon_screen_valid(screen));
|
||||
|
||||
*ui = (typeof(*ui)) {
|
||||
.ticker = ticker,
|
||||
.view = view,
|
||||
};
|
||||
|
||||
loui_combat_initialize(
|
||||
&ui->combat,
|
||||
shaders,
|
||||
ticker,
|
||||
player);
|
||||
loui_hud_initialize(
|
||||
&ui->hud,
|
||||
res,
|
||||
shaders,
|
||||
screen,
|
||||
ticker,
|
||||
player);
|
||||
loui_popup_initialize(
|
||||
&ui->popup,
|
||||
res,
|
||||
shaders,
|
||||
screen,
|
||||
ticker,
|
||||
player);
|
||||
loui_menu_initialize(
|
||||
&ui->menu,
|
||||
res,
|
||||
shaders,
|
||||
screen,
|
||||
ticker,
|
||||
player);
|
||||
loui_event_initialize(
|
||||
&ui->event,
|
||||
res,
|
||||
shaders,
|
||||
screen,
|
||||
ticker,
|
||||
player);
|
||||
}
|
||||
|
||||
void loui_deinitialize(loui_t* ui) {
|
||||
assert(ui != NULL);
|
||||
|
||||
loui_event_deinitialize(&ui->event);
|
||||
loui_menu_deinitialize(&ui->menu);
|
||||
loui_popup_deinitialize(&ui->popup);
|
||||
loui_hud_deinitialize(&ui->hud);
|
||||
loui_combat_deinitialize(&ui->combat);
|
||||
}
|
||||
|
||||
void loui_update(loui_t* ui, const locommon_input_t* input) {
|
||||
assert(ui != NULL);
|
||||
assert(input != NULL);
|
||||
|
||||
const bool pressed = input->buttons & LOCOMMON_INPUT_BUTTON_MENU;
|
||||
const float dt = ui->ticker->delta_f;
|
||||
|
||||
if (pressed && !ui->pressed) ui->menu_shown = !ui->menu_shown;
|
||||
ui->pressed = pressed;
|
||||
locommon_easing_smooth_float(
|
||||
&ui->menu.alpha, !!ui->menu_shown, dt*FADE_SPEED_);
|
||||
|
||||
const bool hud = !ui->menu_shown;
|
||||
locommon_easing_smooth_float(
|
||||
&ui->hud.alpha, !!hud, dt*FADE_SPEED_);
|
||||
|
||||
const loworld_chunk_t* chunk = loworld_view_get_looking_chunk(ui->view);
|
||||
ui->hud.current_biome = chunk->biome;
|
||||
|
||||
loui_combat_update(&ui->combat);
|
||||
loui_hud_update(&ui->hud);
|
||||
loui_popup_update(&ui->popup);
|
||||
loui_menu_update(&ui->menu, ui->menu_shown? input: NULL);
|
||||
loui_event_update(&ui->event);
|
||||
}
|
||||
|
||||
void loui_draw(const loui_t* ui) {
|
||||
assert(ui != NULL);
|
||||
|
||||
loui_combat_draw(&ui->combat);
|
||||
loui_hud_draw(&ui->hud);
|
||||
loui_popup_draw(&ui->popup);
|
||||
loui_menu_draw(&ui->menu);
|
||||
loui_event_draw(&ui->event);
|
||||
}
|
||||
|
||||
bool loui_is_grabbing_input(const loui_t* ui) {
|
||||
assert(ui != NULL);
|
||||
|
||||
return ui->menu_shown;
|
||||
}
|
63
core/loui/ui.h
Normal file
63
core/loui/ui.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "core/locommon/input.h"
|
||||
#include "core/locommon/screen.h"
|
||||
#include "core/locommon/ticker.h"
|
||||
#include "core/loplayer/player.h"
|
||||
#include "core/loresource/set.h"
|
||||
#include "core/loshader/set.h"
|
||||
#include "core/loworld/view.h"
|
||||
|
||||
#include "./combat.h"
|
||||
#include "./event.h"
|
||||
#include "./hud.h"
|
||||
#include "./menu.h"
|
||||
#include "./popup.h"
|
||||
|
||||
typedef struct {
|
||||
const locommon_ticker_t* ticker;
|
||||
const loworld_view_t* view;
|
||||
|
||||
loui_combat_t combat;
|
||||
loui_hud_t hud;
|
||||
loui_popup_t popup;
|
||||
loui_menu_t menu;
|
||||
loui_event_t event;
|
||||
|
||||
bool pressed;
|
||||
bool menu_shown;
|
||||
} loui_t;
|
||||
|
||||
void
|
||||
loui_initialize(
|
||||
loui_t* ui,
|
||||
loresource_set_t* res,
|
||||
loshader_set_t* shaders,
|
||||
const locommon_screen_t* screen,
|
||||
const locommon_ticker_t* ticker,
|
||||
loplayer_t* player,
|
||||
const loworld_view_t* view
|
||||
);
|
||||
|
||||
void
|
||||
loui_deinitialize(
|
||||
loui_t* ui
|
||||
);
|
||||
|
||||
void
|
||||
loui_update(
|
||||
loui_t* ui,
|
||||
const locommon_input_t* input
|
||||
);
|
||||
|
||||
void
|
||||
loui_draw(
|
||||
const loui_t* ui
|
||||
);
|
||||
|
||||
bool
|
||||
loui_is_grabbing_input(
|
||||
const loui_t* ui
|
||||
);
|
Reference in New Issue
Block a user