diff --git a/lib/imgui-node-editor b/lib/imgui-node-editor index acd0b3bc..9ef2040f 160000 --- a/lib/imgui-node-editor +++ b/lib/imgui-node-editor @@ -1 +1 @@ -Subproject commit acd0b3bcf4fb4aac64787268a51a31157076dc04 +Subproject commit 9ef2040f56c771ab5c7c89398d3d39c69c1ce607 diff --git a/src/Cool/ImGui/ImGuiExtras.cpp b/src/Cool/ImGui/ImGuiExtras.cpp index 3d801de3..5d19578e 100644 --- a/src/Cool/ImGui/ImGuiExtras.cpp +++ b/src/Cool/ImGui/ImGuiExtras.cpp @@ -17,16 +17,26 @@ namespace Cool::ImGuiExtras { void help_marker(const char* text) { ImGui::SameLine(); - ImGui::TextDisabled(" " ICOMOON_INFO); + help_marker_icon(); if (ImGui::BeginItemTooltip()) { - ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.f); - ImGui::TextUnformatted(text); - ImGui::PopTextWrapPos(); + help_marker_tooltip_content(text); ImGui::EndTooltip(); } } +void help_marker_icon() +{ + ImGui::TextDisabled(" " ICOMOON_INFO); +} + +void help_marker_tooltip_content(const char* text) +{ + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.f); + ImGui::TextUnformatted(text); + ImGui::PopTextWrapPos(); +} + bool angle_wheel(const char* label, float* value_p, int number_of_snaps, float snaps_offset, bool always_snap) { static constexpr float thickness = 2.0f; diff --git a/src/Cool/ImGui/ImGuiExtras.h b/src/Cool/ImGui/ImGuiExtras.h index 7842a86b..c98e92fa 100644 --- a/src/Cool/ImGui/ImGuiExtras.h +++ b/src/Cool/ImGui/ImGuiExtras.h @@ -6,9 +6,14 @@ namespace Cool::ImGuiExtras { -/// A small "?" that displays some text when hovered. +/// A small info icon that displays some text when hovered. void help_marker(const char* text); +/// A building block for help_marker(). In most cases you should just use help_marker(). This is only needed when you need to customize how help_marker() is rendered. +void help_marker_icon(); +/// A building block for help_marker(). In most cases you should just use help_marker(). This is only needed when you need to customize how help_marker() is rendered. +void help_marker_tooltip_content(const char* text); + /// A widget to pick an angle (in radians), displayed as a direction on a wheel /// When SHIFT is pressed (or `always_snap` is set to true) the angle will snap to some precise angles. `number_of_snaps` controls the number of such angles, and `snaps_offset` will offset these. /// `number_of_snaps` must be >= 1. `snaps_offset` is expressed in radians. diff --git a/src/Cool/Nodes/EditorImpl.cpp b/src/Cool/Nodes/EditorImpl.cpp index 7313bebc..6ad0ec62 100644 --- a/src/Cool/Nodes/EditorImpl.cpp +++ b/src/Cool/Nodes/EditorImpl.cpp @@ -5,6 +5,7 @@ #include "Cool/DebugOptions/DebugOptions.h" #include "Cool/ImGui/Fonts.h" #include "Cool/ImGui/IcoMoonCodepoints.h" +#include "Cool/ImGui/ImGuiExtras.h" #include "Cool/ImGui/ImGuiExtrasStyle.h" #include "Cool/ImGui/icon_fmt.h" #include "Cool/Nodes/EditorImpl.h" @@ -324,6 +325,13 @@ static auto output_pin_icon(size_t pin_index) : ax::Drawing::IconType::Circle; } +void NodesEditorImpl::help_marker_for_pin(std::string text) +{ + ImGuiExtras::help_marker_icon(); + if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip)) + _deferred_tooltip_text = std::move(text); // HACK don't create the tooltip here, because imgui-node-editor doesn't support it (even when calling Suspend() and Resume()) because of a bug (https://github.com/thedmd/imgui-node-editor/issues/282) +} + void NodesEditorImpl::render_node(Node& node, NodeId const& id, NodesConfig& nodes_cfg, NodesLibrary const& library, ax::NodeEditor::Utilities::BlueprintNodeBuilder& builder) { auto const color = nodes_cfg.node_color(node, id); @@ -375,6 +383,11 @@ void NodesEditorImpl::render_node(Node& node, NodeId const& id, NodesConfig& nod ImGui::TextUnformatted(input_pin.name().c_str()); ImGui::Spring(0); } + if (!input_pin.description().empty()) + { + help_marker_for_pin(input_pin.description()); + ImGui::Spring(0); + } ImGui::PopStyleVar(); builder.EndInput(); } @@ -392,6 +405,11 @@ void NodesEditorImpl::render_node(Node& node, NodeId const& id, NodesConfig& nod ImGui::Spring(0); ImGui::TextUnformatted(output_pin.name().c_str()); } + if (!output_pin.description().empty()) + { + ImGui::Spring(0); + help_marker_for_pin(output_pin.description()); + } ImGui::Spring(0); render_pin_icon(output_pin_icon(idx), alpha, nodes_cfg.pin_color(output_pin, idx, node, id)); ImGui::PopStyleVar(); @@ -711,11 +729,9 @@ auto NodesEditorImpl::imgui_workspace(NodesConfig& nodes_cfg, NodesLibrary const } bool graph_has_changed = false; + _deferred_tooltip_text.reset(); // Might be filled by one of the nodes, and will be rendered later ed::SetCurrentEditor(_context); - // GImGui->CurrentWindow->DrawList->AddRectFilled(ImVec2{0.f, 0.f}, ImVec2{0.f, 0.f}, ImGui::GetColorU32(ImGuiCol_SeparatorHovered), 0.0f); // TODO(JF) Remove this. (But atm when removing it the view gets clipped when zooming in) EDIT this is caused by the suspend / resume - GImGui->CurrentWindow->DrawList->AddLine(ImVec2{0.f, 0.f}, ImVec2{0.f, 0.f}, ImGui::GetColorU32(ImGuiCol_SeparatorHovered)); // TODO(JF) Remove this. (But atm when removing it the view gets clipped when zooming in) EDIT this is caused by the suspend / resume - ed::Begin("Node editor"); render_editor(nodes_cfg, library); @@ -740,6 +756,11 @@ auto NodesEditorImpl::imgui_workspace(NodesConfig& nodes_cfg, NodesLibrary const } ed::Suspend(); + if (_deferred_tooltip_text.has_value() && ImGui::BeginTooltip()) + { + ImGuiExtras::help_marker_tooltip_content(_deferred_tooltip_text->c_str()); + ImGui::EndTooltip(); + } if (ImGui::BeginPopup("Nodes Library Menu")) { auto const new_node_def_id = imgui_nodes_menu(library, nodes_cfg.maybe_disable_node_definition(), _menu_just_opened); diff --git a/src/Cool/Nodes/EditorImpl.h b/src/Cool/Nodes/EditorImpl.h index 06ace866..52102c0e 100644 --- a/src/Cool/Nodes/EditorImpl.h +++ b/src/Cool/Nodes/EditorImpl.h @@ -74,6 +74,7 @@ class NodesEditorImpl : public INodesEditor { auto wants_to_open_nodes_menu() const -> bool; void open_nodes_menu(); void remove_all_links_connected_to_input_pin(PinId const& input_pin_id, NodesConfig& nodes_cfg); + void help_marker_for_pin(std::string text); private: internal::UniqueEdContext _context{}; @@ -88,7 +89,8 @@ class NodesEditorImpl : public INodesEditor { Pin const* _new_link_pin = nullptr; bool _link_has_just_been_released{false}; // HACK because we can't open the nodes menu just after a link has been released (otherwise _next_node_position is wrong). So we have to delay the opening. - int _frames_count{0}; + int _frames_count{0}; + std::optional _deferred_tooltip_text{}; private: // ImColor GetIconColor(PinType type); diff --git a/src/Cool/Nodes/Pin.cpp b/src/Cool/Nodes/Pin.cpp index d5f29c19..1e92e5ee 100644 --- a/src/Cool/Nodes/Pin.cpp +++ b/src/Cool/Nodes/Pin.cpp @@ -2,8 +2,9 @@ namespace Cool { -Pin::Pin(std::string_view name) - : _name{name} +Pin::Pin(std::string name, std::string description) + : _name{std::move(name)} + , _description{std::move(description)} , _id{reg::internal::generate_uuid()} { } diff --git a/src/Cool/Nodes/Pin.h b/src/Cool/Nodes/Pin.h index ca3ac229..e40b87cf 100644 --- a/src/Cool/Nodes/Pin.h +++ b/src/Cool/Nodes/Pin.h @@ -17,7 +17,7 @@ enum class PinKind { class Pin { public: Pin() = default; - explicit Pin(std::string_view name); + Pin(std::string name, std::string description); Pin(Pin const&) = default; Pin(Pin&&) = default; auto operator=(Pin const&) -> Pin& = default; @@ -25,6 +25,7 @@ class Pin { virtual ~Pin() = default; [[nodiscard]] auto name() const -> std::string const& { return _name; } + [[nodiscard]] auto description() const -> std::string const& { return _description; } [[nodiscard]] auto id() const -> PinId const& { return _id; } void set_id(PinId const& id) { _id = id; } @@ -36,6 +37,7 @@ class Pin { private: std::string _name{}; + std::string _description{}; PinId _id{}; private: @@ -46,6 +48,7 @@ class Pin { { archive( cereal::make_nvp("Name", _name), + cereal::make_nvp("Description", _description), cereal::make_nvp("ID", _id) ); }