@@ -811,7 +811,7 @@ void Graph::setRenderMaterial(UiNodePtr node)
811811 for (const std::string& testPath : testPaths)
812812 {
813813 mx::ElementPtr testElem = _graphDoc->getDescendant (testPath);
814- mx::NodePtr testNode = testElem->asA <mx::Node>();
814+ mx::NodePtr testNode = testElem ? testElem ->asA <mx::Node>() : nullptr ;
815815 std::vector<mx::PortElementPtr> downstreamPorts;
816816 if (testNode)
817817 {
@@ -931,7 +931,7 @@ void Graph::updateMaterials(mx::InputPtr input /* = nullptr */, mx::ValuePtr val
931931 }
932932}
933933
934- void Graph::setConstant (UiNodePtr node, mx::InputPtr& input, const mx::UIProperties& uiProperties)
934+ void Graph::showPropertyEditorValue (UiNodePtr node, mx::InputPtr& input, const mx::UIProperties& uiProperties)
935935{
936936 ImGui::PushItemWidth (-1 );
937937
@@ -3377,6 +3377,129 @@ void Graph::graphButtons()
33773377 }
33783378}
33793379
3380+ void Graph::showPropertyEditorOutputConnections (UiNodePtr node)
3381+ {
3382+ if (node->_showOutputsInEditor )
3383+ {
3384+ std::vector<UiPinPtr> pinList = node->outputPins ;
3385+ size_t pinCount = 0 ;
3386+ for (UiPinPtr outputPin : node->outputPins )
3387+ {
3388+ std::vector<UiPinPtr> connectedPins = outputPin->getConnections ();
3389+ pinCount += connectedPins.size ();
3390+ }
3391+
3392+ if (pinCount > 0 )
3393+ {
3394+ const float TEXT_BASE_HEIGHT = ImGui::GetTextLineHeightWithSpacing () * 1 .3f ;
3395+ const int SCROLL_LINE_COUNT = 20 ;
3396+ ImGuiTableFlags tableFlags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings |
3397+ ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_NoBordersInBody;
3398+
3399+ ImVec2 tableSize (0 .0f , TEXT_BASE_HEIGHT * std::min (SCROLL_LINE_COUNT, (int )pinCount));
3400+ bool haveTable = ImGui::BeginTable (" outputs_node_table" , 2 , tableFlags, tableSize);
3401+ if (haveTable)
3402+ {
3403+ ImGui::SetWindowFontScale (_fontScale);
3404+ for (UiPinPtr outputPin : node->outputPins )
3405+ {
3406+ bool firstPin = true ;
3407+ std::string outputPinName = outputPin->_name ;
3408+ std::string blankPinName;
3409+ for (size_t i = 0 ; i < outputPinName.length (); i++)
3410+ {
3411+ blankPinName += ' ' ;
3412+ }
3413+
3414+ std::vector<UiPinPtr> connectedPins = outputPin->getConnections ();
3415+ for (UiPinPtr connectedPin : connectedPins)
3416+ {
3417+ ImGui::TableNextRow ();
3418+ ImGui::TableNextColumn ();
3419+
3420+ std::string connectedPinName = connectedPin->_name ;
3421+ if (connectedPin->_pinNode )
3422+ {
3423+ connectedPinName = connectedPin->_pinNode ->getName () + " ." + connectedPinName;
3424+ }
3425+ // Display outputPin name, and connectedPinName in same row
3426+ //
3427+ if (firstPin)
3428+ {
3429+ ImGui::Text (" %s" , outputPinName.c_str ());
3430+ firstPin = false ;
3431+ }
3432+ else
3433+ {
3434+ ImGui::Text (" %s" , blankPinName.c_str ());
3435+ }
3436+
3437+ std::string displayString = connectedPinName;
3438+ ImGui::SameLine ();
3439+ ImGui::TableNextColumn ();
3440+ ImGui::PushItemWidth (-1 );
3441+
3442+ ImGui::PushStyleColor (ImGuiCol_Button, ImVec4 (0 .15f , 0 .15f , 0 .15f , 1 .0f ));
3443+ ImGui::PushStyleColor (ImGuiCol_ButtonHovered, ImVec4 (0 .2f , 0 .4f , 0 .6f , 1 .0f ));
3444+ ImGui::PushStyleColor (ImGuiCol_ButtonActive, ImVec4 (0 .1f , 0 .2f , 0 .4f , 1 .0f ));
3445+
3446+ if (ImGui::Button (displayString.c_str ()))
3447+ {
3448+ std::shared_ptr<UiNode> pinNode = connectedPin->_pinNode ;
3449+ if (pinNode)
3450+ {
3451+ ed::SelectNode (pinNode->getId ());
3452+ ed::NavigateToSelection ();
3453+ }
3454+ }
3455+ ImGui::PopStyleColor (3 );
3456+ ImGui::PopItemWidth ();
3457+ }
3458+ }
3459+ ImGui::EndTable ();
3460+ ImGui::SetWindowFontScale (1 .0f );
3461+ }
3462+ }
3463+ }
3464+
3465+ }
3466+
3467+ void Graph::showPropertyEditorInputConnection (UiPinPtr displayPin)
3468+ {
3469+ // Allow for upstream traversal via button
3470+ //
3471+ std::string displayString = displayPin->_input ->getType ();
3472+ const std::vector<UiPinPtr>& connections = displayPin->getConnections ();
3473+ std::shared_ptr<UiNode> pinNode = nullptr ;
3474+ if (!connections.empty ())
3475+ {
3476+ UiPinPtr pin = connections[0 ];
3477+ std::string pinName = std::string (pin->_name );
3478+
3479+ pinNode = pin->_pinNode ;
3480+ if (pinNode)
3481+ {
3482+ pinName = std::string (pinNode->getName ()) + " ." + pinName;
3483+ }
3484+ displayString = pinName;
3485+ }
3486+
3487+ ImGui::PushStyleColor (ImGuiCol_Button, ImVec4 (0 .15f , 0 .15f , 0 .15f , 1 .0f ));
3488+ ImGui::PushStyleColor (ImGuiCol_ButtonHovered, ImVec4 (0 .2f , 0 .4f , 0 .6f , 1 .0f ));
3489+ ImGui::PushStyleColor (ImGuiCol_ButtonActive, ImVec4 (0 .1f , 0 .2f , 0 .4f , 1 .0f ));
3490+ ImGui::PushItemWidth (-1 );
3491+ if (ImGui::Button (displayString.c_str ()))
3492+ {
3493+ if (pinNode)
3494+ {
3495+ ed::SelectNode (pinNode->getId ());
3496+ ed::NavigateToSelection ();
3497+ }
3498+ }
3499+ ImGui::PopItemWidth ();
3500+ ImGui::PopStyleColor (3 );
3501+ }
3502+
33803503void Graph::propertyEditor ()
33813504{
33823505 // Get parent dimensions
@@ -3532,6 +3655,7 @@ void Graph::propertyEditor()
35323655 }
35333656
35343657 ImGui::Checkbox (" Show all inputs" , &_currUiNode->_showAllInputs );
3658+ ImGui::Checkbox (" Show output connections" , &_currUiNode->_showOutputsInEditor );
35353659
35363660 int count = 0 ;
35373661 for (UiPinPtr input : _currUiNode->inputPins )
@@ -3580,12 +3704,11 @@ void Graph::propertyEditor()
35803704 ImGui::TableNextColumn ();
35813705 if (!input->getConnected ())
35823706 {
3583- setConstant (_currUiNode, input->_input , uiProperties);
3707+ showPropertyEditorValue (_currUiNode, input->_input , uiProperties);
35843708 }
35853709 else
35863710 {
3587- std::string typeText = " [" + input->_input ->getType () + " ]" ;
3588- ImGui::Text (" %s" , typeText.c_str ());
3711+ showPropertyEditorInputConnection (input);
35893712 }
35903713
35913714 ImGui::PopID ();
@@ -3596,6 +3719,8 @@ void Graph::propertyEditor()
35963719 ImGui::SetWindowFontScale (1 .0f );
35973720 }
35983721 }
3722+
3723+ showPropertyEditorOutputConnections (_currUiNode);;
35993724 }
36003725
36013726 else if (_currUiNode->getInput () != nullptr )
@@ -3630,28 +3755,34 @@ void Graph::propertyEditor()
36303755 // Set constant sliders for input values
36313756 if (!inputs[i]->getConnected ())
36323757 {
3633- setConstant (_currUiNode, inputs[i]->_input , uiProperties);
3758+ showPropertyEditorValue (_currUiNode, inputs[i]->_input , uiProperties);
36343759 }
36353760 else
36363761 {
3637- std::string typeText = " [" + inputs[i]->_input ->getType () + " ]" ;
3638- ImGui::Text (" %s" , typeText.c_str ());
3762+ showPropertyEditorInputConnection (inputs[i]);
36393763 }
36403764 ImGui::PopID ();
36413765 }
36423766 ImGui::EndTable ();
36433767 ImGui::SetWindowFontScale (1 .0f );
36443768 }
36453769 }
3770+
3771+ showPropertyEditorOutputConnections (_currUiNode);;
36463772 }
36473773 else if (_currUiNode->getOutput () != nullptr )
36483774 {
36493775 ImGui::Text (" %s" , _currUiNode->getOutput ()->getCategory ().c_str ());
36503776 }
36513777 else if (_currUiNode->getNodeGraph () != nullptr )
36523778 {
3779+
36533780 std::vector<UiPinPtr> inputs = _currUiNode->inputPins ;
36543781 ImGui::Text (" %s" , _currUiNode->getCategory ().c_str ());
3782+
3783+ ImGui::Checkbox (" Show all inputs" , &_currUiNode->_showAllInputs );
3784+ ImGui::Checkbox (" Show output connections" , &_currUiNode->_showOutputsInEditor );
3785+
36553786 int count = 0 ;
36563787 for (UiPinPtr input : inputs)
36573788 {
@@ -3688,12 +3819,11 @@ void Graph::propertyEditor()
36883819 ImGui::TableNextColumn ();
36893820 if (!input->_input ->getConnectedNode () && _currUiNode->getNodeGraph ()->getActiveInput (input->_input ->getName ()))
36903821 {
3691- setConstant (_currUiNode, input->_input , uiProperties);
3822+ showPropertyEditorValue (_currUiNode, input->_input , uiProperties);
36923823 }
36933824 else
36943825 {
3695- std::string typeText = " [" + input->_input ->getType () + " ]" ;
3696- ImGui::Text (" %s" , typeText.c_str ());
3826+ showPropertyEditorInputConnection (input);
36973827 }
36983828
36993829 ImGui::PopID ();
@@ -3703,7 +3833,8 @@ void Graph::propertyEditor()
37033833 ImGui::SetWindowFontScale (1 .0f );
37043834 }
37053835 }
3706- ImGui::Checkbox (" Show all inputs" , &_currUiNode->_showAllInputs );
3836+
3837+ showPropertyEditorOutputConnections (_currUiNode);;
37073838 }
37083839
37093840 // Find tokens within currUiNode
@@ -4078,6 +4209,53 @@ void Graph::handleRenderViewInputs()
40784209 }
40794210}
40804211
4212+
4213+ UiNodePtr Graph::traverseConnection (UiNodePtr node, bool traverseDownstream)
4214+ {
4215+ if (!node)
4216+ {
4217+ return nullptr ;
4218+ }
4219+
4220+ // Get first connected downstream node
4221+ if (traverseDownstream)
4222+ {
4223+ for (UiPinPtr outputPin : node->outputPins )
4224+ {
4225+ // Update downNode info
4226+ for (UiPinPtr connectedPin : outputPin.get ()->getConnections ())
4227+ {
4228+ std::shared_ptr<UiNode> pinNode = connectedPin->_pinNode ;
4229+ if (pinNode)
4230+ {
4231+ return pinNode;
4232+ }
4233+ }
4234+ }
4235+ }
4236+
4237+ // Get first upstream connected node
4238+ else
4239+ {
4240+ for (UiPinPtr inputPin: node->inputPins )
4241+ {
4242+ const std::vector<UiPinPtr>& connections = inputPin->getConnections ();
4243+ std::shared_ptr<UiNode> pinNode = nullptr ;
4244+ if (!connections.empty ())
4245+ {
4246+ UiPinPtr pin = connections[0 ];
4247+ pinNode = pin->_pinNode ;
4248+ if (pinNode)
4249+ {
4250+ return pinNode;
4251+ }
4252+ }
4253+ }
4254+ }
4255+
4256+ return nullptr ;
4257+ }
4258+
40814259void Graph::drawGraph (ImVec2 mousePos)
40824260{
40834261 if (_searchNodeId > 0 )
@@ -4299,7 +4477,47 @@ void Graph::drawGraph(ImVec2 mousePos)
42994477 // or if the shortcut for cut is used
43004478 if (ImGui::IsWindowFocused (ImGuiFocusedFlags_RootWindow))
43014479 {
4302- if (ImGui::IsKeyReleased (ImGuiKey_Delete) || ImGui::IsKeyReleased (ImGuiKey_Backspace) || _isCut)
4480+ bool traverseDownstream = ImGui::IsKeyReleased (ImGuiKey_RightArrow);
4481+ bool traverseUpstream = ImGui::IsKeyReleased (ImGuiKey_LeftArrow);
4482+
4483+ // Traverse connections with arrow keys
4484+ if (traverseDownstream || traverseUpstream)
4485+ {
4486+ UiNodePtr selectedNode = nullptr ;
4487+ if (selectedNodes.size () > 0 )
4488+ {
4489+ for (ed::NodeId id : selectedNodes)
4490+ {
4491+ if (int (id.Get ()) > 0 )
4492+ {
4493+ int pos = findNode (int (id.Get ()));
4494+ if (pos >= 0 )
4495+ {
4496+ selectedNode = _graphNodes[pos];
4497+ break ;
4498+ }
4499+ }
4500+ }
4501+ }
4502+ if (selectedNode && _currUiNode)
4503+ {
4504+ selectedNode = _currUiNode;
4505+ }
4506+
4507+ if (selectedNode)
4508+ {
4509+ UiNodePtr connectedNode = traverseConnection (selectedNode, traverseDownstream);
4510+ if (connectedNode)
4511+ {
4512+ _currUiNode = connectedNode;
4513+ ed::SelectNode (connectedNode->getId ());
4514+ ed::NavigateToSelection ();
4515+ }
4516+
4517+ }
4518+ }
4519+
4520+ else if (ImGui::IsKeyReleased (ImGuiKey_Delete) || ImGui::IsKeyReleased (ImGuiKey_Backspace) || _isCut)
43034521 {
43044522 if (selectedNodes.size () > 0 )
43054523 {
@@ -4352,13 +4570,13 @@ void Graph::drawGraph(ImVec2 mousePos)
43524570 }
43534571
43544572 // Hotkey to frame selected node(s)
4355- if (ImGui::IsKeyReleased (ImGuiKey_F) && !_fileDialogSave.isOpened ())
4573+ else if (ImGui::IsKeyReleased (ImGuiKey_F) && !_fileDialogSave.isOpened ())
43564574 {
43574575 ed::NavigateToSelection ();
43584576 }
43594577
43604578 // Go back up from inside a subgraph
4361- if (ImGui::IsKeyReleased (ImGuiKey_U) && (!ImGui::IsPopupOpen (" add node" )) && (!ImGui::IsPopupOpen (" search" )) && !_fileDialogSave.isOpened ())
4579+ else if (ImGui::IsKeyReleased (ImGuiKey_U) && (!ImGui::IsPopupOpen (" add node" )) && (!ImGui::IsPopupOpen (" search" )) && !_fileDialogSave.isOpened ())
43624580 {
43634581 upNodeGraph ();
43644582 }
0 commit comments