@preference-sl/pref-viewer 2.11.0-beta.9 → 2.12.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +61 -50
- package/src/babylonjs-animation-controller.js +95 -95
- package/src/babylonjs-animation-opening-menu.js +255 -156
- package/src/babylonjs-animation-opening.js +74 -36
- package/src/babylonjs-controller.js +189 -60
- package/src/file-storage.js +11 -2
- package/src/index.js +18 -912
- package/src/panzoom-controller.js +92 -55
- package/src/pref-viewer-2d.js +15 -3
- package/src/pref-viewer-3d-data.js +3 -2
- package/src/pref-viewer-3d.js +11 -4
- package/src/pref-viewer-dialog.js +16 -9
- package/src/pref-viewer-task.js +1 -1
- package/src/pref-viewer.js +934 -0
- package/src/styles.js +381 -0
- package/src/svg-resolver.js +23 -0
- package/src/css/pref-viewer-2d.css +0 -39
- package/src/css/pref-viewer-3d.css +0 -28
- package/src/css/pref-viewer-dialog.css +0 -105
- package/src/css/pref-viewer.css +0 -11
|
@@ -1,24 +1,40 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import OpeningAnimation from "./babylonjs-animation-opening.js";
|
|
2
|
+
import { PrefViewer3DAnimationMenuStyles } from "./styles.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* OpeningAnimationMenu - Manages and renders the animation control menu for opening/closing animations in a Babylon.js scene.
|
|
5
|
+
* OpeningAnimationMenu - Manages and renders the interactive animation control menu for opening/closing animations in a Babylon.js scene.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Summary:
|
|
8
|
+
* Provides a floating HTML-based GUI menu with playback and loop controls for animated nodes, including buttons, a progress slider, and a selector for switching between multiple animations.
|
|
9
|
+
* Handles user interaction, updates UI state based on animation state, and invokes external callbacks for animation actions.
|
|
10
|
+
* Designed for integration with Babylon.js product configurators and interactive 3D applications.
|
|
11
|
+
*
|
|
12
|
+
* Key Features:
|
|
13
|
+
* - Renders a menu with buttons for controlling animation playback (open, close, pause, go to opened/closed, loop).
|
|
14
|
+
* - Displays a selector UI for switching between multiple opening animations, showing only the animation name without prefix.
|
|
9
15
|
* - Updates button states and slider position based on animation state, progress, and loop mode.
|
|
10
16
|
* - Handles user interactions and invokes provided callbacks for animation actions.
|
|
11
17
|
* - Synchronizes the slider value with animation progress, avoiding callback loops.
|
|
18
|
+
* - Provides setters to update animation state, progress, and loop mode from external controllers.
|
|
19
|
+
* - Disposes and cleans up all DOM resources when no longer needed.
|
|
20
|
+
* - Resets other animation menus when switching between animations.
|
|
12
21
|
*
|
|
13
22
|
* Public Setters:
|
|
14
23
|
* - set animationState(state): Updates the animation state and button states.
|
|
15
24
|
* - set animationProgress(progress): Updates the animation progress and slider value.
|
|
16
25
|
* - set animationLoop(loop): Updates the loop mode and loop button states.
|
|
17
26
|
*
|
|
27
|
+
* Public Methods:
|
|
28
|
+
* - dispose(): Disposes the animation menu and releases all associated DOM resources.
|
|
29
|
+
*
|
|
30
|
+
* Public Getters:
|
|
31
|
+
* - isVisible: Returns whether the animation menu is currently visible in the DOM.
|
|
32
|
+
*
|
|
18
33
|
* Private Methods:
|
|
19
|
-
* - #createMenu(): Initializes and renders the menu UI.
|
|
20
|
-
* - #addButton(name,
|
|
34
|
+
* - #createMenu(): Initializes and renders the menu UI, including the selector, buttons, and slider.
|
|
35
|
+
* - #addButton(name, imageSVG, enabled, active, visible, callback): Adds a button to the menu with specified properties.
|
|
21
36
|
* - #createButtons(): Creates all control buttons and sets their initial states.
|
|
37
|
+
* - #createSelector(): Creates a selector UI element for switching between available opening animations, omitting the prefix in the display name.
|
|
22
38
|
* - #getButtonByName(name): Retrieves a button control by its name.
|
|
23
39
|
* - #setButtonState(name, enabled, active, visible): Updates the visual state of a button.
|
|
24
40
|
* - #getPlayerButtonsState(): Returns the state (enabled, active, visible) for playback control buttons.
|
|
@@ -27,97 +43,75 @@ import { OpeningAnimation } from "./babylonjs-animation-opening.js";
|
|
|
27
43
|
* - #setPlayerButtonsState(): Updates all playback control buttons.
|
|
28
44
|
* - #setLoopButtonsState(): Updates all loop control buttons.
|
|
29
45
|
* - #createSlider(): Creates and configures the animation progress slider.
|
|
46
|
+
* - #onSliderInput(event): Handles the slider input event for animation progress.
|
|
47
|
+
* - #resetOtherAnimations(): Resets all other opening animations except the current one.
|
|
30
48
|
*
|
|
31
49
|
* Usage Example:
|
|
32
|
-
* const menu = new OpeningAnimationMenu(
|
|
50
|
+
* const menu = new OpeningAnimationMenu(name, canvas, state, progress, loop, openingAnimations, {
|
|
33
51
|
* onOpen: () => { ... },
|
|
34
52
|
* onClose: () => { ... },
|
|
35
53
|
* onPause: () => { ... },
|
|
36
54
|
* onGoToOpened: () => { ... },
|
|
37
55
|
* onGoToClosed: () => { ... },
|
|
38
56
|
* onToggleLoop: () => { ... },
|
|
39
|
-
* onSetAnimationProgress: (progress) => { ... }
|
|
57
|
+
* onSetAnimationProgress: (progress) => { ... },
|
|
58
|
+
* onChangeAnimation: () => { ... }
|
|
40
59
|
* });
|
|
41
60
|
* menu.animationState = OpeningAnimation.states.opening;
|
|
42
61
|
* menu.animationProgress = 0.5;
|
|
43
62
|
* menu.animationLoop = true;
|
|
44
63
|
*/
|
|
45
|
-
export class OpeningAnimationMenu {
|
|
64
|
+
export default class OpeningAnimationMenu {
|
|
46
65
|
#animationState = OpeningAnimation.states.closed;
|
|
47
66
|
#animationProgress = 0;
|
|
48
67
|
#animationLoop = false;
|
|
68
|
+
#openingAnimations = [];
|
|
49
69
|
#callbacks = null;
|
|
50
70
|
|
|
51
|
-
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
#
|
|
71
|
+
#name = "";
|
|
72
|
+
#canvas = null;
|
|
73
|
+
#containerMain = null;
|
|
74
|
+
#containerButtons = null;
|
|
55
75
|
#slider = null;
|
|
56
76
|
|
|
57
|
-
// Style properties
|
|
58
|
-
#buttonSize = 28;
|
|
59
|
-
#buttonLoopPaddingLeft = 3;
|
|
60
|
-
#colorActive = "#6BA53A";
|
|
61
|
-
#colorEnabled = "#333333";
|
|
62
|
-
#colorDisabled = "#777777";
|
|
63
|
-
#colorIcon = "#FFFFFF";
|
|
64
|
-
#colorBorder = "#FFFFFF";
|
|
65
|
-
#sliderThumbWidth = 20;
|
|
66
|
-
#sliderBarOffset = 10;
|
|
67
77
|
#icon = {
|
|
68
|
-
close: `<svg id="play-backwards" width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path
|
|
69
|
-
closed: `<svg id="skip-backward" width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path
|
|
70
|
-
open: `<svg id="play" width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path
|
|
71
|
-
opened: `<svg id="skip-forward" width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path
|
|
72
|
-
pause: `<svg id="pause" width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path
|
|
73
|
-
repeat: `<svg id="repeat" width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path
|
|
74
|
-
repeatOff: `<svg id="repeat-off" width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path
|
|
78
|
+
close: `<svg id="play-backwards" width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M16,18.86V4.86l-11,7,11,7Z"/></svg>`,
|
|
79
|
+
closed: `<svg id="skip-backward" width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M20,5V19L13,12M6,5V19H4V5M13,5V19L6,12"/></svg>`,
|
|
80
|
+
open: `<svg id="play" width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M8,5.14v14l11-7-11-7Z"/></svg>`,
|
|
81
|
+
opened: `<svg id="skip-forward" width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M4,5V19L11,12M18,5V19H20V5M11,5V19L18,12"/></svg>`,
|
|
82
|
+
pause: `<svg id="pause" width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M14,19H18V5H14M6,19H10V5H6V19Z"/></svg>`,
|
|
83
|
+
repeat: `<svg id="repeat" width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M17,17H7V14L3,18L7,22V19H19V13H17M7,7H17V10L21,6L17,2V5H5V11H7V7Z"/></svg>`,
|
|
84
|
+
repeatOff: `<svg id="repeat-off" width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M2,5.27L3.28,4L20,20.72L18.73,22L15.73,19H7V22L3,18L7,14V17H13.73L7,10.27V11H5V8.27L2,5.27M17,13H19V17.18L17,15.18V13M17,5V2L21,6L17,10V7H8.82L6.82,5H17Z"/></svg>`,
|
|
75
85
|
};
|
|
76
86
|
|
|
77
|
-
#
|
|
87
|
+
#handler = {
|
|
88
|
+
onSliderInput: null,
|
|
89
|
+
};
|
|
78
90
|
|
|
79
91
|
/**
|
|
80
92
|
* Constructs the OpeningAnimationMenu and initializes the menu UI.
|
|
81
|
-
* @param {
|
|
93
|
+
* @param {string} name - The name of the animation.
|
|
94
|
+
* @param {HTMLCanvasElement} canvas - The canvas element for rendering.
|
|
82
95
|
* @param {number} animationState - Current animation state (enum).
|
|
83
96
|
* @param {number} animationProgress - Current animation progress (0 to 1).
|
|
84
97
|
* @param {boolean} animationLoop - Whether the animation is set to loop.
|
|
98
|
+
* @param {Array<OpeningAnimation>} openingAnimations - Array of OpeningAnimation instances to manage.
|
|
85
99
|
* @param {object} callbacks - Callback functions for menu actions (play, pause, open, close, etc.).
|
|
86
100
|
* @public
|
|
87
101
|
*/
|
|
88
|
-
constructor(
|
|
89
|
-
this.#
|
|
102
|
+
constructor(name, canvas, animationState, animationProgress, animationLoop, openingAnimations, callbacks) {
|
|
103
|
+
this.#name = name;
|
|
104
|
+
this.#canvas = canvas;
|
|
90
105
|
this.#animationState = animationState;
|
|
91
106
|
this.#animationProgress = animationProgress;
|
|
92
107
|
this.#animationLoop = animationLoop;
|
|
108
|
+
this.#openingAnimations = openingAnimations;
|
|
93
109
|
this.#callbacks = callbacks;
|
|
94
110
|
|
|
111
|
+
this.#resetOtherAnimations();
|
|
95
112
|
this.#createMenu(animationState);
|
|
96
113
|
}
|
|
97
114
|
|
|
98
|
-
/**
|
|
99
|
-
* Initializes and renders the menu UI, including buttons and slider.
|
|
100
|
-
* @private
|
|
101
|
-
*/
|
|
102
|
-
#createMenu() {
|
|
103
|
-
if (!this.#advancedDynamicTexture) {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
this.#mainPanel = new StackPanel();
|
|
107
|
-
this.#mainPanel.isVertical = true;
|
|
108
|
-
this.#secondaryPanel = new StackPanel();
|
|
109
|
-
this.#secondaryPanel.isVertical = false;
|
|
110
|
-
this.#secondaryPanel.height = `${this.#buttonSize}px`;
|
|
111
|
-
this.#mainPanel.addControl(this.#secondaryPanel);
|
|
112
|
-
|
|
113
|
-
this.#advancedDynamicTexture.addControl(this.#mainPanel);
|
|
114
|
-
this.#mainPanel.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
|
|
115
|
-
this.#mainPanel.verticalAlignment = Control.VERTICAL_ALIGNMENT_BOTTOM;
|
|
116
|
-
|
|
117
|
-
this.#createButtons();
|
|
118
|
-
this.#createSlider();
|
|
119
|
-
}
|
|
120
|
-
|
|
121
115
|
/**
|
|
122
116
|
* Internal helper to add a button to the menu.
|
|
123
117
|
* Sets button appearance and attaches the callback for user interaction.
|
|
@@ -129,25 +123,61 @@ export class OpeningAnimationMenu {
|
|
|
129
123
|
* @param {boolean} visible - Whether the button is visible.
|
|
130
124
|
* @param {function} callback - Callback to invoke on button click.
|
|
131
125
|
*/
|
|
132
|
-
#addButton(name,
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
};
|
|
142
|
-
const button = Button.CreateImageOnlyButton(`button_animation_${name}`, imageURL);
|
|
143
|
-
Object.assign(button, buttonProps);
|
|
144
|
-
button.image.stretch = Image.STRETCH_UNIFORM;
|
|
145
|
-
button.onPointerUpObservable.add(() => {
|
|
126
|
+
#addButton(name, imageSVG, enabled = true, active = false, visible = true, callback) {
|
|
127
|
+
const stateClass = active ? "active" : enabled ? "enabled" : "disabled";
|
|
128
|
+
const visibilityClass = visible ? "visible" : "hidden";
|
|
129
|
+
|
|
130
|
+
const button = document.createElement("button");
|
|
131
|
+
button.classList.add(stateClass, visibilityClass);
|
|
132
|
+
button.setAttribute("name", `button_animation_${name}`);
|
|
133
|
+
button.innerHTML = imageSVG;
|
|
134
|
+
button.addEventListener("click", (event) => {
|
|
146
135
|
if (callback && typeof callback === "function") {
|
|
147
136
|
callback();
|
|
148
137
|
}
|
|
149
138
|
});
|
|
150
|
-
|
|
139
|
+
|
|
140
|
+
this.#containerButtons.appendChild(button);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Creates a selector UI element for switching between available opening animations.
|
|
145
|
+
* @private
|
|
146
|
+
* @returns {void}
|
|
147
|
+
*/
|
|
148
|
+
#createSelector() {
|
|
149
|
+
if (!Array.isArray(this.#openingAnimations) || this.#openingAnimations.length < 2) {
|
|
150
|
+
return; // No selector needed if only one animation
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const selector = document.createElement("div");
|
|
154
|
+
selector.classList.add("animation-menu-selector");
|
|
155
|
+
|
|
156
|
+
this.#openingAnimations.forEach((animation) => {
|
|
157
|
+
const button = document.createElement("button");
|
|
158
|
+
button.classList.add("button-selector");
|
|
159
|
+
// Remove prefix before "_" for display
|
|
160
|
+
const nameParts = animation.name.split("_");
|
|
161
|
+
button.textContent = nameParts.length > 1 ? nameParts.slice(1).join("_") : animation.name;
|
|
162
|
+
|
|
163
|
+
// Highlight the current animation
|
|
164
|
+
if (animation.name === this.#name) {
|
|
165
|
+
button.classList.add("active");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
button.addEventListener("click", (event) => {
|
|
169
|
+
if (animation.name !== this.#name) {
|
|
170
|
+
if (this.#callbacks.onChangeAnimation && typeof this.#callbacks.onChangeAnimation === "function") {
|
|
171
|
+
this.#callbacks.onChangeAnimation();
|
|
172
|
+
}
|
|
173
|
+
animation.showControls(this.#canvas, this.#openingAnimations);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
selector.appendChild(button);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
this.#containerMain.prepend(selector);
|
|
151
181
|
}
|
|
152
182
|
|
|
153
183
|
/**
|
|
@@ -156,19 +186,55 @@ export class OpeningAnimationMenu {
|
|
|
156
186
|
*/
|
|
157
187
|
#createButtons() {
|
|
158
188
|
const buttonsState = this.#getButtonsState();
|
|
159
|
-
this.#addButton("closed",
|
|
160
|
-
this.#addButton("close",
|
|
161
|
-
this.#addButton("pause",
|
|
162
|
-
this.#addButton("open",
|
|
163
|
-
this.#addButton("opened",
|
|
164
|
-
this.#addButton("repeat",
|
|
165
|
-
this.#addButton("repeatOff",
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
189
|
+
this.#addButton("closed", this.#icon.closed, buttonsState.closed.enabled, buttonsState.closed.active, buttonsState.closed.visible, this.#callbacks.onGoToClosed);
|
|
190
|
+
this.#addButton("close", this.#icon.close, buttonsState.close.enabled, buttonsState.close.active, buttonsState.close.visible, this.#callbacks.onClose);
|
|
191
|
+
this.#addButton("pause", this.#icon.pause, buttonsState.pause.enabled, buttonsState.pause.active, buttonsState.pause.visible, this.#callbacks.onPause);
|
|
192
|
+
this.#addButton("open", this.#icon.open, buttonsState.open.enabled, buttonsState.open.active, buttonsState.open.visible, this.#callbacks.onOpen);
|
|
193
|
+
this.#addButton("opened", this.#icon.opened, buttonsState.opened.enabled, buttonsState.opened.active, buttonsState.opened.visible, this.#callbacks.onGoToOpened);
|
|
194
|
+
this.#addButton("repeat", this.#icon.repeat, buttonsState.repeat.enabled, buttonsState.repeat.active, buttonsState.repeat.visible, this.#callbacks.onToggleLoop);
|
|
195
|
+
this.#addButton("repeatOff", this.#icon.repeatOff, buttonsState.repeatOff.enabled, buttonsState.repeatOff.active, buttonsState.repeatOff.visible, this.#callbacks.onToggleLoop);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Creates and configures the animation progress slider.
|
|
200
|
+
* @private
|
|
201
|
+
*/
|
|
202
|
+
#createSlider() {
|
|
203
|
+
this.#slider = document.createElement("input");
|
|
204
|
+
this.#slider.setAttribute("type", "range");
|
|
205
|
+
this.#slider.setAttribute("min", "0");
|
|
206
|
+
this.#slider.setAttribute("max", "1");
|
|
207
|
+
this.#slider.setAttribute("step", "0.01");
|
|
208
|
+
this.#slider.setAttribute("value", this.#animationProgress.toString());
|
|
209
|
+
this.#slider.classList.add("animation-menu-slider");
|
|
210
|
+
this.#handler.onSliderInput = this.#onSliderInput.bind(this);
|
|
211
|
+
this.#slider.addEventListener("input", this.#handler.onSliderInput);
|
|
212
|
+
|
|
213
|
+
this.#containerMain.appendChild(this.#slider);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Initializes and renders the menu UI, including buttons and slider.
|
|
218
|
+
* @private
|
|
219
|
+
*/
|
|
220
|
+
#createMenu() {
|
|
221
|
+
this.#containerMain = document.createElement("div");
|
|
222
|
+
this.#containerMain.classList.add("pref-viewer-3d");
|
|
223
|
+
this.#containerMain.classList.add("animation-menu");
|
|
224
|
+
this.#containerMain.setAttribute("data-animation-name", this.#name);
|
|
225
|
+
this.#canvas.parentElement.prepend(this.#containerMain);
|
|
226
|
+
|
|
227
|
+
const style = document.createElement("style");
|
|
228
|
+
style.textContent = PrefViewer3DAnimationMenuStyles;
|
|
229
|
+
this.#containerMain.appendChild(style);
|
|
230
|
+
|
|
231
|
+
this.#containerButtons = document.createElement("div");
|
|
232
|
+
this.#containerButtons.classList.add("animation-menu-buttons");
|
|
233
|
+
this.#containerMain.appendChild(this.#containerButtons);
|
|
234
|
+
|
|
235
|
+
this.#createSelector();
|
|
236
|
+
this.#createButtons();
|
|
237
|
+
this.#createSlider();
|
|
172
238
|
}
|
|
173
239
|
|
|
174
240
|
/**
|
|
@@ -178,24 +244,37 @@ export class OpeningAnimationMenu {
|
|
|
178
244
|
* @returns {Button|null} The button control or null if not found.
|
|
179
245
|
*/
|
|
180
246
|
#getButtonByName(name) {
|
|
181
|
-
return this.#
|
|
247
|
+
return this.#containerButtons.querySelector(`button[name="button_animation_${name}"]`);
|
|
182
248
|
}
|
|
183
249
|
|
|
184
250
|
/**
|
|
185
|
-
*
|
|
251
|
+
* Combines player and loop button states.
|
|
186
252
|
* @private
|
|
187
|
-
* @
|
|
188
|
-
* @param {boolean} enabled
|
|
189
|
-
* @param {boolean} active
|
|
190
|
-
* @param {boolean} visible
|
|
253
|
+
* @returns {object}
|
|
191
254
|
*/
|
|
192
|
-
#
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
255
|
+
#getButtonsState() {
|
|
256
|
+
return Object.assign(this.#getPlayerButtonsState(), this.#getLoopButtonsState());
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Returns the state for loop control buttons.
|
|
261
|
+
* @private
|
|
262
|
+
* @returns {object}
|
|
263
|
+
*/
|
|
264
|
+
#getLoopButtonsState() {
|
|
265
|
+
const buttonsState = {
|
|
266
|
+
repeat: {
|
|
267
|
+
enabled: this.#animationLoop,
|
|
268
|
+
active: false,
|
|
269
|
+
visible: this.#animationLoop,
|
|
270
|
+
},
|
|
271
|
+
repeatOff: {
|
|
272
|
+
enabled: !this.#animationLoop,
|
|
273
|
+
active: false,
|
|
274
|
+
visible: !this.#animationLoop,
|
|
275
|
+
},
|
|
276
|
+
};
|
|
277
|
+
return buttonsState;
|
|
199
278
|
}
|
|
200
279
|
|
|
201
280
|
/**
|
|
@@ -235,33 +314,47 @@ export class OpeningAnimationMenu {
|
|
|
235
314
|
}
|
|
236
315
|
|
|
237
316
|
/**
|
|
238
|
-
*
|
|
317
|
+
* Resets all other opening animations except the current one.
|
|
239
318
|
* @private
|
|
240
|
-
* @returns {
|
|
319
|
+
* @returns {void}
|
|
241
320
|
*/
|
|
242
|
-
#
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
repeatOff: {
|
|
250
|
-
enabled: !this.#animationLoop,
|
|
251
|
-
active: false,
|
|
252
|
-
visible: !this.#animationLoop,
|
|
253
|
-
},
|
|
254
|
-
};
|
|
255
|
-
return buttonsState;
|
|
321
|
+
#resetOtherAnimations() {
|
|
322
|
+
this.#openingAnimations.forEach((animation) => {
|
|
323
|
+
if (animation.name !== this.#name) {
|
|
324
|
+
animation.hideControls();
|
|
325
|
+
animation.goToClosed();
|
|
326
|
+
}
|
|
327
|
+
});
|
|
256
328
|
}
|
|
257
329
|
|
|
258
330
|
/**
|
|
259
|
-
*
|
|
331
|
+
* Updates the visual state of a button (enabled, active, visible).
|
|
260
332
|
* @private
|
|
261
|
-
* @
|
|
333
|
+
* @param {string} name - Button identifier.
|
|
334
|
+
* @param {boolean} enabled
|
|
335
|
+
* @param {boolean} active
|
|
336
|
+
* @param {boolean} visible
|
|
262
337
|
*/
|
|
263
|
-
#
|
|
264
|
-
|
|
338
|
+
#setButtonState(name, enabled, active, visible = true) {
|
|
339
|
+
const button = this.#getButtonByName(name);
|
|
340
|
+
if (!button) {
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
const classToRemove = ["active", "enabled", "disabled", "hidden", "visible"];
|
|
344
|
+
button.classList.remove(...classToRemove);
|
|
345
|
+
const stateClass = active ? "active" : enabled ? "enabled" : "disabled";
|
|
346
|
+
const visibilityClass = visible ? "visible" : "hidden";
|
|
347
|
+
button.classList.add(stateClass, visibilityClass);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Updates all loop control buttons according to current loop mode.
|
|
352
|
+
* @private
|
|
353
|
+
*/
|
|
354
|
+
#setLoopButtonsState() {
|
|
355
|
+
const buttonsState = this.#getLoopButtonsState();
|
|
356
|
+
this.#setButtonState("repeat", buttonsState.repeat.enabled, buttonsState.repeat.active, buttonsState.repeat.visible);
|
|
357
|
+
this.#setButtonState("repeatOff", buttonsState.repeatOff.enabled, buttonsState.repeatOff.active, buttonsState.repeatOff.visible);
|
|
265
358
|
}
|
|
266
359
|
|
|
267
360
|
/**
|
|
@@ -278,46 +371,38 @@ export class OpeningAnimationMenu {
|
|
|
278
371
|
}
|
|
279
372
|
|
|
280
373
|
/**
|
|
281
|
-
*
|
|
374
|
+
* Handles the slider input event for animation progress.
|
|
282
375
|
* @private
|
|
376
|
+
* @param {Event} event - The input event from the slider.
|
|
377
|
+
* @returns {void}
|
|
378
|
+
* @description
|
|
379
|
+
* If the slider value is being set programmatically, the event is ignored to prevent callback loops.
|
|
283
380
|
*/
|
|
284
|
-
#
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
381
|
+
#onSliderInput(event) {
|
|
382
|
+
if (this.#callbacks && typeof this.#callbacks.onSetAnimationProgress === "function") {
|
|
383
|
+
this.#callbacks.onSetAnimationProgress(event.target.value);
|
|
384
|
+
}
|
|
288
385
|
}
|
|
289
386
|
|
|
290
387
|
/**
|
|
291
|
-
*
|
|
292
|
-
*
|
|
388
|
+
* ---------------------------
|
|
389
|
+
* Public methods
|
|
390
|
+
* ---------------------------
|
|
293
391
|
*/
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
};
|
|
309
|
-
this.#slider = new Slider("slider_animation_progress");
|
|
310
|
-
Object.assign(this.#slider, sliderProps);
|
|
311
|
-
this.#slider.onValueChangedObservable.add((value) => {
|
|
312
|
-
if (this.#isSettingSliderValue) {
|
|
313
|
-
this.#isSettingSliderValue = false;
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
|
-
if (this.#callbacks && typeof this.#callbacks.onSetAnimationProgress === "function") {
|
|
317
|
-
this.#callbacks.onSetAnimationProgress(value);
|
|
318
|
-
}
|
|
319
|
-
});
|
|
320
|
-
this.#mainPanel.addControl(this.#slider);
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Disposes the animation menu and releases all associated DOM resources.
|
|
395
|
+
* @public
|
|
396
|
+
* @returns {void}
|
|
397
|
+
*/
|
|
398
|
+
dispose() {
|
|
399
|
+
this.#slider.removeEventListener("input", this.#handler.onSliderInput);
|
|
400
|
+
if (this.isVisible) {
|
|
401
|
+
this.#containerMain.remove();
|
|
402
|
+
}
|
|
403
|
+
this.#containerMain = null;
|
|
404
|
+
this.#containerButtons = null;
|
|
405
|
+
this.#slider = null;
|
|
321
406
|
}
|
|
322
407
|
|
|
323
408
|
/**
|
|
@@ -338,14 +423,12 @@ export class OpeningAnimationMenu {
|
|
|
338
423
|
|
|
339
424
|
/**
|
|
340
425
|
* Sets the animation progress value and updates the slider position.
|
|
341
|
-
* When called, the slider value is updated programmatically without triggering the slider's value change callback.
|
|
342
426
|
* @public
|
|
343
427
|
* @param {number} progress - The new animation progress value (between 0 and 1).
|
|
344
428
|
*/
|
|
345
429
|
set animationProgress(progress) {
|
|
346
430
|
this.#animationProgress = progress;
|
|
347
|
-
this.#
|
|
348
|
-
this.#slider.value = progress;
|
|
431
|
+
this.#slider.value = progress.toString();
|
|
349
432
|
}
|
|
350
433
|
|
|
351
434
|
/**
|
|
@@ -357,4 +440,20 @@ export class OpeningAnimationMenu {
|
|
|
357
440
|
this.#animationState = state;
|
|
358
441
|
this.#setPlayerButtonsState();
|
|
359
442
|
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* ---------------------------
|
|
446
|
+
* Public getters
|
|
447
|
+
* ---------------------------
|
|
448
|
+
*/
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Returns whether the animation menu is currently visible in the DOM.
|
|
452
|
+
* @public
|
|
453
|
+
* @returns {boolean} True if the menu is visible, false otherwise.
|
|
454
|
+
*/
|
|
455
|
+
get isVisible() {
|
|
456
|
+
const menuElement = this.#canvas.parentElement.querySelector(`div.animation-menu[data-animation-name="${this.#name}"]`);
|
|
457
|
+
return !!menuElement;
|
|
458
|
+
}
|
|
360
459
|
}
|