Delete Camera Fix#1398
Open
kmeirlaen wants to merge 2 commits into
Open
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes camera-node deletion and related downstream behaviors across the GUI scene tree, backend removal policy enforcement, Python/MCP surfaces, and COLMAP export. It aligns structural affordances (what actions are available) with runtime guards (what actions are currently enabled), and ensures state derived from cameras (counts, exports) stays consistent after deletions.
Changes:
- Unifies delete/rename enablement across scene-tree inline actions, context menus, keyboard, and operator execution by separating “can_” (structural) vs “_enabled” (runtime policy).
- Adds result-returning removal helpers in
SceneManagerand propagates backend rejection as errors through GUI operators, MCP, and Python bindings/stubs. - Makes COLMAP sparse export resilient to deleted cameras by dropping unmatched source images and clearing stale observation/track references.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/test_undo_history.cpp | Adds regression test verifying delete results respect training removal policy. |
| src/visualizer/scene/scene_manager.hpp | Adds result-returning node deletion APIs and a removal capability query. |
| src/visualizer/scene/scene_manager.cpp | Implements canRemoveNode, result-returning delete wrappers, and camera-count recomputation after camera removals. |
| src/visualizer/operator/ops/edit_ops.cpp | Ensures delete operator validates/returns errors instead of silently ignoring backend rejections. |
| src/visualizer/gui/rmlui/resources/scene_tree.theme.rcss | Adds theme rule for disabled trash icon color when selected. |
| src/visualizer/gui/rmlui/resources/scene_tree.rcss | Styles disabled trash icon states in the scene tree. |
| src/visualizer/gui/rmlui/elements/scene_graph_element.hpp | Splits delete/rename state into structural vs enabled booleans; tracks training-delete policy changes. |
| src/visualizer/gui/rmlui/elements/scene_graph_element.cpp | Implements new delete/rename enablement logic, training-delete blocked subtree detection, and live camera-group count labels. |
| src/visualizer/gui/async_task_manager.hpp | Adds setter to update import overlay camera/image count. |
| src/visualizer/gui/async_task_manager.cpp | Implements setImportNumImages() and republishes overlay state. |
| src/training/training_setup.cpp | Stops baking camera counts into training/validation group names. |
| src/python/stubs/lichtfeld/scene.pyi | Documents that remove_node() may raise RuntimeError when GUI manager rejects removal. |
| src/python/stubs/lichtfeld/init.pyi | Documents that remove_node() may raise RuntimeError when GUI manager rejects removal. |
| src/python/lfs/py_scene.cpp | Throws std::runtime_error on GUI-manager deletion rejection so Python sees RuntimeError. |
| src/io/formats/colmap.cpp | Drops source images whose cameras were deleted and clears stale observation/track references when needed. |
| src/app/mcp_operator_tools.cpp | Returns operator-provided error messages on cancellation (instead of generic cancel messaging). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…odes in the request before actually deleting
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Delete Camera Fix
Summary
This patch enables deleting individual camera nodes from the RmlUi scene tree, keeps camera counts current after camera removal, allows COLMAP sparse export after a camera has been deleted, and tightens scene-tree action guards so structural availability and runtime enabled state are handled separately.
Description of the observed issues
After fixing, more things surfaced:
Delkey path.CAMERArows during training, while the backend also rejects the training model node, its ancestor groups, and any subtree containing a training-enabled camera whenDeleteTrainingNodeis blocked.Root Cause
Camera deletion only removed scene graph nodes. The load-time image count stored in the import/app state was not recomputed after camera removal, scene-tree menu actions were not all checking the same runtime guards, the UI delete guard used a camera-type heuristic instead of the backend training-removal policy, training camera groups baked the initial count into the node name, and the COLMAP writer expected every source image from the original sparse model to still have a matching live scene camera.
What This Patch Fixes
can_delete) from runtime enabled state (delete_enabled); the trash icon remains visible but greyed out only for nodes blocked by the backend training-removal policy, and inline click,Del, context-menu Delete, andexecuteAction("delete")all use the same enabled guard.SceneManagerexposes result-returning delete helpers so GUI/MCP/Python paths can preserve the backend rejection result; existing void delete methods remain compatibility wrappers that log failures.scene.delete_nodeand Pythonremove_node()now surface a backend delete rejection instead of reporting success or silently no-oping.remove_node()may raiseRuntimeErrorwhen the GUI scene manager rejects removal; the headless fallback path without aSceneManagerstill calls rawScene::removeNode()and does not apply training validation.can_rename) from runtime enabled state (rename_enabled); cameras and camera groups are not offered Rename, while normal renamable nodes remain rename-enabled during training to match the backend.Training (0)/Validation (0)camera groups are accepted for this patch; camera groups remain structurally non-deletable and are not auto-pruned.Before:

After:

Test Results
lichtfeld_tests.exe --gtest_filter=OperatorRegistryPropsTest.*Delete*:ColmapImageLayoutTest.WriteBackAppliesSceneTransformsToTextSparseModel:ColmapImageLayoutTest.WriteBackRemovesStaleOppositeFormatSparseFiles:UndoHistoryTest.*SceneGraph*:UndoHistoryTest.*Delete* --gtest_brief=1 --gtest_color=nopassed, 25/25 tests.