Skip to content

Commit 4f41c1b

Browse files
Image use key to know if it changed
I do that so that I can disable the save menu if the image hasn't been changed. This is cleaner than having a 'dirty' attribute I think, but I am a bit worried this might be a bit slow since it forces us to recompute the key at each iteration. If this pose problem in the future I'll remove it.
1 parent 5f7f707 commit 4f41c1b

File tree

5 files changed

+80
-18
lines changed

5 files changed

+80
-18
lines changed

src/camera.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,18 @@ void camera_fit_box(camera_t *cam, const float box[4][4])
150150
// XXX: not the proper way to compute the distance.
151151
cam->dist = max3(size[0], size[1], size[2]) * 8;
152152
}
153+
154+
/*
155+
* Function: camera_get_key
156+
* Return a value that is guarantied to change when the camera change.
157+
*/
158+
uint64_t camera_get_key(const camera_t *cam)
159+
{
160+
uint64_t key = 0;
161+
key = crc64(key, &cam->name, sizeof(cam->name));
162+
key = crc64(key, &cam->ortho, sizeof(cam->ortho));
163+
key = crc64(key, &cam->dist, sizeof(cam->dist));
164+
key = crc64(key, &cam->rot, sizeof(cam->rot));
165+
key = crc64(key, &cam->ofs, sizeof(cam->ofs));
166+
return key;
167+
}

src/formats/gox.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ int load_from_file(const char *path)
537537
}
538538

539539
goxel->image->path = strdup(path);
540+
goxel->image->saved_key = image_get_key(goxel->image);
540541
goxel_update_meshes(-1);
541542
gzclose(in);
542543

@@ -582,6 +583,7 @@ static void save_as(const char *path, bool with_preview)
582583
if (path != goxel->image->path) {
583584
free(goxel->image->path);
584585
goxel->image->path = strdup(path);
586+
goxel->image->saved_key = image_get_key(goxel->image);
585587
}
586588
save_to_file(goxel->image->path, with_preview);
587589
}

src/goxel.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,6 +1462,12 @@ void camera_get_ray(const camera_t *camera, const float win[2],
14621462
*/
14631463
void camera_fit_box(camera_t *camera, const float box[4][4]);
14641464

1465+
/*
1466+
* Function: camera_get_key
1467+
* Return a value that is guarantied to change when the camera change.
1468+
*/
1469+
uint64_t camera_get_key(const camera_t *camera);
1470+
14651471
typedef struct history history_t;
14661472

14671473
typedef struct layer layer_t;
@@ -1489,9 +1495,10 @@ struct image {
14891495
float box[4][4];
14901496

14911497
// For saving.
1492-
char *path;
1493-
int export_width;
1494-
int export_height;
1498+
char *path;
1499+
int export_width;
1500+
int export_height;
1501+
uint64_t saved_key; // image_get_key() value of saved file.
14951502

14961503
image_t *history;
14971504
image_t *history_next, *history_prev;
@@ -1509,6 +1516,12 @@ void image_undo(image_t *img);
15091516
void image_redo(image_t *img);
15101517
bool image_layer_can_edit(const image_t *img, const layer_t *layer);
15111518

1519+
/*
1520+
* Function: image_get_key
1521+
* Return a value that is guarantied to change when the image change.
1522+
*/
1523+
uint64_t image_get_key(const image_t *img);
1524+
15121525
// ##### Procedural rendering ########################
15131526

15141527
// The possible states of the procedural program.

src/gui.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,11 +1063,11 @@ static int export_menu_action_callback(action_t *a, void *user)
10631063
return 0;
10641064
}
10651065

1066-
static bool render_menu_item(const char *id, const char *label)
1066+
static bool render_menu_item(const char *id, const char *label, bool enabled)
10671067
{
10681068
const action_t *action = action_get(id);
10691069
assert(action);
1070-
if (ImGui::MenuItem(label, action->shortcut)) {
1070+
if (ImGui::MenuItem(label, action->shortcut, false, enabled)) {
10711071
action_exec(action, "");
10721072
return true;
10731073
}
@@ -1081,9 +1081,10 @@ static void render_menu(void)
10811081

10821082
if (!ImGui::BeginMenuBar()) return;
10831083
if (ImGui::BeginMenu("File")) {
1084-
render_menu_item("save", "Save");
1085-
render_menu_item("save_as", "Save as");
1086-
render_menu_item("open", "Open");
1084+
render_menu_item("save", "Save",
1085+
image_get_key(goxel->image) != goxel->image->saved_key);
1086+
render_menu_item("save_as", "Save as", true);
1087+
render_menu_item("open", "Open", true);
10871088
if (ImGui::BeginMenu("Import...")) {
10881089
if (ImGui::MenuItem("image plane")) import_image_plane(goxel);
10891090
actions_iter(import_menu_action_callback, NULL);
@@ -1093,16 +1094,16 @@ static void render_menu(void)
10931094
actions_iter(export_menu_action_callback, NULL);
10941095
ImGui::EndMenu();
10951096
}
1096-
render_menu_item("quit", "Quit");
1097+
render_menu_item("quit", "Quit", true);
10971098
ImGui::EndMenu();
10981099
}
10991100
if (ImGui::BeginMenu("Edit")) {
11001101
if (ImGui::MenuItem("Clear", "Delete"))
11011102
action_exec2("layer_clear", "");
1102-
render_menu_item("undo", "Undo");
1103-
render_menu_item("redo", "Redo");
1104-
render_menu_item("copy", "Copy");
1105-
render_menu_item("past", "Past");
1103+
render_menu_item("undo", "Undo", true);
1104+
render_menu_item("redo", "Redo", true);
1105+
render_menu_item("copy", "Copy", true);
1106+
render_menu_item("past", "Past", true);
11061107
if (ImGui::MenuItem("Shift Alpha"))
11071108
gui_open_popup("Shift Alpha", 0, NULL, shift_alpha_popup);
11081109
if (ImGui::MenuItem("Settings"))
@@ -1111,11 +1112,11 @@ static void render_menu(void)
11111112
ImGui::EndMenu();
11121113
}
11131114
if (ImGui::BeginMenu("View")) {
1114-
render_menu_item("view_left", "Left");
1115-
render_menu_item("view_right", "Right");
1116-
render_menu_item("view_front", "Front");
1117-
render_menu_item("view_top", "Top");
1118-
render_menu_item("view_default", "Default");
1115+
render_menu_item("view_left", "Left", true);
1116+
render_menu_item("view_right", "Right", true);
1117+
render_menu_item("view_front", "Front", true);
1118+
render_menu_item("view_top", "Top", true);
1119+
render_menu_item("view_default", "Default", true);
11191120
ImGui::EndMenu();
11201121
}
11211122
if (ImGui::BeginMenu("Help")) {

src/image.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,17 @@ static void layer_delete(layer_t *layer)
134134
free(layer);
135135
}
136136

137+
static uint64_t layer_get_key(const layer_t *layer)
138+
{
139+
uint64_t key;
140+
key = mesh_get_key(layer->mesh);
141+
key = crc64(key, &layer->visible, sizeof(layer->visible));
142+
key = crc64(key, &layer->name, sizeof(layer->name));
143+
key = crc64(key, &layer->box, sizeof(layer->box));
144+
key = crc64(key, &layer->mat, sizeof(layer->mat));
145+
return key;
146+
}
147+
137148
image_t *image_new(void)
138149
{
139150
layer_t *layer;
@@ -470,6 +481,26 @@ bool image_layer_can_edit(const image_t *img, const layer_t *layer)
470481
return !layer->base_id && !layer->image;
471482
}
472483

484+
/*
485+
* Function: image_get_key
486+
* Return a value that is garantied to change when the image change.
487+
*/
488+
uint64_t image_get_key(const image_t *img)
489+
{
490+
uint64_t key = 0, k;
491+
layer_t *layer;
492+
camera_t *camera;
493+
DL_FOREACH(img->layers, layer) {
494+
k = layer_get_key(layer);
495+
key = crc64(key, &k, sizeof(k));
496+
}
497+
DL_FOREACH(img->cameras, camera) {
498+
k = camera_get_key(camera);
499+
key = crc64(key, &k, sizeof(k));
500+
}
501+
return key;
502+
}
503+
473504
ACTION_REGISTER(layer_clear,
474505
.help = "Clear the current layer",
475506
.cfunc = image_clear_layer,

0 commit comments

Comments
 (0)