浏览代码

Refactor the HUD and separate internal components from user space

customisations
alemart 5 个月前
父节点
当前提交
010228ea5f
共有 5 个文件被更改,包括 82 次插入59 次删除
  1. 44
    6
      src/core/hud.ts
  2. 6
    12
      src/core/session.ts
  3. 14
    15
      src/core/viewport.ts
  4. 6
    2
      src/ui/fullscreen-button.ts
  5. 12
    24
      src/ui/stats-panel.ts

+ 44
- 6
src/core/hud.ts 查看文件

20
  * Heads Up Display
20
  * Heads Up Display
21
  */
21
  */
22
 
22
 
23
-import { Nullable, Utils } from "../utils/utils";
23
+import { Viewport } from './viewport';
24
+import { StatsPanel } from '../ui/stats-panel';
25
+import { FullscreenButton } from '../ui/fullscreen-button';
26
+import { Nullable, Utils } from '../utils/utils';
24
 
27
 
25
 /** HUD container */
28
 /** HUD container */
26
 export type HUDContainer = HTMLDivElement;
29
 export type HUDContainer = HTMLDivElement;
36
     /** Whether or not we have created our own container */
39
     /** Whether or not we have created our own container */
37
     private _isOwnContainer: boolean;
40
     private _isOwnContainer: boolean;
38
 
41
 
42
+    /** Container for the internal components */
43
+    private _internalContainer: ShadowRoot;
44
+
45
+    /** Stats panel */
46
+    #statsPanel: StatsPanel;
47
+
48
+    /** Fullscreen button */
49
+    #fullscreenButton: FullscreenButton;
50
+
39
 
51
 
40
 
52
 
41
     /**
53
     /**
42
      * Constructor
54
      * Constructor
55
+     * @param viewport viewport
43
      * @param parent parent of the hud container
56
      * @param parent parent of the hud container
44
      * @param hudContainer an existing hud container (optional)
57
      * @param hudContainer an existing hud container (optional)
45
      */
58
      */
46
-    constructor(parent: HTMLElement, hudContainer: Nullable<HUDContainer>)
59
+    constructor(viewport: Viewport, parent: HTMLElement, hudContainer: Nullable<HUDContainer> = null)
47
     {
60
     {
48
         this._container = hudContainer || this._createContainer(parent);
61
         this._container = hudContainer || this._createContainer(parent);
49
         this._isOwnContainer = (hudContainer == null);
62
         this._isOwnContainer = (hudContainer == null);
59
             Utils.warning(`The container of the HUD should have the hidden attribute`);
72
             Utils.warning(`The container of the HUD should have the hidden attribute`);
60
             this._container.hidden = true;
73
             this._container.hidden = true;
61
         }
74
         }
75
+
76
+        // create a shadow tree for the internal components
77
+        this._internalContainer = parent.attachShadow({ mode: 'closed' });
78
+        this._internalContainer.appendChild(document.createElement('slot'));
79
+
80
+        // create internal components
81
+        this.#statsPanel = new StatsPanel();
82
+        this.#fullscreenButton = new FullscreenButton(viewport);
62
     }
83
     }
63
 
84
 
64
     /**
85
     /**
86
     }
107
     }
87
 
108
 
88
     /**
109
     /**
110
+     * Stats panel
111
+     * @internal
112
+     */
113
+    get _statsPanel(): StatsPanel
114
+    {
115
+        return this.#statsPanel; // same name
116
+    }
117
+
118
+    /**
89
      * Initialize the HUD
119
      * Initialize the HUD
90
      * @param zIndex the z-index of the container
120
      * @param zIndex the z-index of the container
121
+     * @param wantStatsPanel
122
+     * @param wantFullscreenButton
91
      * @internal
123
      * @internal
92
      */
124
      */
93
-    _init(zIndex: number): void
125
+    _init(zIndex: number, wantStatsPanel: boolean, wantFullscreenButton: boolean): void
94
     {
126
     {
95
-        const container = this._container;
127
+        const parent = this._internalContainer;
128
+        this.#statsPanel.init(parent, wantStatsPanel);
129
+        this.#fullscreenButton.init(parent, wantFullscreenButton);
96
 
130
 
131
+        const container = this._container;
97
         container.style.position = 'absolute';
132
         container.style.position = 'absolute';
98
         container.style.left = container.style.top = '0px';
133
         container.style.left = container.style.top = '0px';
99
         container.style.right = container.style.bottom = '0px';
134
         container.style.right = container.style.bottom = '0px';
112
     {
147
     {
113
         this.visible = false;
148
         this.visible = false;
114
 
149
 
150
+        this.#fullscreenButton.release();
151
+        this.#statsPanel.release();
152
+
115
         if(this._isOwnContainer) {
153
         if(this._isOwnContainer) {
116
             this._isOwnContainer = false;
154
             this._isOwnContainer = false;
117
             this._container.remove();
155
             this._container.remove();
125
      */
163
      */
126
     private _createContainer(parent: HTMLElement): HUDContainer
164
     private _createContainer(parent: HTMLElement): HUDContainer
127
     {
165
     {
128
-        const node = document.createElement('div') as HTMLDivElement;
166
+        const node = document.createElement('div');
129
 
167
 
130
         node.hidden = true;
168
         node.hidden = true;
131
         parent.insertAdjacentElement('afterbegin', node);
169
         parent.insertAdjacentElement('afterbegin', node);
132
 
170
 
133
         return node;
171
         return node;
134
     }
172
     }
135
-}
173
+}

+ 6
- 12
src/core/session.ts 查看文件

31
 import { Viewport } from './viewport';
31
 import { Viewport } from './viewport';
32
 import { Settings } from './settings';
32
 import { Settings } from './settings';
33
 import { Stats } from './stats';
33
 import { Stats } from './stats';
34
-import { StatsPanel } from '../ui/stats-panel';
35
 import { Gizmos } from '../ui/gizmos';
34
 import { Gizmos } from '../ui/gizmos';
36
 import { Frame } from './frame';
35
 import { Frame } from './frame';
37
 import { Tracker } from '../trackers/tracker';
36
 import { Tracker } from '../trackers/tracker';
132
     /** Render stats (FPS) */
131
     /** Render stats (FPS) */
133
     private _renderStats: Stats;
132
     private _renderStats: Stats;
134
 
133
 
135
-    /** Stats panel */
136
-    private _statsPanel: StatsPanel;
137
-
138
     /** Gizmos */
134
     /** Gizmos */
139
     private _gizmos: Gizmos;
135
     private _gizmos: Gizmos;
140
 
136
 
174
         // setup the viewport
170
         // setup the viewport
175
         this._viewport = viewport;
171
         this._viewport = viewport;
176
         if(this._primarySource !== null)
172
         if(this._primarySource !== null)
177
-            this._viewport._init(() => this._primarySource!._internalMedia.size, mode);
173
+            this._viewport._init(() => this._primarySource!._internalMedia.size, mode, stats);
178
         else
174
         else
179
-            this._viewport._init(() => Utils.resolution('sm', window.innerWidth / window.innerHeight), mode);
180
-
181
-        // setup the stats panel
182
-        this._statsPanel = new StatsPanel(this._viewport);
183
-        this._statsPanel.visible = stats;
175
+            this._viewport._init(() => Utils.resolution('sm', window.innerWidth / window.innerHeight), mode, stats);
184
 
176
 
185
         // done!
177
         // done!
186
         Session._count++;
178
         Session._count++;
397
             // release internal components
389
             // release internal components
398
             this._updateStats.reset();
390
             this._updateStats.reset();
399
             this._renderStats.reset();
391
             this._renderStats.reset();
400
-            this._statsPanel.release();
401
             this._viewport._release();
392
             this._viewport._release();
402
 
393
 
403
             // end the session
394
             // end the session
735
 
726
 
736
                 // update internals
727
                 // update internals
737
                 this._renderStats.update();
728
                 this._renderStats.update();
738
-                this._statsPanel.update(time, this._sources, this._trackers, this._viewport, this._updateStats.cyclesPerSecond, this._renderStats.cyclesPerSecond);
739
                 this._frameReady = false;
729
                 this._frameReady = false;
740
 
730
 
731
+                // update stats panel
732
+                const statsPanel = this._viewport.hud._statsPanel;
733
+                statsPanel.update(time, this._sources, this._trackers, this._viewport, this._updateStats.cyclesPerSecond, this._renderStats.cyclesPerSecond);
734
+
741
             }
735
             }
742
             else {
736
             else {
743
 
737
 

+ 14
- 15
src/core/viewport.ts 查看文件

26
 import { SpeedyPromise } from 'speedy-vision/types/core/speedy-promise';
26
 import { SpeedyPromise } from 'speedy-vision/types/core/speedy-promise';
27
 import { SessionMode } from './session';
27
 import { SessionMode } from './session';
28
 import { HUD, HUDContainer } from './hud';
28
 import { HUD, HUDContainer } from './hud';
29
-import { FullscreenButton } from '../ui/fullscreen-button';
30
 import { Vector2 } from '../geometry/vector2';
29
 import { Vector2 } from '../geometry/vector2';
31
 import { Resolution } from '../utils/resolution';
30
 import { Resolution } from '../utils/resolution';
32
 import { Nullable } from '../utils/utils';
31
 import { Nullable } from '../utils/utils';
794
     /** Viewport resolution (controls the size of the drawing buffer of the foreground canvas) */
793
     /** Viewport resolution (controls the size of the drawing buffer of the foreground canvas) */
795
     private readonly _resolution: Resolution;
794
     private readonly _resolution: Resolution;
796
 
795
 
796
+    /** Viewport settings */
797
+    private readonly _settings: Readonly<Required<ViewportSettings>>
798
+
797
     /** The containers */
799
     /** The containers */
798
     private readonly _containers: ViewportContainers;
800
     private readonly _containers: ViewportContainers;
799
 
801
 
815
     /** Fullscreen utilities */
817
     /** Fullscreen utilities */
816
     private readonly _fullscreen: ViewportFullscreenHelper;
818
     private readonly _fullscreen: ViewportFullscreenHelper;
817
 
819
 
818
-    /** Built-in fullscreen button */
819
-    private readonly _fullscreenButton: Nullable<FullscreenButton>;
820
 
820
 
821
 
821
 
822
 
822
 
827
      */
827
      */
828
     constructor(viewportSettings: ViewportSettings)
828
     constructor(viewportSettings: ViewportSettings)
829
     {
829
     {
830
-        const settings = Object.assign({}, DEFAULT_VIEWPORT_SETTINGS, viewportSettings);
831
-
832
         super();
830
         super();
833
 
831
 
832
+        const settings = Object.assign({}, DEFAULT_VIEWPORT_SETTINGS, viewportSettings);
833
+        this._settings = Object.freeze(settings);
834
+
834
         const guessedAspectRatio = window.innerWidth / window.innerHeight;
835
         const guessedAspectRatio = window.innerWidth / window.innerHeight;
835
         const initialSize = Utils.resolution(settings.resolution, guessedAspectRatio);
836
         const initialSize = Utils.resolution(settings.resolution, guessedAspectRatio);
836
         this._mediaSize = () => initialSize;
837
         this._mediaSize = () => initialSize;
839
         this._style = settings.style;
840
         this._style = settings.style;
840
 
841
 
841
         this._containers = new ViewportContainers(settings.container);
842
         this._containers = new ViewportContainers(settings.container);
842
-        this._hud = new HUD(this._subContainer, settings.hudContainer);
843
+        this._hud = new HUD(this, this._subContainer, settings.hudContainer);
843
         this._canvases = new ViewportCanvases(this._subContainer, initialSize, settings.canvas);
844
         this._canvases = new ViewportCanvases(this._subContainer, initialSize, settings.canvas);
844
 
845
 
845
         this._resizer = new ViewportResizer(this);
846
         this._resizer = new ViewportResizer(this);
846
         this._resizer.setStrategyByName(this._style);
847
         this._resizer.setStrategyByName(this._style);
847
 
848
 
848
         this._fullscreen = new ViewportFullscreenHelper(this);
849
         this._fullscreen = new ViewportFullscreenHelper(this);
849
-        this._fullscreenButton = null;
850
-
851
-        if(settings.fullscreenUI && this.fullscreenAvailable)
852
-            this._fullscreenButton = new FullscreenButton(this);
853
     }
850
     }
854
 
851
 
855
     /**
852
     /**
1054
      * Initialize the viewport (when the session starts)
1051
      * Initialize the viewport (when the session starts)
1055
      * @param getMediaSize
1052
      * @param getMediaSize
1056
      * @param sessionMode
1053
      * @param sessionMode
1054
+     * @param wantStatsPanel
1057
      * @internal
1055
      * @internal
1058
      */
1056
      */
1059
-    _init(getMediaSize: ViewportSizeGetter, sessionMode: SessionMode): void
1057
+    _init(getMediaSize: ViewportSizeGetter, sessionMode: SessionMode, wantStatsPanel: boolean): void
1060
     {
1058
     {
1061
         // validate if the viewport style matches the session mode
1059
         // validate if the viewport style matches the session mode
1062
         if(sessionMode == 'immersive') {
1060
         if(sessionMode == 'immersive') {
1079
 
1077
 
1080
         // initialize the components
1078
         // initialize the components
1081
         this._containers.init();
1079
         this._containers.init();
1082
-        this._hud._init(HUD_ZINDEX);
1083
         this._canvases.init();
1080
         this._canvases.init();
1084
         this._resizer.init();
1081
         this._resizer.init();
1085
         this._fullscreen.init();
1082
         this._fullscreen.init();
1086
-        this._fullscreenButton?.init();
1083
+
1084
+        // initialize the HUD
1085
+        const wantFullscreenButton = this.fullscreenAvailable && this._settings.fullscreenUI;
1086
+        this._hud._init(HUD_ZINDEX, wantStatsPanel, wantFullscreenButton);
1087
     }
1087
     }
1088
 
1088
 
1089
     /**
1089
     /**
1092
      */
1092
      */
1093
     _release(): void
1093
     _release(): void
1094
     {
1094
     {
1095
-        this._fullscreenButton?.release();
1095
+        this._hud._release();
1096
         this._fullscreen.release();
1096
         this._fullscreen.release();
1097
         this._resizer.release();
1097
         this._resizer.release();
1098
         this._canvases.release();
1098
         this._canvases.release();
1099
-        this._hud._release();
1100
         this._containers.release();
1099
         this._containers.release();
1101
     }
1100
     }
1102
 }
1101
 }

+ 6
- 2
src/ui/fullscreen-button.ts 查看文件

65
 
65
 
66
     /**
66
     /**
67
      * Initialize
67
      * Initialize
68
+     * @param parent parent node
69
+     * @param isVisible
68
      */
70
      */
69
-    init(): void
71
+    init(parent: Node, isVisible: boolean): void
70
     {
72
     {
71
-        this._viewport.hud.container.appendChild(this._button);
73
+        parent.appendChild(this._button);
74
+        this._button.hidden = !isVisible;
72
         this._viewport.addEventListener('fullscreenchange', this._boundEventHandler);
75
         this._viewport.addEventListener('fullscreenchange', this._boundEventHandler);
73
     }
76
     }
74
 
77
 
95
         button.style.height = BUTTON_SIZE + 'px';
98
         button.style.height = BUTTON_SIZE + 'px';
96
 
99
 
97
         button.style.opacity = '0.5';
100
         button.style.opacity = '0.5';
101
+        button.style.zIndex = '1000000';
98
         button.style.cursor = 'pointer';
102
         button.style.cursor = 'pointer';
99
         button.style.outline = 'none';
103
         button.style.outline = 'none';
100
         (button.style as any)['-webkit-tap-highlight-color'] = 'transparent';
104
         (button.style as any)['-webkit-tap-highlight-color'] = 'transparent';

+ 12
- 24
src/ui/stats-panel.ts 查看文件

49
  */
49
  */
50
 export class StatsPanel
50
 export class StatsPanel
51
 {
51
 {
52
-    /** The viewport associated to this panel */
53
-    private readonly _viewport: Viewport;
54
-
55
     /** A container for the panel */
52
     /** A container for the panel */
56
     private readonly _container: HTMLDivElement;
53
     private readonly _container: HTMLDivElement;
57
 
54
 
63
 
60
 
64
     /**
61
     /**
65
      * Constructor
62
      * Constructor
66
-     * @param viewport Viewport
67
      */
63
      */
68
-    constructor(viewport: Viewport)
64
+    constructor()
69
     {
65
     {
70
-        this._viewport = viewport;
66
+        this._container = this._createContainer();
71
         this._lastUpdate = 0;
67
         this._lastUpdate = 0;
68
+    }
72
 
69
 
73
-        this._container = this._createContainer();
74
-        viewport.hud.container.appendChild(this._container);
70
+    /**
71
+     * Initialize the panel
72
+     * @param parent parent node
73
+     * @param isVisible
74
+     */
75
+    init(parent: Node, isVisible: boolean): void
76
+    {
77
+        parent.appendChild(this._container);
78
+        this._container.hidden = !isVisible;
75
     }
79
     }
76
 
80
 
77
     /**
81
     /**
100
     }
104
     }
101
 
105
 
102
     /**
106
     /**
103
-     * Visibility of the panel
104
-     */
105
-    get visible(): boolean
106
-    {
107
-        return !this._container.hidden;
108
-    }
109
-
110
-    /**
111
-     * Visibility of the panel
112
-     */
113
-    set visible(visible: boolean)
114
-    {
115
-        this._container.hidden = !visible;
116
-    }
117
-
118
-    /**
119
      * Update the contents of the panel
107
      * Update the contents of the panel
120
      * @param sources the sources of media linked to the session
108
      * @param sources the sources of media linked to the session
121
      * @param trackers the trackers attached to the session
109
      * @param trackers the trackers attached to the session

正在加载...
取消
保存