rts/src/gui/src/gui.c

212 lines
4.7 KiB
C

#include <gui.h>
#include <camera.h>
#include <input.h>
#include <peripheral.h>
static void get_centered(const struct gui_common *const g,
short *const x, short *const y)
{
if (!g->hidden && g->cb && g->cb->get_dim)
{
short w, h, pw = 0, ph = 0;
const struct gui_common *p = g->parent;
if (p)
{
if (!p->hidden && p->cb && p->cb->get_dim)
p->cb->get_dim(p, &pw, &ph);
}
else
{
pw = screen_w;
ph = screen_h;
}
g->cb->get_dim(g, &w, &h);
if (g->hcentered)
*x += (pw - w) / 2;
if (g->vcentered)
*y += (ph - h) / 2;
}
}
void gui_coords(const struct gui_common *const g, short *const x,
short *const y)
{
if (g->hidden)
return;
*x = g->x + g->xoff;
*y = g->y + g->yoff;
const struct gui_common *p = g->parent;
if (p)
{
short px = p->x + p->xoff, py = p->y + p->yoff;
if (p->hcentered || p->vcentered)
gui_coords(p, &px, &py);
*x += px;
*y += py;
}
if (g->hcentered || g->vcentered)
get_centered(g, x, y);
}
static bool check_collision(const struct gui_common *const g,
const union peripheral *const p,
const struct camera *cam, const short w, const short h)
{
short x, y;
gui_coords(g, &x, &y);
const struct util_rect d =
{
.x = x,
.y = y,
.w = w,
.h = h
};
return cursor_collision(cam, &d);
}
bool gui_pressed(const struct gui_common *const g,
const struct input *const in,
const union peripheral *const p,
const struct camera *const cam, const short w, const short h)
{
if (g->hidden)
return false;
bool check = false;
switch (p->common.type)
{
case PERIPHERAL_TYPE_PAD:
check = input_pad_justpressed(in, &p->pad.pad, PAD_KEY_A);
break;
case PERIPHERAL_TYPE_KEYBOARD_MOUSE:
/* Fall through. */
case PERIPHERAL_TYPE_TOUCH:
check = input_mouse_justreleased(in, &p->kbm.mouse,
MOUSE_BUTTON_LEFT);
break;
}
if (check)
return check_collision(g, p, cam, w, h);
return false;
}
bool gui_released(const struct gui_common *const g,
const union peripheral *const p,
const struct camera *const cam, const short w, const short h)
{
if (g->hidden)
return false;
bool check = false;
switch (p->common.type)
{
case PERIPHERAL_TYPE_PAD:
check = pad_justpressed(&p->pad.pad, PAD_KEY_A);
break;
case PERIPHERAL_TYPE_KEYBOARD_MOUSE:
/* Fall through. */
case PERIPHERAL_TYPE_TOUCH:
check = mouse_justreleased(&p->kbm.mouse,
MOUSE_BUTTON_LEFT);
break;
}
if (check)
return !check_collision(g, p, cam, w, h);
return false;
}
void gui_add_sibling(struct gui_common *const g,
struct gui_common *const s)
{
for (struct gui_common *c = g; c; c = c->sibling)
if (!c->sibling)
{
c->sibling = s;
break;
}
}
void gui_add_child(struct gui_common *const p,
struct gui_common *const c)
{
if (p->child)
gui_add_sibling(p->child, c);
else
p->child = c;
c->parent = p;
if (p->cb && p->cb->add_child)
p->cb->add_child(p, c);
}
int gui_update(struct gui_common *const g, const union peripheral *const p,
const struct camera *const c, struct input *const in)
{
if (!g->hidden
&& ((g->child && gui_update(g->child, p, c, in))
|| (g->cb && g->cb->update && g->cb->update(g, p, c, in))))
return -1;
for (struct gui_common *s = g->sibling; s; s = s->sibling)
if (!s->hidden && ((s->child && gui_update(s->child, p, c, in))
|| (s->cb && s->cb->update && s->cb->update(s, p, c, in))))
return -1;
return 0;
}
int gui_render(const struct gui_common *const g)
{
if (!g->hidden && ((g->cb && g->cb->render && g->cb->render(g))
|| (g->child && gui_render(g->child))))
return -1;
for (struct gui_common *s = g->sibling; s; s = s->sibling)
if (!s->hidden && ((s->cb && s->cb->render && s->cb->render(s))
|| (s->child && gui_render(s->child))))
return -1;
return 0;
}
void gui_deinit(struct gui_common *const g, struct input *const in)
{
if (g->cb && g->cb->deinit)
g->cb->deinit(g, in);
if (g->child)
gui_deinit(g->child, in);
for (struct gui_common *s = g->sibling; s; s = s->sibling)
{
if (s->cb && s->cb->deinit)
s->cb->deinit(s, in);
if (s->child)
gui_deinit(s->child, in);
}
}