// 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; }