@@ -21,18 +21,15 @@ import { CarouselPanel } from "./CarouselPanel.js";
2121import type { ComponentKey } from "./ComponentCarousel.js" ;
2222import { DetectorView } from "./detectors/DetectorView.js" ;
2323import { EditContainerNode } from "./EditContainerNode.js" ;
24- import { focalMarkersVisibleProperty } from "./FocalMarkersVisibleProperty.js" ;
25- import { handlesVisibleProperty } from "./HandlesVisibleProperty.js" ;
2624import { ImageOverlayNode } from "./ImageOverlayNode.js" ;
2725import { InfoDialogNode } from "./InfoDialogNode.js" ;
2826import { ObserverNode } from "./ObserverNode.js" ;
2927import { createOpticalElementView , type OpticalElementView } from "./OpticalElementViewFactory.js" ;
30- import { rayArrowsVisibleProperty } from "./RayArrowsVisibleProperty.js" ;
3128import { RayPropagationView } from "./RayPropagationView.js" ;
32- import { rayStubsEnabledProperty } from "./RayStubsProperty.js" ;
3329import { sceneHistoryRegistry } from "./SceneHistoryRegistry.js" ;
3430import { downloadSceneSVG } from "./SceneSVGExporter.js" ;
3531import { ToolsPanel } from "./ToolsPanel.js" ;
32+ import { ViewOptionsModel } from "./ViewOptionsModel.js" ;
3633import { viewSnapState } from "./ViewSnapState.js" ;
3734
3835/**
@@ -83,6 +80,10 @@ function tryHandleToolsPanelShortcut(
8380 extendedRaysProperty : BooleanProperty ;
8481 gridVisibleProperty : BooleanProperty ;
8582 snapToGridProperty : BooleanProperty ;
83+ handlesVisibleProperty : BooleanProperty ;
84+ focalMarkersVisibleProperty : BooleanProperty ;
85+ rayArrowsVisibleProperty : BooleanProperty ;
86+ rayStubsEnabledProperty : BooleanProperty ;
8687 } ,
8788) : boolean {
8889 if ( isTextInput || event . ctrlKey || event . metaKey || event . altKey || event . key . length !== 1 ) {
@@ -95,6 +96,10 @@ function tryHandleToolsPanelShortcut(
9596 extendedRaysProperty,
9697 gridVisibleProperty,
9798 snapToGridProperty,
99+ handlesVisibleProperty,
100+ focalMarkersVisibleProperty,
101+ rayArrowsVisibleProperty,
102+ rayStubsEnabledProperty,
98103 } = locals ;
99104 if ( letter === "m" ) {
100105 measuringTapeVisibleProperty . toggle ( ) ;
@@ -178,6 +183,9 @@ export class RayTracingCommonView extends ScreenView {
178183 /** Maps element id → view so we can remove views and provide rebuild callbacks. */
179184 private readonly elementViewMap = new Map < string , OpticalElementView > ( ) ;
180185
186+ /** Per-screen view state (handles visibility, ray arrows, focal markers, etc.). */
187+ protected readonly viewOptions : ViewOptionsModel ;
188+
181189 /**
182190 * Maps element id → its Tandem so we can remove it from the global tandem tree on deletion.
183191 * RichDragListener is not a PhetioObject, so its tandem's dispose() is never triggered
@@ -230,6 +238,8 @@ export class RayTracingCommonView extends ScreenView {
230238 const tandem = options ?. tandem ;
231239 const uiStrings = StringManager . getInstance ( ) . getUIStrings ( ) ;
232240
241+ this . viewOptions = new ViewOptionsModel ( tandem ?. createTandem ( "viewOptions" ) ) ;
242+
233243 // ── Model-View Transform ────────────────────────────────────────────────
234244 // Maps model origin (0, 0) to the centre of the visible play area.
235245 // 100 px = 1 m; y-axis is inverted (model +y = up, view +y = down).
@@ -316,7 +326,11 @@ export class RayTracingCommonView extends ScreenView {
316326 viewSnapState . setSnapToGrid ( snapToGridProperty ) ;
317327
318328 // ── Ray Propagation Layer (behind elements so rays don't block handles) ─
319- this . rayPropagationView = new RayPropagationView ( this . visibleBoundsProperty . value , modelViewTransform ) ;
329+ this . rayPropagationView = new RayPropagationView (
330+ this . visibleBoundsProperty . value ,
331+ modelViewTransform ,
332+ this . viewOptions ,
333+ ) ;
320334 this . visibleBoundsProperty . link ( ( visibleBounds ) => {
321335 this . rayPropagationView . canvasBounds = visibleBounds ;
322336 } ) ;
@@ -398,7 +412,7 @@ export class RayTracingCommonView extends ScreenView {
398412 // view already exists and skips duplicate creation.
399413 const tandemName = element . id . replace ( / - ( \d + ) $ / , ( _ , n ) => n ) ;
400414 const elementTandem = tandem ?. createTandem ( tandemName ) ?? Tandem . OPTIONAL ;
401- const view = createOpticalElementView ( element , modelViewTransform , elementTandem ) ;
415+ const view = createOpticalElementView ( element , modelViewTransform , elementTandem , this . viewOptions ) ;
402416 if ( view ) {
403417 this . elementTandemMap . set ( element . id , elementTandem ) ;
404418 this . _setupView ( element , view ) ;
@@ -435,7 +449,7 @@ export class RayTracingCommonView extends ScreenView {
435449 for ( const element of model . scene . getAllElements ( ) ) {
436450 const tandemName = element . id . replace ( / - ( \d + ) $ / , ( _ , n ) => n ) ;
437451 const elementTandem = tandem ?. createTandem ( tandemName ) ?? Tandem . OPTIONAL ;
438- const elementView = createOpticalElementView ( element , modelViewTransform , elementTandem ) ;
452+ const elementView = createOpticalElementView ( element , modelViewTransform , elementTandem , this . viewOptions ) ;
439453 if ( elementView ) {
440454 this . elementTandemMap . set ( element . id , elementTandem ) ;
441455 this . _setupView ( element , elementView ) ;
@@ -452,7 +466,7 @@ export class RayTracingCommonView extends ScreenView {
452466 }
453467 const tn = element . id . replace ( / - ( \d + ) $ / , ( _ , n : string ) => n ) ;
454468 const et = tandem ?. createTandem ( tn ) ?? Tandem . OPTIONAL ;
455- const view = createOpticalElementView ( element , modelViewTransform , et ) ;
469+ const view = createOpticalElementView ( element , modelViewTransform , et , this . viewOptions ) ;
456470 if ( view ) {
457471 this . elementTandemMap . set ( element . id , et ) ;
458472 this . _setupView ( element , view ) ;
@@ -492,6 +506,7 @@ export class RayTracingCommonView extends ScreenView {
492506 this . selectedElementProperty ,
493507 this . visibleBoundsProperty ,
494508 _opticsLabPreferences . snapToGridProperty ,
509+ this . viewOptions ,
495510 tandem ,
496511 ) ;
497512 this . addChild ( toolsPanel ) ;
@@ -526,7 +541,7 @@ export class RayTracingCommonView extends ScreenView {
526541 viewState : {
527542 showGrid : model . scene . showGridProperty . value ,
528543 gridSpacing : model . scene . gridSizeProperty . value ,
529- showHandles : handlesVisibleProperty . value ,
544+ showHandles : this . viewOptions . handlesVisibleProperty . value ,
530545 measuringTape : {
531546 visible : toolsPanel . measuringTapeVisibleProperty . value ,
532547 basePosition : toolsPanel . measuringTapeNode . basePositionProperty . value . copy ( ) ,
@@ -618,6 +633,10 @@ export class RayTracingCommonView extends ScreenView {
618633 extendedRaysProperty : toolsPanel . extendedRaysProperty ,
619634 gridVisibleProperty : model . scene . showGridProperty ,
620635 snapToGridProperty : _opticsLabPreferences . snapToGridProperty ,
636+ handlesVisibleProperty : this . viewOptions . handlesVisibleProperty ,
637+ focalMarkersVisibleProperty : this . viewOptions . focalMarkersVisibleProperty ,
638+ rayArrowsVisibleProperty : this . viewOptions . rayArrowsVisibleProperty ,
639+ rayStubsEnabledProperty : this . viewOptions . rayStubsEnabledProperty ,
621640 } )
622641 ) {
623642 event . preventDefault ( ) ;
@@ -667,6 +686,7 @@ export class RayTracingCommonView extends ScreenView {
667686 public override dispose ( ) : void {
668687 window . removeEventListener ( "keydown" , this . _handleKeyDown ) ;
669688 super . dispose ( ) ;
689+ this . viewOptions . dispose ( ) ;
670690 }
671691
672692 public override step ( _dt : number ) : void {
0 commit comments