Skip to content

Commit 0250794

Browse files
committed
Fix wires disapearing when nodes go out of screen.
AddNodePins() must now always be called, even when BeginNode() returns false.
1 parent b16492b commit 0250794

File tree

2 files changed

+79
-58
lines changed

2 files changed

+79
-58
lines changed

src/PatchObject.cpp

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -172,27 +172,13 @@ void PatchObject::drawImGuiNode(ImGuiEx::NodeCanvas& _nodeCanvas, map<int,shared
172172
ImVec2 imPos( this->getPos() );
173173
ImVec2 imSize( this->width, this->height );
174174

175-
if(_nodeCanvas.BeginNode( nId, PatchObject::getUID().c_str(), PatchObject::getDisplayName(), imPos, imSize, this->getNumInlets(), this->getNumOutlets(), this->getIsResizable(), this->getIsTextureObject() )){
176-
177-
// save node state on click
178-
if(ImGui::IsWindowHovered() && ImGui::IsMouseReleased(0)){
179-
//ofLog(OF_LOG_NOTICE, "Clicked object with id %i", this->nId);
180-
saveConfig(false);
181-
}
182-
183-
// Check menu state
184-
if( _nodeCanvas.doNodeMenuAction(ImGuiExNodeMenuActionFlags_DeleteNode) ){
185-
ofNotifyEvent(removeEvent, nId);
186-
this->setWillErase(true);
187-
}
188-
//else if( _nodeCanvas.doNodeMenuAction(ImGuiExNodeMenuActionFlags_CopyNode) ){
189-
// ofGetWindowPtr()->setClipboardString( this->serialize() );
190-
// ofNotifyEvent(copyEvent, nId); ?
191-
//}
192-
else if( _nodeCanvas.doNodeMenuAction(ImGuiExNodeMenuActionFlags_DuplicateNode) ){
193-
ofNotifyEvent(duplicateEvent, nId);
194-
}
175+
// Begin Node
176+
static bool isNodeVisible;
177+
isNodeVisible = _nodeCanvas.BeginNode( nId, PatchObject::getUID().c_str(), PatchObject::getDisplayName(), imPos, imSize, this->getNumInlets(), this->getNumOutlets(), this->getIsResizable(), this->getIsTextureObject() );
195178

179+
// Always draw [in/out]lets (so wires render correctly)
180+
// Updates pin positions
181+
{
196182
// Inlets
197183
for(int i=0;i<static_cast<int>(inletsType.size());i++){
198184
auto pinCol = getInletColor(i);
@@ -254,7 +240,6 @@ void PatchObject::drawImGuiNode(ImGuiEx::NodeCanvas& _nodeCanvas, map<int,shared
254240

255241
}
256242

257-
258243
// Outlets
259244
for(int i=0;i<static_cast<int>(outletsType.size());i++){
260245
auto pinCol = getOutletColor(i);
@@ -280,6 +265,29 @@ void PatchObject::drawImGuiNode(ImGuiEx::NodeCanvas& _nodeCanvas, map<int,shared
280265

281266
outletsPositions[i] = _nodeCanvas.getOutletPosition(nId,i);
282267
}
268+
}
269+
270+
// Draw Node content and handle
271+
if(isNodeVisible){
272+
273+
// save node state on click
274+
if(ImGui::IsWindowHovered() && ImGui::IsMouseReleased(0)){
275+
//ofLog(OF_LOG_NOTICE, "Clicked object with id %i", this->nId);
276+
saveConfig(false);
277+
}
278+
279+
// Check menu state
280+
if( _nodeCanvas.doNodeMenuAction(ImGuiExNodeMenuActionFlags_DeleteNode) ){
281+
ofNotifyEvent(removeEvent, nId);
282+
this->setWillErase(true);
283+
}
284+
//else if( _nodeCanvas.doNodeMenuAction(ImGuiExNodeMenuActionFlags_CopyNode) ){
285+
// ofGetWindowPtr()->setClipboardString( this->serialize() );
286+
// ofNotifyEvent(copyEvent, nId); ?
287+
//}
288+
else if( _nodeCanvas.doNodeMenuAction(ImGuiExNodeMenuActionFlags_DuplicateNode) ){
289+
ofNotifyEvent(duplicateEvent, nId);
290+
}
283291

284292
// Refresh links to eventually disconnect ( backspace key )
285293
linksToDisconnect = _nodeCanvas.getSelectedLinks();

src/core/imgui_node_canvas.cpp

Lines changed: 50 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -283,13 +283,13 @@ bool ImGuiEx::NodeCanvas::BeginNode( int nId, const char* _id, std::string name,
283283

284284
// Is the node out of sight on canvas ?
285285
bool isNodeVisible = ImGui::IsRectVisible( curNodeData.outerContentBox.Min, curNodeData.outerContentBox.Max );
286+
287+
// Calc zoom name
286288
if( !isNodeVisible ){
287289
curNodeData.zoomName = ImGuiExNodeZoom_Invisible;
288-
return false;
290+
//return false; // Note: Commented so that pins and wires can still be drawn
289291
}
290-
291-
// Calc zoom name
292-
{
292+
else {
293293
unsigned int curWidth = curNodeData.outerContentBox.GetSize().x;
294294
if( curWidth < IMGUI_EX_NODE_MIN_WIDTH_SMALL )
295295
curNodeData.zoomName = ImGuiExNodeZoom_Imploded;
@@ -351,6 +351,13 @@ bool ImGuiEx::NodeCanvas::BeginNode( int nId, const char* _id, std::string name,
351351
fg->AddRect(curNodeData.outerContentBox.Min, ImVec2(curNodeData.outerContentBox.Max.x,curNodeData.outerContentBox.Min.y+IMGUI_EX_NODE_HEADER_HEIGHT), IM_COL32(255,255,255,200));
352352
fg->AddRect(ImVec2(curNodeData.outerContentBox.Min.x, curNodeData.outerContentBox.Max.y-IMGUI_EX_NODE_FOOTER_HEIGHT), curNodeData.outerContentBox.Max, IM_COL32(255,255,255,200));
353353
#endif
354+
355+
// Return early now that everything has been calc'd.
356+
if( !isNodeVisible ){
357+
nodeDrawList = ImGui::GetWindowDrawList(); // So that nodes can still draw pins !
358+
return false;
359+
}
360+
354361
// Create node window
355362
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0,0));//IMGUI_EX_NODE_CONTENT_PADDING,IMGUI_EX_NODE_CONTENT_PADDING));
356363
ImGui::SetNextWindowPos(curNodeData.outerContentBox.Min);
@@ -580,7 +587,7 @@ bool ImGuiEx::NodeCanvas::BeginNode( int nId, const char* _id, std::string name,
580587

581588
// Draw default menu items
582589
if(ImGui::BeginPopup(IMGUI_EX_NODE_MENU_ID)){
583-
if(name != "audio device"){
590+
if(name != "audio device"){ // Todo: should not be checked on title... maybe: if(node->canBeRemoved())
584591
if(ImGui::MenuItem("Delete")) curNodeData.menuActions |= ImGuiExNodeMenuActionFlags_DeleteNode;
585592
//if(ImGui::MenuItem("Copy")) curNodeData.menuActions |= ImGuiExNodeMenuActionFlags_CopyNode;
586593
if(ImGui::MenuItem("Duplicate")) curNodeData.menuActions |= ImGuiExNodeMenuActionFlags_DuplicateNode;
@@ -699,6 +706,7 @@ ImGuiEx::NodeConnectData ImGuiEx::NodeCanvas::AddNodePin( const int nodeID, cons
699706
static int linkID = -1;
700707

701708
// Check ImGui Callstack
709+
IM_ASSERT(nodeDrawList != NULL ); // Huh ?
702710
IM_ASSERT(isDrawingCanvas == true); // Please Call between Begin() and End()
703711
IM_ASSERT(isDrawingNode == true); // Please Call between BeginNode() and EndNode()
704712
IM_ASSERT(_pinFlag == ImGuiExNodePinsFlags_Left || _pinFlag == ImGuiExNodePinsFlags_Right); // Only left / right pins can be created
@@ -713,7 +721,7 @@ ImGuiEx::NodeConnectData ImGuiEx::NodeCanvas::AddNodePin( const int nodeID, cons
713721
ImGui::NextColumn(); // right col
714722
if( _pinFlag==ImGuiExNodePinsFlags_Left ) ImGui::NextColumn(); // left column
715723

716-
// Hover interaction
724+
// Draw pins
717725
if(pinLayout.pinSpace.x > 0){
718726
if( _pinFlag==ImGuiExNodePinsFlags_Left ){
719727
ImGui::SetCursorScreenPos( pinLayout.curDrawPos );
@@ -855,38 +863,38 @@ ImGuiEx::NodeConnectData ImGuiEx::NodeCanvas::AddNodePin( const int nodeID, cons
855863
//float pinSpace = (ImGui::IsItemHovered()) ? IMGUI_EX_NODE_PIN_WIDTH_HOVERED : IMGUI_EX_NODE_PIN_WIDTH;
856864
float pinSpace = IMGUI_EX_NODE_PIN_WIDTH*scaleFactor;
857865

858-
// Draw pin
859-
860866
// Left side (INLETS)
861867
if( _pinFlag==ImGuiExNodePinsFlags_Left ){
862-
868+
// Update pin position
863869
inletPinsPositions[nodeID][pinID] = pinLayout.curDrawPos + ImVec2( IMGUI_EX_NODE_PIN_WIDTH*scaleFactor * .5f, pinLayout.pinSpace.y * .5f) + ImVec2(IMGUI_EX_NODE_PIN_WIDTH*scaleFactor,0);
864870

865-
nodeDrawList->AddCircleFilled(inletPinsPositions[nodeID][pinID], pinSpace * .5f, _color, 6);
871+
// Draw pin
872+
if( curNodeData.zoomName != ImGuiExNodeZoom_Invisible ){
873+
nodeDrawList->AddCircleFilled(inletPinsPositions[nodeID][pinID], pinSpace * .5f, _color, 6);
874+
875+
// Interactivity
876+
if(ImGui::GetMousePos().x > inletPinsPositions[nodeID][pinID].x-(pinLayout.pinSpace.x*.5f) && ImGui::GetMousePos().x < inletPinsPositions[nodeID][pinID].x+(pinLayout.pinSpace.x*.5f) && ImGui::GetMousePos().y > inletPinsPositions[nodeID][pinID].y-(pinLayout.pinSpace.y*.5f) && ImGui::GetMousePos().y < inletPinsPositions[nodeID][pinID].y+(pinLayout.pinSpace.y*.5f)){
877+
if(activePinType == _type || activePinType == ""){
878+
nodeDrawList->AddCircle(inletPinsPositions[nodeID][pinID],pinSpace * 0.9f, _color, 6);
879+
ImVec2 tempPos = inletPinsPositions[nodeID][pinID] - ImVec2(pinSpace * .5f + (IMGUI_EX_NODE_PIN_WIDTH + 6)*scaleFactor,ImGui::GetTextLineHeight()*-.4f) - ImGui::CalcTextSize(_label);
880+
canvasDrawList->AddRectFilled(tempPos + ImVec2(-IMGUI_EX_NODE_PIN_WIDTH*scaleFactor,-IMGUI_EX_NODE_PIN_WIDTH*scaleFactor),tempPos + ImGui::CalcTextSize(_label) + ImVec2(IMGUI_EX_NODE_PIN_WIDTH*scaleFactor,IMGUI_EX_NODE_PIN_WIDTH*scaleFactor),IM_COL32(40,40,40,180) );
881+
canvasDrawList->AddText( tempPos, _color, _label);
882+
}
866883

867-
if(ImGui::GetMousePos().x > inletPinsPositions[nodeID][pinID].x-(pinLayout.pinSpace.x*.5f) && ImGui::GetMousePos().x < inletPinsPositions[nodeID][pinID].x+(pinLayout.pinSpace.x*.5f) && ImGui::GetMousePos().y > inletPinsPositions[nodeID][pinID].y-(pinLayout.pinSpace.y*.5f) && ImGui::GetMousePos().y < inletPinsPositions[nodeID][pinID].y+(pinLayout.pinSpace.y*.5f)){
868-
if(activePinType == _type || activePinType == ""){
869-
nodeDrawList->AddCircle(inletPinsPositions[nodeID][pinID],pinSpace * 0.9f, _color, 6);
870-
ImVec2 tempPos = inletPinsPositions[nodeID][pinID] - ImVec2(pinSpace * .5f + (IMGUI_EX_NODE_PIN_WIDTH + 6)*scaleFactor,ImGui::GetTextLineHeight()*-.4f) - ImGui::CalcTextSize(_label);
871-
canvasDrawList->AddRectFilled(tempPos + ImVec2(-IMGUI_EX_NODE_PIN_WIDTH*scaleFactor,-IMGUI_EX_NODE_PIN_WIDTH*scaleFactor),tempPos + ImGui::CalcTextSize(_label) + ImVec2(IMGUI_EX_NODE_PIN_WIDTH*scaleFactor,IMGUI_EX_NODE_PIN_WIDTH*scaleFactor),IM_COL32(40,40,40,180) );
872-
canvasDrawList->AddText( tempPos, _color, _label);
873884
}
874885

886+
// Draw Connected Appearance
887+
if(_connected){
888+
nodeDrawList->AddCircle(inletPinsPositions[nodeID][pinID],pinSpace * 0.9f, _color, 6);
889+
}
875890
}
876-
877-
if(_connected){
878-
nodeDrawList->AddCircle(inletPinsPositions[nodeID][pinID],pinSpace * 0.9f, _color, 6);
879-
}
880-
881891
}
882892

883893
// right side (OUTLETS)
884894
else if( _pinFlag==ImGuiExNodePinsFlags_Right ){
885-
895+
// Update pin position
886896
outletPinsPositions[nodeID][pinID] = pinLayout.curDrawPos + ImVec2( IMGUI_EX_NODE_PIN_WIDTH*scaleFactor * -.5f, pinLayout.pinSpace.y * .5f);
887897

888-
nodeDrawList->AddCircleFilled(outletPinsPositions[nodeID][pinID], pinSpace * .5f, _color, 6);
889-
890898
// draw links (OUTLETS to INLETS ONLY)
891899
for(int i=0;i<_linksData.size();i++){
892900
const LinkBezierData link_data = get_link_renderable(outletPinsPositions[nodeID][pinID], canvasView.translation+(_linksData.at(i)._toPinPosition*canvasView.scale), IMGUI_EX_NODE_LINK_LINE_SEGMENTS_PER_LENGTH);
@@ -907,30 +915,35 @@ ImGuiEx::NodeConnectData ImGuiEx::NodeCanvas::AddNodePin( const int nodeID, cons
907915
}
908916

909917

910-
ImU32 _tempColor = _color;
918+
static ImU32 _tempColor;
919+
_tempColor = _color;
911920
if (std::find(selected_links.begin(), selected_links.end(),_linksData.at(i)._linkID)!=selected_links.end()){ // selected
912921
_tempColor = IM_COL32(255,0,0,255);
913922
}
914923

915924
canvasDrawList->AddBezierCubic(link_data.bezier.p0, link_data.bezier.p1, link_data.bezier.p2, link_data.bezier.p3, _tempColor, IMGUI_EX_NODE_LINK_THICKNESS, link_data.num_segments);
916925
}
917926

918-
// draw labels
919-
if(ImGui::GetMousePos().x > outletPinsPositions[nodeID][pinID].x-IMGUI_EX_NODE_PIN_WIDTH_HOVERED && ImGui::GetMousePos().x < outletPinsPositions[nodeID][pinID].x+IMGUI_EX_NODE_PIN_WIDTH_HOVERED && ImGui::GetMousePos().y > outletPinsPositions[nodeID][pinID].y-IMGUI_EX_NODE_PIN_WIDTH_HOVERED && ImGui::GetMousePos().y < outletPinsPositions[nodeID][pinID].y+IMGUI_EX_NODE_PIN_WIDTH_HOVERED){
920-
if(connectType == 0){
921-
nodeDrawList->AddCircle(outletPinsPositions[nodeID][pinID],pinSpace * 0.9f, _color, 6);
922-
ImVec2 tempPos = outletPinsPositions[nodeID][pinID] + ImVec2(pinSpace * .5f + 6,ImGui::GetTextLineHeight()*-.5f);
923-
canvasDrawList->AddRectFilled(tempPos + ImVec2(-IMGUI_EX_NODE_PIN_WIDTH*scaleFactor,-IMGUI_EX_NODE_PIN_WIDTH*scaleFactor),tempPos + ImGui::CalcTextSize(_label) + ImVec2(IMGUI_EX_NODE_PIN_WIDTH*scaleFactor,IMGUI_EX_NODE_PIN_WIDTH*scaleFactor),IM_COL32(40,40,40,180) );
924-
canvasDrawList->AddText( tempPos, _color, _label);
927+
// Draw pin
928+
if( curNodeData.zoomName != ImGuiExNodeZoom_Invisible ){
929+
nodeDrawList->AddCircleFilled(outletPinsPositions[nodeID][pinID], pinSpace * .5f, _color, 6);
930+
931+
// draw labels
932+
if(ImGui::GetMousePos().x > outletPinsPositions[nodeID][pinID].x-IMGUI_EX_NODE_PIN_WIDTH_HOVERED && ImGui::GetMousePos().x < outletPinsPositions[nodeID][pinID].x+IMGUI_EX_NODE_PIN_WIDTH_HOVERED && ImGui::GetMousePos().y > outletPinsPositions[nodeID][pinID].y-IMGUI_EX_NODE_PIN_WIDTH_HOVERED && ImGui::GetMousePos().y < outletPinsPositions[nodeID][pinID].y+IMGUI_EX_NODE_PIN_WIDTH_HOVERED){
933+
if(connectType == 0){
934+
nodeDrawList->AddCircle(outletPinsPositions[nodeID][pinID],pinSpace * 0.9f, _color, 6);
935+
ImVec2 tempPos = outletPinsPositions[nodeID][pinID] + ImVec2(pinSpace * .5f + 6,ImGui::GetTextLineHeight()*-.5f);
936+
canvasDrawList->AddRectFilled(tempPos + ImVec2(-IMGUI_EX_NODE_PIN_WIDTH*scaleFactor,-IMGUI_EX_NODE_PIN_WIDTH*scaleFactor),tempPos + ImGui::CalcTextSize(_label) + ImVec2(IMGUI_EX_NODE_PIN_WIDTH*scaleFactor,IMGUI_EX_NODE_PIN_WIDTH*scaleFactor),IM_COL32(40,40,40,180) );
937+
canvasDrawList->AddText( tempPos, _color, _label);
938+
}
925939
}
926-
}
927940

928-
// draw pin connected
929-
if(_connected){
930-
nodeDrawList->AddCircle(outletPinsPositions[nodeID][pinID],pinSpace * 0.9f, _color, 6);
941+
// Draw Connected Appearance
942+
if(_connected){
943+
nodeDrawList->AddCircle(outletPinsPositions[nodeID][pinID],pinSpace * 0.9f, _color, 6);
944+
}
931945
}
932946

933-
934947
}
935948
pinLayout.curDrawPos += ImVec2(0,pinLayout.pinSpace.y);
936949

0 commit comments

Comments
 (0)