GoldFish Engine
Quite simple and lightweight game engine
Loading...
Searching...
No Matches
gf_gui.c
1#define GF_EXPOSE_GUI
2#define GF_EXPOSE_DRAW
3#define GF_EXPOSE_INPUT
4
5#include <gf_pre.h>
6
7/* External library */
8
9/* Interface */
10#include <gf_gui.h>
11
12/* Engine */
13#include <gf_graphic.h>
14#include <gf_draw.h>
15#include <gf_log.h>
16
17/* Standard */
18#include <stdlib.h>
19#include <string.h>
20
21const double gf_gui_border_width = 2;
22
23gf_graphic_color_t gf_gui_base_color;
24gf_graphic_color_t gf_gui_font_color;
25
26gf_gui_t* gf_gui_create(gf_engine_t* engine, gf_draw_t* draw) {
27 gf_gui_t* gui = malloc(sizeof(*gui));
29 memset(gui, 0, sizeof(*gui));
30 gui->engine = engine;
31 gui->draw = draw;
32
33 gui->pressed = -1;
34
35 GF_SET_COLOR(gf_gui_base_color, 48, 96, 48, 255);
36 GF_SET_COLOR(gf_gui_font_color, 256 - 32, 256 - 32, 256 - 32, 255);
37
38 for(i = 0; i < GF_GUI_MAX_COMPONENTS; i++) gui->area[i].type = -1;
39
40 return gui;
41}
42
43void gf_gui_destroy(gf_gui_t* gui) {
45 for(i = 0; i < GF_GUI_MAX_COMPONENTS; i++) {
46 gf_gui_destroy_id(gui, i);
47 }
48 gf_log_function(gui->engine, "Destroyed GUI", "");
49 free(gui);
50}
51
52void gf_gui_destroy_id(gf_gui_t* gui, gf_gui_id_t id) {
53 gf_gui_component_t* c = &gui->area[id];
54 switch(c->type) {
55 case GF_GUI_BUTTON: {
56 if(c->u.button.text != NULL) free(c->u.button.text);
57 c->u.button.text = NULL;
58 }
59 }
60 c->type = GF_GUI_UNUSED;
61}
62
63/* note... left top should be the lightest in the border */
64
65void gf_gui_draw_box(gf_gui_t* gui, int mul, double x, double y, double w, double h) {
66 const int color_diff = 32; /* color diff */
68
69 int cd = mul * color_diff;
70
71 col = gf_gui_base_color;
72 col.r += cd;
73 col.g += cd;
74 col.b += cd;
75 gf_graphic_fill_rect(gui->draw, x, y, w, h, col);
76
77 col = gf_gui_base_color;
78 col.r -= cd;
79 col.g -= cd;
80 col.b -= cd;
81 gf_graphic_fill_polygon(gui->draw, col, GF_GRAPHIC_2D, 5, x + w, y + h, x + w, y, x + w - gf_gui_border_width, y + gf_gui_border_width, x + gf_gui_border_width, y + h - gf_gui_border_width, x, y + h);
82
83 col = gf_gui_base_color;
84 gf_graphic_fill_rect(gui->draw, x + gf_gui_border_width, y + gf_gui_border_width, w - gf_gui_border_width * 2, h - gf_gui_border_width * 2, col);
85}
86
87gf_gui_component_t* gf_gui_first_unused(gf_gui_t* gui, gf_gui_id_t* id) {
89 for(i = 0; i < GF_GUI_MAX_COMPONENTS; i++) {
90 if(gui->area[i].type == GF_GUI_UNUSED) {
91 *id = i;
92 return &gui->area[i];
93 }
94 }
95 return NULL;
96}
97
98gf_gui_id_t gf_gui_create_button(gf_gui_t* gui, double x, double y, double w, double h, const char* text) {
99 gf_gui_id_t id;
100 gf_gui_component_t* c = gf_gui_first_unused(gui, &id);
101
102 c->type = GF_GUI_BUTTON;
103 c->x = x;
104 c->y = y;
105 c->width = w;
106 c->height = h;
107
108 c->pressed = 0;
109 c->callback = NULL;
110
111 c->u.button.text = malloc(strlen(text) + 1);
112 strcpy(c->u.button.text, text);
113 return id;
114}
115
116void gf_gui_render(gf_gui_t* gui) {
117 gf_gui_id_t i;
118 gf_input_t* input = gui->draw->input;
119 for(i = GF_GUI_MAX_COMPONENTS - 1; i >= 0; i--) {
120 gf_gui_component_t* c = &gui->area[i];
121 double cx = c->x;
122 double cy = c->y;
123 double cw = c->width;
124 double ch = c->height;
125 switch(c->type) {
126 case GF_GUI_BUTTON: {
127 if(input->mouse_x != -1 && input->mouse_y != -1 && gui->pressed == -1 && (input->mouse_flag & GF_INPUT_MOUSE_LEFT_MASK) && (cx <= input->mouse_x && input->mouse_x <= cx + cw) && (cy <= input->mouse_y && input->mouse_y <= cy + ch)) {
128 gui->pressed = i;
129 } else if(gui->pressed == -1) {
130 c->pressed = 0;
131 }
132 break;
133 }
134 }
135 }
136 for(i = 0; i < GF_GUI_MAX_COMPONENTS; i++) {
137 gf_gui_component_t* c = &gui->area[i];
138 double cx = c->x;
139 double cy = c->y;
140 double cw = c->width;
141 double ch = c->height;
142 switch(c->type) {
143 case GF_GUI_BUTTON: {
144 double x = cx + cw / 2 - gf_graphic_text_width(gui->draw, GF_GUI_FONT_SIZE, c->u.button.text) / 2;
145 double y = cy + ch / 2 - GF_GUI_FONT_SIZE / 2;
146 if(gui->pressed == i) {
147 x += gf_gui_border_width / 1;
148 y += gf_gui_border_width / 1;
149 }
150 gf_gui_draw_box(gui, (gui->pressed == i) ? GF_GUI_INVERT : GF_GUI_NORMAL, cx, cy, cw, ch);
151 gf_graphic_text(gui->draw, x, y, GF_GUI_FONT_SIZE, c->u.button.text, gf_gui_font_color);
152 break;
153 }
154 }
155 }
156 if((gui->pressed != -1) && !(input->mouse_flag & GF_INPUT_MOUSE_LEFT_MASK)) {
157 if(gui->area[gui->pressed].callback != NULL) {
158 gui->area[gui->pressed].callback(gui->engine, gui->draw, gui->pressed, GF_GUI_PRESS_EVENT);
159 }
160 gui->area[gui->pressed].pressed = 1;
161 gui->pressed = -1;
162 }
163}
164
165void gf_gui_set_callback(gf_gui_t* gui, gf_gui_id_t id, gf_gui_callback_t callback) { gui->area[id].callback = callback; }
Drawing interface.
Graphic interface.
#define GF_SET_COLOR(color, red, green, blue, alpha)
Macro to set color safely and shorter.
Definition gf_graphic.h:39
#define GF_GRAPHIC_2D
Dimension parameter for 2D.
Definition gf_graphic.h:26
#define GF_GUI_INVERT
Draw border inverted.
Definition gf_gui.h:32
#define GF_GUI_FONT_SIZE
Default GUI font size.
Definition gf_gui.h:38
#define GF_GUI_NORMAL
Draw border normally.
Definition gf_gui.h:26
Logger.
#define gf_log_function(engine, fmt,...)
Output log with line number and function name.
Definition gf_log.h:33
Required headers before anything.
int gf_gui_id_t
Component ID.
Definition gui.h:17
#define GF_GUI_MAX_COMPONENTS
Max components GUI can handle.
Definition gui.h:48
#define GF_INPUT_MOUSE_LEFT_MASK
Mask for left mouse button.
Definition input.h:28
Drawing interface.
Definition draw.h:108
gf_input_t * input
Input interface.
Definition draw.h:108
Engine instance.
Definition core.h:46
double g
Green.
Definition graphic.h:44
double b
Blue.
Definition graphic.h:44
double r
Red.
Definition graphic.h:44
char * text
Button text.
Definition gui.h:67
Component.
Definition gui.h:120
int pressed
1 if pressed, otherwise 0
Definition gui.h:120
double y
X coord of component.
Definition gui.h:120
double width
Width of component.
Definition gui.h:120
double height
Height of component.
Definition gui.h:120
gf_gui_callback_t callback
Event callback.
Definition gui.h:120
gf_gui_union_t u
Component union.
Definition gui.h:120
int type
Component type.
Definition gui.h:120
double x
X coord of component.
Definition gui.h:120
GUI.
Definition gui.h:144
gf_gui_id_t pressed
1 if something is being pressed, otherwise 0
Definition gui.h:144
gf_engine_t * engine
Engine instance.
Definition gui.h:144
gf_draw_t * draw
Drawing interface.
Definition gui.h:144
gf_gui_component_t area[64]
Created components.
Definition gui.h:144
Input interface.
Definition input.h:64
int mouse_flag
Mouse flag.
Definition input.h:64
int mouse_y
Y coord of mouse.
Definition input.h:64
int mouse_x
X coord of mouse.
Definition input.h:64
gf_gui_button_t button
Button component.
Definition gui.h:78