forked from sudip-mondal-2002/Amplitron
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommand_graph.h
More file actions
180 lines (148 loc) · 5.77 KB
/
Copy pathcommand_graph.h
File metadata and controls
180 lines (148 loc) · 5.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#pragma once
#include "gui/command_base.h"
#include "audio/audio_engine.h"
#include "audio/audio_graph.h"
#include "gui/gui_graph_state.h"
namespace Amplitron {
using NodeId = int;
using EffectType = NodeRoutingType;
struct AddGraphNodeCommand : public Command {
AudioEngine& engine_;
NodeId node_id = -1; // Assigned on first execute
std::string name;
EffectType type;
std::shared_ptr<Effect> pedal;
ImVec2 position;
DSPNode cached_node; // To remember exactly what was added for redo
AddGraphNodeCommand(AudioEngine& engine, const std::string& name, EffectType type, std::shared_ptr<Effect> pedal, ImVec2 pos)
: engine_(engine), name(name), type(type), pedal(pedal), position(pos) {}
bool execute() override {
if (node_id == -1) {
node_id = engine_.graph().add_node(name, type, pedal);
auto* added_node = engine_.graph().find_node(node_id);
if (added_node) cached_node = *added_node;
} else {
// Re-adding the previously deleted/undone node
engine_.graph().restore_node(cached_node);
}
// Only write a fixed position when one was explicitly requested;
// if position is (0,0) the auto-placement logic in render_signal_chain
// will assign the correct cascading position on the next frame.
if (position.x != 0.0f || position.y != 0.0f) {
GuiGraphState::get_instance().node_positions[node_id] = { position, false, ImVec2(0, 0) };
}
engine_.commit_graph_changes();
return true;
}
void undo() override {
engine_.graph().remove_node(node_id);
GuiGraphState::get_instance().node_positions.erase(node_id);
engine_.commit_graph_changes();
}
const char* description() const override { return "Add Node"; }
};
struct RemoveGraphNodeCommand : public Command {
AudioEngine& engine_;
NodeId node_id;
EffectType type;
ImVec2 position;
std::vector<GraphLink> severed_links; // cache for undo
DSPNode cached_node; // full node data for exact restoration
RemoveGraphNodeCommand(AudioEngine& engine, NodeId id, EffectType t, ImVec2 pos)
: engine_(engine), node_id(id), type(t), position(pos) {}
bool execute() override {
auto* node_to_remove = engine_.graph().find_node(node_id);
if (node_to_remove) {
cached_node = *node_to_remove;
}
// Cache severed links before removal
severed_links.clear();
for (const auto& link : engine_.graph().get_links()) {
if (std::find(cached_node.input_pin_ids.begin(), cached_node.input_pin_ids.end(), link.dest_pin_id) != cached_node.input_pin_ids.end() ||
std::find(cached_node.output_pin_ids.begin(), cached_node.output_pin_ids.end(), link.source_pin_id) != cached_node.output_pin_ids.end()) {
severed_links.push_back(link);
}
}
engine_.graph().remove_node(node_id);
GuiGraphState::get_instance().node_positions.erase(node_id);
engine_.commit_graph_changes();
return true;
}
void undo() override {
engine_.graph().restore_node(cached_node);
GuiGraphState::get_instance().node_positions[node_id] = { position, false, ImVec2(0, 0) };
for (const auto& link : severed_links) {
engine_.graph().restore_link(link);
}
engine_.commit_graph_changes();
}
const char* description() const override { return "Remove Node"; }
};
struct AddGraphLinkCommand : public Command {
AudioEngine& engine_;
GraphLink link;
bool was_successful = false;
AddGraphLinkCommand(AudioEngine& engine, int src_pin, int dst_pin)
: engine_(engine) {
link.source_pin_id = src_pin;
link.dest_pin_id = dst_pin;
link.id = -1; // Unknown until execute
}
bool execute() override {
if (link.id == -1) {
link.id = engine_.graph().add_link(link.source_pin_id, link.dest_pin_id);
was_successful = (link.id != -1);
} else if (was_successful) {
engine_.graph().restore_link(link);
}
if (was_successful) {
engine_.commit_graph_changes();
}
return was_successful;
}
void undo() override {
if (was_successful) {
engine_.graph().remove_link(link.id);
engine_.commit_graph_changes();
}
}
const char* description() const override { return "Add Link"; }
};
struct RemoveGraphLinkCommand : public Command {
AudioEngine& engine_;
GraphLink link;
RemoveGraphLinkCommand(AudioEngine& engine, const GraphLink& l)
: engine_(engine), link(l) {}
bool execute() override {
engine_.graph().remove_link(link.id);
engine_.commit_graph_changes();
return true;
}
void undo() override {
engine_.graph().restore_link(link);
engine_.commit_graph_changes();
}
const char* description() const override { return "Remove Link"; }
};
struct MoveGraphNodeCommand : public Command {
NodeId node_id;
ImVec2 old_pos;
ImVec2 new_pos;
MoveGraphNodeCommand(NodeId id, ImVec2 old_pos, ImVec2 new_pos)
: node_id(id), old_pos(old_pos), new_pos(new_pos) {}
bool execute() override {
auto& positions = GuiGraphState::get_instance().node_positions;
if (positions.count(node_id)) {
positions[node_id].position = new_pos;
}
return true;
}
void undo() override {
auto& positions = GuiGraphState::get_instance().node_positions;
if (positions.count(node_id)) {
positions[node_id].position = old_pos;
}
}
const char* description() const override { return "Move Node"; }
};
} // namespace Amplitron