Skip to content

Commit

Permalink
feat(ui): Allow a single instance only for input and output nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
mfep committed Apr 20, 2024
1 parent 9921a7e commit e473193
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 17 deletions.
36 changes: 24 additions & 12 deletions src/NodeEditor.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "NodeEditor.hpp"

#include <algorithm>
#include <string_view>

#include "imgui.h"
Expand All @@ -25,6 +26,24 @@ constexpr std::string_view contex_popup_name = "NodeEditorContextMenu";

namespace mc
{
namespace
{

template <class MidiInfo>
std::vector<MidiInfo> filter_to_non_instantiated_midi_infos(
NodeFactory& factory, const std::vector<MidiInfo>& unfiltered_infos)
{
std::vector<MidiInfo> ret;
std::copy_if(unfiltered_infos.begin(),
unfiltered_infos.end(),
std::back_inserter(ret),
[&](const auto& info) {
return !factory.is_node_instantiated(info);
});
return ret;
}

} // namespace

NodeEditor::NodeEditor(NodeFactory& node_factory,
const PortNameDisplay& port_name_display,
Expand Down Expand Up @@ -133,16 +152,7 @@ std::shared_ptr<Node> NodeEditor::renderContextMenu(bool show_outputting_nodes,
ImGui::TreeNodeEx(port_name.c_str(), leaf_flags);
if (ImGui::IsItemClicked())
{
std::shared_ptr<Node> node;
if constexpr (std::is_same_v<midi::InputInfo, std::decay_t<decltype(info)>>)
{
node = m_node_factory->build_midi_node(info);
}
else
{
node = m_node_factory->build_midi_node(info);
}

std::shared_ptr<Node> node = m_node_factory->build_midi_node(info);
m_nodes.push_back(node);

ImNodes::SetNodeScreenSpacePos(node->id(),
Expand All @@ -161,8 +171,10 @@ std::shared_ptr<Node> NodeEditor::renderContextMenu(bool show_outputting_nodes,
{
if (ImGui::IsWindowAppearing())
{
m_input_infos = midi::MidiProbe::get_inputs();
m_output_infos = midi::MidiProbe::get_outputs();
m_input_infos = filter_to_non_instantiated_midi_infos(*m_node_factory,
midi::MidiProbe::get_inputs());
m_output_infos = filter_to_non_instantiated_midi_infos(*m_node_factory,
midi::MidiProbe::get_outputs());
}
if (show_outputting_nodes || show_inputting_nodes)
{
Expand Down
39 changes: 34 additions & 5 deletions src/NodeFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,35 @@ std::shared_ptr<MidiNode> get_cached_midi_node(
{
std::shared_ptr<MidiNode> midi_node_ptr;
auto found_it = node_map.find(info.m_id);
if (found_it == node_map.end() || (found_it->second.expired()))
if (found_it == node_map.end())
{
return nullptr;
}
else if (auto midi_node_ptr = found_it->second.lock(); midi_node_ptr == nullptr)
{
node_map.erase(found_it);
return nullptr;
}
else
{
return midi_node_ptr;
}
}

template <class MidiNode, class MidiInfo>
std::shared_ptr<MidiNode> make_cached_midi_node(
std::map<std::size_t, std::weak_ptr<MidiNode>>& node_map, const MidiInfo& info)
{
if (auto midi_node_ptr = get_cached_midi_node(node_map, info); midi_node_ptr == nullptr)
{
midi_node_ptr = std::make_shared<MidiNode>(info);
node_map.emplace(std::make_pair(info.m_id, midi_node_ptr));
return midi_node_ptr;
}
else
{
midi_node_ptr = found_it->second.lock();
return midi_node_ptr;
}
return midi_node_ptr;
}

} // namespace
Expand All @@ -43,13 +62,13 @@ NodeFactory::NodeFactory(const ThemeControl& theme_control,
std::shared_ptr<MidiInNode> NodeFactory::build_midi_node(const midi::InputInfo& input_info)
{
return std::make_shared<MidiInNode>(
input_info, get_cached_midi_node(m_input_nodes, input_info), *m_port_name_display);
input_info, make_cached_midi_node(m_input_nodes, input_info), *m_port_name_display);
}

std::shared_ptr<MidiOutNode> NodeFactory::build_midi_node(const midi::OutputInfo& output_info)
{
return std::make_shared<MidiOutNode>(
output_info, get_cached_midi_node(m_output_nodes, output_info), *m_port_name_display);
output_info, make_cached_midi_node(m_output_nodes, output_info), *m_port_name_display);
}

std::shared_ptr<DisconnectedMidiInNode> NodeFactory::build_disconnected_midi_in_node(
Expand All @@ -71,4 +90,14 @@ std::shared_ptr<MidiChannelNode> NodeFactory::build_midi_channel_node()
});
}

bool NodeFactory::is_node_instantiated(const midi::InputInfo& input_info)
{
return nullptr != get_cached_midi_node(m_input_nodes, input_info);
}

bool NodeFactory::is_node_instantiated(const midi::OutputInfo& output_info)
{
return nullptr != get_cached_midi_node(m_output_nodes, output_info);
}

} // namespace mc
3 changes: 3 additions & 0 deletions src/NodeFactory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ class NodeFactory final
const std::string& output_name);
std::shared_ptr<MidiChannelNode> build_midi_channel_node();

bool is_node_instantiated(const midi::InputInfo& input_info);
bool is_node_instantiated(const midi::OutputInfo& output_info);

private:
const ThemeControl* m_theme_control;
const PortNameDisplay* m_port_name_display;
Expand Down

0 comments on commit e473193

Please sign in to comment.