#pragma once #include "edge.h" #include "datatypes.h" #include "graph-manager.h" #include "signal-manager.h" #include "ui.h" #include #include #include #include class AppState{ public: AppState() : sm(&gm, &mutex), ui(&settings, &sm, &gm) {} enum States {IDLE, CONFIG}; AppSettings settings; States state; std::mutex mutex; GraphManager gm; SignalManager sm; AppUI ui; void updateMidiPorts(){ for(auto&n : gm.nodes | std::views::values){ for(auto& mo : sm.midi.midi_out_ports){ if(!n.midi_outs.contains(mo.number) && mo.enabled){ n.midi_outs[mo.number] = {mo.number, mo.port.port_name, false}; } if(n.midi_outs.contains(mo.number) && !mo.enabled){ n.midi_outs.erase(mo.number); } } } } void copyNodesAndConnections(Vec2D position){ auto copy_nodes_ids = gm.nodes | std::ranges::views::values | std::ranges::views::filter([](Node n){return n.copied;}) | std::views::transform([](Node n){return n.id;}) | std::ranges::to>(); std::vector copy_connections; std::ranges::copy_if(gm.connections, std::back_inserter(copy_connections), [copy_nodes_ids](Edge c){return std::ranges::contains(copy_nodes_ids, c.node_id_start) && std::ranges::contains(copy_nodes_ids, c.node_id_end);}); for(auto &n : copy_nodes_ids){ int old_id = n; int new_id = gm.copyNode(n, position + gm.nodes[n].drag_offset); gm.nodes[new_id].copied = false; gm.nodes[new_id].selected = true; for(auto &c : copy_connections){ if(c.node_id_start == old_id) c.node_id_start = new_id; if(c.node_id_end == old_id) c.node_id_end = new_id; } } gm.connections.insert(gm.connections.end(), copy_connections.cbegin(), copy_connections.cend()); } void removeNodes(){ for(auto &n : gm.nodes){ n.second.highlighted = false; } auto erase_nodes = gm.nodes | std::ranges::views::values | std::ranges::views::filter([](Node n){return n.erase;}); std::vector erase_nodes_ids; for(auto &e : erase_nodes){ erase_nodes_ids.push_back(e.id); } auto erase_connections = gm.connections | std::ranges::views::filter([erase_nodes_ids](Edge c){ return std::ranges::contains(erase_nodes_ids, c.node_id_start) || std::ranges::contains(erase_nodes_ids, c.node_id_end);}); std::vector adjacent_nodes_ids; for(auto &c : erase_connections){ if(!gm.nodes.at(c.node_id_start).selected) adjacent_nodes_ids.push_back(c.node_id_start); if(!gm.nodes.at(c.node_id_end).selected) adjacent_nodes_ids.push_back(c.node_id_end); } auto reroute_signals = sm.signals | std::ranges::views::filter([erase_nodes_ids](Signal s){ return std::ranges::contains(erase_nodes_ids, s.next); }); for(auto &s : reroute_signals){ float dist = 10000000; int next_id = -1; for(int i : adjacent_nodes_ids){ if(gm.nodes.at(i).position.dist(&s.position) < dist) { dist = gm.nodes.at(i).position.dist(&s.position); next_id = i; } } s.next = next_id; s.last = next_id; } auto rebase_signals = sm.signals | std::ranges::views::filter([erase_nodes_ids](Signal s){ return std::ranges::contains(erase_nodes_ids, s.start); }); for(auto &s : rebase_signals){ s.start = s.next; } for(auto &n : erase_nodes){ std::erase_if(gm.connections, [n](Edge c){ return c.node_id_start == n.id || c.node_id_end == n.id;}); } std::erase_if(gm.nodes, [](std::pair n){ return n.second.erase;}); gm.keys.clear(); std::ranges::copy(gm.nodes | std::ranges::views::keys, std::back_inserter(gm.keys)); } void draw(Vec2D *mouse_pos, Camera2D *camera){ mutex.lock(); updateMidiPorts(); mutex.unlock(); gm.drawNodes(mouse_pos, camera); gm.drawConnections(mouse_pos, camera); sm.drawSignals(mouse_pos, camera); } void drawUI(Vec2D *mouse_pos, Camera2D *camera){ mutex.lock(); ui.draw(mouse_pos, camera); mutex.unlock(); } };