thomwolf HF staff commited on
Commit
baae2de
1 Parent(s): 165c2c8

resolving WASM

Browse files
Files changed (1) hide show
  1. index.html +699 -665
index.html CHANGED
@@ -1,684 +1,718 @@
1
  <!DOCTYPE html>
2
  <html xmlns="https://www.w3.org/1999/xhtml" lang="en">
 
3
  <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no" />
6
- <meta name="author" content="Godot Engine" />
7
- <meta name="description" content="Use the Godot Engine editor directly in your web browser, without having to install anything." />
8
- <meta name="mobile-web-app-capable" content="yes" />
9
- <meta name="apple-mobile-web-app-capable" content="yes" />
10
- <meta name="application-name" content="Godot" />
11
- <meta name="apple-mobile-web-app-title" content="Godot" />
12
- <meta name="theme-color" content="#202531" />
13
- <meta name="msapplication-navbutton-color" content="#202531" />
14
- <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
15
- <meta name="msapplication-starturl" content="/latest" />
16
- <meta property="og:site_name" content="Godot Engine Web Editor" />
17
- <meta property="og:url" name="twitter:url" content="https://editor.godotengine.org/releases/latest/" />
18
- <meta property="og:title" name="twitter:title" content="Free and open source 2D and 3D game engine" />
19
- <meta property="og:description" name="twitter:description" content="Use the Godot Engine editor directly in your web browser, without having to install anything." />
20
- <meta property="og:image" name="twitter:image" content="https://godotengine.org/themes/godotengine/assets/og_image.png" />
21
- <meta property="og:type" content="website" />
22
- <meta name="twitter:card" content="summary" />
23
- <link id="-gd-engine-icon" rel="icon" type="image/png" href="favicon.png" />
24
- <link rel="apple-touch-icon" type="image/png" href="favicon.png" />
25
- <link rel="manifest" href="manifest.json" />
26
- <title>Godot Engine Web Editor (3.4.4.rc.custom_build)</title>
27
- <style>
28
- *:focus {
29
- /* More visible outline for better keyboard navigation. */
30
- outline: 0.125rem solid hsl(220, 100%, 62.5%);
31
- /* Make the outline always appear above other elements. */
32
- /* Otherwise, one of its sides can be hidden by tabs in the Download and More layouts. */
33
- position: relative;
34
- }
35
-
36
- body {
37
- touch-action: none;
38
- font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
39
- margin: 0;
40
- border: 0 none;
41
- padding: 0;
42
- text-align: center;
43
- background-color: #333b4f;
44
- overflow: hidden;
45
- }
46
-
47
- a {
48
- color: hsl(205, 100%, 75%);
49
- text-decoration-color: hsla(205, 100%, 75%, 0.3);
50
- text-decoration-thickness: 0.125rem;
51
- }
52
-
53
- a:hover {
54
- filter: brightness(117.5%);
55
- }
56
-
57
- a:active {
58
- filter: brightness(82.5%);
59
- }
60
-
61
- .welcome-modal {
62
- display: none;
63
- position: fixed;
64
- z-index: 1;
65
- left: 0;
66
- top: 0;
67
- width: 100%;
68
- height: 100%;
69
- overflow: auto;
70
- background-color: hsla(0, 0%, 0%, 0.5);
71
- }
72
-
73
- .welcome-modal-content {
74
- background-color: #333b4f;
75
- box-shadow: 0 0.25rem 0.25rem hsla(0, 0%, 0%, 0.5);
76
- line-height: 1.5;
77
- max-width: 38rem;
78
- margin: 4rem auto 0 auto;
79
- color: white;
80
- border-radius: 0.5rem;
81
- padding: 1rem 1rem 2rem 1rem;
82
- }
83
-
84
- #tabs-buttons {
85
- /* Match the default background color of the editor window for a seamless appearance. */
86
- background-color: #202531;
87
- }
88
-
89
- #tab-game {
90
- /* Use a pure black background to better distinguish the running project */
91
- /* from the editor window, and to use a more neutral background color (no tint). */
92
- background-color: black;
93
- /* Make the background span the entire page height. */
94
- min-height: 100vh;
95
- }
96
-
97
- #canvas, #gameCanvas {
98
- display: block;
99
- margin: 0;
100
- color: white;
101
- }
102
-
103
- /* Don't show distracting focus outlines for the main tabs' contents. */
104
- #tab-editor canvas:focus,
105
- #tab-game canvas:focus,
106
- #canvas:focus,
107
- #gameCanvas:focus {
108
- outline: none;
109
- }
110
-
111
- .godot {
112
- color: #e0e0e0;
113
- background-color: #3b3943;
114
- background-image: linear-gradient(to bottom, #403e48, #35333c);
115
- border: 1px solid #45434e;
116
- box-shadow: 0 0 1px 1px #2f2d35;
117
- }
118
-
119
- .btn {
120
- appearance: none;
121
- color: #e0e0e0;
122
- background-color: #262c3b;
123
- border: 1px solid #202531;
124
- padding: 0.5rem 1rem;
125
- margin: 0 0.5rem;
126
- }
127
-
128
- .btn:not(:disabled):hover {
129
- color: #e0e1e5;
130
- border-color: #666c7b;
131
- }
132
-
133
- .btn:active {
134
- border-color: #699ce8;
135
- color: #699ce8;
136
- }
137
-
138
- .btn:disabled {
139
- color: #aaa;
140
- border-color: #242937;
141
- }
142
-
143
- .btn.tab-btn {
144
- padding: 0.3rem 1rem;
145
- }
146
-
147
- .btn.close-btn {
148
- padding: 0.3rem 1rem;
149
- margin-left: -0.75rem;
150
- font-weight: 700;
151
- }
152
-
153
-
154
- /* Status display
155
  * ============== */
156
-
157
- #status {
158
- position: absolute;
159
- left: 0;
160
- top: 0;
161
- right: 0;
162
- bottom: 0;
163
- display: flex;
164
- justify-content: center;
165
- align-items: center;
166
- /* don't consume click events - make children visible explicitly */
167
- visibility: hidden;
168
- }
169
-
170
- #status-progress {
171
- width: 366px;
172
- height: 7px;
173
- background-color: #38363A;
174
- border: 1px solid #444246;
175
- padding: 1px;
176
- box-shadow: 0 0 2px 1px #1B1C22;
177
- border-radius: 2px;
178
- visibility: visible;
179
- }
180
-
181
- @media only screen and (orientation:portrait) {
182
- #status-progress {
183
- width: 61.8%;
184
- }
185
- }
186
-
187
- #status-progress-inner {
188
- height: 100%;
189
- width: 0;
190
- box-sizing: border-box;
191
- transition: width 0.5s linear;
192
- background-color: #202020;
193
- border: 1px solid #222223;
194
- box-shadow: 0 0 1px 1px #27282E;
195
- border-radius: 3px;
196
- }
197
-
198
- #status-indeterminate {
199
- visibility: visible;
200
- position: relative;
201
- }
202
-
203
- #status-indeterminate > div {
204
- width: 4.5px;
205
- height: 0;
206
- border-style: solid;
207
- border-width: 9px 3px 0 3px;
208
- border-color: #2b2b2b transparent transparent transparent;
209
- transform-origin: center 21px;
210
- position: absolute;
211
- }
212
-
213
- #status-indeterminate > div:nth-child(1) { transform: rotate( 22.5deg); }
214
- #status-indeterminate > div:nth-child(2) { transform: rotate( 67.5deg); }
215
- #status-indeterminate > div:nth-child(3) { transform: rotate(112.5deg); }
216
- #status-indeterminate > div:nth-child(4) { transform: rotate(157.5deg); }
217
- #status-indeterminate > div:nth-child(5) { transform: rotate(202.5deg); }
218
- #status-indeterminate > div:nth-child(6) { transform: rotate(247.5deg); }
219
- #status-indeterminate > div:nth-child(7) { transform: rotate(292.5deg); }
220
- #status-indeterminate > div:nth-child(8) { transform: rotate(337.5deg); }
221
-
222
- #status-notice {
223
- margin: 0 100px;
224
- line-height: 1.3;
225
- visibility: visible;
226
- padding: 4px 6px;
227
- visibility: visible;
228
- }
229
- </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  </head>
 
231
  <body>
232
- <div
233
- id="welcome-modal"
234
- class="welcome-modal"
235
- role="dialog"
236
- aria-labelledby="welcome-modal-title"
237
- aria-describedby="welcome-modal-description"
238
- onclick="if (event.target === this) closeWelcomeModal(false)"
239
- >
240
- <div class="welcome-modal-content">
241
- <h2 id="welcome-modal-title">Important - Please read before continuing</h2>
242
- <div id="welcome-modal-description">
243
- <p>
244
- The Godot Web Editor has some limitations compared to the native version.
245
- Its main focus is education and experimentation;
246
- <strong>it is not recommended for production</strong>.
247
- </p>
248
- <p>
249
- Refer to the
250
- <a
251
- href="https://docs.godotengine.org/en/latest/tutorials/editor/using_the_web_editor.html"
252
- target="_blank"
253
- rel="noopener"
254
- >Web editor documentation</a> for usage instructions and limitations.
255
- </p>
256
- </div>
257
- <button id="welcome-modal-dismiss" class="btn" type="button" onclick="closeWelcomeModal(true)" style="margin-top: 1rem">
258
  OK, don't show again
259
  </button>
260
- </div>
261
- </div>
262
- <div id="tabs-buttons">
263
- <button id="btn-tab-loader" class="btn tab-btn" onclick="showTab('loader')">Loader</button>
264
- <button id="btn-tab-editor" class="btn tab-btn" disabled="disabled" onclick="showTab('editor')">Editor</button>
265
- <button id="btn-close-editor" class="btn close-btn" disabled="disabled" onclick="closeEditor()">×</button>
266
- <button id="btn-tab-game" class="btn tab-btn" disabled="disabled" onclick="showTab('game')">Game</button>
267
- <button id="btn-close-game" class="btn close-btn" disabled="disabled" onclick="closeGame()">×</button>
268
- </div>
269
- <div id="tabs">
270
- <div id="tab-loader">
271
- <div style="color: #e0e0e0;" id="persistence">
272
- <br />
273
- <img src="logo.svg" alt="Godot Engine logo" width="1024" height="414" style="width: auto; height: auto; max-width: min(85%, 50vh); max-height: 250px" />
274
- <br />
275
- 3.4.4.rc.custom_build
276
- <br />
277
- <a href="releases/">Need an old version?</a>
278
- <br />
279
- <br />
280
- <br />
281
- <label for="videoMode" style="margin-right: 1rem">Video driver:</label>
282
- <select id="videoMode">
283
  <option value="" selected="selected">Auto</option>
284
  <option value="GLES2">WebGL</option>
285
  <option value="GLES3">WebGL 2</option>
286
  </select>
287
- <br />
288
- <br />
289
- <label for="zip-file" style="margin-right: 1rem">Preload project ZIP:</label> <input id="zip-file" type="file" name="files" style="margin-bottom: 1rem"/>
290
- <br />
291
- <a href="demo.zip">(Try this for example)</a>
292
- <br />
293
- <br />
294
- <button id="startButton" class="btn" style="margin-bottom: 4rem; font-weight: 700">Start Godot editor</button>
295
- <br />
296
- <button class="btn" onclick="clearPersistence()" style="margin-bottom: 1.5rem">Clear persistent data</button>
297
- <br />
298
- <a href="https://docs.godotengine.org/en/3.4/tutorials/editor/using_the_web_editor.html">Web editor documentation</a>
299
- </div>
300
- </div>
301
- <div id="tab-editor" style="display: none;">
302
- <canvas id="editor-canvas" tabindex="1">
303
  HTML5 canvas appears to be unsupported in the current browser.<br />
304
  Please try updating or use a different browser.
305
  </canvas>
306
- </div>
307
- <div id="tab-game" style="display: none;">
308
- <canvas id="game-canvas" tabindex="2">
309
  HTML5 canvas appears to be unsupported in the current browser.<br />
310
  Please try updating or use a different browser.
311
  </canvas>
312
- </div>
313
- <div id="tab-status" style="display: none;">
314
- <div id="status-progress" style="display: none;" oncontextmenu="event.preventDefault();"><div id="status-progress-inner"></div></div>
315
- <div id="status-indeterminate" style="display: none;" oncontextmenu="event.preventDefault();">
316
- <div></div>
317
- <div></div>
318
- <div></div>
319
- <div></div>
320
- <div></div>
321
- <div></div>
322
- <div></div>
323
- <div></div>
324
- </div>
325
- <div id="status-notice" class="godot" style="display: none;"></div>
326
- </div>
327
- </div>
328
- <script>
329
- window.addEventListener("load", () => {
330
- if ("serviceWorker" in navigator) {
331
- navigator.serviceWorker.register("service.worker.js");
332
- }
333
-
334
- if (localStorage.getItem("welcomeModalDismissed") !== 'true') {
335
- document.getElementById("welcome-modal").style.display = "block";
336
- document.getElementById("welcome-modal-dismiss").focus();
337
- }
338
- });
339
-
340
- function closeWelcomeModal(dontShowAgain) {
341
- document.getElementById("welcome-modal").style.display = "none";
342
- if (dontShowAgain) {
343
- localStorage.setItem("welcomeModalDismissed", 'true');
344
- }
345
- }
346
- </script>
347
- <script src="godot.tools.js"></script>
348
- <script>//<![CDATA[
349
-
350
- var editor = null;
351
- var game = null;
352
- var setStatusMode;
353
- var setStatusNotice;
354
- var video_driver = "";
355
-
356
- function clearPersistence() {
357
- function deleteDB(path) {
358
- return new Promise(function(resolve, reject) {
359
- var req = indexedDB.deleteDatabase(path);
360
- req.onsuccess = function() {
361
- resolve();
362
- };
363
- req.onerror = function(err) {
364
- reject(err);
365
- };
366
- req.onblocked = function(err) {
367
- reject(err);
368
- }
369
-
370
- });
371
- }
372
- if (!window.confirm("Are you sure you want to delete all the locally stored files?\nClicking \"OK\" will permanently remove your projects and editor settings!")) {
373
- return;
374
- }
375
- Promise.all([
376
- deleteDB("/home/web_user"),
377
- ]).then(function(results) {
378
- alert("Done.");
379
- }).catch(function (err) {
380
- alert("Error deleting local files. Please retry after reloading the page.");
381
- });
382
- }
383
-
384
- function selectVideoMode() {
385
- var select = document.getElementById('videoMode');
386
- video_driver = select.selectedOptions[0].value;
387
- }
388
-
389
- var tabs = [
390
- document.getElementById('tab-loader'),
391
- document.getElementById('tab-editor'),
392
- document.getElementById('tab-game')
393
- ]
394
- function showTab(name) {
395
- tabs.forEach(function (elem) {
396
- if (elem.id == 'tab-' + name) {
397
- elem.style.display = 'block';
398
- if (name == 'editor' || name == 'game') {
399
- const canvas = document.getElementById(name + '-canvas');
400
- canvas.focus();
401
- }
402
- } else {
403
- elem.style.display = 'none';
404
- }
405
- });
406
- }
407
-
408
- function setButtonEnabled(id, enabled) {
409
- if (enabled) {
410
- document.getElementById(id).disabled = "";
411
- } else {
412
- document.getElementById(id).disabled = "disabled";
413
- }
414
- }
415
-
416
- function setLoaderEnabled(enabled) {
417
- setButtonEnabled('btn-tab-loader', enabled);
418
- setButtonEnabled('btn-tab-editor', !enabled);
419
- setButtonEnabled('btn-close-editor', !enabled);
420
- }
421
-
422
- function setGameTabEnabled(enabled) {
423
- setButtonEnabled('btn-tab-game', enabled);
424
- setButtonEnabled('btn-close-game', enabled);
425
- }
426
-
427
- function closeGame() {
428
- if (game) {
429
- game.requestQuit();
430
- }
431
- }
432
-
433
- function closeEditor() {
434
- closeGame();
435
- if (editor) {
436
- editor.requestQuit();
437
- }
438
- }
439
-
440
- function startEditor(zip) {
441
- const INDETERMINATE_STATUS_STEP_MS = 100;
442
- const persistentPaths = ['/home/web_user'];
443
-
444
- var editorCanvas = document.getElementById('editor-canvas');
445
- var gameCanvas = document.getElementById('game-canvas');
446
- var statusProgress = document.getElementById('status-progress');
447
- var statusProgressInner = document.getElementById('status-progress-inner');
448
- var statusIndeterminate = document.getElementById('status-indeterminate');
449
- var statusNotice = document.getElementById('status-notice');
450
- var headerDiv = document.getElementById('tabs-buttons');
451
-
452
- var initializing = true;
453
- var statusMode = 'hidden';
454
-
455
- showTab('status');
456
-
457
- var animationCallbacks = [];
458
- function animate(time) {
459
- animationCallbacks.forEach(callback => callback(time));
460
- requestAnimationFrame(animate);
461
- }
462
- requestAnimationFrame(animate);
463
-
464
- var lastScale = 0;
465
- var lastWidth = 0;
466
- var lastHeight = 0;
467
- function adjustCanvasDimensions() {
468
- var scale = window.devicePixelRatio || 1;
469
- var headerHeight = headerDiv.offsetHeight + 1;
470
- var width = window.innerWidth;
471
- var height = window.innerHeight - headerHeight;
472
- if (lastScale !== scale || lastWidth !== width || lastHeight !== height) {
473
- editorCanvas.width = width * scale;
474
- editorCanvas.height = height * scale;
475
- editorCanvas.style.width = width + "px";
476
- editorCanvas.style.height = height + "px";
477
- lastScale = scale;
478
- lastWidth = width;
479
- lastHeight = height;
480
- }
481
- }
482
- animationCallbacks.push(adjustCanvasDimensions);
483
- adjustCanvasDimensions();
484
-
485
- function replaceCanvas(from) {
486
- const out = document.createElement("canvas");
487
- out.id = from.id;
488
- out.tabIndex = from.tabIndex;
489
- from.parentNode.replaceChild(out, from);
490
- lastScale = 0;
491
- return out;
492
- }
493
-
494
- setStatusMode = function setStatusMode(mode) {
495
- if (statusMode === mode || !initializing)
496
- return;
497
- [statusProgress, statusIndeterminate, statusNotice].forEach(elem => {
498
- elem.style.display = 'none';
499
- });
500
- animationCallbacks = animationCallbacks.filter(function(value) {
501
- return (value != animateStatusIndeterminate);
502
- });
503
- switch (mode) {
504
- case 'progress':
505
- statusProgress.style.display = 'block';
506
- break;
507
- case 'indeterminate':
508
- statusIndeterminate.style.display = 'block';
509
- animationCallbacks.push(animateStatusIndeterminate);
510
- break;
511
- case 'notice':
512
- statusNotice.style.display = 'block';
513
- break;
514
- case 'hidden':
515
- break;
516
- default:
517
- throw new Error('Invalid status mode');
518
- }
519
- statusMode = mode;
520
- };
521
-
522
- function animateStatusIndeterminate(ms) {
523
- var i = Math.floor(ms / INDETERMINATE_STATUS_STEP_MS % 8);
524
- if (statusIndeterminate.children[i].style.borderTopColor == '') {
525
- Array.prototype.slice.call(statusIndeterminate.children).forEach(child => {
526
- child.style.borderTopColor = '';
527
- });
528
- statusIndeterminate.children[i].style.borderTopColor = '#dfdfdf';
529
- }
530
- }
531
-
532
- setStatusNotice = function setStatusNotice(text) {
533
- while (statusNotice.lastChild) {
534
- statusNotice.removeChild(statusNotice.lastChild);
535
- }
536
- var lines = text.split('\n');
537
- lines.forEach((line) => {
538
- statusNotice.appendChild(document.createTextNode(line));
539
- statusNotice.appendChild(document.createElement('br'));
540
- });
541
- };
542
-
543
- const gameConfig = {
544
- 'persistentPaths': persistentPaths,
545
- 'unloadAfterInit': false,
546
- 'canvas': gameCanvas,
547
- 'canvasResizePolicy': 1,
548
- 'onExit': function () {
549
- gameCanvas = replaceCanvas(gameCanvas);
550
- setGameTabEnabled(false);
551
- showTab('editor');
552
- game = null;
553
- },
554
- };
555
-
556
- var OnEditorExit = function () {
557
- showTab('loader');
558
- setLoaderEnabled(true);
559
- };
560
- function Execute(args) {
561
- const is_editor = args.filter(function(v) { return v == '--editor' || v == '-e' }).length != 0;
562
- const is_project_manager = args.filter(function(v) { return v == '--project-manager' }).length != 0;
563
- const is_game = !is_editor && !is_project_manager;
564
- if (video_driver) {
565
- args.push('--video-driver', video_driver);
566
- }
567
- if (is_game) {
568
- if (game) {
569
- console.error("A game is already running. Close it first");
570
- return;
571
- }
572
- setGameTabEnabled(true);
573
- game = new Engine(gameConfig);
574
- showTab('game');
575
- game.init().then(function() {
576
- requestAnimationFrame(function() {
577
- game.start({'args': args, 'canvas': gameCanvas}).then(function() {
578
- gameCanvas.focus();
579
- });
580
- });
581
- });
582
- } else { // New editor instances will be run in the same canvas. We want to wait for it to exit.
583
- OnEditorExit = function(code) {
584
- setLoaderEnabled(true);
585
- setTimeout(function() {
586
- editor.init().then(function() {
587
- setLoaderEnabled(false);
588
- OnEditorExit = function() {
589
- showTab('loader');
590
- setLoaderEnabled(true);
591
- };
592
- editor.start({'args': args, 'persistentDrops': is_project_manager, 'canvas': editorCanvas});
593
- });
594
- }, 0);
595
- OnEditorExit = null;
596
- };
597
- }
598
- }
599
-
600
- const editorConfig = {
601
- 'unloadAfterInit': false,
602
- 'onProgress': function progressFunction (current, total) {
603
- if (total > 0) {
604
- statusProgressInner.style.width = current/total * 100 + '%';
605
- setStatusMode('progress');
606
- if (current === total) {
607
- // wait for progress bar animation
608
- setTimeout(() => {
609
- setStatusMode('indeterminate');
610
- }, 100);
611
- }
612
- } else {
613
- setStatusMode('indeterminate');
614
- }
615
- },
616
- 'canvas': editorCanvas,
617
- 'canvasResizePolicy': 0,
618
- 'onExit': function() {
619
- editorCanvas = replaceCanvas(editorCanvas);
620
- if (OnEditorExit) {
621
- OnEditorExit();
622
- }
623
- },
624
- 'onExecute': Execute,
625
- 'persistentPaths': persistentPaths,
626
- };
627
- editor = new Engine(editorConfig);
628
-
629
- function displayFailureNotice(err) {
630
- var msg = err.message || err;
631
- console.error(msg);
632
- setStatusNotice(msg);
633
- setStatusMode('notice');
634
- initializing = false;
635
- };
636
-
637
- if (!Engine.isWebGLAvailable()) {
638
- displayFailureNotice('WebGL not available');
639
- } else {
640
- setStatusMode('indeterminate');
641
- editor.init('godot.tools').then(function() {
642
- if (zip) {
643
- editor.copyToFS("/tmp/preload.zip", zip);
644
- }
645
- try {
646
- // Avoid user creating project in the persistent root folder.
647
- editor.copyToFS("/home/web_user/keep", new Uint8Array());
648
- } catch(e) {
649
- // File exists
650
- }
651
- selectVideoMode();
652
- showTab('editor');
653
- setLoaderEnabled(false);
654
- const args = ['--project-manager'];
655
- if (video_driver) {
656
- args.push('--video-driver', video_driver);
657
- }
658
- editor.start({'args': args, 'persistentDrops': true}).then(function() {
659
- setStatusMode('hidden');
660
- initializing = false;
661
- });
662
- }).catch(displayFailureNotice);
663
- }
664
- };
665
- document.getElementById("startButton").onclick = function() {
666
- preloadZip(document.getElementById('zip-file')).then(function(zip) {
667
- startEditor(zip);
668
- });
669
- }
670
-
671
- function preloadZip(target) {
672
- return new Promise(function(resolve, reject) {
673
- if (target.files.length > 0) {
674
- target.files[0].arrayBuffer().then(function(data) {
675
- resolve(data);
676
- });
677
- } else {
678
- resolve();
679
- }
680
- });
681
- }
682
- //]]></script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
683
  </body>
684
- </html>
 
 
1
  <!DOCTYPE html>
2
  <html xmlns="https://www.w3.org/1999/xhtml" lang="en">
3
+
4
  <head>
5
+ <meta charset="utf-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no" />
7
+ <meta name="author" content="Godot Engine" />
8
+ <meta name="description" content="Use the Godot Engine editor directly in your web browser, without having to install anything." />
9
+ <meta name="mobile-web-app-capable" content="yes" />
10
+ <meta name="apple-mobile-web-app-capable" content="yes" />
11
+ <meta name="application-name" content="Godot" />
12
+ <meta name="apple-mobile-web-app-title" content="Godot" />
13
+ <meta name="theme-color" content="#202531" />
14
+ <meta name="msapplication-navbutton-color" content="#202531" />
15
+ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
16
+ <meta name="msapplication-starturl" content="/latest" />
17
+ <meta property="og:site_name" content="Godot Engine Web Editor" />
18
+ <meta property="og:url" name="twitter:url" content="https://editor.godotengine.org/releases/latest/" />
19
+ <meta property="og:title" name="twitter:title" content="Free and open source 2D and 3D game engine" />
20
+ <meta property="og:description" name="twitter:description" content="Use the Godot Engine editor directly in your web browser, without having to install anything." />
21
+ <meta property="og:image" name="twitter:image" content="https://godotengine.org/themes/godotengine/assets/og_image.png" />
22
+ <meta property="og:type" content="website" />
23
+ <meta name="twitter:card" content="summary" />
24
+ <link id="-gd-engine-icon" rel="icon" type="image/png" href="favicon.png" />
25
+ <link rel="apple-touch-icon" type="image/png" href="favicon.png" />
26
+ <link rel="manifest" href="manifest.json" />
27
+ <title>Godot Engine Web Editor (3.4.4.rc.custom_build)</title>
28
+ <style>
29
+ *:focus {
30
+ /* More visible outline for better keyboard navigation. */
31
+ outline: 0.125rem solid hsl(220, 100%, 62.5%);
32
+ /* Make the outline always appear above other elements. */
33
+ /* Otherwise, one of its sides can be hidden by tabs in the Download and More layouts. */
34
+ position: relative;
35
+ }
36
+
37
+ body {
38
+ touch-action: none;
39
+ font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
40
+ margin: 0;
41
+ border: 0 none;
42
+ padding: 0;
43
+ text-align: center;
44
+ background-color: #333b4f;
45
+ overflow: hidden;
46
+ }
47
+
48
+ a {
49
+ color: hsl(205, 100%, 75%);
50
+ text-decoration-color: hsla(205, 100%, 75%, 0.3);
51
+ text-decoration-thickness: 0.125rem;
52
+ }
53
+
54
+ a:hover {
55
+ filter: brightness(117.5%);
56
+ }
57
+
58
+ a:active {
59
+ filter: brightness(82.5%);
60
+ }
61
+
62
+ .welcome-modal {
63
+ display: none;
64
+ position: fixed;
65
+ z-index: 1;
66
+ left: 0;
67
+ top: 0;
68
+ width: 100%;
69
+ height: 100%;
70
+ overflow: auto;
71
+ background-color: hsla(0, 0%, 0%, 0.5);
72
+ }
73
+
74
+ .welcome-modal-content {
75
+ background-color: #333b4f;
76
+ box-shadow: 0 0.25rem 0.25rem hsla(0, 0%, 0%, 0.5);
77
+ line-height: 1.5;
78
+ max-width: 38rem;
79
+ margin: 4rem auto 0 auto;
80
+ color: white;
81
+ border-radius: 0.5rem;
82
+ padding: 1rem 1rem 2rem 1rem;
83
+ }
84
+
85
+ #tabs-buttons {
86
+ /* Match the default background color of the editor window for a seamless appearance. */
87
+ background-color: #202531;
88
+ }
89
+
90
+ #tab-game {
91
+ /* Use a pure black background to better distinguish the running project */
92
+ /* from the editor window, and to use a more neutral background color (no tint). */
93
+ background-color: black;
94
+ /* Make the background span the entire page height. */
95
+ min-height: 100vh;
96
+ }
97
+
98
+ #canvas,
99
+ #gameCanvas {
100
+ display: block;
101
+ margin: 0;
102
+ color: white;
103
+ }
104
+ /* Don't show distracting focus outlines for the main tabs' contents. */
105
+
106
+ #tab-editor canvas:focus,
107
+ #tab-game canvas:focus,
108
+ #canvas:focus,
109
+ #gameCanvas:focus {
110
+ outline: none;
111
+ }
112
+
113
+ .godot {
114
+ color: #e0e0e0;
115
+ background-color: #3b3943;
116
+ background-image: linear-gradient(to bottom, #403e48, #35333c);
117
+ border: 1px solid #45434e;
118
+ box-shadow: 0 0 1px 1px #2f2d35;
119
+ }
120
+
121
+ .btn {
122
+ appearance: none;
123
+ color: #e0e0e0;
124
+ background-color: #262c3b;
125
+ border: 1px solid #202531;
126
+ padding: 0.5rem 1rem;
127
+ margin: 0 0.5rem;
128
+ }
129
+
130
+ .btn:not(:disabled):hover {
131
+ color: #e0e1e5;
132
+ border-color: #666c7b;
133
+ }
134
+
135
+ .btn:active {
136
+ border-color: #699ce8;
137
+ color: #699ce8;
138
+ }
139
+
140
+ .btn:disabled {
141
+ color: #aaa;
142
+ border-color: #242937;
143
+ }
144
+
145
+ .btn.tab-btn {
146
+ padding: 0.3rem 1rem;
147
+ }
148
+
149
+ .btn.close-btn {
150
+ padding: 0.3rem 1rem;
151
+ margin-left: -0.75rem;
152
+ font-weight: 700;
153
+ }
154
+ /* Status display
 
155
  * ============== */
156
+
157
+ #status {
158
+ position: absolute;
159
+ left: 0;
160
+ top: 0;
161
+ right: 0;
162
+ bottom: 0;
163
+ display: flex;
164
+ justify-content: center;
165
+ align-items: center;
166
+ /* don't consume click events - make children visible explicitly */
167
+ visibility: hidden;
168
+ }
169
+
170
+ #status-progress {
171
+ width: 366px;
172
+ height: 7px;
173
+ background-color: #38363A;
174
+ border: 1px solid #444246;
175
+ padding: 1px;
176
+ box-shadow: 0 0 2px 1px #1B1C22;
177
+ border-radius: 2px;
178
+ visibility: visible;
179
+ }
180
+
181
+ @media only screen and (orientation:portrait) {
182
+ #status-progress {
183
+ width: 61.8%;
184
+ }
185
+ }
186
+
187
+ #status-progress-inner {
188
+ height: 100%;
189
+ width: 0;
190
+ box-sizing: border-box;
191
+ transition: width 0.5s linear;
192
+ background-color: #202020;
193
+ border: 1px solid #222223;
194
+ box-shadow: 0 0 1px 1px #27282E;
195
+ border-radius: 3px;
196
+ }
197
+
198
+ #status-indeterminate {
199
+ visibility: visible;
200
+ position: relative;
201
+ }
202
+
203
+ #status-indeterminate>div {
204
+ width: 4.5px;
205
+ height: 0;
206
+ border-style: solid;
207
+ border-width: 9px 3px 0 3px;
208
+ border-color: #2b2b2b transparent transparent transparent;
209
+ transform-origin: center 21px;
210
+ position: absolute;
211
+ }
212
+
213
+ #status-indeterminate>div:nth-child(1) {
214
+ transform: rotate( 22.5deg);
215
+ }
216
+
217
+ #status-indeterminate>div:nth-child(2) {
218
+ transform: rotate( 67.5deg);
219
+ }
220
+
221
+ #status-indeterminate>div:nth-child(3) {
222
+ transform: rotate(112.5deg);
223
+ }
224
+
225
+ #status-indeterminate>div:nth-child(4) {
226
+ transform: rotate(157.5deg);
227
+ }
228
+
229
+ #status-indeterminate>div:nth-child(5) {
230
+ transform: rotate(202.5deg);
231
+ }
232
+
233
+ #status-indeterminate>div:nth-child(6) {
234
+ transform: rotate(247.5deg);
235
+ }
236
+
237
+ #status-indeterminate>div:nth-child(7) {
238
+ transform: rotate(292.5deg);
239
+ }
240
+
241
+ #status-indeterminate>div:nth-child(8) {
242
+ transform: rotate(337.5deg);
243
+ }
244
+
245
+ #status-notice {
246
+ margin: 0 100px;
247
+ line-height: 1.3;
248
+ visibility: visible;
249
+ padding: 4px 6px;
250
+ visibility: visible;
251
+ }
252
+ </style>
253
  </head>
254
+
255
  <body>
256
+ <div id="welcome-modal" class="welcome-modal" role="dialog" aria-labelledby="welcome-modal-title" aria-describedby="welcome-modal-description" onclick="if (event.target === this) closeWelcomeModal(false)">
257
+ <div class="welcome-modal-content">
258
+ <h2 id="welcome-modal-title">Important - Please read before continuing</h2>
259
+ <div id="welcome-modal-description">
260
+ <p>
261
+ The Godot Web Editor has some limitations compared to the native version. Its main focus is education and experimentation;
262
+ <strong>it is not recommended for production</strong>.
263
+ </p>
264
+ <p>
265
+ Refer to the
266
+ <a href="https://docs.godotengine.org/en/latest/tutorials/editor/using_the_web_editor.html" target="_blank" rel="noopener">Web editor documentation</a> for usage instructions and limitations.
267
+ </p>
268
+ </div>
269
+ <button id="welcome-modal-dismiss" class="btn" type="button" onclick="closeWelcomeModal(true)" style="margin-top: 1rem">
 
 
 
 
 
 
 
 
 
 
 
 
270
  OK, don't show again
271
  </button>
272
+ </div>
273
+ </div>
274
+ <div id="tabs-buttons">
275
+ <button id="btn-tab-loader" class="btn tab-btn" onclick="showTab('loader')">Loader</button>
276
+ <button id="btn-tab-editor" class="btn tab-btn" disabled="disabled" onclick="showTab('editor')">Editor</button>
277
+ <button id="btn-close-editor" class="btn close-btn" disabled="disabled" onclick="closeEditor()">×</button>
278
+ <button id="btn-tab-game" class="btn tab-btn" disabled="disabled" onclick="showTab('game')">Game</button>
279
+ <button id="btn-close-game" class="btn close-btn" disabled="disabled" onclick="closeGame()">×</button>
280
+ </div>
281
+ <div id="tabs">
282
+ <div id="tab-loader">
283
+ <div style="color: #e0e0e0;" id="persistence">
284
+ <br />
285
+ <img src="logo.svg" alt="Godot Engine logo" width="1024" height="414" style="width: auto; height: auto; max-width: min(85%, 50vh); max-height: 250px" />
286
+ <br /> 3.4.4.rc.custom_build
287
+ <br />
288
+ <a href="releases/">Need an old version?</a>
289
+ <br />
290
+ <br />
291
+ <br />
292
+ <label for="videoMode" style="margin-right: 1rem">Video driver:</label>
293
+ <select id="videoMode">
 
294
  <option value="" selected="selected">Auto</option>
295
  <option value="GLES2">WebGL</option>
296
  <option value="GLES3">WebGL 2</option>
297
  </select>
298
+ <br />
299
+ <br />
300
+ <label for="zip-file" style="margin-right: 1rem">Preload project ZIP:</label> <input id="zip-file" type="file" name="files" style="margin-bottom: 1rem" />
301
+ <br />
302
+ <a href="demo.zip">(Try this for example)</a>
303
+ <br />
304
+ <br />
305
+ <button id="startButton" class="btn" style="margin-bottom: 4rem; font-weight: 700">Start Godot editor</button>
306
+ <br />
307
+ <button class="btn" onclick="clearPersistence()" style="margin-bottom: 1.5rem">Clear persistent data</button>
308
+ <br />
309
+ <a href="https://docs.godotengine.org/en/3.4/tutorials/editor/using_the_web_editor.html">Web editor documentation</a>
310
+ </div>
311
+ </div>
312
+ <div id="tab-editor" style="display: none;">
313
+ <canvas id="editor-canvas" tabindex="1">
314
  HTML5 canvas appears to be unsupported in the current browser.<br />
315
  Please try updating or use a different browser.
316
  </canvas>
317
+ </div>
318
+ <div id="tab-game" style="display: none;">
319
+ <canvas id="game-canvas" tabindex="2">
320
  HTML5 canvas appears to be unsupported in the current browser.<br />
321
  Please try updating or use a different browser.
322
  </canvas>
323
+ </div>
324
+ <div id="tab-status" style="display: none;">
325
+ <div id="status-progress" style="display: none;" oncontextmenu="event.preventDefault();">
326
+ <div id="status-progress-inner"></div>
327
+ </div>
328
+ <div id="status-indeterminate" style="display: none;" oncontextmenu="event.preventDefault();">
329
+ <div></div>
330
+ <div></div>
331
+ <div></div>
332
+ <div></div>
333
+ <div></div>
334
+ <div></div>
335
+ <div></div>
336
+ <div></div>
337
+ </div>
338
+ <div id="status-notice" class="godot" style="display: none;"></div>
339
+ </div>
340
+ </div>
341
+ <script>
342
+ window.addEventListener("load", () => {
343
+ if ("serviceWorker" in navigator) {
344
+ navigator.serviceWorker.register("service.worker.js");
345
+ }
346
+
347
+ if (localStorage.getItem("welcomeModalDismissed") !== 'true') {
348
+ document.getElementById("welcome-modal").style.display = "block";
349
+ document.getElementById("welcome-modal-dismiss").focus();
350
+ }
351
+ });
352
+
353
+ function closeWelcomeModal(dontShowAgain) {
354
+ document.getElementById("welcome-modal").style.display = "none";
355
+ if (dontShowAgain) {
356
+ localStorage.setItem("welcomeModalDismissed", 'true');
357
+ }
358
+ }
359
+ </script>
360
+ <script src="godot.tools.js"></script>
361
+ <script>
362
+ //<![CDATA[
363
+
364
+ var editor = null;
365
+ var game = null;
366
+ var setStatusMode;
367
+ var setStatusNotice;
368
+ var video_driver = "";
369
+
370
+ function clearPersistence() {
371
+ function deleteDB(path) {
372
+ return new Promise(function(resolve, reject) {
373
+ var req = indexedDB.deleteDatabase(path);
374
+ req.onsuccess = function() {
375
+ resolve();
376
+ };
377
+ req.onerror = function(err) {
378
+ reject(err);
379
+ };
380
+ req.onblocked = function(err) {
381
+ reject(err);
382
+ }
383
+
384
+ });
385
+ }
386
+ if (!window.confirm("Are you sure you want to delete all the locally stored files?\nClicking \"OK\" will permanently remove your projects and editor settings!")) {
387
+ return;
388
+ }
389
+ Promise.all([
390
+ deleteDB("/home/web_user"),
391
+ ]).then(function(results) {
392
+ alert("Done.");
393
+ }).catch(function(err) {
394
+ alert("Error deleting local files. Please retry after reloading the page.");
395
+ });
396
+ }
397
+
398
+ function selectVideoMode() {
399
+ var select = document.getElementById('videoMode');
400
+ video_driver = select.selectedOptions[0].value;
401
+ }
402
+
403
+ var tabs = [
404
+ document.getElementById('tab-loader'),
405
+ document.getElementById('tab-editor'),
406
+ document.getElementById('tab-game')
407
+ ]
408
+
409
+ function showTab(name) {
410
+ tabs.forEach(function(elem) {
411
+ if (elem.id == 'tab-' + name) {
412
+ elem.style.display = 'block';
413
+ if (name == 'editor' || name == 'game') {
414
+ const canvas = document.getElementById(name + '-canvas');
415
+ canvas.focus();
416
+ }
417
+ } else {
418
+ elem.style.display = 'none';
419
+ }
420
+ });
421
+ }
422
+
423
+ function setButtonEnabled(id, enabled) {
424
+ if (enabled) {
425
+ document.getElementById(id).disabled = "";
426
+ } else {
427
+ document.getElementById(id).disabled = "disabled";
428
+ }
429
+ }
430
+
431
+ function setLoaderEnabled(enabled) {
432
+ setButtonEnabled('btn-tab-loader', enabled);
433
+ setButtonEnabled('btn-tab-editor', !enabled);
434
+ setButtonEnabled('btn-close-editor', !enabled);
435
+ }
436
+
437
+ function setGameTabEnabled(enabled) {
438
+ setButtonEnabled('btn-tab-game', enabled);
439
+ setButtonEnabled('btn-close-game', enabled);
440
+ }
441
+
442
+ function closeGame() {
443
+ if (game) {
444
+ game.requestQuit();
445
+ }
446
+ }
447
+
448
+ function closeEditor() {
449
+ closeGame();
450
+ if (editor) {
451
+ editor.requestQuit();
452
+ }
453
+ }
454
+
455
+ function startEditor(zip) {
456
+ const INDETERMINATE_STATUS_STEP_MS = 100;
457
+ const persistentPaths = ['/home/web_user'];
458
+
459
+ var editorCanvas = document.getElementById('editor-canvas');
460
+ var gameCanvas = document.getElementById('game-canvas');
461
+ var statusProgress = document.getElementById('status-progress');
462
+ var statusProgressInner = document.getElementById('status-progress-inner');
463
+ var statusIndeterminate = document.getElementById('status-indeterminate');
464
+ var statusNotice = document.getElementById('status-notice');
465
+ var headerDiv = document.getElementById('tabs-buttons');
466
+
467
+ var initializing = true;
468
+ var statusMode = 'hidden';
469
+
470
+ showTab('status');
471
+
472
+ var animationCallbacks = [];
473
+
474
+ function animate(time) {
475
+ animationCallbacks.forEach(callback => callback(time));
476
+ requestAnimationFrame(animate);
477
+ }
478
+ requestAnimationFrame(animate);
479
+
480
+ var lastScale = 0;
481
+ var lastWidth = 0;
482
+ var lastHeight = 0;
483
+
484
+ function adjustCanvasDimensions() {
485
+ var scale = window.devicePixelRatio || 1;
486
+ var headerHeight = headerDiv.offsetHeight + 1;
487
+ var width = window.innerWidth;
488
+ var height = window.innerHeight - headerHeight;
489
+ if (lastScale !== scale || lastWidth !== width || lastHeight !== height) {
490
+ editorCanvas.width = width * scale;
491
+ editorCanvas.height = height * scale;
492
+ editorCanvas.style.width = width + "px";
493
+ editorCanvas.style.height = height + "px";
494
+ lastScale = scale;
495
+ lastWidth = width;
496
+ lastHeight = height;
497
+ }
498
+ }
499
+ animationCallbacks.push(adjustCanvasDimensions);
500
+ adjustCanvasDimensions();
501
+
502
+ function replaceCanvas(from) {
503
+ const out = document.createElement("canvas");
504
+ out.id = from.id;
505
+ out.tabIndex = from.tabIndex;
506
+ from.parentNode.replaceChild(out, from);
507
+ lastScale = 0;
508
+ return out;
509
+ }
510
+
511
+ setStatusMode = function setStatusMode(mode) {
512
+ if (statusMode === mode || !initializing)
513
+ return;
514
+ [statusProgress, statusIndeterminate, statusNotice].forEach(elem => {
515
+ elem.style.display = 'none';
516
+ });
517
+ animationCallbacks = animationCallbacks.filter(function(value) {
518
+ return (value != animateStatusIndeterminate);
519
+ });
520
+ switch (mode) {
521
+ case 'progress':
522
+ statusProgress.style.display = 'block';
523
+ break;
524
+ case 'indeterminate':
525
+ statusIndeterminate.style.display = 'block';
526
+ animationCallbacks.push(animateStatusIndeterminate);
527
+ break;
528
+ case 'notice':
529
+ statusNotice.style.display = 'block';
530
+ break;
531
+ case 'hidden':
532
+ break;
533
+ default:
534
+ throw new Error('Invalid status mode');
535
+ }
536
+ statusMode = mode;
537
+ };
538
+
539
+ function animateStatusIndeterminate(ms) {
540
+ var i = Math.floor(ms / INDETERMINATE_STATUS_STEP_MS % 8);
541
+ if (statusIndeterminate.children[i].style.borderTopColor == '') {
542
+ Array.prototype.slice.call(statusIndeterminate.children).forEach(child => {
543
+ child.style.borderTopColor = '';
544
+ });
545
+ statusIndeterminate.children[i].style.borderTopColor = '#dfdfdf';
546
+ }
547
+ }
548
+
549
+ setStatusNotice = function setStatusNotice(text) {
550
+ while (statusNotice.lastChild) {
551
+ statusNotice.removeChild(statusNotice.lastChild);
552
+ }
553
+ var lines = text.split('\n');
554
+ lines.forEach((line) => {
555
+ statusNotice.appendChild(document.createTextNode(line));
556
+ statusNotice.appendChild(document.createElement('br'));
557
+ });
558
+ };
559
+
560
+ const gameConfig = {
561
+ 'persistentPaths': persistentPaths,
562
+ 'unloadAfterInit': false,
563
+ 'canvas': gameCanvas,
564
+ 'canvasResizePolicy': 1,
565
+ 'onExit': function() {
566
+ gameCanvas = replaceCanvas(gameCanvas);
567
+ setGameTabEnabled(false);
568
+ showTab('editor');
569
+ game = null;
570
+ },
571
+ };
572
+
573
+ var OnEditorExit = function() {
574
+ showTab('loader');
575
+ setLoaderEnabled(true);
576
+ };
577
+
578
+ function Execute(args) {
579
+ const is_editor = args.filter(function(v) {
580
+ return v == '--editor' || v == '-e'
581
+ }).length != 0;
582
+ const is_project_manager = args.filter(function(v) {
583
+ return v == '--project-manager'
584
+ }).length != 0;
585
+ const is_game = !is_editor && !is_project_manager;
586
+ if (video_driver) {
587
+ args.push('--video-driver', video_driver);
588
+ }
589
+ if (is_game) {
590
+ if (game) {
591
+ console.error("A game is already running. Close it first");
592
+ return;
593
+ }
594
+ setGameTabEnabled(true);
595
+ game = new Engine(gameConfig);
596
+ showTab('game');
597
+ game.init().then(function() {
598
+ requestAnimationFrame(function() {
599
+ game.start({
600
+ 'args': args,
601
+ 'canvas': gameCanvas
602
+ }).then(function() {
603
+ gameCanvas.focus();
604
+ });
605
+ });
606
+ });
607
+ } else { // New editor instances will be run in the same canvas. We want to wait for it to exit.
608
+ OnEditorExit = function(code) {
609
+ setLoaderEnabled(true);
610
+ setTimeout(function() {
611
+ editor.init().then(function() {
612
+ setLoaderEnabled(false);
613
+ OnEditorExit = function() {
614
+ showTab('loader');
615
+ setLoaderEnabled(true);
616
+ };
617
+ editor.start({
618
+ 'args': args,
619
+ 'persistentDrops': is_project_manager,
620
+ 'canvas': editorCanvas
621
+ });
622
+ });
623
+ }, 0);
624
+ OnEditorExit = null;
625
+ };
626
+ }
627
+ }
628
+
629
+ const editorConfig = {
630
+ 'unloadAfterInit': false,
631
+ 'onProgress': function progressFunction(current, total) {
632
+ if (total > 0) {
633
+ statusProgressInner.style.width = current / total * 100 + '%';
634
+ setStatusMode('progress');
635
+ if (current === total) {
636
+ // wait for progress bar animation
637
+ setTimeout(() => {
638
+ setStatusMode('indeterminate');
639
+ }, 100);
640
+ }
641
+ } else {
642
+ setStatusMode('indeterminate');
643
+ }
644
+ },
645
+ 'canvas': editorCanvas,
646
+ 'canvasResizePolicy': 0,
647
+ 'onExit': function() {
648
+ editorCanvas = replaceCanvas(editorCanvas);
649
+ if (OnEditorExit) {
650
+ OnEditorExit();
651
+ }
652
+ },
653
+ 'onExecute': Execute,
654
+ 'persistentPaths': persistentPaths,
655
+ };
656
+ editor = new Engine(editorConfig);
657
+
658
+ function displayFailureNotice(err) {
659
+ var msg = err.message || err;
660
+ console.error(msg);
661
+ setStatusNotice(msg);
662
+ setStatusMode('notice');
663
+ initializing = false;
664
+ };
665
+
666
+ if (!Engine.isWebGLAvailable()) {
667
+ displayFailureNotice('WebGL not available');
668
+ } else {
669
+ setStatusMode('indeterminate');
670
+ editor.init('https://huggingface.co/spaces/thomwolf/test_godot_editor/resolve/main/godot.tools').then(function() {
671
+ if (zip) {
672
+ editor.copyToFS("/tmp/preload.zip", zip);
673
+ }
674
+ try {
675
+ // Avoid user creating project in the persistent root folder.
676
+ editor.copyToFS("/home/web_user/keep", new Uint8Array());
677
+ } catch (e) {
678
+ // File exists
679
+ }
680
+ selectVideoMode();
681
+ showTab('editor');
682
+ setLoaderEnabled(false);
683
+ const args = ['--project-manager'];
684
+ if (video_driver) {
685
+ args.push('--video-driver', video_driver);
686
+ }
687
+ editor.start({
688
+ 'args': args,
689
+ 'persistentDrops': true
690
+ }).then(function() {
691
+ setStatusMode('hidden');
692
+ initializing = false;
693
+ });
694
+ }).catch(displayFailureNotice);
695
+ }
696
+ };
697
+ document.getElementById("startButton").onclick = function() {
698
+ preloadZip(document.getElementById('zip-file')).then(function(zip) {
699
+ startEditor(zip);
700
+ });
701
+ }
702
+
703
+ function preloadZip(target) {
704
+ return new Promise(function(resolve, reject) {
705
+ if (target.files.length > 0) {
706
+ target.files[0].arrayBuffer().then(function(data) {
707
+ resolve(data);
708
+ });
709
+ } else {
710
+ resolve();
711
+ }
712
+ });
713
+ }
714
+ //]]>
715
+ </script>
716
  </body>
717
+
718
+ </html>