undo.h 2.65 KB
Newer Older
TheNumbat's avatar
TheNumbat committed
1
2
3
4
5
6
7

#pragma once

#include <memory>
#include <stack>

#include "../gui/widgets.h"
TheNumbat's avatar
TheNumbat committed
8
#include "scene.h"
TheNumbat's avatar
TheNumbat committed
9

TheNumbat's avatar
TheNumbat committed
10
11
12
13
14
namespace Gui {
class Manager;
class Anim_Camera;
class Rig;
} // namespace Gui
TheNumbat's avatar
TheNumbat committed
15
16
17
18
19

class Action_Base {
    virtual void undo() = 0;
    virtual void redo() = 0;
    friend class Undo;
TheNumbat's avatar
TheNumbat committed
20

TheNumbat's avatar
TheNumbat committed
21
22
23
24
public:
    virtual ~Action_Base() = default;
};

TheNumbat's avatar
TheNumbat committed
25
26
template <typename T> 
class MeshOp : public Action_Base {
TheNumbat's avatar
TheNumbat committed
27
    void undo() {
TheNumbat's avatar
TheNumbat committed
28
        Scene_Object &obj = scene.get_obj(id);
TheNumbat's avatar
TheNumbat committed
29
30
31
        obj.set_mesh(mesh);
    }
    void redo() {
TheNumbat's avatar
TheNumbat committed
32
        Scene_Object &obj = scene.get_obj(id);
TheNumbat's avatar
TheNumbat committed
33
34
        auto sel = obj.set_mesh(mesh, eid);
        op(obj.get_mesh(), sel);
TheNumbat's avatar
TheNumbat committed
35
        obj.get_mesh().do_erase();
TheNumbat's avatar
TheNumbat committed
36
    }
TheNumbat's avatar
TheNumbat committed
37
    Scene &scene;
TheNumbat's avatar
TheNumbat committed
38
39
40
41
    Scene_ID id;
    unsigned int eid;
    T op;
    Halfedge_Mesh mesh;
TheNumbat's avatar
TheNumbat committed
42

TheNumbat's avatar
TheNumbat committed
43
public:
TheNumbat's avatar
TheNumbat committed
44
45
    MeshOp(Scene &s, Scene_ID i, unsigned int e, Halfedge_Mesh &&m, T &&t)
        : scene(s), id(i), eid(e), op(t), mesh(std::move(m)) {}
TheNumbat's avatar
TheNumbat committed
46
47
48
49
50
    ~MeshOp() = default;
};

class Undo {
public:
TheNumbat's avatar
TheNumbat committed
51
    Undo(Scene &scene, Gui::Manager &man);
TheNumbat's avatar
TheNumbat committed
52
53

    // These could just take Scene_Object&& but this was easier
TheNumbat's avatar
TheNumbat committed
54
55
56
    Scene_Object &add_obj(GL::Mesh &&mesh, std::string name);
    Scene_Object &add_obj(Halfedge_Mesh &&mesh, std::string name);
    void add_light(Scene_Light &&mesh);
TheNumbat's avatar
TheNumbat committed
57
58
59
60

    void del_obj(Scene_ID id);
    void update_pose(Scene_ID id, Pose old);

TheNumbat's avatar
TheNumbat committed
61
62
63
64
    void del_bone(Scene_ID id, Joint *j);
    void add_bone(Scene_ID id, Joint *j);
    void move_bone(Scene_ID id, Joint *j, Vec3 old);
    void pose_bone(Scene_ID id, Joint *j, Vec3 old);
TheNumbat's avatar
TheNumbat committed
65
66
67
68
69
    void move_root(Scene_ID id, Vec3 old);

    void update_light(Scene_ID id, Scene_Light::Options old);
    void update_object(Scene_ID id, Scene_Object::Options old);
    void update_material(Scene_ID id, Material::Options old);
TheNumbat's avatar
TheNumbat committed
70
    void update_camera(Gui::Widget_Camera &widget, Camera old);
TheNumbat's avatar
TheNumbat committed
71

TheNumbat's avatar
TheNumbat committed
72
73
    template <typename T>
    void update_mesh(Scene_ID id, Halfedge_Mesh &&old, unsigned int e_id, T &&op) {
TheNumbat's avatar
TheNumbat committed
74
75
76
77
        std::stack<std::unique_ptr<Action_Base>> empty;
        redos.swap(empty);
        undos.push(std::make_unique<MeshOp<T>>(scene, id, e_id, std::move(old), std::move(op)));
    }
TheNumbat's avatar
TheNumbat committed
78
    void update_mesh_full(Scene_ID id, Halfedge_Mesh &&old_mesh);
TheNumbat's avatar
TheNumbat committed
79
80
81

    void anim_pose(Scene_ID id, float t);
    void anim_pose_bones(Scene_ID id, float t);
TheNumbat's avatar
TheNumbat committed
82
    void anim_camera(Gui::Anim_Camera &anim, float t, const Camera &cam);
TheNumbat's avatar
TheNumbat committed
83
84
85
86
87
88
89
    void anim_light(Scene_ID id, float t);

    void undo();
    void redo();
    void reset();

private:
TheNumbat's avatar
TheNumbat committed
90
91
92
93
94
    Scene &scene;
    Gui::Manager &gui;

    template <typename R, typename U> void action(R &&redo, U &&undo);
    void action(std::unique_ptr<Action_Base> &&action);
TheNumbat's avatar
TheNumbat committed
95
96
97
98

    std::stack<std::unique_ptr<Action_Base>> undos;
    std::stack<std::unique_ptr<Action_Base>> redos;
};