From d162f4aaddea6eb8cb5c0a2f57804cd541a8d751 Mon Sep 17 00:00:00 2001 From: codereader Date: Thu, 1 Oct 2020 06:04:07 +0200 Subject: [PATCH] #5347: Fix a crash in scene::getNodeIndices when a primitive without a parent is encountered. Protect the calling EntityInspector code against out_of_range exceptions that might be thrown by getNodeIndices. --- libs/scene/SelectionIndex.cpp | 22 ++++++++++++++-------- radiant/ui/einspector/EntityInspector.cpp | 12 ++++++++++-- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/libs/scene/SelectionIndex.cpp b/libs/scene/SelectionIndex.cpp index cdc2b7242c..3c3dbc9c73 100644 --- a/libs/scene/SelectionIndex.cpp +++ b/libs/scene/SelectionIndex.cpp @@ -115,18 +115,24 @@ std::pair getNodeIndices(const scene::INodePtr& node) } else if (Node_isPrimitive(node)) { - scene::INodePtr parent = node->getParent(); + auto parent = node->getParent(); - // Node is a primitive, find parent entity and child index - EntityFindIndexWalker walker(parent); - GlobalSceneGraph().root()->traverse(walker); + // In rare cases, such as when a drag-selection brush is deleted + // but still selected, we might reach this point with a primitive + // node without a parent. At least we shouldn't crash. + if (parent) + { + // Node is a primitive, find parent entity and child index + EntityFindIndexWalker walker(parent); + GlobalSceneGraph().root()->traverse(walker); - result.first = walker.getIndex(); // might throw + result.first = walker.getIndex(); // might throw - PrimitiveFindIndexWalker brushWalker(node); - parent->traverse(brushWalker); + PrimitiveFindIndexWalker brushWalker(node); + parent->traverse(brushWalker); - result.second = walker.getIndex(); // might throw + result.second = walker.getIndex(); // might throw + } } else { diff --git a/radiant/ui/einspector/EntityInspector.cpp b/radiant/ui/einspector/EntityInspector.cpp index b30a2c039d..b13722eaed 100644 --- a/radiant/ui/einspector/EntityInspector.cpp +++ b/radiant/ui/einspector/EntityInspector.cpp @@ -1197,9 +1197,17 @@ void EntityInspector::getEntityFromSelectionSystem() scene::INodePtr selectedNodeParent = selectedNode->getParent(); changeSelectedEntity(selectedNodeParent); - auto indices = scene::getNodeIndices(selectedNode); + try + { + auto indices = scene::getNodeIndices(selectedNode); - _primitiveNumLabel->SetLabelText(fmt::format(_("Entity {0}, Primitive {1}"), indices.first, indices.second)); + _primitiveNumLabel->SetLabelText(fmt::format(_("Entity {0}, Primitive {1}"), indices.first, indices.second)); + } + catch (const std::out_of_range& ex) + { + rWarning() << ex.what() << std::endl; + _primitiveNumLabel->SetLabelText("-"); + } } }