Przeglądaj źródła

Update scripts

customisations
alemart 10 miesięcy temu
rodzic
commit
e15bca056e
2 zmienionych plików z 377 dodań i 221 usunięć
  1. 374
    218
      dist/encantar.js
  2. 3
    3
      dist/encantar.min.js

+ 374
- 218
dist/encantar.js Wyświetl plik

@@ -1,11 +1,11 @@
1 1
 /*!
2
- * encantAR.js version 0.3.0
2
+ * encantar.js version 0.3.0
3 3
  * GPU-accelerated Augmented Reality for the web
4 4
  * Copyright 2022-2024 Alexandre Martins <alemartf(at)gmail.com> (https://github.com/alemart)
5 5
  * https://github.com/alemart/encantar-js
6 6
  *
7 7
  * @license LGPL-3.0-or-later
8
- * Date: 2024-10-05T04:17:49.391Z
8
+ * Date: 2024-10-20T01:13:15.146Z
9 9
  */
10 10
 (function webpackUniversalModuleDefinition(root, factory) {
11 11
 	if(typeof exports === 'object' && typeof module === 'object')
@@ -19538,16 +19538,21 @@ class TrainingError extends BaseError {
19538 19538
  */
19539 19539
 
19540 19540
 
19541
-/** Reference heights when in landscape mode, measured in pixels */
19542
-const REFERENCE_HEIGHT = {
19541
+/** A regex that identifies custom resolutions */
19542
+const CUSTOM_RESOLUTION_REGEX = /^[1-9][0-9]?[0-9][02468]p$/;
19543
+/** Reference heights when in landscape mode, measured in pixels, for all aliases */
19544
+const ALIAS_TO_HEIGHT = {
19543 19545
     'xs': 120,
19544
-    'xs+': 160,
19545
-    'sm': 200,
19546
-    'sm+': 240,
19546
+    'xs+': 144,
19547
+    'sm': 240,
19548
+    'sm+': 288,
19547 19549
     'md': 320,
19548 19550
     'md+': 360,
19549 19551
     'lg': 480,
19550 19552
     'lg+': 600,
19553
+    'xl': 720,
19554
+    'xl+': 900,
19555
+    'xxl': 1080,
19551 19556
 };
19552 19557
 /**
19553 19558
  * Convert a resolution type to a (width, height) pair
@@ -19556,26 +19561,38 @@ const REFERENCE_HEIGHT = {
19556 19561
  * @returns size in pixels
19557 19562
  */
19558 19563
 function computeResolution(resolution, aspectRatio) {
19559
-    const referenceHeight = REFERENCE_HEIGHT[resolution];
19564
+    const referenceHeight = parseHeight(resolution);
19560 19565
     let width = 0, height = 0;
19561
-    if (referenceHeight === undefined)
19566
+    if (Number.isNaN(referenceHeight))
19562 19567
         throw new IllegalArgumentError('Invalid resolution: ' + resolution);
19563 19568
     else if (aspectRatio <= 0)
19564 19569
         throw new IllegalArgumentError('Invalid aspect ratio: ' + aspectRatio);
19565 19570
     if (aspectRatio >= 1) {
19566 19571
         // landscape
19567 19572
         height = referenceHeight;
19568
-        width = Math.round(height * aspectRatio);
19569
-        width -= width % 2;
19573
+        width = Math.floor(height * aspectRatio);
19574
+        width += width % 2;
19570 19575
     }
19571 19576
     else {
19572 19577
         // portrait
19573 19578
         width = referenceHeight;
19574
-        height = Math.round(width / aspectRatio);
19575
-        height -= height % 2;
19579
+        height = Math.floor(width / aspectRatio);
19580
+        height += height % 2;
19576 19581
     }
19577 19582
     return speedy_vision_default().Size(width, height);
19578 19583
 }
19584
+/**
19585
+ * Get the height in pixels of a resolution
19586
+ * @param resolution resolution type
19587
+ * @returns the height in pixels, or NaN on error
19588
+ */
19589
+function parseHeight(resolution) {
19590
+    if (ALIAS_TO_HEIGHT.hasOwnProperty(resolution))
19591
+        return ALIAS_TO_HEIGHT[resolution];
19592
+    if (CUSTOM_RESOLUTION_REGEX.test(resolution))
19593
+        return parseInt(resolution);
19594
+    return Number.NaN;
19595
+}
19579 19596
 
19580 19597
 ;// CONCATENATED MODULE: ./src/utils/utils.ts
19581 19598
 /*
@@ -19891,7 +19908,7 @@ class Stats {
19891 19908
     }
19892 19909
 }
19893 19910
 
19894
-;// CONCATENATED MODULE: ./src/core/stats-panel.ts
19911
+;// CONCATENATED MODULE: ./src/ui/stats-panel.ts
19895 19912
 /*
19896 19913
  * encantar.js
19897 19914
  * GPU-accelerated Augmented Reality for the web
@@ -19915,7 +19932,6 @@ class Stats {
19915 19932
  */
19916 19933
 
19917 19934
 
19918
-
19919 19935
 /** Update interval, in ms */
19920 19936
 const stats_panel_UPDATE_INTERVAL = 500;
19921 19937
 /** Icons for different power profiles */
@@ -19930,7 +19946,7 @@ const POWER_ICON = Object.freeze({
19930 19946
 class StatsPanel {
19931 19947
     /**
19932 19948
      * Constructor
19933
-     * @param parent parent element of the panel
19949
+     * @param viewport Viewport
19934 19950
      */
19935 19951
     constructor(viewport) {
19936 19952
         this._viewport = viewport;
@@ -20049,8 +20065,7 @@ class StatsPanel {
20049 20065
         title.style.fontSize = '14px';
20050 20066
         title.style.fontWeight = 'bold';
20051 20067
         title.style.padding = '2px';
20052
-        title.innerHTML = '&#x2728;';
20053
-        title.innerText += 'encantar.js ' + AR.version;
20068
+        title.innerText = 'encantar.js ' + AR.version;
20054 20069
         return title;
20055 20070
     }
20056 20071
     /**
@@ -20074,179 +20089,11 @@ class StatsPanel {
20074 20089
         print('IN: <span class="_ar_in"></span>');
20075 20090
         print('<br>');
20076 20091
         print('OUT: <span class="_ar_out"></span>');
20077
-        if (this._viewport.fullscreenAvailable) {
20078
-            print('<br>');
20079
-            content.appendChild(this._createFullscreenToggle());
20080
-        }
20081 20092
         return content;
20082 20093
     }
20083
-    /**
20084
-     * Create a fullscreen toggle
20085
-     * @returns a fullscreen toggle
20086
-     */
20087
-    _createFullscreenToggle() {
20088
-        const toggle = document.createElement('a');
20089
-        Utils.assert(this._viewport != null);
20090
-        toggle.href = 'javascript:void(0)';
20091
-        toggle.innerText = 'Toggle fullscreen';
20092
-        toggle.style.color = 'white';
20093
-        toggle.setAttribute('role', 'button');
20094
-        toggle.addEventListener('click', () => {
20095
-            if (!this._viewport.fullscreen) {
20096
-                this._viewport.requestFullscreen().catch(err => {
20097
-                    alert(`Can't enable fullscreen mode. ` + err.toString());
20098
-                });
20099
-            }
20100
-            else {
20101
-                this._viewport.exitFullscreen();
20102
-            }
20103
-        });
20104
-        return toggle;
20105
-    }
20106
-}
20107
-
20108
-;// CONCATENATED MODULE: ./src/core/frame.ts
20109
-/*
20110
- * encantar.js
20111
- * GPU-accelerated Augmented Reality for the web
20112
- * Copyright (C) 2022-2024 Alexandre Martins <alemartf(at)gmail.com>
20113
- *
20114
- * This program is free software: you can redistribute it and/or modify
20115
- * it under the terms of the GNU Lesser General Public License as published
20116
- * by the Free Software Foundation, either version 3 of the License, or
20117
- * (at your option) any later version.
20118
- *
20119
- * This program is distributed in the hope that it will be useful,
20120
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
20121
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20122
- * GNU Lesser General Public License for more details.
20123
- *
20124
- * You should have received a copy of the GNU Lesser General Public License
20125
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20126
- *
20127
- * frame.ts
20128
- * A Frame holds information used to render a single animation frame of a Session
20129
- */
20130
-/**
20131
- * A Frame holds information used to render a single animation frame of a Session
20132
- */
20133
-class Frame {
20134
-    /**
20135
-     * Constructor
20136
-     * @param session
20137
-     * @param results
20138
-     */
20139
-    constructor(session, results) {
20140
-        this._session = session;
20141
-        this._results = results;
20142
-    }
20143
-    /**
20144
-     * The session of which this frame holds data
20145
-     */
20146
-    get session() {
20147
-        return this._session;
20148
-    }
20149
-    /**
20150
-     * The results of all trackers in this frame
20151
-     */
20152
-    get results() {
20153
-        // we want to be able to iterate over the results of a frame multiple times
20154
-        return this._results[Symbol.iterator]();
20155
-    }
20156
-}
20157
-
20158
-;// CONCATENATED MODULE: ./src/core/time.ts
20159
-/*
20160
- * encantar.js
20161
- * GPU-accelerated Augmented Reality for the web
20162
- * Copyright (C) 2022-2024 Alexandre Martins <alemartf(at)gmail.com>
20163
- *
20164
- * This program is free software: you can redistribute it and/or modify
20165
- * it under the terms of the GNU Lesser General Public License as published
20166
- * by the Free Software Foundation, either version 3 of the License, or
20167
- * (at your option) any later version.
20168
- *
20169
- * This program is distributed in the hope that it will be useful,
20170
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
20171
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20172
- * GNU Lesser General Public License for more details.
20173
- *
20174
- * You should have received a copy of the GNU Lesser General Public License
20175
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20176
- *
20177
- * time.ts
20178
- * Time utilities
20179
- */
20180
-/**
20181
- * Time Manager
20182
- */
20183
-class Time {
20184
-    constructor() {
20185
-        /** time scale */
20186
-        this._scale = 1;
20187
-        /** time since the start of the session, in milliseconds */
20188
-        this._time = 0;
20189
-        /** unscaled time since the start of the session, in milliseconds */
20190
-        this._unscaledTime = 0;
20191
-        /** elapsed time between the current and the previous frame, in milliseconds */
20192
-        this._delta = 0;
20193
-        /** time of the first update call, in milliseconds */
20194
-        this._firstUpdate = 0;
20195
-        /** time of the last update call, in milliseconds */
20196
-        this._lastUpdate = Number.POSITIVE_INFINITY;
20197
-    }
20198
-    /**
20199
-     * Update the Time Manager
20200
-     * @param timestamp in milliseconds
20201
-     * @internal
20202
-     */
20203
-    _update(timestamp) {
20204
-        if (timestamp < this._lastUpdate) {
20205
-            this._firstUpdate = this._lastUpdate = timestamp;
20206
-            return;
20207
-        }
20208
-        this._delta = (timestamp - this._lastUpdate) * this._scale;
20209
-        this._time += this._delta;
20210
-        this._unscaledTime = timestamp - this._firstUpdate;
20211
-        this._lastUpdate = timestamp;
20212
-    }
20213
-    /**
20214
-     * Elapsed time since the start of the session, measured at the
20215
-     * beginning of the current animation frame and given in seconds
20216
-     */
20217
-    get elapsed() {
20218
-        return this._time * 0.001;
20219
-    }
20220
-    /**
20221
-     * Elapsed time between the current and the previous animation
20222
-     * frame, given in seconds
20223
-     */
20224
-    get delta() {
20225
-        return this._delta * 0.001;
20226
-    }
20227
-    /**
20228
-     * Time scale (defaults to 1)
20229
-     */
20230
-    get scale() {
20231
-        return this._scale;
20232
-    }
20233
-    /**
20234
-     * Time scale (defaults to 1)
20235
-     */
20236
-    set scale(scale) {
20237
-        this._scale = Math.max(0, +scale);
20238
-    }
20239
-    /**
20240
-     * Time scale independent elapsed time since the start of the session,
20241
-     * measured at the beginning of the current animation frame and given
20242
-     * in seconds
20243
-     */
20244
-    get unscaled() {
20245
-        return this._unscaledTime * 0.001;
20246
-    }
20247 20094
 }
20248 20095
 
20249
-;// CONCATENATED MODULE: ./src/core/gizmos.ts
20096
+;// CONCATENATED MODULE: ./src/ui/gizmos.ts
20250 20097
 /*
20251 20098
  * encantar.js
20252 20099
  * GPU-accelerated Augmented Reality for the web
@@ -20470,6 +20317,147 @@ class Gizmos {
20470 20317
     }
20471 20318
 }
20472 20319
 
20320
+;// CONCATENATED MODULE: ./src/core/frame.ts
20321
+/*
20322
+ * encantar.js
20323
+ * GPU-accelerated Augmented Reality for the web
20324
+ * Copyright (C) 2022-2024 Alexandre Martins <alemartf(at)gmail.com>
20325
+ *
20326
+ * This program is free software: you can redistribute it and/or modify
20327
+ * it under the terms of the GNU Lesser General Public License as published
20328
+ * by the Free Software Foundation, either version 3 of the License, or
20329
+ * (at your option) any later version.
20330
+ *
20331
+ * This program is distributed in the hope that it will be useful,
20332
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20333
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20334
+ * GNU Lesser General Public License for more details.
20335
+ *
20336
+ * You should have received a copy of the GNU Lesser General Public License
20337
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20338
+ *
20339
+ * frame.ts
20340
+ * A Frame holds information used to render a single animation frame of a Session
20341
+ */
20342
+/**
20343
+ * A Frame holds information used to render a single animation frame of a Session
20344
+ */
20345
+class Frame {
20346
+    /**
20347
+     * Constructor
20348
+     * @param session
20349
+     * @param results
20350
+     */
20351
+    constructor(session, results) {
20352
+        this._session = session;
20353
+        this._results = results;
20354
+    }
20355
+    /**
20356
+     * The session of which this frame holds data
20357
+     */
20358
+    get session() {
20359
+        return this._session;
20360
+    }
20361
+    /**
20362
+     * The results of all trackers in this frame
20363
+     */
20364
+    get results() {
20365
+        // we want to be able to iterate over the results of a frame multiple times
20366
+        return this._results[Symbol.iterator]();
20367
+    }
20368
+}
20369
+
20370
+;// CONCATENATED MODULE: ./src/core/time.ts
20371
+/*
20372
+ * encantar.js
20373
+ * GPU-accelerated Augmented Reality for the web
20374
+ * Copyright (C) 2022-2024 Alexandre Martins <alemartf(at)gmail.com>
20375
+ *
20376
+ * This program is free software: you can redistribute it and/or modify
20377
+ * it under the terms of the GNU Lesser General Public License as published
20378
+ * by the Free Software Foundation, either version 3 of the License, or
20379
+ * (at your option) any later version.
20380
+ *
20381
+ * This program is distributed in the hope that it will be useful,
20382
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20383
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20384
+ * GNU Lesser General Public License for more details.
20385
+ *
20386
+ * You should have received a copy of the GNU Lesser General Public License
20387
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20388
+ *
20389
+ * time.ts
20390
+ * Time utilities
20391
+ */
20392
+/**
20393
+ * Time Manager
20394
+ */
20395
+class Time {
20396
+    constructor() {
20397
+        /** time scale */
20398
+        this._scale = 1;
20399
+        /** time since the start of the session, in milliseconds */
20400
+        this._time = 0;
20401
+        /** unscaled time since the start of the session, in milliseconds */
20402
+        this._unscaledTime = 0;
20403
+        /** elapsed time between the current and the previous frame, in milliseconds */
20404
+        this._delta = 0;
20405
+        /** time of the first update call, in milliseconds */
20406
+        this._firstUpdate = 0;
20407
+        /** time of the last update call, in milliseconds */
20408
+        this._lastUpdate = Number.POSITIVE_INFINITY;
20409
+    }
20410
+    /**
20411
+     * Update the Time Manager
20412
+     * @param timestamp in milliseconds
20413
+     * @internal
20414
+     */
20415
+    _update(timestamp) {
20416
+        if (timestamp < this._lastUpdate) {
20417
+            this._firstUpdate = this._lastUpdate = timestamp;
20418
+            return;
20419
+        }
20420
+        this._delta = (timestamp - this._lastUpdate) * this._scale;
20421
+        this._time += this._delta;
20422
+        this._unscaledTime = timestamp - this._firstUpdate;
20423
+        this._lastUpdate = timestamp;
20424
+    }
20425
+    /**
20426
+     * Elapsed time since the start of the session, measured at the
20427
+     * beginning of the current animation frame and given in seconds
20428
+     */
20429
+    get elapsed() {
20430
+        return this._time * 0.001;
20431
+    }
20432
+    /**
20433
+     * Elapsed time between the current and the previous animation
20434
+     * frame, given in seconds
20435
+     */
20436
+    get delta() {
20437
+        return this._delta * 0.001;
20438
+    }
20439
+    /**
20440
+     * Time scale (defaults to 1)
20441
+     */
20442
+    get scale() {
20443
+        return this._scale;
20444
+    }
20445
+    /**
20446
+     * Time scale (defaults to 1)
20447
+     */
20448
+    set scale(scale) {
20449
+        this._scale = Math.max(0, +scale);
20450
+    }
20451
+    /**
20452
+     * Time scale independent elapsed time since the start of the session,
20453
+     * measured at the beginning of the current animation frame and given
20454
+     * in seconds
20455
+     */
20456
+    get unscaled() {
20457
+        return this._unscaledTime * 0.001;
20458
+    }
20459
+}
20460
+
20473 20461
 ;// CONCATENATED MODULE: ./src/utils/asap.ts
20474 20462
 /*
20475 20463
  * encantar.js
@@ -20592,26 +20580,11 @@ class Session extends AREventTarget {
20592 20580
         this._gizmos = new Gizmos();
20593 20581
         this._gizmos.visible = gizmos;
20594 20582
         // validate the mode
20595
-        if (mode == 'immersive') {
20596
-            if (viewport.style != 'best-fit' && viewport.style != 'stretch') {
20597
-                Utils.warning(`Invalid viewport style \"${viewport.style}\" for the \"${mode}\" mode`);
20598
-                viewport.style = 'best-fit';
20599
-            }
20600
-        }
20601
-        else if (mode == 'inline') {
20602
-            if (viewport.style != 'inline') {
20603
-                Utils.warning(`Invalid viewport style \"${viewport.style}\" for the \"${mode}\" mode`);
20604
-                viewport.style = 'inline';
20605
-            }
20606
-        }
20607
-        else
20583
+        if (mode != 'immersive' && mode != 'inline')
20608 20584
             throw new IllegalArgumentError(`Invalid session mode "${mode}"`);
20609
-        // get media
20610
-        const media = this.media;
20611
-        const getMediaSize = () => media.size;
20612 20585
         // setup the viewport
20613 20586
         this._viewport = viewport;
20614
-        this._viewport._init(getMediaSize);
20587
+        this._viewport._init(() => this.media.size, mode);
20615 20588
         // setup the main loop
20616 20589
         this._setupUpdateLoop();
20617 20590
         this._setupRenderLoop();
@@ -21184,16 +21157,19 @@ class ReferenceImageDatabase {
21184 21157
         const referenceImage = referenceImages[0];
21185 21158
         // locked database?
21186 21159
         if (this._locked)
21187
-            throw new IllegalOperationError(`Can't add reference image to the database: it's locked`);
21160
+            throw new IllegalOperationError(`Can't add reference image "${referenceImage.name}" to the database: it's locked`);
21188 21161
         // busy loading another image?
21189 21162
         if (this._busy)
21190 21163
             return Utils.wait(4).then(() => this.add(referenceImages)); // try again later
21191 21164
         // reached full capacity?
21192 21165
         if (this.count >= this.capacity)
21193
-            throw new IllegalOperationError(`Can't add reference image to the database: the capacity of ${this.capacity} images has been exceeded.`);
21166
+            throw new IllegalOperationError(`Can't add reference image "${referenceImage.name}" to the database: the capacity of ${this.capacity} images has been exceeded.`);
21167
+        // check if the image is valid
21168
+        if (!(referenceImage.image instanceof HTMLImageElement) && !(referenceImage.image instanceof HTMLCanvasElement) && !(referenceImage.image instanceof ImageBitmap))
21169
+            throw new IllegalArgumentError(`Can't add reference image "${referenceImage.name}" to the database: invalid image`);
21194 21170
         // check for duplicate names
21195 21171
         if (this._database.find(entry => entry.referenceImage.name === referenceImage.name) !== undefined)
21196
-            throw new IllegalArgumentError(`Can't add reference image to the database: found duplicated name "${referenceImage.name}"`);
21172
+            throw new IllegalArgumentError(`Can't add reference image "${referenceImage.name}" to the database: found duplicated name`);
21197 21173
         // load the media and add the reference image to the database
21198 21174
         this._busy = true;
21199 21175
         return speedy_vision_default().load(referenceImage.image).then(media => {
@@ -21251,7 +21227,7 @@ class ReferenceImageDatabase {
21251 21227
  * Settings of the Image Tracker
21252 21228
  */
21253 21229
 /** Default tracking resolution */
21254
-const DEFAULT_TRACKING_RESOLUTION = 'sm+';
21230
+const DEFAULT_TRACKING_RESOLUTION = 'sm';
21255 21231
 /** Maximum number of keypoints to be stored for each reference image when in the training state */
21256 21232
 const TRAIN_MAX_KEYPOINTS = 1024; //512;
21257 21233
 /** Percentage relative to the screen size adjusted to the aspect ratio of the reference image */
@@ -25377,6 +25353,127 @@ class HUD {
25377 25353
     }
25378 25354
 }
25379 25355
 
25356
+;// CONCATENATED MODULE: ./src/ui/fullscreen-button.ts
25357
+/*
25358
+ * encantar.js
25359
+ * GPU-accelerated Augmented Reality for the web
25360
+ * Copyright (C) 2022-2024 Alexandre Martins <alemartf(at)gmail.com>
25361
+ *
25362
+ * This program is free software: you can redistribute it and/or modify
25363
+ * it under the terms of the GNU Lesser General Public License as published
25364
+ * by the Free Software Foundation, either version 3 of the License, or
25365
+ * (at your option) any later version.
25366
+ *
25367
+ * This program is distributed in the hope that it will be useful,
25368
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25369
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25370
+ * GNU Lesser General Public License for more details.
25371
+ *
25372
+ * You should have received a copy of the GNU Lesser General Public License
25373
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
25374
+ *
25375
+ * fullscreen-button.ts
25376
+ * A built-in fullscreen button introduced as a convenience
25377
+ */
25378
+/** Button icon to be displayed when the fullscreen mode is disabled */
25379
+const BUTTON_ICON_OFF = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAbUlEQVRYR+2WOQ4AIAgE5f+PVhobDZANBZAsraAwXMoqFil+f9GBj8BW8dIiKt45at/XgShStHgvmfdekwAdIIEyAmh1Z/U5ikmABPoRsLZWtt+5DUlgHgGr6qM1Pf9XnO131L7fJEQjyOqXEzjP1YAhNmUTrgAAAABJRU5ErkJggg==';
25380
+/** Button icon to be displayed when the fullscreen mode is enabled */
25381
+const BUTTON_ICON_ON = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAZElEQVRYR+2WwRIAEAhE9f8fTQ5OhtkLxbzOyc5rJSvBYcH3FwTIBKpHb5d57Nqm5o0aCIBAPgLDxSunq69APT8RCBdwezTLHjglDAEQgEC+QZR2EqqbjprHRgSB9wjwHX9LoAHP1YAhXF4Z/QAAAABJRU5ErkJggg==';
25382
+/** Button size, in pixels */
25383
+const BUTTON_SIZE = 64;
25384
+/** Button margin, in pixels */
25385
+const BUTTON_MARGIN = 24;
25386
+/**
25387
+ * Built-in fullscreen button
25388
+ */
25389
+class FullscreenButton {
25390
+    /**
25391
+     * Constructor
25392
+     * @param viewport Viewport
25393
+     */
25394
+    constructor(viewport) {
25395
+        this._viewport = viewport;
25396
+        this._button = this._createButton();
25397
+        this._boundEventHandler = this._handleFullscreenEvent.bind(this);
25398
+    }
25399
+    /**
25400
+     * Initialize
25401
+     */
25402
+    init() {
25403
+        this._viewport.hud.container.appendChild(this._button);
25404
+        this._viewport.addEventListener('fullscreenchange', this._boundEventHandler);
25405
+    }
25406
+    /**
25407
+     * Release
25408
+     */
25409
+    release() {
25410
+        this._viewport.removeEventListener('fullscreenchange', this._boundEventHandler);
25411
+        this._button.remove();
25412
+    }
25413
+    /**
25414
+     * Create the <button> element
25415
+     */
25416
+    _createButton() {
25417
+        const button = document.createElement('button');
25418
+        const icon = document.createElement('img');
25419
+        button.style.position = 'absolute';
25420
+        button.style.bottom = BUTTON_MARGIN + 'px';
25421
+        button.style.right = BUTTON_MARGIN + 'px';
25422
+        button.style.width = BUTTON_SIZE + 'px';
25423
+        button.style.height = BUTTON_SIZE + 'px';
25424
+        button.style.display = 'flex';
25425
+        button.style.alignItems = 'center';
25426
+        button.style.padding = '2px';
25427
+        button.style.opacity = '0.5';
25428
+        button.style.outline = 'none';
25429
+        button.style.cursor = 'pointer';
25430
+        button.draggable = false;
25431
+        button.style.backgroundColor = 'transparent';
25432
+        button.style.borderColor = 'white';
25433
+        button.style.borderStyle = 'solid';
25434
+        button.style.borderWidth = '2px';
25435
+        button.style.borderRadius = '8px';
25436
+        icon.src = BUTTON_ICON_OFF;
25437
+        icon.draggable = false;
25438
+        icon.style.display = 'inline-block';
25439
+        icon.style.width = '100%';
25440
+        icon.style.height = '100%';
25441
+        icon.style.imageRendering = 'pixelated';
25442
+        button.appendChild(icon);
25443
+        const highlight = () => {
25444
+            button.style.backgroundColor = '#ffd500';
25445
+            button.style.borderColor = '#ffd500';
25446
+            button.style.opacity = '1.0';
25447
+        };
25448
+        const dehighlight = () => {
25449
+            button.style.backgroundColor = 'transparent';
25450
+            button.style.borderColor = 'white';
25451
+            button.style.opacity = '0.5';
25452
+        };
25453
+        button.addEventListener('pointerdown', highlight);
25454
+        button.addEventListener('pointerup', dehighlight);
25455
+        button.addEventListener('pointerleave', dehighlight);
25456
+        button.addEventListener('click', () => {
25457
+            if (!this._viewport.fullscreen) {
25458
+                this._viewport.requestFullscreen().catch(err => {
25459
+                    alert(`Can't enable the fullscreen mode. ` + err.toString());
25460
+                });
25461
+            }
25462
+            else {
25463
+                this._viewport.exitFullscreen();
25464
+            }
25465
+        });
25466
+        return button;
25467
+    }
25468
+    /**
25469
+     * Handle a fullscreenchange event
25470
+     */
25471
+    _handleFullscreenEvent(event) {
25472
+        const icon = this._button.querySelector('img');
25473
+        icon.src = this._viewport.fullscreen ? BUTTON_ICON_ON : BUTTON_ICON_OFF;
25474
+    }
25475
+}
25476
+
25380 25477
 ;// CONCATENATED MODULE: ./src/core/viewport.ts
25381 25478
 /*
25382 25479
  * encantar.js
@@ -25404,6 +25501,8 @@ class HUD {
25404 25501
 
25405 25502
 
25406 25503
 
25504
+
25505
+
25407 25506
 /** An event emitted by a Viewport */
25408 25507
 class ViewportEvent extends AREvent {
25409 25508
 }
@@ -25417,6 +25516,7 @@ const DEFAULT_VIEWPORT_SETTINGS = {
25417 25516
     resolution: 'lg',
25418 25517
     style: 'best-fit',
25419 25518
     canvas: null,
25519
+    fullscreenUI: true,
25420 25520
 };
25421 25521
 /** Base z-index of the children of the viewport container */
25422 25522
 const BASE_ZINDEX = 0;
@@ -25488,11 +25588,15 @@ class ViewportCanvases {
25488 25588
             throw new IllegalArgumentError('Not a canvas: ' + fgCanvas);
25489 25589
         this._originalCSSTextOfForegroundCanvas = fgCanvas ? fgCanvas.style.cssText : '';
25490 25590
         this._foregroundCanvas = this._styleCanvas(fgCanvas || this._createCanvas(initialSize), FOREGROUND_ZINDEX);
25591
+        this._foregroundCanvas.style.background = 'transparent';
25491 25592
         this._backgroundCanvas = this._styleCanvas(this._createCanvas(initialSize), BACKGROUND_ZINDEX);
25492
-        parent.appendChild(this._backgroundCanvas);
25493
-        parent.appendChild(this._foregroundCanvas);
25494 25593
         this._backgroundCanvas.hidden = true;
25495 25594
         this._foregroundCanvas.hidden = true;
25595
+        const engineInfo = 'encantar.js ' + AR.version;
25596
+        this._backgroundCanvas.dataset.arEngine = engineInfo;
25597
+        this._foregroundCanvas.dataset.arEngine = engineInfo;
25598
+        parent.appendChild(this._backgroundCanvas);
25599
+        parent.appendChild(this._foregroundCanvas);
25496 25600
     }
25497 25601
     /**
25498 25602
      * The background canvas
@@ -25555,10 +25659,24 @@ class ViewportCanvases {
25555 25659
 class ViewportFullscreenHelper {
25556 25660
     /**
25557 25661
      * Constructor
25558
-     * @param _container the container which will be put in fullscreen
25662
+     * @param viewport Viewport
25663
+     */
25664
+    constructor(viewport) {
25665
+        this._viewport = viewport;
25666
+        this._container = viewport.container;
25667
+        this._boundEventHandler = this._triggerEvent.bind(this);
25668
+    }
25669
+    /**
25670
+     * Initialize
25559 25671
      */
25560
-    constructor(_container) {
25561
-        this._container = _container;
25672
+    init() {
25673
+        this._container.addEventListener('fullscreenchange', this._boundEventHandler);
25674
+    }
25675
+    /**
25676
+     * Release
25677
+     */
25678
+    release() {
25679
+        this._container.removeEventListener('fullscreenchange', this._boundEventHandler);
25562 25680
     }
25563 25681
     /**
25564 25682
      * Make a request to the user agent so that the viewport container is
@@ -25659,6 +25777,13 @@ class ViewportFullscreenHelper {
25659 25777
         else
25660 25778
             return false;
25661 25779
     }
25780
+    /**
25781
+     * Trigger a fullscreenchange event
25782
+     */
25783
+    _triggerEvent() {
25784
+        const event = new ViewportEvent('fullscreenchange');
25785
+        this._viewport.dispatchEvent(event);
25786
+    }
25662 25787
 }
25663 25788
 /**
25664 25789
  * Helper class to resize the viewport
@@ -25900,9 +26025,12 @@ class Viewport extends ViewportEventTarget {
25900 26025
         this._containers = new ViewportContainers(settings.container);
25901 26026
         this._hud = new HUD(this._subContainer, settings.hudContainer);
25902 26027
         this._canvases = new ViewportCanvases(this._subContainer, initialSize, settings.canvas);
25903
-        this._fullscreen = new ViewportFullscreenHelper(this.container);
25904 26028
         this._resizer = new ViewportResizer(this);
25905 26029
         this._resizer.setStrategyByName(this._style);
26030
+        this._fullscreen = new ViewportFullscreenHelper(this);
26031
+        this._fullscreenButton = null;
26032
+        if (settings.fullscreenUI && this.fullscreenAvailable)
26033
+            this._fullscreenButton = new FullscreenButton(this);
25906 26034
     }
25907 26035
     /**
25908 26036
      * Viewport container
@@ -25919,13 +26047,16 @@ class Viewport extends ViewportEventTarget {
25919 26047
     /**
25920 26048
      * Set viewport style
25921 26049
      */
25922
-    set style(value) {
26050
+    /*
26051
+    set style(value: ViewportStyle)
26052
+    {
25923 26053
         // note: the viewport style is independent of the session mode!
25924
-        if (value !== this._style) {
26054
+        if(value !== this._style) {
25925 26055
             this._resizer.setStrategyByName(value);
25926 26056
             this._style = value;
25927 26057
         }
25928 26058
     }
26059
+    */
25929 26060
     /**
25930 26061
      * HUD
25931 26062
      */
@@ -26002,20 +26133,45 @@ class Viewport extends ViewportEventTarget {
26002 26133
     }
26003 26134
     /**
26004 26135
      * Initialize the viewport (when the session starts)
26136
+     * @param getMediaSize
26137
+     * @param sessionMode
26005 26138
      * @internal
26006 26139
      */
26007
-    _init(getMediaSize) {
26140
+    _init(getMediaSize, sessionMode) {
26141
+        var _a;
26142
+        // validate if the viewport style matches the session mode
26143
+        if (sessionMode == 'immersive') {
26144
+            if (this._style != 'best-fit' && this._style != 'stretch') {
26145
+                Utils.warning(`Invalid viewport style \"${this._style}\" for the \"${sessionMode}\" mode`);
26146
+                this._style = 'best-fit';
26147
+                this._resizer.setStrategyByName(this._style);
26148
+            }
26149
+        }
26150
+        else if (sessionMode == 'inline') {
26151
+            if (this._style != 'inline') {
26152
+                Utils.warning(`Invalid viewport style \"${this._style}\" for the \"${sessionMode}\" mode`);
26153
+                this._style = 'inline';
26154
+                this._resizer.setStrategyByName(this._style);
26155
+            }
26156
+        }
26157
+        // set the media size getter
26008 26158
         this._mediaSize = getMediaSize;
26159
+        // initialize the components
26009 26160
         this._containers.init();
26010 26161
         this._hud._init(HUD_ZINDEX);
26011 26162
         this._canvases.init();
26012 26163
         this._resizer.init();
26164
+        this._fullscreen.init();
26165
+        (_a = this._fullscreenButton) === null || _a === void 0 ? void 0 : _a.init();
26013 26166
     }
26014 26167
     /**
26015 26168
      * Release the viewport (when the session ends)
26016 26169
      * @internal
26017 26170
      */
26018 26171
     _release() {
26172
+        var _a;
26173
+        (_a = this._fullscreenButton) === null || _a === void 0 ? void 0 : _a.release();
26174
+        this._fullscreen.release();
26019 26175
         this._resizer.release();
26020 26176
         this._canvases.release();
26021 26177
         this._hud._release();
@@ -26118,7 +26274,7 @@ Object.freeze(AR);
26118 26274
 // Add Speedy Vision to global scope
26119 26275
 ((window) => window.Speedy = window.Speedy || (speedy_vision_default()))(window);
26120 26276
 // Display a notice
26121
-Utils.log(`encantAR.js version ${AR.version}. ` +
26277
+Utils.log(`encantar.js version ${AR.version}. ` +
26122 26278
     `GPU-accelerated Augmented Reality for the web by Alexandre Martins. ` +
26123 26279
     "https://github.com/alemart/encantar-js");
26124 26280
 

+ 3
- 3
dist/encantar.min.js
Plik diff jest za duży
Wyświetl plik


Ładowanie…
Anuluj
Zapisz