summaryrefslogtreecommitdiff
path: root/src/static-ui.hpp
blob: 17301a16c1c9399b558bab4638bb1a585a6184f1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#ifndef PKE_STATIC_UI_HPP
#define PKE_STATIC_UI_HPP

#include "components-vk.hpp"
#include "font.hpp"
#include "pk.h"
#include "vendor-glm-include.hpp"

#include <cstdint>

#define built_in_offset 2.0

struct MSDFGlyphSettings {
	float width;
	float height;
	float scale;
	float translate_em;
	float range_em;
};

TypeSafeInt_H(PKE_UI_BOX_TYPE, uint8_t, 0xFF);
TypeSafeInt_H(PKE_UI_BOX_FLAG, uint64_t, 0xFFFFFFFFFFFFFFFF);
TypeSafeInt_H(PKE_UI_BOX_STATE_FLAG, uint64_t, 0xFFFFFFFFFFFFFFFF);

// layouts
const PKE_UI_BOX_TYPE PKE_UI_BOX_TYPE_STANDARD
    = PKE_UI_BOX_TYPE(0);
// TODO columns, rows, tabs, etc

// special (content)
const PKE_UI_BOX_TYPE PKE_UI_BOX_TYPE_TEXT
    = PKE_UI_BOX_TYPE(50);
// TODO image, render target, etc

// inputs
// TODO
const PKE_UI_BOX_TYPE PKE_UI_BOX_TYPE_BUTTON_TEXT
    = PKE_UI_BOX_TYPE(100);
// TODO
const PKE_UI_BOX_TYPE PKE_UI_BOX_TYPE_BUTTON_IMAGE
    = PKE_UI_BOX_TYPE(101);
const PKE_UI_BOX_TYPE PKE_UI_BOX_TYPE_INPUT_TEXT
    = PKE_UI_BOX_TYPE(105);
// TODO
const PKE_UI_BOX_TYPE PKE_UI_BOX_TYPE_INPUT_MULTILINE_TEXT
    = PKE_UI_BOX_TYPE(106);
// TODO scalar, float, slider, etc

const PKE_UI_BOX_FLAG PKE_UI_BOX_FLAG_NONE
    = PKE_UI_BOX_FLAG(0);
// [00-04] position type
// exact screen coordinates
const PKE_UI_BOX_FLAG PKE_UI_BOX_FLAG_POSITION_TYPE_FLEX
    = PKE_UI_BOX_FLAG((1 <<  0));
const PKE_UI_BOX_FLAG PKE_UI_BOX_FLAG_POSITION_TYPE_STATIC
    = PKE_UI_BOX_FLAG((1 <<  1));
const PKE_UI_BOX_FLAG PKE_UI_BOX_FLAG_POSITION_TYPE_DYNAMIC
    = PKE_UI_BOX_FLAG((1 <<  2));
const PKE_UI_BOX_FLAG PKE_UI_BOX_FLAG_POSITION_TYPE_ALL
    = PKE_UI_BOX_FLAG((1 <<  0) | (1 <<  1) | (1 <<  2));
// [05-06] center
const PKE_UI_BOX_FLAG PKE_UI_BOX_FLAG_CENTER_HORIZONTAL
    = PKE_UI_BOX_FLAG((1 <<  5));
const PKE_UI_BOX_FLAG PKE_UI_BOX_FLAG_CENTER_VERTICAL
    = PKE_UI_BOX_FLAG((1 <<  6));
const PKE_UI_BOX_FLAG PKE_UI_BOX_FLAG_CENTER_BOTH
    = PKE_UI_BOX_FLAG((1 <<  5) | (1 <<  6));
// [07-09] visibility
const PKE_UI_BOX_FLAG PKE_UI_BOX_FLAG_VISIBILITY_INVISIBLE
    = PKE_UI_BOX_FLAG((1 <<  7));
const PKE_UI_BOX_FLAG PKE_UI_BOX_FLAG_VISIBILITY_DISABLED
    = PKE_UI_BOX_FLAG((1 <<  8));
// [10-??]

// PKE_UI_BOX_STATE_FLAG represent the current state THIS TICK.
// So, e.g.
//  Did the mouse enter this tick.
//  Is the mouse hovered.
const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_NONE
    = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(0) << 0));
const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_MOUSE_ENTERED
    = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 0));
const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_MOUSE_EXITED
    = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 1));
const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_MOUSE_HOVER
    = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 2));
const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_ON_BTN_PRIMARY_PRESS
    = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 3));
const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_ON_BTN_PRIMARY_RELEASE
    = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 4));
const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_ON_BTN_PRIMARY_PRESSED
    = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 5));
const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_ON_BTN_SECONDARY_PRESS
    = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 6));
const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_ON_BTN_SECONDARY_RELEASE
    = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 7));
const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_ON_BTN_SECONDARY_PRESSED
    = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 8));
const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_ON_BTN_MIDDLE_PRESS
    = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 9));
const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_ON_BTN_MIDDLE_RELEASE
    = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 10));
const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_ON_BTN_MIDDLE_PRESSED
    = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 11));

typedef uint16_t pke_ui_box_count_T;

struct pke_ui_box;

struct pke_ui_box : public Entity_Base {
	PKE_UI_BOX_FLAG flags;
	glm::vec2 pos_top_left;
	glm::vec2 min_size;
	glm::vec2 max_size;
	float flex_weight;
	float flex_padding;
	PKE_UI_BOX_TYPE type;
	uint8_t flex_direction;
	uint8_t layer;
	glm::vec4 color_border = glm::vec4(1.0, 0.0, 0.0, 1.0);
	glm::vec4 color_background = glm::vec4(0.2, 0.3, 0.2, 0.5);
	union pke_ui_box_type_data *type_data;
	PKE_UI_BOX_STATE_FLAG state_flags;
	PKE_UI_BOX_STATE_FLAG state_flags_mem;
	struct pke_ui_box_internals {
		// the exact px to translate (shader)
		glm::vec2 px_corner;
		// the exact px for scaling (shader)
		glm::vec2 px_size;
		// internal padding + running offset for adding children
		// glm::vec4 px_padding;
		float px_padding_l, px_padding_b, px_padding_r, px_padding_t;
		pke_ui_box *parent;
		pke_ui_box **children;
		pke_ui_box_count_T h_children;
		pke_ui_box_count_T r_children;
		uint8_t depth;
	} internal;
};

// separate these if they become silly
union pke_ui_box_type_data {
	struct pke_ui_box_type_data_text {
		FontTypeRender font_type_render;
	} text;
	struct pke_ui_box_type_data_button_text {
		FontTypeRender font_type_render;
		PkeEventHandle pke_event_handle;
		pk_ev_id_T ev_id;
	} button_text;
	struct pke_ui_box_type_data_button_image {
		AssetKey img_key_default;
		AssetKey img_key_hovered;
		AssetKey img_key_pressed;
		pk_bkt_arr_handle gr_binds_bkt_arr_handle;
		PkeEventHandle pke_event_handle;
		pk_ev_id_T ev_id;
	} button_image;
};

struct pke_ui_graphics_bindings {
	VkDeviceMemory deviceMemoryVert = VK_NULL_HANDLE;
	VkDeviceMemory deviceMemoryInst = VK_NULL_HANDLE;
	BufferBindingDetails bd_vertex;
	BufferBindingDetails bd_uv;
	BufferBindingDetails bd_index;
	BufferBindingDetails bd_instance;
	uint32_t index_count;
	uint32_t instance_counter;
	uint32_t instance_buffer_max_count;
};

/* minimum amount of data needed to reuse the normal bindings but also bind textures
 */
struct pke_ui_graphics_bindings_texture {
	uint32_t instance_offset;
	uint32_t instance_count;
	VkDescriptorSet *descriptor_sets;
	VkDescriptorPool descriptor_pool;
	VkDeviceMemory image_memory;
	VkImage image;
	VkImageView image_view;
};

void pke_ui_init();
void pke_ui_init_bindings();
void pke_ui_tick(double delta);
void pke_ui_teardown();
void pke_ui_force_recalc();

pke_ui_box **pke_ui_get_root_boxes(pke_ui_box_count_T *count);

pke_ui_box *pke_ui_box_new_root(const PKE_UI_BOX_TYPE type = PKE_UI_BOX_TYPE_STANDARD, pk_uuid uuid = pk_uuid_zed);
pke_ui_box *pke_ui_box_new_child(pke_ui_box *parent, const PKE_UI_BOX_TYPE type = PKE_UI_BOX_TYPE_STANDARD, pk_uuid uuid = pk_uuid_zed);
void pke_ui_box_update_textures(pke_ui_box *box);

#ifdef PKE_TEST_EXPOSE
void pke_ui_calc_px(pk_arr_t<pke_ui_box_instance_buffer_item> &buffer, pk_arr_t<std::pair<pke_ui_box*,pke_ui_box_instance_buffer_item>> &tmp_txtr_buffer, pke_ui_flex_params *flex_params, pke_ui_box *box, uint8_t child_index);
void pke_ui_recalc_sizes_recursive(pk_arr_t<pke_ui_box_instance_buffer_item> &arr, pk_arr_t<std::pair<pke_ui_box*,pke_ui_box_instance_buffer_item>> &tmp_txtr_buffer, pke_ui_box *box);
#endif

const pke_ui_graphics_bindings &pke_ui_get_graphics_bindings();
void pke_ui_get_graphics_bindings_texture(pk_arr *arr);

#endif /* PKE_STATIC_UI_HPP */