273 lines
6.3 KiB
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;
|
|
}
|