-
Notifications
You must be signed in to change notification settings - Fork 9
/
fwk_editor0.c
390 lines (340 loc) Β· 15.8 KB
/
fwk_editor0.c
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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
// editing:
// nope > functions: add/rem property
#define ICON_PLAY ICON_MD_PLAY_ARROW
#define ICON_PAUSE ICON_MD_PAUSE
#define ICON_STOP ICON_MD_STOP
#define ICON_CANCEL ICON_MD_CLOSE
#define ICON_WARNING ICON_MD_WARNING
#define ICON_BROWSER ICON_MD_FOLDER_SPECIAL
#define ICON_OUTLINER ICON_MD_VIEW_IN_AR
#define ICON_BUILD ICON_MD_BUILD
#define ICON_SCREENSHOT ICON_MD_PHOTO_CAMERA
#define ICON_CAMERA_ON ICON_MD_VIDEOCAM
#define ICON_CAMERA_OFF ICON_MD_VIDEOCAM_OFF
#define ICON_GAMEPAD_ON ICON_MD_VIDEOGAME_ASSET
#define ICON_GAMEPAD_OFF ICON_MD_VIDEOGAME_ASSET_OFF
#define ICON_AUDIO_ON ICON_MD_VOLUME_UP
#define ICON_AUDIO_OFF ICON_MD_VOLUME_OFF
#define ICON_WINDOWED ICON_MD_FULLSCREEN_EXIT
#define ICON_FULLSCREEN ICON_MD_FULLSCREEN
#define ICON_LIGHTS_ON ICON_MD_LIGHTBULB
#define ICON_LIGHTS_OFF ICON_MD_LIGHTBULB_OUTLINE
#define ICON_RENDER_BASIC ICON_MD_IMAGE_SEARCH
#define ICON_RENDER_FULL ICON_MD_INSERT_PHOTO
#define ICON_SIGNAL ICON_MD_SIGNAL_CELLULAR_ALT
#define ICON_DISK ICON_MD_STORAGE
#define ICON_RATE ICON_MD_SPEED
#define ICON_CLOCK ICON_MD_TODAY
#define ICON_CHRONO ICON_MD_TIMELAPSE
#define ICON_SETTINGS ICON_MD_SETTINGS
#define ICON_LANGUAGE ICON_MD_G_TRANSLATE
#define ICON_PERSONA ICON_MD_FACE
#define ICON_SOCIAL ICON_MD_MESSAGE
#define ICON_GAME ICON_MD_ROCKET_LAUNCH
#define ICON_KEYBOARD ICON_MD_KEYBOARD
#define ICON_MOUSE ICON_MD_MOUSE
#define ICON_GAMEPAD ICON_MD_GAMEPAD
#define ICON_MONITOR ICON_MD_MONITOR
#define ICON_WIFI ICON_MD_WIFI
#define ICON_BUDGET ICON_MD_SAVINGS
#define ICON_NEW_FOLDER ICON_MD_CREATE_NEW_FOLDER
#define ICON_PLUGIN ICON_MD_EXTENSION
#define ICON_RESTART ICON_MD_REPLAY
#define ICON_QUIT ICON_MD_CLOSE
#define ICON_POWER ICON_MD_BOLT // ICON_MD_POWER
#define ICON_BATTERY_CHARGING ICON_MD_BATTERY_CHARGING_FULL
#define ICON_BATTERY_LEVELS \
ICON_MD_BATTERY_ALERT, \
ICON_MD_BATTERY_0_BAR,ICON_MD_BATTERY_1_BAR, \
ICON_MD_BATTERY_2_BAR,ICON_MD_BATTERY_3_BAR, \
ICON_MD_BATTERY_4_BAR,ICON_MD_BATTERY_5_BAR, \
ICON_MD_BATTERY_6_BAR,ICON_MD_BATTERY_FULL
char *editor_path(const char *path) {
return va("%s/%s", EDITOR, path);
}
vec3 editor_pick(float mouse_x, float mouse_y) {
#if 0
// unproject 2d coord as 3d coord
camera_t *camera = camera_get_active();
vec3 out, xyd = vec3(mouse_x,window_height()-mouse_y,1); // usually x:mouse_x,y:window_height()-mouse_y,d:0=znear/1=zfar
mat44 mvp, model; identity44(model); multiply44x3(mvp, camera->proj, camera->view, model);
bool ok = unproject44(&out, xyd, vec4(0,0,window_width(),window_height()), mvp);
return out;
#else
// unproject 2d coord as 3d coord
vec2 dpi = ifdef(osx, window_dpi(), vec2(1,1));
camera_t *camera = camera_get_active();
float x = (2.0f * mouse_x) / (dpi.x * window_width()) - 1.0f;
float y = 1.0f - (2.0f * mouse_y) / (dpi.y * window_height());
float z = 1.0f;
vec3 ray_nds = vec3(x, y, z);
vec4 ray_clip = vec4(ray_nds.x, ray_nds.y, -1.0, 1.0);
mat44 inv_proj; invert44(inv_proj, camera->proj);
mat44 inv_view; invert44(inv_view, camera->view);
vec4 p = transform444(inv_proj, ray_clip);
vec4 eye = vec4(p.x, p.y, -1.0, 0.0);
vec4 wld = norm4(transform444(inv_view, eye));
return vec3(wld.x, wld.y, wld.z);
#endif
}
typedef union engine_var {
int i;
float f;
char *s;
} engine_var;
static map(char*,engine_var) engine_vars;
float *engine_getf(const char *key) {
if(!engine_vars) map_init_str(engine_vars);
engine_var *found = map_find_or_add(engine_vars, (char*)key, ((engine_var){0}) );
return &found->f;
}
int *engine_geti(const char *key) {
if(!engine_vars) map_init_str(engine_vars);
engine_var *found = map_find_or_add(engine_vars, (char*)key, ((engine_var){0}) );
return &found->i;
}
char **engine_gets(const char *key) {
if(!engine_vars) map_init_str(engine_vars);
engine_var *found = map_find_or_add(engine_vars, (char*)key, ((engine_var){0}) );
if(!found->s) found->s = stringf("%s","");
return &found->s;
}
int engine_send(const char *cmd, const char *optional_value) {
unsigned *gamepads = engine_geti("gamepads"); // 0 off, mask gamepad1(1), gamepad2(2), gamepad3(4), gamepad4(8)...
unsigned *renders = engine_geti("renders"); // 0 off, mask: 1=lit, 2=ddraw, 3=whiteboxes
float *speed = engine_getf("speed"); // <0 num of frames to advance, 0 paused, [0..1] slomo, 1 play regular speed, >1 fast-forward (x2/x4/x8)
unsigned *powersave = engine_geti("powersave");
char *name;
/**/ if( !strcmp(cmd, "key_quit" )) record_stop(), exit(0);
else if( !strcmp(cmd, "key_stop" )) window_pause(1);
else if( !strcmp(cmd, "key_mute" )) audio_volume_master( 1 ^ !!audio_volume_master(-1) );
else if( !strcmp(cmd, "key_pause" )) window_pause( window_has_pause() ^ 1 );
else if( !strcmp(cmd, "key_reload" )) window_reload();
else if( !strcmp(cmd, "key_battery" )) *powersave = optional_value ? !!atoi(optional_value) : *powersave ^ 1;
else if( !strcmp(cmd, "key_browser" )) ui_show("File Browser", ui_visible("File Browser") ^ true);
else if( !strcmp(cmd, "key_outliner" )) ui_show("Outliner", ui_visible("Outliner") ^ true);
else if( !strcmp(cmd, "key_record" )) if(record_active()) record_stop(), ui_notify(va("Video recorded"), date_string()); else
app_beep(), name = file_counter(va("%s.mp4",app_name())), window_record(name);
else if( !strcmp(cmd, "key_screenshot" )) name = file_counter(va("%s.png",app_name())), window_screenshot(name), ui_notify(va("Screenshot: %s", name), date_string());
else if( !strcmp(cmd, "key_profiler" )) ui_show("Profiler", profiler_enable(ui_visible("Profiler") ^ true));
else if( !strcmp(cmd, "key_fullscreen" )) record_stop(), window_fullscreen( window_has_fullscreen() ^ 1 ); // framebuffer resizing corrupts video stream, so stop any recording beforehand
else if( !strcmp(cmd, "key_gamepad" )) *gamepads = (*gamepads & ~1u) | ((*gamepads & 1) ^ 1);
else if( !strcmp(cmd, "key_lit" )) *renders = (*renders & ~1u) | ((*renders & 1) ^ 1);
else if( !strcmp(cmd, "key_ddraw" )) *renders = (*renders & ~2u) | ((*renders & 2) ^ 2);
else alert(va("editor could not handle `%s` command.", cmd));
return 0;
}
int engine_tick() {
enum { engine_hz_mid = 30 };
enum { engine_hz_low = 10 };
static double old_hz = 0.0;
if( *engine_geti("powersave") ) {
// adaptive framerate
int app_on_background = !window_has_focus();
int hz = app_on_background ? engine_hz_low : engine_hz_mid;
if (!old_hz) old_hz = window_fps_target();
window_fps_lock( hz );
} else if( old_hz && old_hz != window_fps_target() ) {
window_fps_lock( old_hz );
old_hz = 0.0;
}
return 0;
}
int ui_engine() {
static int time_factor = 0;
static int playing = 0;
static int paused = 0;
int advance_frame = 0;
#if 0
static int do_filter = 0;
static int do_profile = 0;
static int do_extra = 0;
char *EDITOR_TOOLBAR_ICONS = va("%s;%s;%s;%s;%s;%s;%s;%s",
do_filter ? ICON_MD_CLOSE : ICON_MD_SEARCH,
ICON_MD_PLAY_ARROW,
paused ? ICON_MD_SKIP_NEXT : ICON_MD_PAUSE,
ICON_MD_FAST_FORWARD,
ICON_MD_STOP,
ICON_MD_REPLAY,
ICON_MD_FACE,
ICON_MD_MENU
);
if( input_down(KEY_F) ) if( input(KEY_LCTRL) || input(KEY_RCTRL) ) do_filter ^= 1;
int choice = ui_toolbar(EDITOR_TOOLBAR_ICONS);
if( choice == 1 ) do_filter ^= 1, do_profile = 0, do_extra = 0;
if( choice == 2 ) playing = 1, paused = 0;
if( choice == 3 ) advance_frame = !!paused, paused = 1;
if( choice == 4 ) paused = 0, time_factor = (++time_factor) % 4;
if( choice == 5 ) playing = 0, paused = 0, advance_frame = 0, time_factor = 0;
if( choice == 6 ) window_reload();
if( choice == 7 ) do_filter = 0, do_profile ^= 1, do_extra = 0;
if( choice == 8 ) do_filter = 0, do_profile = 0, do_extra ^= 1;
if( do_filter ) {
char *bak = ui_filter; ui_filter = 0;
ui_string(ICON_MD_CLOSE " Filter " ICON_MD_SEARCH, &bak);
ui_filter = bak;
if( ui_label_icon_clicked_L.x > 0 && ui_label_icon_clicked_L.x <= 24 ) { // if clicked on CANCEL icon (1st icon)
do_filter = 0;
}
} else {
if( ui_filter ) ui_filter[0] = '\0';
}
char *filter_mask = ui_filter && ui_filter[0] ? va("*%s*", ui_filter) : "*";
static char *username = 0;
static char *userpass = 0;
if( do_profile ) {
ui_string(ICON_MD_FACE " Username", &username);
ui_string(ICON_MD_FACE " Password", &userpass);
}
if( do_extra ) {
int choice2 = ui_label2_toolbar(NULL,
ICON_MD_VIEW_IN_AR
ICON_MD_MESSAGE
ICON_MD_TIPS_AND_UPDATES ICON_MD_LIGHTBULB ICON_MD_LIGHTBULB_OUTLINE
ICON_MD_IMAGE_SEARCH ICON_MD_INSERT_PHOTO
ICON_MD_VIDEOGAME_ASSET ICON_MD_VIDEOGAME_ASSET_OFF
ICON_MD_VOLUME_UP ICON_MD_VOLUME_OFF // audio_volume_master(-1) > 0
ICON_MD_TROUBLESHOOT ICON_MD_SCHEMA ICON_MD_MENU
);
}
#endif
int open = 0, clicked_or_toggled = 0;
#define EDITOR_UI_COLLAPSE(f,...) \
for( int macro(p) = (open = ui_collapse(f,__VA_ARGS__)), macro(dummy) = (clicked_or_toggled = ui_collapse_clicked()); macro(p); ui_collapse_end(), macro(p) = 0)
EDITOR_UI_COLLAPSE(ICON_MD_VIEW_QUILT " Windows", "Debug.Windows") {
int choice = ui_toolbar(ICON_MD_RECYCLING "@Reset layout;" ICON_MD_SAVE_AS "@Save layout");
if( choice == 1 ) ui_layout_all_reset("*");
if( choice == 2 ) file_delete(WINDOWS_INI), ui_layout_all_save_disk("*");
for each_map_ptr_sorted(ui_windows, char*, k, unsigned, v) {
bool visible = ui_visible(*k);
if( ui_bool( *k, &visible ) ) {
ui_show( *k, ui_visible(*k) ^ true );
}
}
}
EDITOR_UI_COLLAPSE(ICON_MD_BUG_REPORT " Bugs 0", "Debug.Bugs") {
// @todo. parse /bugs.ini, includes saved screenshots & videos.
// @todo. screenshot include parseable level, position screen markers (same info as /bugs.ini)
}
// Art and bookmarks
EDITOR_UI_COLLAPSE(ICON_MD_FOLDER_SPECIAL " Art", "Debug.Art") {
bool inlined = true;
const char *file = 0;
if( ui_browse(&file, &inlined) ) {
const char *sep = ifdef(win32, "\"", "'");
app_exec(va("%s %s%s%s", ifdef(win32, "start \"\"", ifdef(osx, "open", "xdg-open")), sep, file, sep));
}
}
EDITOR_UI_COLLAPSE(ICON_MD_BOOKMARK " Bookmarks", "Debug.Bookmarks") { /* @todo */ }
// E,C,S,W
EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Scene", "Debug.Scene") {
EDITOR_UI_COLLAPSE(ICON_MD_BUBBLE_CHART/*ICON_MD_SCATTER_PLOT*/ " Entities", "Debug.Entities") { /* @todo */ }
EDITOR_UI_COLLAPSE(ICON_MD_TUNE " Components", "Debug.Components") { /* @todo */ }
EDITOR_UI_COLLAPSE(ICON_MD_PRECISION_MANUFACTURING " Systems", "Debug.Systems") { /* @todo */ }
EDITOR_UI_COLLAPSE(ICON_MD_PUBLIC " Levels", "Debug.Levels") {
//node_edit(editor.edit.down,&editor.edit);
}
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Init", "Debug.HierarchyInit") { /* @todo */ }
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Draw", "Debug.HierarchyDraw") { /* @todo */ }
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Tick", "Debug.HierarchyTick") { /* @todo */ }
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Edit", "Debug.HierarchyEdit") { /* @todo */ }
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Quit", "Debug.HierarchyQuit") { /* @todo */ }
// node_edit(&editor.init,&editor.init);
// node_edit(&editor.draw,&editor.draw);
// node_edit(&editor.tick,&editor.tick);
// node_edit(&editor.edit,&editor.edit);
// node_edit(&editor.quit,&editor.quit);
}
EDITOR_UI_COLLAPSE(ICON_MD_ROCKET_LAUNCH " AI", "Debug.AI") {
// @todo
}
EDITOR_UI_COLLAPSE(ICON_MD_VOLUME_UP " Audio", "Debug.Audio") {
ui_audio();
}
EDITOR_UI_COLLAPSE(ICON_MD_VIDEOCAM " Camera", "Debug.Camera") {
ui_camera( camera_get_active() );
}
EDITOR_UI_COLLAPSE(ICON_MD_MONITOR " Display", "Debug.Display") {
// @todo: fps lock, fps target, aspect ratio, fullscreen
char *text = va("%s;%s;%s",
window_has_fullscreen() ? ICON_MD_FULLSCREEN_EXIT : ICON_MD_FULLSCREEN,
ICON_MD_PHOTO_CAMERA,
record_active() ? ICON_MD_VIDEOCAM_OFF : ICON_MD_VIDEOCAM
);
int choice = ui_toolbar(text);
if( choice == 1 ) engine_send("key_fullscreen",0);
if( choice == 2 ) engine_send("key_screenshot",0);
if( choice == 3 ) engine_send("key_record",0);
}
EDITOR_UI_COLLAPSE(ICON_MD_KEYBOARD " Keyboard", "Debug.Keyboard") {
ui_keyboard();
}
EDITOR_UI_COLLAPSE(ICON_MD_MOUSE " Mouse", "Debug.Mouse") {
ui_mouse();
}
EDITOR_UI_COLLAPSE(ICON_MD_GAMEPAD " Gamepads", "Debug.Gamepads") {
for( int q = 0; q < 4; ++q ) {
for( int r = (open = ui_collapse(va("Gamepad #%d",q+1), va("Debug.Gamepads%d",q))), dummy = (clicked_or_toggled = ui_collapse_clicked()); r; ui_collapse_end(), r = 0) {
ui_gamepad(q);
}
}
}
EDITOR_UI_COLLAPSE(ICON_MD_TEXT_FIELDS " Fonts", "Debug.Fonts") {
ui_font();
}
EDITOR_UI_COLLAPSE(ICON_MD_CONTENT_PASTE " Scripts", "Debug.Scripts") {
// @todo
}
EDITOR_UI_COLLAPSE(ICON_MD_STAR_HALF " Shaders", "Debug.Shaders") {
ui_shaders();
}
EDITOR_UI_COLLAPSE(ICON_MD_MOVIE " FXs", "Debug.FXs") {
ui_fxs();
}
EDITOR_UI_COLLAPSE(ICON_MD_SAVINGS " Budgets", "Debug.Budgets") {
// @todo. // mem,fps,gfx,net,hdd,... also logging
}
EDITOR_UI_COLLAPSE(ICON_MD_WIFI/*ICON_MD_SIGNAL_CELLULAR_ALT*/ " Network 0/0 KiB", "Debug.Network") {
// @todo
// SIGNAL_CELLULAR_1_BAR SIGNAL_CELLULAR_2_BAR
}
EDITOR_UI_COLLAPSE(va(ICON_MD_SPEED " Profiler %5.2f/%dfps", window_fps(), (int)window_fps_target()), "Debug.Profiler") {
ui_profiler();
}
EDITOR_UI_COLLAPSE(va(ICON_MD_STORAGE " Storage %s", xstats()), "Debug.Storage") {
// @todo
}
// logic: either plug icon (power saving off) or one of the following ones (power saving on):
// if 0% batt (no batt): battery alert
// if discharging: battery levels [alert,0..6,full]
// if charging: battery charging
int battery_read = app_battery();
int battery_level = abs(battery_read);
int battery_discharging = battery_read < 0 && battery_level < 100;
const char *power_icon_label = ICON_MD_POWER " Power";
if( battery_level ) {
const char *battery_levels[9] = { // @todo: remap [7%..100%] -> [0..1] ?
ICON_MD_BATTERY_ALERT,ICON_MD_BATTERY_0_BAR,ICON_MD_BATTERY_1_BAR,
ICON_MD_BATTERY_2_BAR,ICON_MD_BATTERY_3_BAR,ICON_MD_BATTERY_4_BAR,
ICON_MD_BATTERY_5_BAR,ICON_MD_BATTERY_6_BAR,ICON_MD_BATTERY_FULL,
};
power_icon_label = (const char*)va("%s Power %d%%",
battery_discharging ? battery_levels[(int)((9-1)*clampf(battery_level/100.f,0,1))] : ICON_MD_BATTERY_CHARGING_FULL,
battery_level);
}
EDITOR_UI_COLLAPSE(power_icon_label, "Debug.Power") {
int choice = ui_toolbar( ICON_MD_POWER ";" ICON_MD_BOLT );
if( choice == 1 ) engine_send("key_battery","0");
if( choice == 2 ) engine_send("key_battery","1");
}
EDITOR_UI_COLLAPSE(ICON_MD_WATER " Reflection", "Debug.Reflect") {
ui_reflect("*");
}
EDITOR_UI_COLLAPSE(ICON_MD_EXTENSION " Plugins", "Debug.Plugins") {
// @todo. include VCS
EDITOR_UI_COLLAPSE(ICON_MD_BUILD " Cook", "Debug.Cook") {
// @todo
}
}
return 0;
}