@@ -91,29 +91,36 @@ void PedalBoard::render_signal_chain() {
9191 ui_state.node_positions .erase (id);
9292 }
9393
94- // Give all new nodes a default position at the end of the chain without shifting existing nodes
94+ // Give new nodes a default position at the end, unless they have saved coordinates
9595 for (const auto & node : audio_graph.get_nodes ()) {
9696 if (ui_state.node_positions .find (node.id ) == ui_state.node_positions .end ()) {
97- float max_right = 40 .0f ;
98- for (const auto & existing_node : audio_graph.get_nodes ()) {
99- auto pos_it = ui_state.node_positions .find (existing_node.id );
100- if (pos_it != ui_state.node_positions .end ()) {
101- float width = 110 .0f ;
102- if (existing_node.routing_type == NodeRoutingType::StandardEffect) {
103- if (existing_node.pedal && std::strcmp (existing_node.pedal ->name (), " MultiBand Compressor" ) == 0 ) {
104- width = 190 .0f * 2 .2f ;
105- } else {
106- width = 190 .0f ;
97+ if (node.x != 0 .0f || node.y != 0 .0f ) {
98+ ui_state.node_positions [node.id ] = { ImVec2 (node.x , node.y ), false };
99+ } else {
100+ float max_right = 40 .0f ;
101+ for (const auto & existing_node : audio_graph.get_nodes ()) {
102+ auto pos_it = ui_state.node_positions .find (existing_node.id );
103+ if (pos_it != ui_state.node_positions .end ()) {
104+ float width = 110 .0f ;
105+ if (existing_node.routing_type == NodeRoutingType::StandardEffect) {
106+ if (existing_node.pedal && std::strcmp (existing_node.pedal ->name (), " MultiBand Compressor" ) == 0 ) {
107+ width = 190 .0f * 2 .2f ;
108+ } else {
109+ width = 190 .0f ;
110+ }
111+ }
112+ float right_edge = pos_it->second .position .x + width;
113+ if (right_edge > max_right) {
114+ max_right = right_edge;
107115 }
108- }
109- float right_edge = pos_it->second .position .x + width;
110- if (right_edge > max_right) {
111- max_right = right_edge;
112116 }
113117 }
118+ float insert_x = ui_state.node_positions .empty () ? 40 .0f : max_right + 80 .0f ;
119+ ui_state.node_positions [node.id ] = { ImVec2 (insert_x, 60 .0f ), false };
114120 }
115- float insert_x = ui_state.node_positions .empty () ? 40 .0f : max_right + 80 .0f ;
116- ui_state.node_positions [node.id ] = { ImVec2 (insert_x, 60 .0f ), false };
121+ } else {
122+ // Write manual dragging updates back to the audio engine so they serialize correctly
123+ audio_graph.set_node_position (node.id , ui_state.node_positions [node.id ].position .x , ui_state.node_positions [node.id ].position .y );
117124 }
118125 }
119126
@@ -286,8 +293,8 @@ void PedalBoard::render_signal_chain() {
286293 // ====================================================================
287294 // THE DELETION [X] BUTTON
288295 // ====================================================================
289- bool is_amp = ( node.name == " Amp Sim " ) ;
290- bool is_input_node = (node.name == " Input" );
296+ bool is_amp = node.is_graph_output ;
297+ bool is_input_node = node. is_graph_input || (node.name == " Input" );
291298
292299 if (!is_amp && !is_input_node) {
293300 ImVec2 cross_pos = ImVec2 (node_screen_pos.x + node_width - 24 .0f * ui_state.zoom , node_screen_pos.y + 4 .0f * ui_state.zoom );
0 commit comments