Skip to content

Commit

Permalink
wip: save/restore ui window open state
Browse files Browse the repository at this point in the history
  • Loading branch information
floooh committed Dec 19, 2024
1 parent 3ec0a50 commit 5d7b19a
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 4 deletions.
89 changes: 86 additions & 3 deletions examples/common/ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "sokol_app.h"
#include "sokol_time.h"
#include "imgui.h"
#include "imgui_internal.h" // ImGui::SettingsHandler
#define SOKOL_IMGUI_IMPL
#include "sokol_imgui.h"
#include "gfx.h"
Expand All @@ -24,6 +25,7 @@

static struct {
ui_draw_t draw_cb;
ui_save_settings_t save_settings_cb;
sg_sampler nearest_sampler;
sg_sampler linear_sampler;
sg_image empty_snapshot_texture;
Expand All @@ -32,6 +34,7 @@ static struct {
size_t cur_slot;
} delete_stack;
char imgui_ini_key[128];
ui_settings_t settings;
} state;

static const struct {
Expand Down Expand Up @@ -66,15 +69,18 @@ static const struct {
static void commit_listener(void* user_data);
static void load_imgui_ini(void);
static void handle_save_imgui_ini(void);
static void register_imgui_settings_handler(void);

void ui_init(const ui_desc_t* desc) {
assert(desc && desc->draw_cb && desc->imgui_ini_key);

state.draw_cb = desc->draw_cb;
state.save_settings_cb = desc->save_settings_cb;
snprintf(state.imgui_ini_key, sizeof(state.imgui_ini_key), "%s", desc->imgui_ini_key);

simgui_desc_t simgui_desc = { };
simgui_setup(&simgui_desc);
register_imgui_settings_handler();
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_DockingEnable;
auto& style = ImGui::GetStyle();
style.WindowRounding = 0.0f;
Expand Down Expand Up @@ -106,6 +112,10 @@ void ui_init(const ui_desc_t* desc) {

}

const ui_settings_t* ui_settings(void) {
return &state.settings;
}

void ui_discard(void) {
sg_destroy_sampler(state.nearest_sampler);
sg_destroy_sampler(state.linear_sampler);
Expand Down Expand Up @@ -256,18 +266,91 @@ EM_JS(const char*, emsc_js_load_imgui_ini, (const char* c_key), {
static void handle_save_imgui_ini(void) {
if (ImGui::GetIO().WantSaveIniSettings) {
ImGui::GetIO().WantSaveIniSettings = false;
const char* settings = ImGui::SaveIniSettingsToMemory();
#if defined(__EMSCRIPTEN__)
emsc_js_save_imgui_ini(state.imgui_ini_key, ImGui::SaveIniSettingsToMemory());
emsc_js_save_imgui_ini(state.imgui_ini_key, settings);
#else
(void)settings;
#endif
}
}

static void load_imgui_ini(void) {
const char* payload = 0;
#if defined(__EMSCRIPTEN__)
const char* payload = emsc_js_load_imgui_ini(state.imgui_ini_key);
payload = emsc_js_load_imgui_ini(state.imgui_ini_key);
#endif
if (payload) {
ImGui::LoadIniSettingsFromMemory(payload);
free((void*)payload);
}
#endif
}

// ImGui Settings handler implementation

// clear all settings data
static void imgui_ClearAllFn(ImGuiContext* ctx, ImGuiSettingsHandler* handler) {
(void)ctx; (void)handler;
ui_settings_init(&state.settings);
}

// read: Called before reading (in registration order)
static void imgui_ReadInitFn(ImGuiContext* ctx, ImGuiSettingsHandler* handler) {
(void)ctx; (void)handler;
ui_settings_init(&state.settings);
}

// read: Called when entering into a new ini entry e.g. "[Window][Name]"
static void* imgui_ReadOpenFn(ImGuiContext* ctx, ImGuiSettingsHandler* handler, const char* name) {
(void)ctx; (void)handler;
ui_settings_add(&state.settings, name, false);
// NOTE: cannot return nullptr since this means 'no valid ini entry'
return (void*)&state.settings;
}

// read: Called for every line of text within an ini entry
static void imgui_ReadLineFn(ImGuiContext* ctx, ImGuiSettingsHandler* handler, void* entry, const char* line) {
(void)ctx; (void)handler; (void)entry;
assert(state.settings.num_slots > 0);
int cur_slot_idx = state.settings.num_slots - 1;
int is_open = 0;
if (sscanf(line, "IsOpen=%i", &is_open) == 1) {
state.settings.slots[cur_slot_idx].open = true;
}
}

// read: Called after reading (in registration order)
static void imgui_ApplyAllFn(ImGuiContext* ctx, ImGuiSettingsHandler* handler) {
(void)ctx; (void)handler;
}

// write: output all entries into 'out_buf'
static void imgui_WriteAllFn(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) {
(void)ctx; (void)handler;
if (state.save_settings_cb) {
ui_settings_t settings = state.save_settings_cb();
buf->reserve(buf->size() + settings.num_slots * 64);
for (int i = 0; i < settings.num_slots; i++) {
const ui_settings_slot_t* slot = &settings.slots[i];
buf->appendf("[%s][%s]\n", handler->TypeName, slot->window_title.buf);
if (slot->open) {
buf->append("IsOpen=1\n");
}
}
buf->append("\n");
}
}

static void register_imgui_settings_handler(void) {
const char* type_name = "floooh.chips";
ImGuiSettingsHandler ini_handler;
ini_handler.TypeName = type_name;;
ini_handler.TypeHash = ImHashStr(type_name);
ini_handler.ClearAllFn = imgui_ClearAllFn;
ini_handler.ReadInitFn = imgui_ReadInitFn;
ini_handler.ReadOpenFn = imgui_ReadOpenFn;
ini_handler.ReadLineFn = imgui_ReadLineFn;
ini_handler.ApplyAllFn = imgui_ApplyAllFn;
ini_handler.WriteAllFn = imgui_WriteAllFn;
ImGui::AddSettingsHandler(&ini_handler);
}
6 changes: 5 additions & 1 deletion examples/common/ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,25 @@
#include "sokol_gfx.h"
#include "sokol_imgui.h"
#include "chips/chips_common.h"
#include "ui/ui_settings.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef uint64_t ui_texture_t;

typedef void(*ui_draw_t)(void);
typedef void (*ui_draw_t)(void);
typedef ui_settings_t (*ui_save_settings_t)(void);

typedef struct {
ui_draw_t draw_cb;
ui_save_settings_t save_settings_cb;
const char* imgui_ini_key;
} ui_desc_t;

void ui_init(const ui_desc_t* desc);
const ui_settings_t* ui_settings(void);
void ui_discard(void);
void ui_draw(void);
bool ui_input(const sapp_event* event);
Expand Down
1 change: 1 addition & 0 deletions examples/sokol/atom-ui-impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "util/m6502dasm.h"
#define CHIPS_UI_IMPL
#include "imgui.h"
#include "ui/ui_settings.h"
#include "ui/ui_util.h"
#include "ui/ui_chip.h"
#include "ui/ui_memedit.h"
Expand Down
9 changes: 9 additions & 0 deletions examples/sokol/atom.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#if defined(CHIPS_USE_UI)
#define UI_DBG_USE_M6502
#include "ui.h"
#include "ui/ui_settings.h"
#include "ui/ui_chip.h"
#include "ui/ui_memedit.h"
#include "ui/ui_memmap.h"
Expand Down Expand Up @@ -59,6 +60,7 @@ static struct {

#ifdef CHIPS_USE_UI
static void ui_draw_cb(void);
static ui_settings_t ui_save_settings_cb(void);
static void ui_boot_cb(atom_t* sys);
static void ui_save_snapshot(size_t slot_index);
static bool ui_load_snapshot(size_t slot_index);
Expand Down Expand Up @@ -126,6 +128,7 @@ void app_init(void) {
#ifdef CHIPS_USE_UI
ui_init(&(ui_desc_t){
.draw_cb = ui_draw_cb,
.save_settings_cb = ui_save_settings_cb,
.imgui_ini_key = "floooh.chips.atom",
});
ui_atom_init(&state.ui, &(ui_atom_desc_t){
Expand All @@ -152,6 +155,7 @@ void app_init(void) {
.toggle_breakpoint = { .keycode = simgui_map_keycode(SAPP_KEYCODE_F9), .name = "F9" }
}
});
ui_atom_load_settings(&state.ui, ui_settings());
ui_load_snapshots_from_storage();
#endif
bool delay_input = false;
Expand Down Expand Up @@ -300,6 +304,11 @@ static void draw_status_bar(void) {
static void ui_draw_cb(void) {
ui_atom_draw(&state.ui);
}

static ui_settings_t ui_save_settings_cb(void) {
return ui_atom_save_settings(&state.ui);
}

static void ui_boot_cb(atom_t* sys) {
atom_desc_t desc = atom_desc(sys->joystick_type);
atom_init(sys, &desc);
Expand Down

0 comments on commit 5d7b19a

Please sign in to comment.