@@ -381,7 +381,8 @@ impl Plugin for RenzoraEditorPlugin {
381381 . init_resource :: < ShortcutRegistry > ( )
382382 . init_resource :: < EditorActionHooks > ( )
383383 . init_resource :: < MaterialThumbnailRegistry > ( )
384- . init_resource :: < ModelThumbnailRegistry > ( ) ;
384+ . init_resource :: < ModelThumbnailRegistry > ( )
385+ . init_resource :: < renzora:: core:: IsolationMode > ( ) ;
385386
386387 register_builtin_tools (
387388 & mut app. world_mut ( ) . resource_mut :: < ToolbarRegistry > ( ) ,
@@ -435,6 +436,10 @@ impl Plugin for RenzoraEditorPlugin {
435436 sync_active_tool_to_gizmo_mode. run_if ( in_state ( SplashState :: Editor ) ) ,
436437 )
437438 . add_systems ( Update , apply_vsync_setting)
439+ . add_systems (
440+ Update ,
441+ apply_isolation_mode. run_if ( in_state ( SplashState :: Editor ) ) ,
442+ )
438443 ;
439444 }
440445}
@@ -459,6 +464,73 @@ fn apply_vsync_setting(
459464 }
460465}
461466
467+ /// View menu Isolation Mode: when active, hide all mesh entities that aren't
468+ /// the current selection (or its ancestors/descendants). On deactivate,
469+ /// restore the entities we hid back to `Visibility::Inherited`.
470+ fn apply_isolation_mode (
471+ iso : Res < renzora:: core:: IsolationMode > ,
472+ selection : Res < EditorSelection > ,
473+ children_q : Query < & Children > ,
474+ parent_q : Query < & ChildOf > ,
475+ mut visibility_q : Query <
476+ ( Entity , & mut Visibility ) ,
477+ (
478+ With < Mesh3d > ,
479+ Without < renzora:: core:: EditorCamera > ,
480+ Without < renzora:: core:: HideInHierarchy > ,
481+ ) ,
482+ > ,
483+ mut hidden_entities : Local < Vec < Entity > > ,
484+ mut last_active : Local < bool > ,
485+ ) {
486+ if iso. active == * last_active {
487+ return ;
488+ }
489+ * last_active = iso. active ;
490+
491+ if iso. active {
492+ let mut keep: std:: collections:: HashSet < Entity > = std:: collections:: HashSet :: new ( ) ;
493+ for sel in selection. get_all ( ) {
494+ keep. insert ( sel) ;
495+ let mut cur = sel;
496+ while let Ok ( child_of) = parent_q. get ( cur) {
497+ let parent = child_of. parent ( ) ;
498+ keep. insert ( parent) ;
499+ cur = parent;
500+ }
501+ collect_descendants ( sel, & children_q, & mut keep) ;
502+ }
503+ hidden_entities. clear ( ) ;
504+ for ( entity, mut vis) in & mut visibility_q {
505+ if !keep. contains ( & entity) && * vis != Visibility :: Hidden {
506+ * vis = Visibility :: Hidden ;
507+ hidden_entities. push ( entity) ;
508+ }
509+ }
510+ } else {
511+ let drained: Vec < Entity > = hidden_entities. drain ( ..) . collect ( ) ;
512+ for entity in drained {
513+ if let Ok ( ( _, mut vis) ) = visibility_q. get_mut ( entity) {
514+ * vis = Visibility :: Inherited ;
515+ }
516+ }
517+ }
518+ }
519+
520+ fn collect_descendants (
521+ entity : Entity ,
522+ children_q : & Query < & Children > ,
523+ out : & mut std:: collections:: HashSet < Entity > ,
524+ ) {
525+ if let Ok ( children) = children_q. get ( entity) {
526+ for child in children. iter ( ) {
527+ if out. insert ( child) {
528+ collect_descendants ( child, children_q, out) ;
529+ }
530+ }
531+ }
532+ }
533+
462534/// Observer: show toast notifications when scripts are hot-reloaded.
463535fn show_script_reload_toasts (
464536 trigger : On < renzora:: ScriptsReloaded > ,
@@ -841,6 +913,10 @@ pub fn editor_ui_system(world: &mut World) {
841913 )
842914 } )
843915 . unwrap_or ( ( false , false ) ) ;
916+ let isolation_active = world
917+ . get_resource :: < renzora:: core:: IsolationMode > ( )
918+ . map ( |m| m. active )
919+ . unwrap_or ( false ) ;
844920 let title_action = renzora_ui:: title_bar:: render_title_bar (
845921 & ctx,
846922 & theme,
@@ -852,6 +928,7 @@ pub fn editor_ui_system(world: &mut World) {
852928 & mut window_queue,
853929 can_undo,
854930 can_redo,
931+ isolation_active,
855932 ) ;
856933
857934 // 6. Document tabs (below title bar)
@@ -1166,6 +1243,25 @@ pub fn editor_ui_system(world: &mut World) {
11661243 }
11671244 }
11681245 TitleBarAction :: ResetLayout => reset_layout ( world) ,
1246+ TitleBarAction :: ZoomIn => {
1247+ world. insert_resource ( renzora:: core:: CameraViewRequest :: ZoomIn ) ;
1248+ }
1249+ TitleBarAction :: ZoomOut => {
1250+ world. insert_resource ( renzora:: core:: CameraViewRequest :: ZoomOut ) ;
1251+ }
1252+ TitleBarAction :: ResetZoom => {
1253+ world. insert_resource ( renzora:: core:: CameraViewRequest :: ResetZoom ) ;
1254+ }
1255+ TitleBarAction :: FrameAll => {
1256+ world. insert_resource ( renzora:: core:: CameraViewRequest :: FrameAll ) ;
1257+ }
1258+ TitleBarAction :: ToggleIsolation => {
1259+ let mut iso = world
1260+ . remove_resource :: < renzora:: core:: IsolationMode > ( )
1261+ . unwrap_or_default ( ) ;
1262+ iso. active = !iso. active ;
1263+ world. insert_resource ( iso) ;
1264+ }
11691265 TitleBarAction :: None => { }
11701266 }
11711267
0 commit comments