169 lines
6.9 KiB
C
169 lines
6.9 KiB
C
#include "settings.h"
|
|
#include "sys.h"
|
|
#include "json.h"
|
|
#include "scratch.h"
|
|
#include "string.h"
|
|
#include "app.h"
|
|
#include "math.h"
|
|
|
|
/* TODO:
|
|
* Rework the whole settings system to be not so rigid.
|
|
* - Multi-threaded
|
|
* - Current settings state is readable & modifiable at any time
|
|
* - Can be done w/ a settings_open / settings_close block
|
|
* - Allow for dot notation in settings queries (should probably be implemented in the json layer).
|
|
* - "." denotes subindexing, IE: settings_get("window.width") (numbers can also be implemented for arrays).
|
|
* - "\." escapable
|
|
*/
|
|
|
|
#define SETTINGS_FILENAME "settings.json"
|
|
|
|
INTERNAL struct buffer serialize_window_settings(struct arena *arena, const struct sys_window_settings *settings)
|
|
{
|
|
__prof;
|
|
struct temp_arena scratch = scratch_begin(arena);
|
|
struct json_ir *root_obj = json_ir_object(scratch.arena);
|
|
struct json_ir *window_settings_obj = json_ir_object_set(root_obj, STR("window"), json_ir_object(scratch.arena));
|
|
json_ir_object_set(window_settings_obj, STR("minimized"), json_ir_bool(scratch.arena, settings->flags & SYS_WINDOW_SETTINGS_FLAG_MINIMIZED));
|
|
json_ir_object_set(window_settings_obj, STR("maximized"), json_ir_bool(scratch.arena, settings->flags & SYS_WINDOW_SETTINGS_FLAG_MAXIMIZED));
|
|
json_ir_object_set(window_settings_obj, STR("fullscreen"), json_ir_bool(scratch.arena, settings->flags & SYS_WINDOW_SETTINGS_FLAG_FULLSCREEN));
|
|
json_ir_object_set(window_settings_obj, STR("x"), json_ir_number(scratch.arena, settings->floating_x));
|
|
json_ir_object_set(window_settings_obj, STR("y"), json_ir_number(scratch.arena, settings->floating_y));
|
|
json_ir_object_set(window_settings_obj, STR("width"), json_ir_number(scratch.arena, settings->floating_width));
|
|
json_ir_object_set(window_settings_obj, STR("height"), json_ir_number(scratch.arena, settings->floating_height));
|
|
|
|
const struct json_val *formatted = json_format(scratch.arena, root_obj);
|
|
struct buffer buff = BUFFER_FROM_STRING(json_dump_to_string(arena, formatted, 2));
|
|
|
|
scratch_end(scratch);
|
|
return buff;
|
|
}
|
|
|
|
INTERNAL void deserialize_window_settings(struct buffer json_bytes, struct sys_window_settings *settings)
|
|
{
|
|
__prof;
|
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
|
struct string error = { 0 };
|
|
|
|
if (json_bytes.size <= 0) {
|
|
goto end;
|
|
}
|
|
|
|
struct string *parse_error = NULL;
|
|
const struct json_val *root_json = json_parse_and_format(scratch.arena, json_bytes, &parse_error);
|
|
if (parse_error) {
|
|
error = *parse_error;
|
|
goto end;
|
|
}
|
|
|
|
const struct json_val *window_settings_json = json_object_get(root_json, STR("window"));
|
|
if (!window_settings_json || !json_is_object(window_settings_json)) {
|
|
goto end;
|
|
}
|
|
|
|
const struct json_val *minimized = json_object_get(window_settings_json, STR("minimized"));
|
|
const struct json_val *maximized = json_object_get(window_settings_json, STR("maximized"));
|
|
const struct json_val *fullscreen = json_object_get(window_settings_json, STR("fullscreen"));
|
|
const struct json_val *width = json_object_get(window_settings_json, STR("width"));
|
|
const struct json_val *height = json_object_get(window_settings_json, STR("height"));
|
|
const struct json_val *x = json_object_get(window_settings_json, STR("x"));
|
|
const struct json_val *y = json_object_get(window_settings_json, STR("y"));
|
|
|
|
if (!(json_is_bool(minimized) && json_bool(minimized))) {
|
|
/* Only trust pos/size settings if window wasn't closed while minimized */
|
|
settings->floating_x = json_is_number(x) ? (i32)clamp_f64(json_number(x), I32_MIN, I32_MAX) : settings->floating_x;
|
|
settings->floating_y = json_is_number(y) ? (i32)clamp_f64(json_number(y), I32_MIN, I32_MAX) : settings->floating_y;
|
|
settings->floating_width = json_is_number(width) ? (i32)clamp_f64(json_number(width), I32_MIN, I32_MAX) : settings->floating_width;
|
|
settings->floating_height = json_is_number(height) ? (i32)clamp_f64(json_number(height), I32_MIN, I32_MAX) : settings->floating_height;
|
|
}
|
|
settings->flags = json_is_bool(maximized) ? (json_bool(maximized) ? (settings->flags | SYS_WINDOW_SETTINGS_FLAG_MAXIMIZED) : (settings->flags & ~SYS_WINDOW_SETTINGS_FLAG_MAXIMIZED)) : settings->flags;
|
|
settings->flags = json_is_bool(fullscreen) ? (json_bool(fullscreen) ? (settings->flags | SYS_WINDOW_SETTINGS_FLAG_FULLSCREEN) : (settings->flags & ~SYS_WINDOW_SETTINGS_FLAG_FULLSCREEN)) : settings->flags;
|
|
|
|
|
|
end:
|
|
if (error.len > 0) {
|
|
sys_message_box(
|
|
SYS_MESSAGE_BOX_KIND_WARNING,
|
|
string_format(
|
|
scratch.arena,
|
|
STR("Error loading settings file:\n%F"),
|
|
FMT_STR(error)
|
|
)
|
|
);
|
|
}
|
|
|
|
scratch_end(scratch);
|
|
}
|
|
|
|
struct sys_window_settings settings_default_window_settings(struct sys_window *window)
|
|
{
|
|
__prof;
|
|
|
|
struct v2 window_size = sys_window_get_size(window);
|
|
struct v2 monitor_size = sys_window_get_monitor_size(window);
|
|
|
|
i32 window_width = math_round(window_size.x);
|
|
i32 window_height = math_round(window_size.y);
|
|
i32 monitor_width = math_round(monitor_size.x);
|
|
i32 monitor_height = math_round(monitor_size.y);
|
|
|
|
i32 width = window_width / 2;
|
|
i32 height = window_height / 2;
|
|
i32 x = monitor_width / 2 - width / 2;
|
|
i32 y = monitor_height / 2 - height / 2;
|
|
|
|
return (struct sys_window_settings) {
|
|
#if RTC
|
|
# if DEVELOPER
|
|
.title = "Debug (Developer Build)",
|
|
# else
|
|
.title = "Debug",
|
|
# endif
|
|
#else
|
|
# if DEVELOPER
|
|
.title = "Power Play (Developer Build)",
|
|
# else
|
|
.title = "Power Play",
|
|
# endif
|
|
#endif
|
|
.floating_x = x,
|
|
.floating_y = y,
|
|
.floating_width = width,
|
|
.floating_height = height
|
|
};
|
|
}
|
|
|
|
void settings_read_from_file(struct sys_window_settings *default_settings)
|
|
{
|
|
__prof;
|
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
|
|
|
/* Read window settings file if it exists */
|
|
struct string window_settings_path = app_write_path_cat(scratch.arena, STR(SETTINGS_FILENAME));
|
|
if (sys_is_file(window_settings_path)) {
|
|
struct sys_file settings_file = sys_file_open_read(window_settings_path);
|
|
struct buffer file_data = sys_file_read_all(scratch.arena, settings_file);
|
|
sys_file_close(settings_file);
|
|
deserialize_window_settings(file_data, default_settings);
|
|
}
|
|
|
|
scratch_end(scratch);
|
|
}
|
|
|
|
void settings_write_to_file(const struct sys_window_settings *settings)
|
|
{
|
|
__prof;
|
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
|
|
|
/* Write window settings to file */
|
|
struct buffer settings_file_data = serialize_window_settings(scratch.arena, settings);
|
|
if (settings_file_data.size > 0) {
|
|
struct string window_settings_path = app_write_path_cat(scratch.arena, STR(SETTINGS_FILENAME));
|
|
struct sys_file settings_file = sys_file_open_write(window_settings_path);
|
|
sys_file_write(settings_file, settings_file_data);
|
|
sys_file_close(settings_file);
|
|
}
|
|
|
|
scratch_end(scratch);
|
|
}
|