Commit e9df5b99ebad4f639f81c0dc50513fd331d8895b

Authored by xp.Huang
2 parents bcd77b64 3617dff6

Merge branch 'perf/model-editor-save-tooltop' into 'main_dev'

perf: 新增3d模型编辑器tooltip

See merge request yunteng/thingskit-view!312
... ... @@ -7,10 +7,10 @@ import { Strings } from './Strings.js';
7 7 import { Storage as _Storage } from './Storage.js';
8 8 import { Selector } from './Selector.js';
9 9
10   -var _DEFAULT_CAMERA = new THREE.PerspectiveCamera( 50, 1, 0.01, 1000 );
  10 +var _DEFAULT_CAMERA = new THREE.PerspectiveCamera(50, 1, 0.01, 1000);
11 11 _DEFAULT_CAMERA.name = 'Camera';
12   -_DEFAULT_CAMERA.position.set( 0, 5, 10 );
13   -_DEFAULT_CAMERA.lookAt( new THREE.Vector3() );
  12 +_DEFAULT_CAMERA.position.set(0, 5, 10);
  13 +_DEFAULT_CAMERA.lookAt(new THREE.Vector3());
14 14
15 15 function Editor() {
16 16
... ... @@ -97,12 +97,12 @@ function Editor() {
97 97 };
98 98
99 99 this.config = new Config();
100   - this.history = new _History( this );
101   - this.selector = new Selector( this );
  100 + this.history = new _History(this);
  101 + this.selector = new Selector(this);
102 102 this.storage = new _Storage();
103   - this.strings = new Strings( this.config );
  103 + this.strings = new Strings(this.config);
104 104
105   - this.loader = new Loader( this );
  105 + this.loader = new Loader(this);
106 106
107 107 this.camera = _DEFAULT_CAMERA.clone();
108 108
... ... @@ -110,7 +110,7 @@ function Editor() {
110 110 this.scene.name = 'Scene';
111 111
112 112 this.sceneHelpers = new THREE.Scene();
113   - this.sceneHelpers.add( new THREE.HemisphereLight( 0xffffff, 0x888888, 2 ) );
  113 + this.sceneHelpers.add(new THREE.HemisphereLight(0xffffff, 0x888888, 2));
114 114
115 115 this.object = {};
116 116 this.geometries = {};
... ... @@ -120,7 +120,7 @@ function Editor() {
120 120
121 121 this.materialsRefCounter = new Map(); // tracks how often is a material used by a 3D object
122 122
123   - this.mixer = new THREE.AnimationMixer( this.scene );
  123 + this.mixer = new THREE.AnimationMixer(this.scene);
124 124
125 125 this.selected = null;
126 126 this.helpers = {};
... ... @@ -130,13 +130,13 @@ function Editor() {
130 130 this.viewportCamera = this.camera;
131 131 this.viewportShading = 'default';
132 132
133   - this.addCamera( this.camera );
  133 + this.addCamera(this.camera);
134 134
135 135 }
136 136
137 137 Editor.prototype = {
138 138
139   - setScene: function ( scene ) {
  139 + setScene: function (scene) {
140 140
141 141 this.scene.uuid = scene.uuid;
142 142 this.scene.name = scene.name;
... ... @@ -147,15 +147,15 @@ Editor.prototype = {
147 147 this.scene.backgroundBlurriness = scene.backgroundBlurriness;
148 148 this.scene.backgroundIntensity = scene.backgroundIntensity;
149 149
150   - this.scene.userData = JSON.parse( JSON.stringify( scene.userData ) );
  150 + this.scene.userData = JSON.parse(JSON.stringify(scene.userData));
151 151
152 152 // avoid render per object
153 153
154 154 this.signals.sceneGraphChanged.active = false;
155 155
156   - while ( scene.children.length > 0 ) {
  156 + while (scene.children.length > 0) {
157 157
158   - this.addObject( scene.children[ 0 ] );
  158 + this.addObject(scene.children[0]);
159 159
160 160 }
161 161
... ... @@ -166,91 +166,91 @@ Editor.prototype = {
166 166
167 167 //
168 168
169   - addObject: function ( object, parent, index ) {
  169 + addObject: function (object, parent, index) {
170 170
171 171 var scope = this;
172 172
173   - object.traverse( function ( child ) {
  173 + object.traverse(function (child) {
174 174
175   - if ( child.geometry !== undefined ) scope.addGeometry( child.geometry );
176   - if ( child.material !== undefined ) scope.addMaterial( child.material );
  175 + if (child.geometry !== undefined) scope.addGeometry(child.geometry);
  176 + if (child.material !== undefined) scope.addMaterial(child.material);
177 177
178   - scope.addCamera( child );
179   - scope.addHelper( child );
  178 + scope.addCamera(child);
  179 + scope.addHelper(child);
180 180
181   - } );
  181 + });
182 182
183   - if ( parent === undefined ) {
  183 + if (parent === undefined) {
184 184
185   - this.scene.add( object );
  185 + this.scene.add(object);
186 186
187 187 } else {
188 188
189   - parent.children.splice( index, 0, object );
  189 + parent.children.splice(index, 0, object);
190 190 object.parent = parent;
191 191
192 192 }
193 193
194   - this.signals.objectAdded.dispatch( object );
  194 + this.signals.objectAdded.dispatch(object);
195 195 this.signals.sceneGraphChanged.dispatch();
196 196
197 197 },
198 198
199   - nameObject: function ( object, name ) {
  199 + nameObject: function (object, name) {
200 200
201 201 object.name = name;
202 202 this.signals.sceneGraphChanged.dispatch();
203 203
204 204 },
205 205
206   - removeObject: function ( object ) {
  206 + removeObject: function (object) {
207 207
208   - if ( object.parent === null ) return; // avoid deleting the camera or scene
  208 + if (object.parent === null) return; // avoid deleting the camera or scene
209 209
210 210 var scope = this;
211 211
212   - object.traverse( function ( child ) {
  212 + object.traverse(function (child) {
213 213
214   - scope.removeCamera( child );
215   - scope.removeHelper( child );
  214 + scope.removeCamera(child);
  215 + scope.removeHelper(child);
216 216
217   - if ( child.material !== undefined ) scope.removeMaterial( child.material );
  217 + if (child.material !== undefined) scope.removeMaterial(child.material);
218 218
219   - } );
  219 + });
220 220
221   - object.parent.remove( object );
  221 + object.parent.remove(object);
222 222
223   - this.signals.objectRemoved.dispatch( object );
  223 + this.signals.objectRemoved.dispatch(object);
224 224 this.signals.sceneGraphChanged.dispatch();
225 225
226 226 },
227 227
228   - addGeometry: function ( geometry ) {
  228 + addGeometry: function (geometry) {
229 229
230   - this.geometries[ geometry.uuid ] = geometry;
  230 + this.geometries[geometry.uuid] = geometry;
231 231
232 232 },
233 233
234   - setGeometryName: function ( geometry, name ) {
  234 + setGeometryName: function (geometry, name) {
235 235
236 236 geometry.name = name;
237 237 this.signals.sceneGraphChanged.dispatch();
238 238
239 239 },
240 240
241   - addMaterial: function ( material ) {
  241 + addMaterial: function (material) {
242 242
243   - if ( Array.isArray( material ) ) {
  243 + if (Array.isArray(material)) {
244 244
245   - for ( var i = 0, l = material.length; i < l; i ++ ) {
  245 + for (var i = 0, l = material.length; i < l; i++) {
246 246
247   - this.addMaterialToRefCounter( material[ i ] );
  247 + this.addMaterialToRefCounter(material[i]);
248 248
249 249 }
250 250
251 251 } else {
252 252
253   - this.addMaterialToRefCounter( material );
  253 + this.addMaterialToRefCounter(material);
254 254
255 255 }
256 256
... ... @@ -258,39 +258,39 @@ Editor.prototype = {
258 258
259 259 },
260 260
261   - addMaterialToRefCounter: function ( material ) {
  261 + addMaterialToRefCounter: function (material) {
262 262
263 263 var materialsRefCounter = this.materialsRefCounter;
264 264
265   - var count = materialsRefCounter.get( material );
  265 + var count = materialsRefCounter.get(material);
266 266
267   - if ( count === undefined ) {
  267 + if (count === undefined) {
268 268
269   - materialsRefCounter.set( material, 1 );
270   - this.materials[ material.uuid ] = material;
  269 + materialsRefCounter.set(material, 1);
  270 + this.materials[material.uuid] = material;
271 271
272 272 } else {
273 273
274   - count ++;
275   - materialsRefCounter.set( material, count );
  274 + count++;
  275 + materialsRefCounter.set(material, count);
276 276
277 277 }
278 278
279 279 },
280 280
281   - removeMaterial: function ( material ) {
  281 + removeMaterial: function (material) {
282 282
283   - if ( Array.isArray( material ) ) {
  283 + if (Array.isArray(material)) {
284 284
285   - for ( var i = 0, l = material.length; i < l; i ++ ) {
  285 + for (var i = 0, l = material.length; i < l; i++) {
286 286
287   - this.removeMaterialFromRefCounter( material[ i ] );
  287 + this.removeMaterialFromRefCounter(material[i]);
288 288
289 289 }
290 290
291 291 } else {
292 292
293   - this.removeMaterialFromRefCounter( material );
  293 + this.removeMaterialFromRefCounter(material);
294 294
295 295 }
296 296
... ... @@ -298,36 +298,36 @@ Editor.prototype = {
298 298
299 299 },
300 300
301   - removeMaterialFromRefCounter: function ( material ) {
  301 + removeMaterialFromRefCounter: function (material) {
302 302
303 303 var materialsRefCounter = this.materialsRefCounter;
304 304
305   - var count = materialsRefCounter.get( material );
306   - count --;
  305 + var count = materialsRefCounter.get(material);
  306 + count--;
307 307
308   - if ( count === 0 ) {
  308 + if (count === 0) {
309 309
310   - materialsRefCounter.delete( material );
311   - delete this.materials[ material.uuid ];
  310 + materialsRefCounter.delete(material);
  311 + delete this.materials[material.uuid];
312 312
313 313 } else {
314 314
315   - materialsRefCounter.set( material, count );
  315 + materialsRefCounter.set(material, count);
316 316
317 317 }
318 318
319 319 },
320 320
321   - getMaterialById: function ( id ) {
  321 + getMaterialById: function (id) {
322 322
323 323 var material;
324   - var materials = Object.values( this.materials );
  324 + var materials = Object.values(this.materials);
325 325
326   - for ( var i = 0; i < materials.length; i ++ ) {
  326 + for (var i = 0; i < materials.length; i++) {
327 327
328   - if ( materials[ i ].id === id ) {
  328 + if (materials[i].id === id) {
329 329
330   - material = materials[ i ];
  330 + material = materials[i];
331 331 break;
332 332
333 333 }
... ... @@ -338,40 +338,40 @@ Editor.prototype = {
338 338
339 339 },
340 340
341   - setMaterialName: function ( material, name ) {
  341 + setMaterialName: function (material, name) {
342 342
343 343 material.name = name;
344 344 this.signals.sceneGraphChanged.dispatch();
345 345
346 346 },
347 347
348   - addTexture: function ( texture ) {
  348 + addTexture: function (texture) {
349 349
350   - this.textures[ texture.uuid ] = texture;
  350 + this.textures[texture.uuid] = texture;
351 351
352 352 },
353 353
354 354 //
355 355
356   - addCamera: function ( camera ) {
  356 + addCamera: function (camera) {
357 357
358   - if ( camera.isCamera ) {
  358 + if (camera.isCamera) {
359 359
360   - this.cameras[ camera.uuid ] = camera;
  360 + this.cameras[camera.uuid] = camera;
361 361
362   - this.signals.cameraAdded.dispatch( camera );
  362 + this.signals.cameraAdded.dispatch(camera);
363 363
364 364 }
365 365
366 366 },
367 367
368   - removeCamera: function ( camera ) {
  368 + removeCamera: function (camera) {
369 369
370   - if ( this.cameras[ camera.uuid ] !== undefined ) {
  370 + if (this.cameras[camera.uuid] !== undefined) {
371 371
372   - delete this.cameras[ camera.uuid ];
  372 + delete this.cameras[camera.uuid];
373 373
374   - this.signals.cameraRemoved.dispatch( camera );
  374 + this.signals.cameraRemoved.dispatch(camera);
375 375
376 376 }
377 377
... ... @@ -381,40 +381,40 @@ Editor.prototype = {
381 381
382 382 addHelper: function () {
383 383
384   - var geometry = new THREE.SphereGeometry( 2, 4, 2 );
385   - var material = new THREE.MeshBasicMaterial( { color: 0xff0000, visible: false } );
  384 + var geometry = new THREE.SphereGeometry(2, 4, 2);
  385 + var material = new THREE.MeshBasicMaterial({ color: 0xff0000, visible: false });
386 386
387   - return function ( object, helper ) {
  387 + return function (object, helper) {
388 388
389   - if ( helper === undefined ) {
  389 + if (helper === undefined) {
390 390
391   - if ( object.isCamera ) {
  391 + if (object.isCamera) {
392 392
393   - helper = new THREE.CameraHelper( object );
  393 + helper = new THREE.CameraHelper(object);
394 394
395   - } else if ( object.isPointLight ) {
  395 + } else if (object.isPointLight) {
396 396
397   - helper = new THREE.PointLightHelper( object, 1 );
  397 + helper = new THREE.PointLightHelper(object, 1);
398 398
399   - } else if ( object.isDirectionalLight ) {
  399 + } else if (object.isDirectionalLight) {
400 400
401   - helper = new THREE.DirectionalLightHelper( object, 1 );
  401 + helper = new THREE.DirectionalLightHelper(object, 1);
402 402
403   - } else if ( object.isSpotLight ) {
  403 + } else if (object.isSpotLight) {
404 404
405   - helper = new THREE.SpotLightHelper( object );
  405 + helper = new THREE.SpotLightHelper(object);
406 406
407   - } else if ( object.isHemisphereLight ) {
  407 + } else if (object.isHemisphereLight) {
408 408
409   - helper = new THREE.HemisphereLightHelper( object, 1 );
  409 + helper = new THREE.HemisphereLightHelper(object, 1);
410 410
411   - } else if ( object.isSkinnedMesh ) {
  411 + } else if (object.isSkinnedMesh) {
412 412
413   - helper = new THREE.SkeletonHelper( object.skeleton.bones[ 0 ] );
  413 + helper = new THREE.SkeletonHelper(object.skeleton.bones[0]);
414 414
415   - } else if ( object.isBone === true && object.parent && object.parent.isBone !== true ) {
  415 + } else if (object.isBone === true && object.parent && object.parent.isBone !== true) {
416 416
417   - helper = new THREE.SkeletonHelper( object );
  417 + helper = new THREE.SkeletonHelper(object);
418 418
419 419 } else {
420 420
... ... @@ -423,33 +423,33 @@ Editor.prototype = {
423 423
424 424 }
425 425
426   - const picker = new THREE.Mesh( geometry, material );
  426 + const picker = new THREE.Mesh(geometry, material);
427 427 picker.name = 'picker';
428 428 picker.userData.object = object;
429   - helper.add( picker );
  429 + helper.add(picker);
430 430
431 431 }
432 432
433   - this.sceneHelpers.add( helper );
434   - this.helpers[ object.id ] = helper;
  433 + this.sceneHelpers.add(helper);
  434 + this.helpers[object.id] = helper;
435 435
436   - this.signals.helperAdded.dispatch( helper );
  436 + this.signals.helperAdded.dispatch(helper);
437 437
438 438 };
439 439
440 440 }(),
441 441
442   - removeHelper: function ( object ) {
  442 + removeHelper: function (object) {
443 443
444   - if ( this.helpers[ object.id ] !== undefined ) {
  444 + if (this.helpers[object.id] !== undefined) {
445 445
446   - var helper = this.helpers[ object.id ];
447   - helper.parent.remove( helper );
  446 + var helper = this.helpers[object.id];
  447 + helper.parent.remove(helper);
448 448 helper.dispose();
449 449
450   - delete this.helpers[ object.id ];
  450 + delete this.helpers[object.id];
451 451
452   - this.signals.helperRemoved.dispatch( helper );
  452 + this.signals.helperRemoved.dispatch(helper);
453 453
454 454 }
455 455
... ... @@ -457,43 +457,43 @@ Editor.prototype = {
457 457
458 458 //
459 459
460   - addScript: function ( object, script ) {
  460 + addScript: function (object, script) {
461 461
462   - if ( this.scripts[ object.uuid ] === undefined ) {
  462 + if (this.scripts[object.uuid] === undefined) {
463 463
464   - this.scripts[ object.uuid ] = [];
  464 + this.scripts[object.uuid] = [];
465 465
466 466 }
467 467
468   - this.scripts[ object.uuid ].push( script );
  468 + this.scripts[object.uuid].push(script);
469 469
470   - this.signals.scriptAdded.dispatch( script );
  470 + this.signals.scriptAdded.dispatch(script);
471 471
472 472 },
473 473
474   - removeScript: function ( object, script ) {
  474 + removeScript: function (object, script) {
475 475
476   - if ( this.scripts[ object.uuid ] === undefined ) return;
  476 + if (this.scripts[object.uuid] === undefined) return;
477 477
478   - var index = this.scripts[ object.uuid ].indexOf( script );
  478 + var index = this.scripts[object.uuid].indexOf(script);
479 479
480   - if ( index !== - 1 ) {
  480 + if (index !== - 1) {
481 481
482   - this.scripts[ object.uuid ].splice( index, 1 );
  482 + this.scripts[object.uuid].splice(index, 1);
483 483
484 484 }
485 485
486   - this.signals.scriptRemoved.dispatch( script );
  486 + this.signals.scriptRemoved.dispatch(script);
487 487
488 488 },
489 489
490   - getObjectMaterial: function ( object, slot ) {
  490 + getObjectMaterial: function (object, slot) {
491 491
492 492 var material = object.material;
493 493
494   - if ( Array.isArray( material ) && slot !== undefined ) {
  494 + if (Array.isArray(material) && slot !== undefined) {
495 495
496   - material = material[ slot ];
  496 + material = material[slot];
497 497
498 498 }
499 499
... ... @@ -501,11 +501,11 @@ Editor.prototype = {
501 501
502 502 },
503 503
504   - setObjectMaterial: function ( object, slot, newMaterial ) {
  504 + setObjectMaterial: function (object, slot, newMaterial) {
505 505
506   - if ( Array.isArray( object.material ) && slot !== undefined ) {
  506 + if (Array.isArray(object.material) && slot !== undefined) {
507 507
508   - object.material[ slot ] = newMaterial;
  508 + object.material[slot] = newMaterial;
509 509
510 510 } else {
511 511
... ... @@ -515,14 +515,14 @@ Editor.prototype = {
515 515
516 516 },
517 517
518   - setViewportCamera: function ( uuid ) {
  518 + setViewportCamera: function (uuid) {
519 519
520   - this.viewportCamera = this.cameras[ uuid ];
  520 + this.viewportCamera = this.cameras[uuid];
521 521 this.signals.viewportCameraChanged.dispatch();
522 522
523 523 },
524 524
525   - setViewportShading: function ( value ) {
  525 + setViewportShading: function (value) {
526 526
527 527 this.viewportShading = value;
528 528 this.signals.viewportShadingChanged.dispatch();
... ... @@ -531,38 +531,38 @@ Editor.prototype = {
531 531
532 532 //
533 533
534   - select: function ( object ) {
  534 + select: function (object) {
535 535
536   - this.selector.select( object );
  536 + this.selector.select(object);
537 537
538 538 },
539 539
540   - selectById: function ( id ) {
  540 + selectById: function (id) {
541 541
542   - if ( id === this.camera.id ) {
  542 + if (id === this.camera.id) {
543 543
544   - this.select( this.camera );
  544 + this.select(this.camera);
545 545 return;
546 546
547 547 }
548 548
549   - this.select( this.scene.getObjectById( id ) );
  549 + this.select(this.scene.getObjectById(id));
550 550
551 551 },
552 552
553   - selectByUuid: function ( uuid ) {
  553 + selectByUuid: function (uuid) {
554 554
555 555 var scope = this;
556 556
557   - this.scene.traverse( function ( child ) {
  557 + this.scene.traverse(function (child) {
558 558
559   - if ( child.uuid === uuid ) {
  559 + if (child.uuid === uuid) {
560 560
561   - scope.select( child );
  561 + scope.select(child);
562 562
563 563 }
564 564
565   - } );
  565 + });
566 566
567 567 },
568 568
... ... @@ -572,19 +572,19 @@ Editor.prototype = {
572 572
573 573 },
574 574
575   - focus: function ( object ) {
  575 + focus: function (object) {
576 576
577   - if ( object !== undefined ) {
  577 + if (object !== undefined) {
578 578
579   - this.signals.objectFocused.dispatch( object );
  579 + this.signals.objectFocused.dispatch(object);
580 580
581 581 }
582 582
583 583 },
584 584
585   - focusById: function ( id ) {
  585 + focusById: function (id) {
586 586
587   - this.focus( this.scene.getObjectById( id ) );
  587 + this.focus(this.scene.getObjectById(id));
588 588
589 589 },
590 590
... ... @@ -593,7 +593,7 @@ Editor.prototype = {
593 593 this.history.clear();
594 594 this.storage.clear();
595 595
596   - this.camera.copy( _DEFAULT_CAMERA );
  596 + this.camera.copy(_DEFAULT_CAMERA);
597 597 this.signals.cameraResetted.dispatch();
598 598
599 599 this.scene.name = 'Scene';
... ... @@ -606,9 +606,9 @@ Editor.prototype = {
606 606
607 607 this.signals.sceneGraphChanged.active = false;
608 608
609   - while ( objects.length > 0 ) {
  609 + while (objects.length > 0) {
610 610
611   - this.removeObject( objects[ 0 ] );
  611 + this.removeObject(objects[0]);
612 612
613 613 }
614 614
... ... @@ -632,31 +632,31 @@ Editor.prototype = {
632 632
633 633 //
634 634
635   - fromJSON: async function ( json ) {
  635 + fromJSON: async function (json) {
636 636
637 637 var loader = new THREE.ObjectLoader();
638   - var camera = await loader.parseAsync( json.camera );
  638 + var camera = await loader.parseAsync(json.camera);
639 639
640 640 const existingUuid = this.camera.uuid;
641 641 const incomingUuid = camera.uuid;
642 642
643 643 // copy all properties, including uuid
644   - this.camera.copy( camera );
  644 + this.camera.copy(camera);
645 645 this.camera.uuid = incomingUuid;
646 646
647   - delete this.cameras[ existingUuid ]; // remove old entry [existingUuid, this.camera]
648   - this.cameras[ incomingUuid ] = this.camera; // add new entry [incomingUuid, this.camera]
  647 + delete this.cameras[existingUuid]; // remove old entry [existingUuid, this.camera]
  648 + this.cameras[incomingUuid] = this.camera; // add new entry [incomingUuid, this.camera]
649 649
650 650 this.signals.cameraResetted.dispatch();
651 651
652   - this.history.fromJSON( json.history );
  652 + this.history.fromJSON(json.history);
653 653 this.scripts = json.scripts;
654 654
655   - this.setScene( await loader.parseAsync( json.scene ) );
  655 + this.setScene(await loader.parseAsync(json.scene));
656 656
657   - if ( json.environment === 'ModelViewer' ) {
  657 + if (json.environment === 'ModelViewer') {
658 658
659   - this.signals.sceneEnvironmentChanged.dispatch( json.environment );
  659 + this.signals.sceneEnvironmentChanged.dispatch(json.environment);
660 660 this.signals.refreshSidebarEnvironment.dispatch();
661 661
662 662 }
... ... @@ -670,13 +670,13 @@ Editor.prototype = {
670 670 var scene = this.scene;
671 671 var scripts = this.scripts;
672 672
673   - for ( var key in scripts ) {
  673 + for (var key in scripts) {
674 674
675   - var script = scripts[ key ];
  675 + var script = scripts[key];
676 676
677   - if ( script.length === 0 || scene.getObjectByProperty( 'uuid', key ) === undefined ) {
  677 + if (script.length === 0 || scene.getObjectByProperty('uuid', key) === undefined) {
678 678
679   - delete scripts[ key ];
  679 + delete scripts[key];
680 680
681 681 }
682 682
... ... @@ -686,7 +686,7 @@ Editor.prototype = {
686 686
687 687 let environment = null;
688 688
689   - if ( this.scene.environment !== null && this.scene.environment.isRenderTargetTexture === true ) {
  689 + if (this.scene.environment !== null && this.scene.environment.isRenderTargetTexture === true) {
690 690
691 691 environment = 'ModelViewer';
692 692
... ... @@ -698,10 +698,10 @@ Editor.prototype = {
698 698
699 699 metadata: {},
700 700 project: {
701   - shadows: this.config.getKey( 'project/renderer/shadows' ),
702   - shadowType: this.config.getKey( 'project/renderer/shadowType' ),
703   - toneMapping: this.config.getKey( 'project/renderer/toneMapping' ),
704   - toneMappingExposure: this.config.getKey( 'project/renderer/toneMappingExposure' )
  701 + shadows: this.config.getKey('project/renderer/shadows'),
  702 + shadowType: this.config.getKey('project/renderer/shadowType'),
  703 + toneMapping: this.config.getKey('project/renderer/toneMapping'),
  704 + toneMappingExposure: this.config.getKey('project/renderer/toneMappingExposure')
705 705 },
706 706 camera: this.viewportCamera.toJSON(),
707 707 scene: this.scene.toJSON(),
... ... @@ -713,16 +713,16 @@ Editor.prototype = {
713 713
714 714 },
715 715
716   - objectByUuid: function ( uuid ) {
  716 + objectByUuid: function (uuid) {
717 717
718   - return this.scene.getObjectByProperty( 'uuid', uuid, true );
  718 + return this.scene.getObjectByProperty('uuid', uuid, true);
719 719
720 720 },
721 721
722   - execute: function ( cmd, optionalName ) {
723   -
724   - this.history.execute( cmd, optionalName );
725   -
  722 + execute: function (cmd, optionalName) {
  723 + this.history.execute(cmd, optionalName);
  724 + console.log(this)
  725 + this.saveTooltip?.show?.()
726 726 },
727 727
728 728 undo: function () {
... ... @@ -748,37 +748,37 @@ Editor.prototype = {
748 748
749 749 };
750 750
751   -const link = document.createElement( 'a' );
  751 +const link = document.createElement('a');
752 752
753   -function save( blob, filename ) {
  753 +function save(blob, filename) {
754 754
755   - if ( link.href ) {
  755 + if (link.href) {
756 756
757   - URL.revokeObjectURL( link.href );
  757 + URL.revokeObjectURL(link.href);
758 758
759 759 }
760 760
761   - link.href = URL.createObjectURL( blob );
  761 + link.href = URL.createObjectURL(blob);
762 762 link.download = filename || 'data.json';
763   - link.dispatchEvent( new MouseEvent( 'click' ) );
  763 + link.dispatchEvent(new MouseEvent('click'));
764 764
765 765 }
766 766
767   -function saveArrayBuffer( buffer, filename ) {
  767 +function saveArrayBuffer(buffer, filename) {
768 768
769   - save( new Blob( [ buffer ], { type: 'application/octet-stream' } ), filename );
  769 + save(new Blob([buffer], { type: 'application/octet-stream' }), filename);
770 770
771 771 }
772 772
773   -function saveString( text, filename ) {
  773 +function saveString(text, filename) {
774 774
775   - save( new Blob( [ text ], { type: 'text/plain' } ), filename );
  775 + save(new Blob([text], { type: 'text/plain' }), filename);
776 776
777 777 }
778 778
779   -function formatNumber( number ) {
  779 +function formatNumber(number) {
780 780
781   - return new Intl.NumberFormat( 'en-us', { useGrouping: true } ).format( number );
  781 + return new Intl.NumberFormat('en-us', { useGrouping: true }).format(number);
782 782
783 783 }
784 784
... ...
  1 +import { UIPanel, UIButton } from './libs/ui.js';
  2 +import { useSave } from './libs/hook/useSave.js';
  3 +
  4 +function MenubarSaveTooltip(editor) {
  5 + const strings = editor.strings
  6 +
  7 + const container = new UIPanel();
  8 + container.setClass('menu');
  9 + container.setStyle('height', ['100%'])
  10 + container.setStyle('display', ['flex'])
  11 + container.setStyle('justify-content', ['center'])
  12 + container.setStyle('align-items', ['center'])
  13 +
  14 + const saveButton = new UIButton(strings.getKey('menubar/status/saveTooltip'))
  15 + saveButton.setStyle('height', ['24px'])
  16 + saveButton.setStyle('color', ['#b62623'])
  17 + saveButton.setStyle('padding', ['0 8px'])
  18 + saveButton.setStyle('dispaly', ['flex'])
  19 + saveButton.setStyle('visibility', ['hidden'])
  20 + saveButton.setStyle('border', ['1px solid #dca4ad'])
  21 + saveButton.setStyle('border-radius', ['4px'])
  22 + saveButton.setStyle('font-size', ['12px'])
  23 + saveButton.setStyle('justify-content', ['center'])
  24 + saveButton.setStyle('align-items', ['center'])
  25 + saveButton.setStyle('background-color', ['#eacccc'])
  26 +
  27 + container.add(saveButton)
  28 +
  29 + const { save } = useSave(editor)
  30 + container.onClick(async function () {
  31 + save()
  32 + saveButton.dom.style.setProperty('visibility', ['hidden'])
  33 + })
  34 +
  35 + function show() {
  36 + saveButton.dom.style.setProperty('visibility', ['visible'])
  37 + }
  38 +
  39 + return {
  40 + container,
  41 + show
  42 + };
  43 +}
  44 +
  45 +export { MenubarSaveTooltip };
... ...
... ... @@ -7,6 +7,7 @@ import { MenubarView } from './Menubar.View.js';
7 7 import { MenubarHelp } from './Menubar.Help.js';
8 8 // import { MenubarStatus } from './Menubar.Status.js';
9 9 import { MenubarSave } from './Menubar.Save.js'
  10 +import { MenubarSaveTooltip } from './Menubar.Save.Tooltip.js'
10 11
11 12 function Menubar(editor) {
12 13
... ... @@ -21,7 +22,10 @@ function Menubar(editor) {
21 22
22 23 // container.add( new MenubarStatus( editor ) );
23 24 container.add(new MenubarSave(editor))
  25 + const { container: showTooltipContainer, show } = new MenubarSaveTooltip(editor)
  26 + container.add(showTooltipContainer)
24 27
  28 + editor.saveTooltip = { show }
25 29 return container;
26 30
27 31 }
... ...
... ... @@ -93,6 +93,7 @@ function Strings( config ) {
93 93 'menubar/add/camera/orthographic': 'Orthographic',
94 94
95 95 'menubar/status/autosave': 'autosave',
  96 + 'menubar/status/saveTooltip': 'The changes are not saved. Click here to save.',
96 97
97 98 'menubar/view': 'View',
98 99 'menubar/view/fullscreen': 'Fullscreen',
... ... @@ -495,6 +496,7 @@ function Strings( config ) {
495 496 'menubar/add/camera/orthographic': 'Orthographique',
496 497
497 498 'menubar/status/autosave': 'enregistrement automatique',
  499 + 'menubar/status/autosave': 'Modification non enregistrée. Cliquez ici pour enregistrer.',
498 500
499 501 'menubar/view': 'View',
500 502 'menubar/view/fullscreen': 'Fullscreen',
... ... @@ -897,6 +899,7 @@ function Strings( config ) {
897 899 'menubar/add/camera/orthographic': '正交相机',
898 900
899 901 'menubar/status/autosave': '自动保存',
  902 + 'menubar/status/saveTooltip': '修改未保存。点击此处保存。',
900 903
901 904 'menubar/view': '视图',
902 905 'menubar/view/fullscreen': '全屏',
... ... @@ -1299,6 +1302,7 @@ function Strings( config ) {
1299 1302 'menubar/add/camera/orthographic': '平行投影',
1300 1303
1301 1304 'menubar/status/autosave': '自動保存',
  1305 + 'menubar/status/saveTooltip': '修改未保存。點擊此處保存。',
1302 1306
1303 1307 'menubar/view': '表示',
1304 1308 'menubar/view/fullscreen': 'フルスクリーン',
... ... @@ -1700,6 +1704,7 @@ function Strings( config ) {
1700 1704 'menubar/add/camera/orthographic': '정사영',
1701 1705
1702 1706 'menubar/status/autosave': '자동 저장',
  1707 + 'menubar/status/saveTooltip': '변경 사항이 저장되지 않았습니다.저장하려면 여기를 누르십시오.',
1703 1708
1704 1709 'menubar/view': '보기',
1705 1710 'menubar/view/fullscreen': '전체 화면',
... ...