jancity/src/player/src/human_player_gui.c

273 lines
6.3 KiB
C

#include <building.h>
#include <gfx.h>
#include <human_player.h>
#include <player.h>
#include <unit.h>
#include <gui.h>
#include <gui/bar.h>
#include <gui/button.h>
#include <gui/container.h>
#include <gui/label.h>
#include <gui/progress_bar.h>
#include <gui/rounded_rect.h>
#include <terrain.h>
#include <inttypes.h>
#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
enum {X_OFF = 8, Y_OFF = 8};
static void on_item_pressed(void *const arg)
{
bool *const show = arg;
*show ^= true;
}
static void on_add_car(void *const arg)
{
struct human_player *const h = arg;
struct human_player_item *const it = &h->item;
const struct unit_cfg cfg =
{
.type = UNIT_CFG_TYPE_CAR,
.x = rand() % (MAP_W - 32),
.y = rand() % (MAP_H - 32),
};
player_create_unit(&cfg, &h->pl);
it->show = false;
}
static void on_add_walker(void *const arg)
{
struct human_player *const h = arg;
struct human_player_item *const it = &h->item;
const struct unit_cfg cfg =
{
.type = UNIT_CFG_TYPE_WALKER,
.x = rand() % (MAP_W - 32),
.y = rand() % (MAP_H - 32),
};
player_create_unit(&cfg, &h->pl);
it->show = false;
}
static void on_btn_exit(void *const arg)
{
struct human_player *const h = arg;
h->periph->common.exit = true;
}
static void update_items(struct human_player *const h)
{
struct human_player_item *const it = &h->item;
{
struct gui_rounded_rect *const r = &it->rr;
gui_rounded_rect_init(r);
r->common.hcentered = r->common.vcentered = true;
r->adjust = true;
}
{
struct gui_container *const c = &it->topcnt;
gui_container_init(c);
c->common.vcentered = true;
c->common.hcentered = true;
c->mode = GUI_CONTAINER_MODE_V;
c->spacing = 4;
gui_add_child(&it->rr.common, &c->common);
}
{
struct gui_button *const b = &it->add_car;
gui_button_init(b, GUI_BUTTON_TYPE_1);
b->common.hcentered = true;
b->u.type1.w = 80;
b->u.type1.label.text = "Add car";
b->on_pressed = on_add_car;
b->arg = h;
gui_add_child(&it->topcnt.common, &b->common);
}
{
struct gui_button *const b = &it->add_walker;
gui_button_init(b, GUI_BUTTON_TYPE_1);
b->u.type1.w = 80;
b->common.hcentered = true;
b->u.type1.label.text = "Add walker";
b->on_pressed = on_add_walker;
b->arg = h;
gui_add_child(&it->topcnt.common, &b->common);
}
{
struct gui_button *const b = &it->exit;
gui_button_init(b, GUI_BUTTON_TYPE_1);
b->u.type1.w = 80;
b->common.hcentered = true;
b->u.type1.label.text = "Exit";
b->on_pressed = on_btn_exit;
b->arg = h;
gui_add_child(&it->topcnt.common, &b->common);
}
struct camera cam =
{
.cursor = h->cam.cursor
};
gui_update(&it->rr.common, h->periph, &cam, &h->in);
}
void human_player_gui_update(struct human_player *const h)
{
struct human_player_item *const it = &h->item;
struct gui_button *const b = &it->show_btn;
gui_button_init(b, GUI_BUTTON_TYPE_SPRITE);
b->on_pressed = on_item_pressed;
b->arg = &it->show;
b->u.sprite.s = &gui_button_sprites[GUI_BUTTON_SMALL];
b->common.x = screen_w - b->u.sprite.s->w;
if (it->show)
update_items(h);
struct camera cam =
{
.cursor = h->cam.cursor
};
gui_update(&b->common, h->periph, &cam, &h->in);
}
static int render_sel_single_building(const struct human_player *const h,
const struct sel_instance *const sel, struct gui_common *const r)
{
const struct building *const b = sel->d.b;
struct gui_label bl;
gui_label_init(&bl);
bl.common.x = X_OFF;
bl.common.y = Y_OFF;
bl.text = building_str(b);
gui_add_child(r, &bl.common);
return gui_render(r);
}
static int render_sel_single_unit(const struct human_player *const h,
const struct sel_instance *const sel, struct gui_common *const r)
{
const struct unit *const u = sel->d.u;
struct gui_label ul;
gui_label_init(&ul);
ul.common.hcentered = true;
ul.common.vcentered = true;
ul.text = u->name;
gui_add_child(r, &ul.common);
return gui_render(r);
}
static int render_sel_single(const struct human_player *const h,
struct gui_common *const r)
{
for (size_t i = 0; i < sizeof h->sel / sizeof *h->sel; i++)
{
const struct sel_instance *const sel = &h->sel[i];
if (sel->d.i)
{
switch (sel->type)
{
case INSTANCE_TYPE_BUILDING:
return render_sel_single_building(h, sel, r);
case INSTANCE_TYPE_UNIT:
return render_sel_single_unit(h, sel, r);
}
}
}
fprintf(stderr, "%s: unreachable\n", __func__);
return -1;
}
static int render_sel_multiple(const struct human_player *const h,
struct gui_common *const r)
{
struct gui_label l;
char str[sizeof "4294967295 units selected"];
const int rs = snprintf(str, sizeof str, "%zu units selected", h->n_sel);
if (rs < 0 || rs >= sizeof str)
return -1;
gui_label_init(&l);
l.common.x = X_OFF;
l.common.y = Y_OFF;
l.text = str;
gui_add_child(r, &l.common);
return gui_render(r);
}
static int render_top(const struct human_player *const h)
{
return gui_render(&h->item.show_btn.common);
}
static int render_sel(const struct human_player *const h)
{
const short wlim = 120;
struct gui_rounded_rect r;
short exp_w;
gui_rounded_rect_init(&r);
r.common.hcentered = true;
exp_w = screen_w - 32;
r.w = exp_w > wlim ? wlim : exp_w;
r.h = 40;
r.r = 10;
r.g = 137;
r.b = 225;
r.common.y = screen_h - r.h;
return h->n_sel == 1 ? render_sel_single(h, &r.common)
: render_sel_multiple(h, &r.common);
}
static int render_items(const struct human_player *const h)
{
const struct human_player_item *const it = &h->item;
return gui_render(&it->rr.common);
}
int human_player_gui_render(const struct human_player *const h)
{
if (render_top(h))
return -1;
else if (h->n_sel && render_sel(h))
return -1;
else if (h->item.show && render_items(h))
return -1;
return 0;
}