Status: draft for maintainer review
This proposal recommends two core document objects:
App::ClippingPlaneas the reusable spatial clipping primitiveApp::SavedViewas the higher-level persisted view-state object
The key design choice is to keep clipping definition separate from saved camera and visibility state.
That split gives us:
- a general clipping feature usable anywhere in FreeCAD
- a saved-view workflow comparable to other CAD systems
- a clean path toward attachment, multiple planes, scoped clipping, and optional OCC-based section geometry later
This proposal borrows the user-facing direction of realthunder's SavedView feature, but not its exact storage model.
What to borrow:
- a first-class
SavedViewobject as the main user-facing "restore this view state" feature - partial capture and partial restore instead of forcing one monolithic state bundle
- draggable clipping-plane interaction and visible plane controls
- Coin-based runtime clipping for live view analysis
What not to copy directly:
- clipping existing only as saved view state, with no standalone clipping-plane object
- hidden dynamic-property bags as the main long-term persistence model
- hard-coded X/Y/Z/custom plane slots as the core document abstraction
- restore logic coupled to a specific clipping dialog or widget
Resulting adaptation for core FreeCAD:
App::ClippingPlaneis the typed, reusable document primitiveApp::SavedViewis the higher-level named view-state objectGui::ClippingPlaneManagerowns live per-view Coin clipping stateSavedViewrestores clipping by referencingClippingPlaneobjects, not by being the only place where clip definitions exist
If clipping exists only as state inside a saved view, it becomes awkward to reuse for:
- direct interactive clipping without creating a saved view
- attachment to model references
- multiple active planes
- scoped clipping
- future section/profile generation
If clipping exists only as a standalone plane object, we still miss the user-facing workflow of restoring a named view with camera, visibility, and clipping state together.
So the core model should be:
ClippingPlanedefines clip geometry and clipping behaviorSavedViewstores a named view state and may reference zero, one, or many clipping planes
Purpose:
- persistent clipping-plane definition
- reusable across views and workflows
- spatial object in the document tree
Base type:
App::GeoFeature
Rationale:
- it already provides
Placement - it is the right core base for spatial reference objects
- it avoids introducing a
Partdependency just to represent a plane - it works naturally with nested placements, groups, and links
v1 persistent properties:
PlacementfromApp::GeoFeatureReverse : App::PropertyBool
Likely follow-up properties:
Reference : App::PropertyXLinkSubOffset : App::PropertyDistanceScopeMode : App::PropertyEnumerationTargets : App::PropertyXLinkSubListExtentMode : App::PropertyEnumerationSizeX : App::PropertyLengthSizeY : App::PropertyLength
Notes:
- by default the clip is infinite
- bounded extents are a follow-up, not a blocker for v1
Reference + Offsetis the right long-term model for attachment- free use without attachment remains plain
Placement
Purpose:
- persistent named view-state object
- restores camera, visibility, and clipping configuration
- acts as the user-facing “saved state” feature
Base type:
App::DocumentObject
Rationale:
- it is not a spatial object itself
- it does not need
Placement - it is a document-level state container
v2 persistent properties:
CameraState : App::PropertyFloatListVisibilityState : App::PropertyMapRestoreCamera : App::PropertyBoolRestoreVisibility : App::PropertyBoolRestoreClipping : App::PropertyBoolClipPlanes : App::PropertyXLinkList
Possible follow-up properties:
- display-mode state
- exploded/hidden/isolation state
- section-display preferences
Notes:
SavedViewshould referenceClippingPlaneobjects rather than embedding raw clipping definitions- allowing zero clip planes is important, because saved views are useful even without clipping
Files:
src/Gui/ViewProviderClippingPlane.hsrc/Gui/ViewProviderClippingPlane.cpp
Responsibilities:
- draw the clipping-plane glyph
- expose view-only display properties
- provide edit / double-click entry points
- support manipulator-based interaction later
View properties for ClippingPlane:
DisplayLengthDisplayHeightArrowSizeLineColorTransparencyCutMarginShowLabel
These are display properties only. They should not define activation state.
Files:
src/Gui/ViewProviderSavedView.hsrc/Gui/ViewProviderSavedView.cpp
Responsibilities:
- tree/object interaction for
SavedView - context actions such as restore, overwrite, update from current view
This object likely does not need a 3D representation in v1/v2.
Files:
src/Gui/ClippingPlaneManager.hsrc/Gui/ClippingPlaneManager.cpp
Responsibilities:
- maintain runtime activation state per 3D view
- translate
App::ClippingPlaneinto Coin clip definitions - install and remove
SoClipPlanenodes - react to object edits, deletion, and document close
This manager is the core runtime layer and should be designed from the start to evolve toward:
- multiple active planes per view
- scoped clipping
- saved-view restoration of clip sets
This can be a small helper rather than a formal public class, but the responsibility needs to exist.
Responsibilities:
- capture the active view into an
App::SavedView - restore a saved view into the active 3D view
- activate referenced clipping planes through
ClippingPlaneManager
ClippingPlane activation should be runtime-only, per 3D view.
This state should not be stored on the App::ClippingPlane object.
Why:
- turning a clip on/off is a session action
- it should not dirty the document
- a single clipping plane may be active in one view and inactive in another
Unsaved clipping should also remain runtime-only.
Recommended interaction model:
- opening the clipping tool creates transient GUI-managed clipping state only
- closing the tool without saving discards that state
- saving materializes one or more real document objects such as
App::ClippingPlaneorApp::SavedView
This follows the useful user-facing aspect of the measurement workflow without introducing hidden temporary document objects.
SavedView is different:
- its persisted contents are part of the document
- restoring a saved view is a runtime action
- updating or overwriting a saved view is a document modification
Visual clipping should be handled by Coin:
SoClipPlane- optionally
SoClipPlaneManip
OCC is not required for:
- live clipping
- attached or free clip-plane placement
- saved views restoring clip state
OCC should only enter when we want:
- section profiles
- capped cut faces
- filled cut geometry
- parametric section result objects
Goal:
- land a core
App::ClippingPlaneandGui::ViewProviderClippingPlane - land a
Gui::ClippingPlaneManager - support Coin-based whole-document clipping
- support one active clipping plane per 3D view
Included:
- create/delete/save/restore clipping plane
- edit placement
- reverse direction
- activate/deactivate in active 3D view
- visual plane glyph
Excluded:
SavedView- attachment
- scope filtering
- multi-plane activation
- geometry generation
Files for PR1:
App:
src/App/ClippingPlane.hsrc/App/ClippingPlane.cppsrc/App/CMakeLists.txt
Gui:
src/Gui/ViewProviderClippingPlane.hsrc/Gui/ViewProviderClippingPlane.cppsrc/Gui/ClippingPlaneManager.hsrc/Gui/ClippingPlaneManager.cppsrc/Gui/TaskClippingPlane.hsrc/Gui/TaskClippingPlane.cppsrc/Gui/TaskClippingPlane.uisrc/Gui/CommandView.cppsrc/Gui/CMakeLists.txt- icon/resource registration files
Tests:
src/Mod/Test/TestClipPlaneApp.pysrc/Mod/Test/TestClipPlaneGui.py
Acceptance criteria:
- clipping plane can be created from GUI
- object appears in tree
- placement changes update the displayed plane
- activation clips the active 3D view
- reverse flips the clipped side
- save/reopen preserves definition
- activation does not dirty the document
Goal:
- introduce a core
App::SavedView - persist named view states
- allow restoring one or more referenced clipping planes as part of that state
Included:
- create saved view from current active view
- restore camera and visibility
- restore clipping through
ClippingPlaneManager - overwrite/update a saved view
Files for PR2:
App:
src/App/SavedView.hsrc/App/SavedView.cppsrc/App/CMakeLists.txt
Gui:
src/Gui/ViewProviderSavedView.hsrc/Gui/ViewProviderSavedView.cppsrc/Gui/TaskSavedView.hsrc/Gui/TaskSavedView.cpp- command wiring and icon/resource registration
Tests:
src/Mod/Test/TestSavedViewApp.pysrc/Mod/Test/TestSavedViewGui.py
Acceptance criteria:
- saved view persists camera and visibility state
- saved view can reference clip planes
- restoring a saved view activates the referenced clip planes in the current 3D view
Goal:
- make clip planes practical for model-driven workflows
Included:
ReferenceOffset- free vs attached manipulation behavior
SizeX/SizeYor equivalent bounded extents model
Interaction model:
- attached plane: manipulator primarily edits offset and local transform
- unattached plane: manipulator edits placement directly
Goal:
- support multiple active clipping planes per view
- enable “quarter cut” and similar workflows
Included:
- manager-side support for clip sets
SavedViewreferences to multiple clip planes- activation rules for multiple planes in one view
Goal:
- optional generated section/profile outputs
Included:
- section profile object generation
- capped/fill-ready geometry
- future downstream use in documentation workflows
TestClipPlaneApp.py
- create
App::ClippingPlane - verify default properties
- verify
Placementpersistence - verify
Reversepersistence
TestSavedViewApp.py
- create
App::SavedView - verify camera and clip-plane reference persistence
- verify update/overwrite behavior
TestClipPlaneGui.py
- create object through command
- activate/deactivate in a 3D view
- verify activation does not mark the document modified
- verify deleting an active clipping plane cleans up runtime state
TestSavedViewGui.py
- capture current view to a saved view
- restore saved view
- verify restored camera state
- verify referenced clip planes are activated through the manager
- Do we agree with using realthunder's
SavedViewas the UX precedent for the user-facing feature? - Do we agree with intentionally diverging from that implementation by introducing a typed
App::ClippingPlane, instead of keeping clipping only as state insideSavedView? - Is
App::GeoFeaturethe right base type forApp::ClippingPlane? - Is
App::DocumentObjectthe right base type forApp::SavedView? - Is it acceptable that
ClippingPlaneactivation remains runtime-only and per-view? - Should
SavedViewreference clip planes rather than embed raw clip definitions? - Is one active clipping plane per view acceptable for PR1 if the manager is designed to expand later?
- Is the proposed sequencing acceptable:
ClippingPlanefirst,SavedViewsecond?