nitro-engine/source/NEGUI.c
Antonio Niño Díaz 82171bbf69 chore: Simplify copyright years in notices
Instead of listing every individual year, keep only the first and last
years.
2024-03-09 01:42:29 +00:00

1074 lines
28 KiB
C

// SPDX-License-Identifier: MIT
//
// Copyright (c) 2008-2022 Antonio Niño Díaz
//
// This file is part of Nitro Engine
#include "NEMain.h"
/// @file NEGUI.c
extern NE_Input ne_input;
static NE_GUIObj **NE_guipointers;
static int NE_GUI_OBJECTS;
static bool ne_gui_system_inited = false;
typedef struct {
int x1, y1, x2, y2;
int event; // 0 = nothing, 1 = just pressed, 2 = held, 3 = just released
NE_Material *tex_1, *tex_2;
// Colors when button isn't pressed / is pressed. The default is white
u32 color1, color2;
u32 alpha1, alpha2;
} ne_button_t;
typedef struct {
int x1, y1, x2, y2;
int event;
bool checked;
NE_Material *tex_1, *tex_2;
u32 color1, color2;
u32 alpha1, alpha2;
} ne_checkbox_t;
typedef struct {
int x1, y1, x2, y2;
int event;
bool checked;
int group;
NE_Material *tex_1, *tex_2;
u32 color1, color2;
u32 alpha1, alpha2;
} ne_radiobutton_t;
typedef struct {
int x1, y1, x2, y2;
int event_minus, event_plus, event_bar;
int value;
int range, desp; //range = max - min; value + desp = real value
bool isvertical;
NE_Material *texbtn, *texbar, *texlong;
int totalsize, barsize;
int coord; // helper to avoid some frequent operations
// 1,2 used for buttons, barcolor used for background of slidebar
u32 color1, color2, barcolor;
u32 alpha1, alpha2, baralpha;
} ne_slidebar_t;
// Internal use
static void NE_ResetRadioButtonGroup(int group)
{
for (int i = 0; i < NE_GUI_OBJECTS; i++)
{
if (NE_guipointers[i] == NULL)
continue;
if (NE_guipointers[i]->type != NE_RadioButton)
continue;
ne_radiobutton_t *rabtn = (void *)NE_guipointers[i]->pointer;
if (rabtn->group == group)
rabtn->checked = false;
}
}
static void NE_GUIUpdateButton(NE_GUIObj *obj)
{
ne_button_t *button = (void *)obj;
if (button->x1 < ne_input.touch.px && button->x2 > ne_input.touch.px
&& button->y1 < ne_input.touch.py && button->y2 > ne_input.touch.py)
{
if (ne_input.kdown & KEY_TOUCH)
{
button->event = 1;
}
else if ((ne_input.kheld & KEY_TOUCH)
&& (button->event == 1 || button->event == 2))
{
button->event = 2;
}
else if (ne_input.kup & KEY_TOUCH && button->event == 2)
{
button->event = 4;
}
else
{
button->event = 0;
}
}
else
{
button->event = 0;
}
}
static void NE_GUIUpdateCheckBox(NE_GUIObj *obj)
{
ne_checkbox_t *chbox = (void *)obj;
if (chbox->x1 < ne_input.touch.px && chbox->x2 > ne_input.touch.px
&& chbox->y1 < ne_input.touch.py && chbox->y2 > ne_input.touch.py)
{
if (ne_input.kdown & KEY_TOUCH)
{
chbox->event = 1;
}
else if ((ne_input.kheld & KEY_TOUCH)
&& (chbox->event == 1 || chbox->event == 2))
{
chbox->event = 2;
}
else if (ne_input.kup & KEY_TOUCH && chbox->event == 2)
{
chbox->event = 4;
chbox->checked = !chbox->checked;
}
else
{
chbox->event = 0;
}
}
else
{
chbox->event = 0;
}
}
static void NE_GUIUpdateRadioButton(NE_GUIObj *obj)
{
ne_radiobutton_t *rabtn = (void *)obj;
if (rabtn->x1 < ne_input.touch.px && rabtn->x2 > ne_input.touch.px
&& rabtn->y1 < ne_input.touch.py && rabtn->y2 > ne_input.touch.py)
{
if (ne_input.kdown & KEY_TOUCH)
{
rabtn->event = 1;
}
else if ((ne_input.kheld & KEY_TOUCH)
&& (rabtn->event == 1 || rabtn->event == 2))
{
rabtn->event = 2;
}
else if (ne_input.kup & KEY_TOUCH && rabtn->event == 2)
{
rabtn->event = 4;
NE_ResetRadioButtonGroup(rabtn->group);
rabtn->checked = true;
}
else
{
rabtn->event = 0;
}
}
else
{
rabtn->event = 0;
}
}
static void NE_GUIUpdateSlideBar(NE_GUIObj *obj)
{
ne_slidebar_t *sldbar = (void *)obj;
// Simplify code...
int x1 = sldbar->x1, x2 = sldbar->x2;
int y1 = sldbar->y1, y2 = sldbar->y2;
int px = ne_input.touch.px, py = ne_input.touch.py;
bool vertical = sldbar->isvertical;
int coord = sldbar->coord, barsize = sldbar->barsize;
int tmp1, tmp2; // auxiliary coordinates
if (sldbar->isvertical)
{
tmp1 = y1 + (x2 - x1);
tmp2 = y2 - (x2 - x1);
}
else
{
tmp1 = x1 + (y2 - y1);
tmp2 = x2 - (y2 - y1);
}
// Plus button
// -----------
bool pluspressed;
if (vertical)
pluspressed = x1 < px && x2 > px && tmp2 < py && y2 > py;
else
pluspressed = tmp2 < px && x2 > px && y1 < py && y2 > py;
if (pluspressed)
{
if (ne_input.kdown & KEY_TOUCH)
{
sldbar->event_plus = 1;
}
else if ((ne_input.kheld & KEY_TOUCH)
&& (sldbar->event_plus == 1 || sldbar->event_plus == 2))
{
sldbar->event_plus = 2;
sldbar->value++;
}
else if (ne_input.kup & KEY_TOUCH && sldbar->event_plus == 2)
{
sldbar->event_plus = 4;
}
else
{
sldbar->event_plus = 0;
}
}
else
{
sldbar->event_plus = 0;
}
// Minus button
// ------------
bool minuspressed;
if (vertical)
minuspressed = x1 < px && x2 > px && y1 < py && tmp1 > py;
else
minuspressed = x1 < px && tmp1 > px && y1 < py && y2 > py;
if (minuspressed)
{
if (ne_input.kdown & KEY_TOUCH)
{
sldbar->event_minus = 1;
}
else if ((ne_input.kheld & KEY_TOUCH)
&& (sldbar->event_minus == 1 || sldbar->event_minus == 2))
{
sldbar->event_minus = 2;
sldbar->value--;
}
else if ((ne_input.kup & KEY_TOUCH) && (sldbar->event_minus == 2))
{
sldbar->event_minus = 4;
}
else
{
sldbar->event_minus = 0;
}
}
else
{
sldbar->event_minus = 0;
}
// Bar button
// ----------
if (sldbar->event_bar == 2)
{
int tmp = ((vertical) ? py : px) - tmp1 - (barsize >> 1);
tmp *= sldbar->range;
tmp = divf32(tmp << 12, (tmp2 - tmp1 - barsize) << 12) >> 12;
sldbar->value = tmp;
}
sldbar->value = (sldbar->value > sldbar->range) ? sldbar->range : sldbar->value;
sldbar->value = (sldbar->value < 0) ? 0 : sldbar->value;
sldbar->coord = (sldbar->totalsize - barsize) * sldbar->value;
sldbar->coord = divf32(sldbar->coord << 12, sldbar->range << 12) >> 12;
sldbar->coord += (vertical) ? y1 + (x2 - x1) : x1 + (y2 - y1);
coord = sldbar->coord;
bool barpressed;
if (vertical)
barpressed = x1 < px && x2 > px && coord < py && (coord + barsize) > py;
else
barpressed = y1 < py && y2 > py && coord < px && (coord + barsize) > px;
if (barpressed)
{
if (ne_input.kdown & KEY_TOUCH)
{
sldbar->event_bar = 1;
}
else if ((ne_input.kheld & KEY_TOUCH)
&& (sldbar->event_bar == 1 || sldbar->event_bar == 2))
{
sldbar->event_bar = 2;
}
else if (ne_input.kup & KEY_TOUCH && sldbar->event_bar == 2)
{
sldbar->event_bar = 4;
}
else
{
sldbar->event_bar = 0;
}
}
else
{
sldbar->event_bar = 0;
}
}
void NE_GUIUpdate(void)
{
if (!ne_gui_system_inited)
return;
for (int i = 0; i < NE_GUI_OBJECTS; i++)
{
if (NE_guipointers[i] == NULL)
continue;
NE_GUITypes type = NE_guipointers[i]->type;
if (type == NE_Button)
NE_GUIUpdateButton(NE_guipointers[i]->pointer);
else if (type == NE_CheckBox)
NE_GUIUpdateCheckBox(NE_guipointers[i]->pointer);
else if (type == NE_RadioButton)
NE_GUIUpdateRadioButton(NE_guipointers[i]->pointer);
else if (type == NE_SlideBar)
NE_GUIUpdateSlideBar(NE_guipointers[i]->pointer);
else
NE_DebugPrint("Unknown GUI object type: %d", type);
}
}
static void NE_GUIDrawButton(NE_GUIObj *obj, int priority)
{
ne_button_t *button = (void *)obj;
NE_Material *tex;
u32 color;
if (button->event > 0)
{
// Pressed
GFX_POLY_FORMAT = POLY_ALPHA(button->alpha2)
| POLY_ID(NE_GUI_POLY_ID) | NE_CULL_NONE;
tex = button->tex_2;
color = button->color2;
}
else
{
// Not-pressed
GFX_POLY_FORMAT = POLY_ALPHA(button->alpha1)
| POLY_ID(NE_GUI_POLY_ID) | NE_CULL_NONE;
tex = button->tex_1;
color = button->color1;
}
if (tex == NULL)
{
NE_2DDrawQuad(button->x1, button->y1, button->x2, button->y2,
priority, color);
}
else
{
NE_2DDrawTexturedQuadColor(button->x1, button->y1, button->x2,
button->y2, priority, tex, color);
}
}
static void NE_GUIDrawCheckBox(NE_GUIObj *obj, int priority)
{
ne_checkbox_t *chbox = (void *)obj;
u32 color;
if (chbox->event > 0)
{
GFX_POLY_FORMAT = POLY_ALPHA(chbox->alpha2)
| POLY_ID(NE_GUI_POLY_ID) | NE_CULL_NONE;
color = chbox->color2;
}
else
{
GFX_POLY_FORMAT = POLY_ALPHA(chbox->alpha1)
| POLY_ID(NE_GUI_POLY_ID) | NE_CULL_NONE;
color = chbox->color1;
}
NE_Material *tex = chbox->checked ? chbox->tex_2 : chbox->tex_1;
if (tex == NULL)
{
NE_2DDrawQuad(chbox->x1, chbox->y1, chbox->x2, chbox->y2,
priority, color);
}
else
{
NE_2DDrawTexturedQuadColor(chbox->x1, chbox->y1, chbox->x2,
chbox->y2, priority, tex, color);
}
}
static void NE_GUIDrawRadioButton(NE_GUIObj *obj, int priority)
{
ne_radiobutton_t *rabtn = (void *)obj;
u32 color;
if (rabtn->event > 0)
{
GFX_POLY_FORMAT = POLY_ALPHA(rabtn->alpha2)
| POLY_ID(NE_GUI_POLY_ID) | NE_CULL_NONE;
color = rabtn->color2;
}
else
{
GFX_POLY_FORMAT = POLY_ALPHA(rabtn->alpha1)
| POLY_ID(NE_GUI_POLY_ID) | NE_CULL_NONE;
color = rabtn->color1;
}
NE_Material *tex = rabtn->checked ? rabtn->tex_2 : rabtn->tex_1;
if (tex == NULL)
{
NE_2DDrawQuad(rabtn->x1, rabtn->y1, rabtn->x2, rabtn->y2,
priority, color);
}
else
{
NE_2DDrawTexturedQuadColor(rabtn->x1, rabtn->y1, rabtn->x2,
rabtn->y2, priority, tex, color);
}
}
static void NE_GUIDrawSlideBar(NE_GUIObj *obj, int priority)
{
ne_slidebar_t *sldbar = (void *)obj;
u32 color;
// Helper variables
int x1 = sldbar->x1, x2 = sldbar->x2;
int y1 = sldbar->y1, y2 = sldbar->y2;
int tmp1, tmp2; // Auxiliary coordinates
if (sldbar->isvertical)
{
tmp1 = y1 + (x2 - x1);
tmp2 = y2 - (x2 - x1);
}
else
{
tmp1 = x1 + (y2 - y1);
tmp2 = x2 - (y2 - y1);
}
// Load texture of the two buttons
NE_Material *tex = sldbar->texbtn;
// Plus button
// -----------
if (sldbar->event_plus > 0)
{
GFX_POLY_FORMAT = POLY_ALPHA(sldbar->alpha2)
| POLY_ID(NE_GUI_POLY_ID) | NE_CULL_NONE;
color = sldbar->color2;
}
else
{
GFX_POLY_FORMAT = POLY_ALPHA(sldbar->alpha1)
| POLY_ID(NE_GUI_POLY_ID) | NE_CULL_NONE;
color = sldbar->color1;
}
if (sldbar->isvertical)
{
if (tex == NULL)
NE_2DDrawQuad(x1, tmp2, x2, y2, priority, color);
else
NE_2DDrawTexturedQuadColor(x1, tmp2, x2, y2, priority, tex, color);
}
else
{
if (tex == NULL)
NE_2DDrawQuad(tmp2, y1, x2, y2, priority, color);
else
NE_2DDrawTexturedQuadColor(tmp2, y1, x2, y2, priority, tex, color);
}
// Minus button
// ------------
if (sldbar->event_minus > 0)
{
GFX_POLY_FORMAT = POLY_ALPHA(sldbar->alpha2)
| POLY_ID(NE_GUI_POLY_ID) | NE_CULL_NONE;
color = sldbar->color2;
}
else
{
GFX_POLY_FORMAT = POLY_ALPHA(sldbar->alpha1)
| POLY_ID(NE_GUI_POLY_ID) | NE_CULL_NONE;
color = sldbar->color1;
}
if (sldbar->isvertical)
{
if (tex == NULL)
NE_2DDrawQuad(x1, y1, x2, tmp1, priority, color);
else
NE_2DDrawTexturedQuadColor(x1, y1, x2, tmp1, priority, tex, color);
}
else
{
if (tex == NULL)
NE_2DDrawQuad(x1, y1, tmp1, y2, priority, color);
else
NE_2DDrawTexturedQuadColor(x1, y1, tmp1, y2, priority, tex, color);
}
// Bar button
// ----------
// Load texture of the bar button
tex = sldbar->texbar;
if (sldbar->event_bar > 0)
{
GFX_POLY_FORMAT = POLY_ALPHA(sldbar->alpha2)
| POLY_ID(NE_GUI_POLY_ID) | NE_CULL_NONE;
color = sldbar->color2;
}
else
{
GFX_POLY_FORMAT = POLY_ALPHA(sldbar->alpha1)
| POLY_ID(NE_GUI_POLY_ID) | NE_CULL_NONE;
color = sldbar->color1;
}
if (sldbar->isvertical)
{
if (tex == NULL)
{
NE_2DDrawQuad(x1, sldbar->coord,
x2, sldbar->coord + sldbar->barsize,
priority, color);
}
else
{
NE_2DDrawTexturedQuadColor(x1, sldbar->coord,
x2, sldbar->coord + sldbar->barsize,
priority, tex, color);
}
}
else
{
if (tex == NULL)
{
NE_2DDrawQuad(sldbar->coord, y1,
sldbar->coord + sldbar->barsize, y2,
priority, color);
}
else
{
NE_2DDrawTexturedQuadColor(sldbar->coord, y1,
sldbar->coord + sldbar->barsize, y2,
priority, tex, color);
}
}
// Slide bar
// ---------
// Load texture and color of the slide bar background
tex = sldbar->texlong;
color = sldbar->barcolor;
GFX_POLY_FORMAT = POLY_ALPHA(sldbar->baralpha)
| POLY_ID(NE_GUI_POLY_ID_ALT) | NE_CULL_NONE;
// Now we need to use `priority + 1` as priority. The bar button must
// be in front of bar. `priority + 1` is less priority than `priority`.
if (sldbar->isvertical)
{
if (tex == NULL)
{
NE_2DDrawQuad(x1, tmp1, x2, tmp2, priority + 1, color);
}
else
{
NE_2DDrawTexturedQuadColor(x1, tmp1, x2, tmp2,
priority + 1, tex, color);
}
}
else
{
if (tex == NULL)
{
NE_2DDrawQuad(tmp1, y1, tmp2, y2, priority + 1, color);
}
else
{
NE_2DDrawTexturedQuadColor(tmp1, y1, tmp2, y2,
priority + 1, tex, color);
}
}
}
void NE_GUIDraw(void)
{
if (!ne_gui_system_inited)
return;
for (int i = 0; i < NE_GUI_OBJECTS; i++)
{
if (NE_guipointers[i] == NULL)
continue;
NE_GUIObj *obj = NE_guipointers[i]->pointer;
NE_GUITypes type = NE_guipointers[i]->type;
int priority = i + NE_GUI_MIN_PRIORITY;
if (type == NE_Button)
NE_GUIDrawButton(obj, priority);
else if (type == NE_CheckBox)
NE_GUIDrawCheckBox(obj, priority);
else if (type == NE_RadioButton)
NE_GUIDrawRadioButton(obj, priority);
else if (type == NE_SlideBar)
NE_GUIDrawSlideBar(obj, priority);
else
NE_DebugPrint("Unknown GUI object type: %d", type);
}
}
NE_GUIObj *NE_GUIButtonCreate(s16 x1, s16 y1, s16 x2, s16 y2)
{
if (!ne_gui_system_inited)
{
NE_DebugPrint("System not initialized");
return NULL;
}
for (int i = 0; i < NE_GUI_OBJECTS; i++)
{
if (NE_guipointers[i] != NULL)
continue;
ne_button_t *ptr = malloc(sizeof(ne_button_t));
if (ptr == NULL)
{
NE_DebugPrint("Not enough memory");
return NULL;
}
NE_guipointers[i] = malloc(sizeof(NE_GUIObj));
if (NE_guipointers[i] == NULL)
{
free(ptr);
NE_DebugPrint("Not enough memory");
return NULL;
}
NE_guipointers[i]->pointer = (void *)ptr;
NE_guipointers[i]->type = NE_Button;
ptr->x1 = x1;
ptr->y1 = y1;
ptr->x2 = x2;
ptr->y2 = y2;
ptr->event = -1;
ptr->tex_1 = ptr->tex_2 = NULL;
ptr->color1 = ptr->color2 = NE_White;
ptr->alpha1 = ptr->alpha2 = 31;
return NE_guipointers[i];
}
NE_DebugPrint("No free slots");
return NULL;
}
NE_GUIObj *NE_GUICheckBoxCreate(s16 x1, s16 y1, s16 x2, s16 y2, bool initialvalue)
{
if (!ne_gui_system_inited)
{
NE_DebugPrint("System not initialized");
return NULL;
}
for (int i = 0; i < NE_GUI_OBJECTS; i++)
{
if (NE_guipointers[i] != NULL)
continue;
ne_checkbox_t *ptr = malloc(sizeof(ne_checkbox_t));
if (ptr == NULL)
{
NE_DebugPrint("Not enough memory");
return NULL;
}
NE_guipointers[i] = malloc(sizeof(NE_GUIObj));
if (NE_guipointers[i] == NULL)
{
free(ptr);
NE_DebugPrint("Not enough memory");
return NULL;
}
NE_guipointers[i]->pointer = (void *)ptr;
NE_guipointers[i]->type = NE_CheckBox;
ptr->x1 = x1;
ptr->y1 = y1;
ptr->x2 = x2;
ptr->y2 = y2;
ptr->event = -1;
ptr->tex_1 = ptr->tex_2 = NULL;
ptr->color1 = ptr->color2 = NE_White;
ptr->alpha1 = ptr->alpha2 = 31;
ptr->checked = initialvalue;
return NE_guipointers[i];
}
NE_DebugPrint("No free slots");
return NULL;
}
NE_GUIObj *NE_GUIRadioButtonCreate(s16 x1, s16 y1, s16 x2, s16 y2, int group,
bool initialvalue)
{
if (!ne_gui_system_inited)
{
NE_DebugPrint("System not initialized");
return NULL;
}
for (int i = 0; i < NE_GUI_OBJECTS; i++)
{
if (NE_guipointers[i] != NULL)
continue;
ne_radiobutton_t *ptr = malloc(sizeof(ne_radiobutton_t));
if (ptr == NULL)
{
NE_DebugPrint("Not enough memory");
return NULL;
}
NE_guipointers[i] = malloc(sizeof(NE_GUIObj));
if (NE_guipointers[i] == NULL)
{
free(ptr);
NE_DebugPrint("Not enough memory");
return NULL;
}
NE_guipointers[i]->pointer = (void *)ptr;
NE_guipointers[i]->type = NE_RadioButton;
ptr->x1 = x1;
ptr->y1 = y1;
ptr->x2 = x2;
ptr->y2 = y2;
ptr->event = -1;
ptr->tex_1 = ptr->tex_2 = NULL;
ptr->color1 = ptr->color2 = NE_White;
ptr->alpha1 = ptr->alpha2 = 31;
ptr->group = group;
if (initialvalue)
NE_ResetRadioButtonGroup(group);
ptr->checked = initialvalue;
return NE_guipointers[i];
}
NE_DebugPrint("No free slots");
return NULL;
}
NE_GUIObj *NE_GUISlideBarCreate(s16 x1, s16 y1, s16 x2, s16 y2, int min,
int max, int initialvalue)
{
if (!ne_gui_system_inited)
{
NE_DebugPrint("System not initialized");
return NULL;
}
for (int i = 0; i < NE_GUI_OBJECTS; i++)
{
if (NE_guipointers[i] != NULL)
continue;
ne_slidebar_t *ptr = malloc(sizeof(ne_slidebar_t));
if (ptr == NULL)
{
NE_DebugPrint("Not enough memory");
return NULL;
}
NE_guipointers[i] = malloc(sizeof(NE_GUIObj));
if (NE_guipointers[i] == NULL)
{
free(ptr);
NE_DebugPrint("Not enough memory");
return NULL;
}
NE_guipointers[i]->pointer = (void *)ptr;
NE_guipointers[i]->type = NE_SlideBar;
ptr->x1 = x1;
ptr->y1 = y1;
ptr->x2 = x2;
ptr->y2 = y2;
ptr->event_minus = ptr->event_plus = ptr->event_bar = -1;
ptr->texbtn = ptr->texbar = ptr->texlong = NULL;
ptr->color1 = ptr->color2 = ptr->barcolor = NE_White;
ptr->alpha1 = ptr->alpha2 = ptr->baralpha = 31;
ptr->value = initialvalue - min;
ptr->desp = min;
ptr->range = max - min;
ptr->isvertical = (x2 - x1 > y2 - y1) ? false : true;
if (ptr->isvertical)
ptr->totalsize = y2 - y1 - ((x2 - x1) << 1);
else
ptr->totalsize = x2 - x1 - ((y2 - y1) << 1);
ptr->barsize = 100 - ptr->range;
ptr->barsize = (ptr->barsize < 20) ? (20 << 12) : (ptr->barsize << 12);
ptr->barsize = (divf32(ptr->barsize, 100 << 12) * ptr->totalsize) >> 12;
ptr->coord = (ptr->totalsize - ptr->barsize) * ptr->value;
ptr->coord = divf32(ptr->coord << 12, ptr->range << 12) >> 12;
ptr->coord += (ptr->isvertical) ?
ptr->y1 + (ptr->x2 - ptr->x1) :
ptr->x1 + (ptr->y2 - ptr->y1);
return NE_guipointers[i];
}
NE_DebugPrint("No free slots");
return NULL;
}
void NE_GUIButtonConfig(NE_GUIObj *btn, NE_Material *material, u32 color,
u32 alpha, NE_Material *pressedmaterial,
u32 pressedcolor, u32 pressedalpha)
{
NE_AssertPointer(btn, "NULL pointer");
NE_Assert(btn->type == NE_Button, "Not a button");
ne_button_t *button = btn->pointer;
button->tex_1 = material;
button->tex_2 = pressedmaterial;
button->color1 = color;
button->color2 = pressedcolor;
button->alpha1 = alpha;
button->alpha2 = pressedalpha;
}
void NE_GUICheckBoxConfig(NE_GUIObj *chbx, NE_Material *materialtrue,
NE_Material *materialfalse, u32 color, u32 alpha,
u32 pressedcolor, u32 pressedalpha)
{
NE_AssertPointer(chbx, "NULL pointer");
NE_Assert(chbx->type == NE_CheckBox, "Not a check box");
ne_checkbox_t *checkbox = chbx->pointer;
checkbox->tex_1 = materialfalse;
checkbox->tex_2 = materialtrue;
checkbox->color1 = color;
checkbox->color2 = pressedcolor;
checkbox->alpha1 = alpha;
checkbox->alpha2 = pressedalpha;
}
void NE_GUIRadioButtonConfig(NE_GUIObj *rdbtn, NE_Material *materialtrue,
NE_Material *materialfalse, u32 color, u32 alpha,
u32 pressedcolor, u32 pressedalpha)
{
NE_AssertPointer(rdbtn, "NULL pointer");
NE_Assert(rdbtn->type == NE_RadioButton, "Not a radio button");
ne_radiobutton_t *radiobutton = rdbtn->pointer;
radiobutton->tex_1 = materialfalse;
radiobutton->tex_2 = materialtrue;
radiobutton->color1 = color;
radiobutton->color2 = pressedcolor;
radiobutton->alpha1 = alpha;
radiobutton->alpha2 = pressedalpha;
}
void NE_GUISlideBarConfig(NE_GUIObj *sldbar, NE_Material *matbtn,
NE_Material *matbarbtn, NE_Material *matbar,
u32 normalcolor, u32 pressedcolor, u32 barcolor,
u32 alpha, u32 pressedalpha, u32 baralpha)
{
NE_AssertPointer(sldbar, "NULL pointer");
NE_Assert(sldbar->type == NE_SlideBar, "Not a slide bar");
ne_slidebar_t *slidebar = sldbar->pointer;
slidebar->texbtn = matbtn;
slidebar->texbar = matbarbtn;
slidebar->texlong = matbar;
slidebar->color1 = normalcolor;
slidebar->color2 = pressedcolor;
slidebar->barcolor = barcolor;
slidebar->alpha1 = alpha;
slidebar->alpha2 = pressedalpha;
slidebar->baralpha = baralpha;
}
void NE_GUISlideBarSetMinMax(NE_GUIObj *sldbr, int min, int max)
{
NE_AssertPointer(sldbr, "NULL pointer");
NE_Assert(sldbr->type == NE_SlideBar, "Not a slide bar");
ne_slidebar_t *slidebar = sldbr->pointer;
slidebar->desp = min;
slidebar->range = max - min;
// Bar size
slidebar->barsize = 100 - slidebar->range;
slidebar->barsize = (slidebar->barsize < 20) ?
(20 << 12) : (slidebar->barsize << 12);
slidebar->barsize =
(divf32(slidebar->barsize, 100 << 12) * slidebar->totalsize) >> 12;
// Current coordinate
slidebar->coord =
(slidebar->totalsize - slidebar->barsize) * slidebar->value;
slidebar->coord =
divf32(slidebar->coord << 12, slidebar->range << 12) >> 12;
slidebar->coord += (slidebar->isvertical) ?
slidebar->y1 + (slidebar->x2 - slidebar->x1) :
slidebar->x1 + (slidebar->y2 - slidebar->y1);
}
NE_GUIState NE_GUIObjectGetEvent(const NE_GUIObj *obj)
{
ne_slidebar_t *ptr;
NE_AssertPointer(obj, "NULL pointer");
switch (obj->type)
{
case NE_Button:
return ((ne_button_t *) (obj->pointer))->event;
case NE_CheckBox:
return ((ne_checkbox_t *) (obj->pointer))->event;
case NE_RadioButton:
return ((ne_radiobutton_t *) (obj->pointer))->event;
case NE_SlideBar:
ptr = obj->pointer;
return ptr->event_plus | ptr->event_minus | ptr->event_bar;
default:
NE_DebugPrint("Unknown GUI object type: %d", obj->type);
return -1;
}
}
bool NE_GUICheckBoxGetValue(const NE_GUIObj *chbx)
{
NE_AssertPointer(chbx, "NULL pointer");
NE_Assert(chbx->type == NE_CheckBox, "Not a check box");
return ((ne_checkbox_t *)(chbx->pointer))->checked;
}
bool NE_GUIRadioButtonGetValue(const NE_GUIObj *rdbtn)
{
NE_AssertPointer(rdbtn, "NULL pointer");
NE_Assert(rdbtn->type == NE_RadioButton, "Not a radio button");
return ((ne_radiobutton_t *)(rdbtn->pointer))->checked;
}
int NE_GUISlideBarGetValue(const NE_GUIObj *sldbr)
{
NE_AssertPointer(sldbr, "NULL pointer");
NE_Assert(sldbr->type == NE_SlideBar, "Not a slide bar");
ne_slidebar_t *slidebar = sldbr->pointer;
return slidebar->value + slidebar->desp;
}
void NE_GUIDeleteObject(NE_GUIObj *obj)
{
NE_AssertPointer(obj, "NULL pointer");
for (int i = 0; i < NE_GUI_OBJECTS; i++)
{
if (NE_guipointers[i] == obj)
{
free(obj->pointer);
free(obj);
NE_guipointers[i] = NULL;
return;
}
}
NE_DebugPrint("Object not found");
}
void NE_GUIDeleteAll(void)
{
if (!ne_gui_system_inited)
return;
for (int i = 0; i < NE_GUI_OBJECTS; i++)
{
if (NE_guipointers[i])
{
free(NE_guipointers[i]->pointer);
free(NE_guipointers[i]);
NE_guipointers[i] = NULL;
}
}
}
int NE_GUISystemReset(int max_objects)
{
if (ne_gui_system_inited)
NE_GUISystemEnd();
if (max_objects < 1)
NE_GUI_OBJECTS = NE_GUI_DEFAULT_OBJECTS;
else
NE_GUI_OBJECTS = max_objects;
NE_guipointers = calloc(NE_GUI_OBJECTS, sizeof(NE_guipointers));
if (NE_guipointers == NULL)
{
NE_DebugPrint("Not enough memory");
return -1;
}
ne_gui_system_inited = true;
return 0;
}
void NE_GUISystemEnd(void)
{
if (!ne_gui_system_inited)
return;
NE_GUIDeleteAll();
free(NE_guipointers);
ne_gui_system_inited = false;
}