From d3dc4dbed941753d12cc33b40b34a36a0c63cf8f Mon Sep 17 00:00:00 2001 From: rexim Date: Sun, 4 Aug 2019 03:53:28 +0700 Subject: [PATCH] (#824) Integrate UndoHistory with the LevelEditor --- src/game/level/level_editor.c | 22 +++++++++++-- src/game/level/level_editor.h | 3 ++ src/game/level/level_editor/label_layer.c | 4 ++- src/game/level/level_editor/label_layer.h | 3 +- src/game/level/level_editor/layer.c | 12 ++++--- src/game/level/level_editor/layer.h | 6 +++- src/game/level/level_editor/player_layer.c | 5 +-- src/game/level/level_editor/player_layer.h | 3 +- src/game/level/level_editor/point_layer.c | 38 +++++++++++++++++++--- src/game/level/level_editor/point_layer.h | 3 +- src/game/level/level_editor/rect_layer.c | 6 +++- src/game/level/level_editor/rect_layer.h | 5 ++- src/game/level/level_editor/undo_history.c | 1 + src/game/level/level_editor/undo_history.h | 4 +-- 14 files changed, 91 insertions(+), 24 deletions(-) diff --git a/src/game/level/level_editor.c b/src/game/level/level_editor.c index 2f499283..f9de16b5 100644 --- a/src/game/level/level_editor.c +++ b/src/game/level/level_editor.c @@ -134,7 +134,10 @@ LevelEditor *create_level_editor(void) level_editor->layers[LAYER_PICKER_BACKGROUND] = color_picker_as_layer(&level_editor->background_layer); level_editor->layers[LAYER_PICKER_LABELS] = label_layer_as_layer(level_editor->label_layer); - level_editor->drag = false; + level_editor->undo_history = PUSH_LT( + lt, + create_undo_history(), + destroy_undo_history); level_editor->notice = (FadingWigglyText) { .wiggly_text = { @@ -289,6 +292,11 @@ LevelEditor *create_level_editor_from_file(const char *file_name) level_editor->layers[LAYER_PICKER_BACKGROUND] = color_picker_as_layer(&level_editor->background_layer); level_editor->layers[LAYER_PICKER_LABELS] = label_layer_as_layer(level_editor->label_layer); + level_editor->undo_history = PUSH_LT( + lt, + create_undo_history(), + destroy_undo_history); + level_editor->drag = false; level_editor->notice = (FadingWigglyText) { @@ -415,7 +423,7 @@ int level_editor_idle_event(LevelEditor *level_editor, switch (event->type) { case SDL_KEYDOWN: { - switch(event-> key.keysym.sym) { + switch(event->key.keysym.sym) { case SDLK_s: { if (!SDL_IsTextInputActive()) { if (level_editor->file_name) { @@ -427,6 +435,13 @@ int level_editor_idle_event(LevelEditor *level_editor, } } } break; + + case SDLK_z: { + if (event->key.keysym.mod & KMOD_CTRL) { + log_info("Undo\n"); + undo_history_pop(level_editor->undo_history); + } + } break; } } break; @@ -490,7 +505,8 @@ int level_editor_idle_event(LevelEditor *level_editor, if (layer_event( level_editor->layers[level_editor->layer_picker], event, - camera) < 0) { + camera, + level_editor->undo_history) < 0) { return -1; } } diff --git a/src/game/level/level_editor.h b/src/game/level/level_editor.h index ed86583b..d48a4ce0 100644 --- a/src/game/level/level_editor.h +++ b/src/game/level/level_editor.h @@ -3,6 +3,7 @@ #include "game/level/level_editor/layer.h" #include "game/level/level_editor/layer_picker.h" +#include "game/level/level_editor/undo_history.h" #include "ui/wiggly_text.h" typedef struct LevelMetadata LevelMetadata; @@ -41,6 +42,8 @@ struct LevelEditor LayerPtr layers[LAYER_PICKER_N]; + UndoHistory *undo_history; + bool drag; const char *file_name; diff --git a/src/game/level/level_editor/label_layer.c b/src/game/level/level_editor/label_layer.c index a0085b2d..9075503a 100644 --- a/src/game/level/level_editor/label_layer.c +++ b/src/game/level/level_editor/label_layer.c @@ -536,11 +536,13 @@ int label_layer_edit_id_event(LabelLayer *label_layer, int label_layer_event(LabelLayer *label_layer, const SDL_Event *event, - const Camera *camera) + const Camera *camera, + UndoHistory *undo_history) { trace_assert(label_layer); trace_assert(event); trace_assert(camera); + trace_assert(undo_history); int changed = 0; diff --git a/src/game/level/level_editor/label_layer.h b/src/game/level/level_editor/label_layer.h index 09924678..30c4d76b 100644 --- a/src/game/level/level_editor/label_layer.h +++ b/src/game/level/level_editor/label_layer.h @@ -24,7 +24,8 @@ int label_layer_render(const LabelLayer *label_layer, int active); int label_layer_event(LabelLayer *label_layer, const SDL_Event *event, - const Camera *camera); + const Camera *camera, + UndoHistory *undo_history); size_t label_layer_count(const LabelLayer *label_layer); diff --git a/src/game/level/level_editor/layer.c b/src/game/level/level_editor/layer.c index 783cec1a..87a01d0c 100644 --- a/src/game/level/level_editor/layer.c +++ b/src/game/level/level_editor/layer.c @@ -29,23 +29,25 @@ int layer_render(LayerPtr layer, Camera *camera, int active) int layer_event(LayerPtr layer, const SDL_Event *event, - const Camera *camera) + const Camera *camera, + UndoHistory *undo_history) { switch (layer.type) { case LAYER_RECT: - return rect_layer_event(layer.ptr, event, camera); + return rect_layer_event(layer.ptr, event, camera, undo_history); case LAYER_POINT: - return point_layer_event(layer.ptr, event, camera); + return point_layer_event(layer.ptr, event, camera, undo_history); case LAYER_PLAYER: - return player_layer_event(layer.ptr, event, camera); + return player_layer_event(layer.ptr, event, camera, undo_history); case LAYER_COLOR_PICKER: + // TODO: undo history is not really applicable to color picker as layer return color_picker_event(layer.ptr, event, NULL); case LAYER_LABEL: - return label_layer_event(layer.ptr, event, camera); + return label_layer_event(layer.ptr, event, camera, undo_history); } return -1; diff --git a/src/game/level/level_editor/layer.h b/src/game/level/level_editor/layer.h index e0b55a11..f3678fe0 100644 --- a/src/game/level/level_editor/layer.h +++ b/src/game/level/level_editor/layer.h @@ -15,9 +15,13 @@ typedef struct { } LayerPtr; typedef struct Camera Camera; +typedef struct UndoHistory UndoHistory; int layer_render(LayerPtr layer, Camera *camera, int active); -int layer_event(LayerPtr layer, const SDL_Event *event, const Camera *camera); +int layer_event(LayerPtr layer, + const SDL_Event *event, + const Camera *camera, + UndoHistory *undo_history); int layer_dump_stream(LayerPtr layer, FILE *stream); #endif // LAYER_H_ diff --git a/src/game/level/level_editor/player_layer.c b/src/game/level/level_editor/player_layer.c index 37955e1d..885bc785 100644 --- a/src/game/level/level_editor/player_layer.c +++ b/src/game/level/level_editor/player_layer.c @@ -76,12 +76,13 @@ int player_layer_render(const PlayerLayer *player_layer, int player_layer_event(PlayerLayer *player_layer, const SDL_Event *event, - const Camera *camera) + const Camera *camera, + UndoHistory *undo_history) { trace_assert(player_layer); trace_assert(event); trace_assert(camera); - + trace_assert(undo_history); int selected = 0; if (color_picker_event( diff --git a/src/game/level/level_editor/player_layer.h b/src/game/level/level_editor/player_layer.h index 63cc7c03..50ec08ff 100644 --- a/src/game/level/level_editor/player_layer.h +++ b/src/game/level/level_editor/player_layer.h @@ -20,7 +20,8 @@ int player_layer_render(const PlayerLayer *player_layer, int active); int player_layer_event(PlayerLayer *player_layer, const SDL_Event *event, - const Camera *camera); + const Camera *camera, + UndoHistory *undo_history); int player_layer_dump_stream(const PlayerLayer *player_layer, FILE *filedump); diff --git a/src/game/level/level_editor/point_layer.c b/src/game/level/level_editor/point_layer.c index f59f4e18..1bb70cfa 100644 --- a/src/game/level/level_editor/point_layer.c +++ b/src/game/level/level_editor/point_layer.c @@ -14,6 +14,7 @@ #include "./point_layer.h" #include "math/extrema.h" #include "./color_picker.h" +#include "undo_history.h" #define POINT_LAYER_ELEMENT_RADIUS 10.0f #define POINT_LAYER_ID_TEXT_SIZE vec(2.0f, 2.0f) @@ -219,12 +220,27 @@ int point_layer_element_at(const PointLayer *point_layer, return -1; } +static +void point_layer_pop_element(void *layer, Context context) +{ + trace_assert(layer); + (void) context; + + PointLayer *point_layer = layer; + + dynarray_pop(point_layer->positions, NULL); + dynarray_pop(point_layer->colors, NULL); + dynarray_pop(point_layer->ids, NULL); +} + static int point_layer_add_element(PointLayer *point_layer, Point position, - Color color) + Color color, + UndoHistory *undo_history) { trace_assert(point_layer); + trace_assert(undo_history); char id[ID_MAX_SIZE]; for (size_t i = 0; i < ID_MAX_SIZE - 1; ++i) { @@ -236,6 +252,12 @@ int point_layer_add_element(PointLayer *point_layer, dynarray_push(point_layer->colors, &color); dynarray_push(point_layer->ids, id); + Action action = { + .revert = point_layer_pop_element, + .layer = point_layer + }; + undo_history_push(undo_history, action); + return 0; } @@ -252,7 +274,8 @@ void point_layer_delete_nth_element(PointLayer *point_layer, static int point_layer_idle_event(PointLayer *point_layer, const SDL_Event *event, - const Camera *camera) + const Camera *camera, + UndoHistory *undo_history) { trace_assert(point_layer); trace_assert(event); @@ -287,7 +310,10 @@ int point_layer_idle_event(PointLayer *point_layer, if (point_layer->selected < 0) { point_layer_add_element( - point_layer, position, color_picker_rgba(&point_layer->color_picker)); + point_layer, + position, + color_picker_rgba(&point_layer->color_picker), + undo_history); } else { Color *colors = dynarray_data(point_layer->colors); point_layer->state = POINT_LAYER_MOVE; @@ -390,15 +416,17 @@ int point_layer_move_event(PointLayer *point_layer, int point_layer_event(PointLayer *point_layer, const SDL_Event *event, - const Camera *camera) + const Camera *camera, + UndoHistory *undo_history) { trace_assert(point_layer); trace_assert(event); trace_assert(camera); + trace_assert(undo_history); switch (point_layer->state) { case POINT_LAYER_IDLE: - return point_layer_idle_event(point_layer, event, camera); + return point_layer_idle_event(point_layer, event, camera, undo_history); case POINT_LAYER_EDIT_ID: return point_layer_edit_id_event(point_layer, event, camera); diff --git a/src/game/level/level_editor/point_layer.h b/src/game/level/level_editor/point_layer.h index 83d6032c..db06743f 100644 --- a/src/game/level/level_editor/point_layer.h +++ b/src/game/level/level_editor/point_layer.h @@ -21,7 +21,8 @@ int point_layer_render(const PointLayer *point_layer, int active); int point_layer_event(PointLayer *point_layer, const SDL_Event *event, - const Camera *camera); + const Camera *camera, + UndoHistory *undo_history); int point_layer_dump_stream(const PointLayer *point_layer, FILE *filedump); diff --git a/src/game/level/level_editor/rect_layer.c b/src/game/level/level_editor/rect_layer.c index 118a63e6..d9ddcc04 100644 --- a/src/game/level/level_editor/rect_layer.c +++ b/src/game/level/level_editor/rect_layer.c @@ -516,10 +516,14 @@ int rect_layer_render(const RectLayer *layer, Camera *camera, int active) return 0; } -int rect_layer_event(RectLayer *layer, const SDL_Event *event, const Camera *camera) +int rect_layer_event(RectLayer *layer, + const SDL_Event *event, + const Camera *camera, + UndoHistory *undo_history) { trace_assert(layer); trace_assert(event); + trace_assert(undo_history); int selected = 0; if (color_picker_event(&layer->color_picker, event, &selected) < 0) { diff --git a/src/game/level/level_editor/rect_layer.h b/src/game/level/level_editor/rect_layer.h index 89353e4d..48e53caa 100644 --- a/src/game/level/level_editor/rect_layer.h +++ b/src/game/level/level_editor/rect_layer.h @@ -12,7 +12,10 @@ RectLayer *create_rect_layer_from_line_stream(LineStream *line_stream); void destroy_rect_layer(RectLayer *layer); int rect_layer_render(const RectLayer *layer, Camera *camera, int active); -int rect_layer_event(RectLayer *layer, const SDL_Event *event, const Camera *camera); +int rect_layer_event(RectLayer *layer, + const SDL_Event *event, + const Camera *camera, + UndoHistory *undo_history); int rect_layer_dump_stream(const RectLayer *layer, FILE *filedump); diff --git a/src/game/level/level_editor/undo_history.c b/src/game/level/level_editor/undo_history.c index ce666623..d69619e3 100644 --- a/src/game/level/level_editor/undo_history.c +++ b/src/game/level/level_editor/undo_history.c @@ -22,6 +22,7 @@ UndoHistory *create_undo_history(void) lt, nth_calloc(1, sizeof(UndoHistory)), free); + undo_history->lt = lt; undo_history->actions = PUSH_LT( lt, diff --git a/src/game/level/level_editor/undo_history.h b/src/game/level/level_editor/undo_history.h index 7a119f1e..953bc1cd 100644 --- a/src/game/level/level_editor/undo_history.h +++ b/src/game/level/level_editor/undo_history.h @@ -9,10 +9,10 @@ typedef struct { char data[CONTEXT_SIZE]; } Context; -typedef void (*RevertAction)(LayerPtr layer, Context context); +typedef void (*RevertAction)(void *layer, Context context); typedef struct { - LayerPtr layer; + void *layer; Context context; RevertAction revert; } Action; -- 2.44.0