2024-08-12 14:55:46 +00:00
// 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 ;
}