瀏覽代碼

热点 飞出后focus

xzw 1 年之前
父節點
當前提交
a674f7b6b8
共有 7 個文件被更改,包括 385 次插入170 次删除
  1. 7 9
      edit.html
  2. 73 22
      js/Hot.js
  3. 7 18
      js/TransformControls.js
  4. 87 31
      js/edit.js
  5. 90 56
      js/main_2020_edit.js
  6. 36 27
      js/main_2020_show.js
  7. 85 7
      js/manage.js

+ 7 - 9
edit.html

@@ -929,16 +929,16 @@
                             </div> 
                         </li>  
                         <li> 
-                            <ul id="wireframeSwitch" class="switch clearfix   ">
+                            <ul id="wireframeSwitch" class="switch clearfix ">
                                 <label><input class="mui-switch mui-switch-animbg" type="checkbox">
                                     打开模型线框(临时)
                                 </label>
                             </ul>
                             
-                            <div class="itemTitle">
-                                <span>调整大小(闪烁类型)</span>
+                            <div class="itemTitle" style='margin-top:25px; padding-top: 10px;border-top: 1px #4d4d4d solid;  '>
+                                <span>调整大小</span>
                             </div>
-                              
+                            <label class="remark " >针对所有没在漫游点独立调整的闪烁型热点</label>
                             <!-- <input class="" type="number" placeholder="请输入热点大小比例" value="1" max="100" min="0.1"
                                 step="0.1"> -->
                             <div name='adjustSize' class="buttons " style="font-size: 20px;">
@@ -947,19 +947,17 @@
                             </div>    
                                     
                                     
-                            
-                            
-                            <ul class="switch clearfix   ">
+                            <ul class="switch clearfix" style='margin-top:25px; padding-top: 10px;border-top: 1px #4d4d4d solid;  '>
                                 <label><input  id="autoAdjustHotScale" class="mui-switch mui-switch-animbg" type="checkbox">
                                     自适应热点大小 
                                 </label>
                             </ul>
-                            <label class="remark " >注: 自适应热点大小仅对贴图样式为“闪烁”的热点生效 </label>
+                            <label class="remark " >仅对贴图样式为“闪烁”的热点生效 </label>
                              
                         </li>
                         <li id="hotVisible">
                             <div class="buttons">
-                                <button class="innerBtn cancel" >可</button>
+                                <button class="innerBtn cancel" >可见性设置</button>
                             </div> 
                             <label class="remark hide" >注:修改热点贴图样式或位置大小后,可视性会被自动重新计算。 </label>
                              

+ 73 - 22
js/Hot.js

@@ -10,10 +10,12 @@ g_currentHot = null
 
 const playVideoWhenFlyOut = false
 //同时可播放的最大个数:
-const playVideoMax = window.isEdit ? 3  :   browser.isMobile() ? 1 : 2;   
+const playVideoMax = window.isEdit ? 3  :   browser.isMobile() ? 1 : 3;   
 const playAniMax = window.isEdit ? 6 :   browser.isMobile() ? 3 : 5;
 
-
+const playSyncGroup = [//需要播放同步的视频。  每次都单独定制
+   // ['okh1UR466371',  'LGmLHP2615503' ,  'VNyBI6614896'] //中,左,右   场景SHANGJJ
+]
 
 window.initHot = function(model){
       
@@ -183,14 +185,17 @@ window.initHot = function(model){
             } 
             
             this.transformAtPanos = transformAtPanos */
+            
+            //2024.3.18恢复transformAtPanos三个属性,isSprite优先级高于quaternion,  全局的热点大小改变不会影响当前有transformAtPanos的大小
+            
             //在每个漫游点独立设置的position。 
             var curPanoTransform = this.info.transformAtPanos[ getTransformSid()] || {}
               
         
             //没有单独设置position的漫游点使用的position
             this.position.copy(curPanoTransform.pos || info.position)
-            this.rotation.copy(info.rotation) 
-            this.scale.copy(info.scale)
+            this.quaternion.copy(curPanoTransform.quaternion || info.quaternion) 
+            this.scale.copy(curPanoTransform.scale || info.scale)
             
             this.changeTexType(info.texType, media) 
             
@@ -507,9 +512,10 @@ window.initHot = function(model){
                
                 
                 if(info.quaternion){
-                    info.rotation = new THREE.Euler().setFromVector3(convertValue(info.quaternion, THREE.Quaternion )) 
+                    info.quaternion =  convertValue(info.quaternion, THREE.Quaternion )  
                 }else{
-                    info.rotation = new THREE.Euler().setFromVector3(convertValue(info.rotation, THREE.Vector3 ))  //热点的旧数据很多是字符串 
+                    info.rotation = convertValue(info.rotation, THREE.Vector3 )
+                    info.quaternion = new THREE.Quaternion().setFromEuler( new THREE.Euler().setFromVector3(info.rotation))  //热点的旧数据很多是字符串 
                 }
                  
                 var s = Hot.getDefaulScale(info.hotIconScale) //旧版的大小,统一转换成新版
@@ -534,7 +540,7 @@ window.initHot = function(model){
                       
                     delete info.media
                     
-                    info.rotation = new THREE.Euler().setFromQuaternion(convertValue(info.qua, THREE.Quaternion )) 
+                    info.quaternion = convertValue(info.qua, THREE.Quaternion)
                     info.position = info.pos
                     delete info.pos;
                     delete info.qua;
@@ -552,7 +558,7 @@ window.initHot = function(model){
                     delete info.file
                 }else{
                     
-                    info.rotation = new THREE.Euler().fromArray(info.rotation)//.setFromVector3(info.rotation) 
+                    info.quaternion = new THREE.Quaternion().setFromEuler(new THREE.Euler().fromArray(info.rotation))//.setFromVector3(info.rotation) 
 
                 }                    
                 
@@ -582,14 +588,15 @@ window.initHot = function(model){
             //为了兼容旧数据,尽量和hot的数据靠近,最后保存在hot里
             info.position = convertValue(info.position, THREE.Vector3) 
             info.scale = convertValue(info.scale, THREE.Vector3) 
-            delete info.quaternion
+            delete info.rotation //暂时不用,只有保存时才存为roration
             
             info.linkType = info.linkType || "common"
 
 
             for (let i in info.transformAtPanos) {
                 info.transformAtPanos[i].pos = new THREE.Vector3().fromArray(info.transformAtPanos[i].pos)
-                //info.transformAtPanos[i].qua = new THREE.Quaternion().fromArray(info.transformAtPanos[i].qua)
+                info.transformAtPanos[i].qua && (info.transformAtPanos[i].qua = new THREE.Quaternion().fromArray(info.transformAtPanos[i].qua))
+                info.transformAtPanos[i].scale && (info.transformAtPanos[i].scale = new THREE.Vector3().fromArray(info.transformAtPanos[i].scale))
             }
 
             
@@ -678,7 +685,7 @@ window.initHot = function(model){
             var getPos = (position)=>{//每个overlay位置对应5个坐标,plane中心和四个角的位置
                 if(this.plane){  
                     return cornerPoint.map(e=>{
-                        return e.clone().applyEuler(this.info.rotation).add(position)
+                        return e.clone().applyQuaternion(this.info.quaternion).add(position)
                     })
                     
                 }else{ 
@@ -746,12 +753,13 @@ window.initHot = function(model){
         }
         
             
-        updateVisible(panos, visibility) { 
+        updateVisible(panos, visibility, type) { 
             if(window.isEdit && editTool.hotpoint.editSpot == this){
                 return this.visible = true
             }
             
-            this.visible = visibility != void 0 ? visibility : (!this.info.visiblePanos || !!panos.find(pano=>this.info.visiblePanos.includes(pano.id)))
+            this.visible = visibility != void 0 ? visibility : (!this.info.visiblePanos || 
+               type == 'every' ? panos.every(pano=>this.info.visiblePanos.includes(pano.id)) : panos.some(pano=>this.info.visiblePanos.includes(pano.id)))//type为every时,需要panos中每个都可见才显示
             this.titleElem && this.titleElem.setVisible(this.visible, 'hotVisible', 1)
             
             if (this.texType == 'video'){
@@ -1005,7 +1013,7 @@ window.initHot = function(model){
             if(!state || state == 'stop'){
                 if(!video.paused){
                     video.pause()
-                    console.log({str: "paused " + this.sid, level:1})
+                    //console.log({str: "paused " + this.sid, level:1})
                 }
                 /* video.lastCurTime = state == 'stop' ? 0 : video.currentTime //记录
                 video.src = video.src_ = '' */
@@ -1015,13 +1023,23 @@ window.initHot = function(model){
                 }  
             }else if(state){
                 if(/* !isVideoPlayed(video) */  video.paused  ){
-                    console.log({str: 'videoControl play ' +", "+ this.sid,  level:1})
+                    //console.log({str: 'videoControl play ' +", "+ this.sid,  level:1})
                     this.loadVideo(video)
                     video.play()
                     //video.currentTime = video.lastCurTime || 0
                     this.changeOpaWhenPlay(video)
-                     
-                    if(isVideoPlayed(video))console.log({str:"played " + this.sid + video.duration ,level:1})              
+                    
+                    //处理同步播放
+                    let group = playSyncGroup.find(e=>e.includes(this.sid))
+                    if(group){
+                        let others = group.filter(e=>e != this.sid).map(e=>player.model.hots[e].texMedia)
+                        //console.log('controlVideo play', this.id, 'other currentTime', others.map(e=>e.currentTime))
+                        video.currentTime = others[0].currentTime
+                    }
+                    
+                    
+                    
+                    //if(isVideoPlayed(video))console.log({str:"played " + this.sid + video.duration ,level:1})              
                 }                    
                   
             }
@@ -1180,7 +1198,7 @@ window.initHot = function(model){
                 
                 
             var s = t.model.panos.sortByScore(i, n);
-            console.log(s) 
+            //console.log(s) 
             return s && 0 < s.length && s[0].item
         }
          
@@ -1587,11 +1605,11 @@ window.initHot = function(model){
 
     }
     
-    Hot.updateVisibles = function(panos) { //只显示没被遮挡的,否则会卡
+    Hot.updateVisibles = function(panos, type) { //只显示没被遮挡的,否则会卡
         if (panos === true) {
-            model.hotGroup.children.forEach(e=>e.updateVisible(null,true))
+            model.hotGroup.children.forEach(e=>e.updateVisible(null,true,type))
         } else {
-            model.hotGroup.children.forEach(e=>e.updateVisible(panos))
+            model.hotGroup.children.forEach(e=>e.updateVisible(panos, null, type))
         }
     }
     
@@ -1710,10 +1728,38 @@ window.initHot = function(model){
         
         setTimeout(Hot.beginShineHot, 1000)
         
+        
+        
+        if(!window.isEdit){
+            if(playSyncGroup.length){
+                //每过一段时间校准同步视频的时间,使与第一个视频同步
+                setInterval(()=>{
+                    
+                    playSyncGroup.forEach(group=>{
+                        group = group.map(e=>player.model.hots[e].texMedia).filter(e=>!e.paused) 
+                        if(group.length < 2)return
+                        //console.log('同步',group.map(e=>e.currentTime)) 
+                        for(let i=group.length-1;i>0;i--){
+                            group[i].currentTime = group[0].currentTime
+                        }
+                    }) 
+                    
+                },4000) 
+            }
+        } 
+        
+        
         player.emit('gotHotAndStartload')
     }
+    
     window.Hot = Hot   
-        
+    
+
+
+
+    
+
+    
      /* var ball = new THREE.Mesh(new THREE.SphereBufferGeometry(0.01),new THREE.MeshBasicMaterial({color:"#f00",depthTest:false,transparent:true}))
     var balls = []
     var addPoint = function(point){
@@ -1946,4 +1992,9 @@ function isVideoPlayed(video){
     遇到过ios14.8.1、14.7.1 无法播放webm(来自1050)。 onloadedmetadata失败
     
     
+    
+    
+    显示故障的机型:
+    视频黑屏(4dkk视频漫游点也无法播放):小米10(自带浏览器)、红米K40(微信浏览器)、
+    
 */

+ 7 - 18
js/TransformControls.js

@@ -472,9 +472,8 @@ var TransformControls = function ( camera, domElement, options ) {
 
             //add:
              
-            if(editTool.hotpoint.editSpot){ 
-                editTool.hotpoint.updateTransform('position');
-            }
+            this.dispatchEvent({type:'positionChanged', object })
+
     
             //this.linesAssistance.updateTransform(this.object)
 
@@ -558,12 +557,8 @@ var TransformControls = function ( camera, domElement, options ) {
             
             
            
-            /* if(EditOverlay.editing){
-                EditOverlay.updateScale(); 
-            }  */
-            if(editTool.hotpoint.editSpot){ 
-                editTool.hotpoint.updateTransform('scale');
-            }
+           
+            this.dispatchEvent({type:'scaleChanged', object })
     
 
 
@@ -631,10 +626,8 @@ var TransformControls = function ( camera, domElement, options ) {
                 EditOverlay.updateQua(); 
             }  */
             
-            if(editTool.hotpoint.editSpot){
-                editTool.hotpoint.updateTransform('quaternion');
-            } 
-            
+             
+            this.dispatchEvent({type:'quaternionChanged', object })
 		}
 
 		this.dispatchEvent( changeEvent );
@@ -664,11 +657,7 @@ var TransformControls = function ( camera, domElement, options ) {
 
 		if ( pointer.button === undefined ) this.axis = null;
 		
-		/* if(this.player.cameraControls.activeControl){
-			//this.player.cameraControls.activeControl.locked = false; //add 
-			this.player.cameraControls.activeControl.pointerDragOn = false //add 
-			this.player.cameraControls.activeControl.enabled = true
-		} */
+	 
 		 
 	};
 

+ 87 - 31
js/edit.js

@@ -1073,13 +1073,19 @@ Hotpoint.prototype.init = function() {
         
         s = Math.max(0.001, s) 
         
+        let sid = player.mode == 'panorama' ? player.currentPano.id : "outside";
+        
+        
         player.model.hotGroup.children.forEach(hot=>{
             if(hot.texType == 'shine'){
-                hot.info.scale.multiplyScalar(s)
-                hot.scale.multiplyScalar(s) 
+                hot.info.scale.multiplyScalar(s) 
+                let s1 = hot.info.transformAtPanos[sid] ?.scale   //跳过独立调整的
+                s1 || hot.scale.multiplyScalar(s) 
             }
         })
-        DATA.hotIconScale *= s
+        
+        
+        DATA.hotIconScale *= s //没用,兼容旧版代码
         
     })
     
@@ -1099,7 +1105,7 @@ Hotpoint.prototype.init = function() {
             if(checked) {
                 that.editSpot.update(player)
             }else{  
-                that.editSpot.rotation.copy(that.editSpot.info.rotation)
+                that.editSpot.quaternion.copy(that.editSpot.info.quaternion)
             }  
         }
     })
@@ -1278,9 +1284,10 @@ Hotpoint.prototype.init = function() {
             if(!checked){
                 delete this.editSpot.info.transformAtPanos[getTransformSid()]  
                 this.editSpot.position.copy(this.editSpot.info.position)
-                //this.editSpot.quaternion.copy(this.editSpot.quaternion) 
+                this.editSpot.quaternion.copy(this.editSpot.info.quaternion) 
+                this.editSpot.scale.copy(this.editSpot.info.scale)
             }else{
-                this.getTransformAtPano('position') 
+                this.getTransformAtPano(['position']) 
             } 
             
         }
@@ -1293,7 +1300,7 @@ Hotpoint.prototype.init = function() {
             this.editSpot.position.copy(this.editSpot.info.position)
             //this.editSpot.quaternion.copy(this.editSpot.quaternion) 
         }else{
-            this.getTransformAtPano('position') 
+            this.getTransformAtPano(['position']) 
         }
     })  */ 
     
@@ -1810,7 +1817,7 @@ Hotpoint.prototype.getTempInfos = function(){
     }
 }
 
-Hotpoint.prototype.getTransformAtPano = function(type){
+Hotpoint.prototype.getTransformAtPano = function(types){
     /* var name = getTransformSid()
     var info = {
         pos : this.editSpot.mesh.position.clone() 
@@ -1825,30 +1832,36 @@ Hotpoint.prototype.getTransformAtPano = function(type){
     
     
     var name = getTransformSid()
-    this.editSpot.info.transformAtPanos[name] = {
-        pos : this.editSpot.position.clone() 
+    let info = {
+        pos : this.editSpot.position.clone(),
+        scale : this.editSpot.scale.clone()
     }
+    hot.isSprite || (info.qua = this.editSpot.quaternion.clone())
+      
+    this.editSpot.info.transformAtPanos[name] = info
+        
+     
 }  
 
-Hotpoint.prototype.updateTransform = function(type){
+Hotpoint.prototype.updateTransform = function(types=['position','quaternion','scale']){
     var on = this.panoTransformCheckBox.checked() //$('#setPosForPano input').is(':checked')
     //var name = getTransformSid()
-    if(on && type == 'position'){ 
-        this.getTransformAtPano(type)  
+    if(on ){ 
+        this.getTransformAtPano(types)  
     }else{ 
-        if(type == 'position'){
+        if(types.includes('position')){
             this.editSpot.info.position.copy(this.editSpot.position)
-        }else if(type == 'quaternion'){
+        }else if(types.includes('quaternion')){
             if(!this.editSpot.isSprite){ //如果恒朝向相机就不保存quaternion
-                this.editSpot.info.rotation.copy(this.editSpot.rotation)
+                this.editSpot.info.quaternion.copy(this.editSpot.quaternion)
             }
-        }else if(type == 'scale'){  
+        }else if(types.includes('scale')){  
             this.editSpot.info.scale.copy(this.editSpot.scale)
         }   
     }
     
     
-    type == 'position' && this.updateDis()
+    types.includes('position') && this.updateDis()
 }
 
 Hotpoint.prototype.updatePano = function(){
@@ -2640,7 +2653,7 @@ Hotpoint.prototype.initListSelect = function(){//热点样式图列表
                 {//adjustModelAuto
                     let bound = new THREE.Box3
                     object.traverse( function ( child ) {  
-                        if(child.geometry){
+                        if(child.geometry){//会不会有child自带了一层matrix呢?如果有要乘以matrix。 
                             child.geometry.computeBoundingBox();
                             bound.union(child.geometry.boundingBox) 
                         }                      
@@ -2738,9 +2751,9 @@ Hotpoint.prototype.switchModel = function(o={}){
         o.spot.info.objName = o.add.name  
         o.spot.info.modelBound = o.add.modelBound;
         o.spot.addModel(model)
-        var s = 1;//暂时
-        o.spot.scale.set(s,s,s)//恢复成等大比例,方便用户看清原始比例
-        o.spot.info.scale.set(s,s,s)
+        /* var s = 1;//暂时
+        o.spot.scale.set(s,s,s)//恢复成等大比例,方便用户看清原始比例. 但是换obj后要重新设置大小所以取消
+        o.spot.info.scale.set(s,s,s) */
         //this.updateTransform('scale')
         if(o.spot == this.editSpot){
             transformControls.enableScaleZ()
@@ -3655,14 +3668,14 @@ Hotpoint.prototype.ifNeedResetVisi = function(hot){//修改过贴图或位置或
     var need = !ifSame({
         hasBox: hot.tempInfo.hasBox,
         position: hot.tempInfo.position,
-        rotation: hot.tempInfo.rotation,
+        quaternion: hot.tempInfo.quaternion,
         scale: hot.tempInfo.scale, 
         transformAtPanos: hot.tempInfo.transformAtPanos, 
         modelBound:hot.tempInfo.modelBound
     }, {
         hasBox: hot.info.hasBox,
         position: hot.info.position,
-        rotation: hot.info.rotation,
+        quaternion: hot.info.quaternion,
         scale: hot.info.scale,
         transformAtPanos: hot.info.transformAtPanos,
         modelBound:hot.info.modelBound
@@ -3693,17 +3706,20 @@ Hotpoint.prototype.getSavingInfo = function(){//保存全部
         
         hotData.position = toPrecision(hot.info.position.toArray(), 3) 
         hotData.scale = toPrecision(hot.info.scale.toArray(), 3) 
-        hotData.rotation = toPrecision(hot.info.rotation.toArray().slice(0,3), 4) 
+        hotData.rotation = toPrecision(new THREE.Euler().setFromQuaternion(hot.info.quaternion).toArray().slice(0,3), 4) 
         hotData.order = index
         
         hotData.transformAtPanos = {}
         for(let i in hot.info.transformAtPanos){ 
             hotData.transformAtPanos[i] = {
-                pos : toPrecision(hot.info.transformAtPanos[i].pos.toArray(), 3),
+                pos : toPrecision(hot.info.transformAtPanos[i].pos.toArray(), 4), 
+            }
+            if(hot.info.transformAtPanos[i].qua){
+                hotData.transformAtPanos[i].qua = toPrecision(hot.info.transformAtPanos[i].qua.toArray(), 5)  
+            } 
+            if(hot.info.transformAtPanos[i].scale){
+                hotData.transformAtPanos[i].scale = toPrecision(hot.info.transformAtPanos[i].scale.toArray(), 4)  
             }
-            /* if(hot.transformAtPanos[i].qua){
-                hotData.transformAtPanos[i].qua = toPrecision(hot.transformAtPanos[i].qua.toArray(), 5)  
-            } */
         } 
         hotData.version = 'multi'
         
@@ -5227,6 +5243,44 @@ var initTransformCtl = function(THREE) {
     transformControls.space = 'local'//为了在当前方向上平移
     transformControls.setSize(1.5)
     player.model.add(transformControls)
+    
+    
+    transformControls.addEventListener('positionChanged',()=>{
+        editTool.hotpoint.updateTransform('position');
+    })
+    transformControls.addEventListener('quaternionChanged',()=>{
+        editTool.hotpoint.updateTransform('quaternion');
+    })
+    transformControls.addEventListener('scaleChanged',()=>{
+        editTool.hotpoint.updateTransform('scale');
+    })
+    
+    let history = new HistoryRecord({ 
+            applyData: (data)=>{ 
+                if(data.object.parent && data.object == editTool.hotpoint.editSpot  ){
+                    //data = Potree.Common.CloneObject(data) //避免使用后更改数据又被使用 
+                    data.matrix.decompose( data.object.position, data.object.quaternion, data.object.scale );
+                    editTool.hotpoint.updateTransform()
+                    
+                    return true
+                }  
+            },
+            getData:(object)=>{   
+                return {
+                    object,
+                    matrix:  object.matrixWorld.clone(),
+                }
+            } 
+        })  
+    
+    transformControls.addEventListener('mouseDown', ()=>{ //dragstart
+        history.beforeChange(transformControls.object)
+    })  
+    transformControls.addEventListener('mouseUp',()=>{
+        history.afterChange(transformControls.object)
+    })
+    transformControls.history = history
+    
 
     /* $(".MenuOptions[name='transform'] li").on("click", (e)=>{
         transformControls.transCtlChangeMode($(e.target).attr("index"))
@@ -5261,7 +5315,7 @@ var initTransformCtl = function(THREE) {
         }
         transformControls.scaleShowZ = false
     }
-    
+    editTool.transformControls = transformControls
 }
 
 
@@ -6165,6 +6219,8 @@ var VisiSet = {
             player.model.hots[i].material_.depthTest = false;
             
             player.model.hots[i].position.copy(player.model.hots[i].info.position);//覆盖transformAtPanos
+            player.model.hots[i].scale.copy(player.model.hots[i].info.scale);//覆盖transformAtPanos
+             
             player.model.hots[i].update(player)
         }
         this.setDisplay(true)
@@ -6249,7 +6305,7 @@ var VisiSet = {
 		} */
         for (let i in player.model.hots) {
             player.model.hots[i].info.isSprite = player.model.hots[i]._isSprite;
-            player.model.hots[i].info.isSprite || player.model.hots[i].rotation.copy(player.model.hots[i].info.rotation)
+            player.model.hots[i].info.isSprite || player.model.hots[i].quaternion.copy(player.model.hots[i].info.quaternion)
             player.model.hots[i].material_.depthTest = true;
         }
     },

+ 90 - 56
js/main_2020_edit.js

@@ -18067,7 +18067,7 @@ function o(a, s, l) {
             ),
             r.prototype.placeMarker = function() {
                 this.marker && (this.marker.position.copy(this.floorPosition),
-                this.marker.position.y += .05,
+                this.marker.position.y += .1,   //经常有marker比地面低,所以多往上调5cm
                 this.marker.lookAt(new s.Vector3(0,1,0).add(this.marker.position)))
             }
             ,
@@ -21167,53 +21167,74 @@ function o(a, s, l) {
                 .bind(this)),
                 !0)
             }
-            ),
-            t.prototype.switchCameraMode = function(e, t) {
-                var i = this.cameraControls.controls[e]
-                  , n = i.camera;
-                switch (e) {
-                case V.PANORAMA:
-                    n.position.copy(this.currentPano.position);
-                    var r = t ? T.FORWARD.clone().applyQuaternion(t) : this.getDirection().setY(0).normalize();
-                    i.lookAt(r.add(n.position));
-                    break;
-                case V.DOLLHOUSE:
-                     var o = this.position.clone();
-                    this.mode === V.PANORAMA ? o.add(new B.Vector3(0,6,0)).add(this.getDirection().multiplyScalar(-10)) : o.add(T.DOWN.clone().applyQuaternion(this.quaternion).multiplyScalar(6)).setY(6),
-                    n.position.copy(o),
-                    i.target.copy(this.target.clone().setY(this.model.center.y));
-                    break;  
-                    //for多楼层 且 让模型刚好适应屏幕
-                    
-                    /* var box = this.model.boundingBox.clone();
-                        box.applyMatrix4(this.camera.matrixWorld);//将 boundingbox、也就是模型, 转换到当前相机朝向
-                    var boxSize = box.size() //其中boxSize.x是模型在当前相机视角下的横向宽度,当飞出后,该宽度要刚好占满窗口宽度
-                    
-                    var fov = A.getHFOVFromVFOV(k.insideFOV, n.aspect, 1); //获得在当前窗口的横向的fov
-                    var distance = Math.abs(boxSize.x) / 2 / Math.tan(THREE.Math.degToRad(fov / 2))//根据上面获得的参数得到target到相机的距离
-                    
-                    console.log(boxSize.x,distance, boxSize.length() / 2)
-                    
-                    distance +=  boxSize.length() / 2   //由于此时模型从中心向相机的部分由于近大远小仍超出屏幕,所以将target放在靠近模型靠近相机的这一端,故而再加上box的对角线长度的一半, 虽然本该加上Math.sqrt(boxSize.z*boxSize.z +boxSize.y+boxSize.y)/2,但是这样模型显得比较满
+            ), 
+            t.prototype.switchCameraMode = function(mode, quaternion, target, position, {currentScale, fitBoundSize}) {
+                var control = this.cameraControls.controls[mode]
+                  , camera = control.camera;
+                if(mode == V.PANORAMA){
+                
+                    camera.position.copy(this.currentPano.position);
+                    var r = quaternion ? T.FORWARD.clone().applyQuaternion(quaternion) : this.getDirection().setY(0).normalize();
+                    control.lookAt(r.add(camera.position));
                      
-                    if(this.mode === V.PANORAMA){
-                        i.target.copy(this.model.center); 
-                        var vec = this.getDirection().negate().setY(1).normalize()//获得朝向
-                    }else{
-                        i.target.copy(this.target.clone().setY(this.model.center.y))
-                        var vec = T.DOWN.clone().applyQuaternion(this.quaternion).setY(1).normalize()
-                    }                       
-                      
-                    vec.multiplyScalar(distance )
-                    n.position.copy(i.target.clone().add(vec))  */
-                    break
-                case V.FLOORPLAN:
-                    n.position.copy(this.model.center).setY(k.floorplan.cameraHeight),
-                    i.target.copy(this.model.center).setY(0),
-                    i.zoomToContain(this.model.size),
-                    i.rotateToView(this.model.size, this.getDirection())
+                }else{
+                    if (target) {
+                        control.target.copy(target)
+                    }
+                    if (position) {
+                        camera.position.copy(position)
+                    }
+                    if(mode == V.DOLLHOUSE){
+                    
+                        var o = this.position.clone();
+                        this.mode === V.PANORAMA ? o.add(new B.Vector3(0,6,0)).add(this.getDirection().multiplyScalar(-10)) : o.add(T.DOWN.clone().applyQuaternion(this.quaternion).multiplyScalar(6)).setY(6),
+                        camera.position.copy(o),
+                        control.target.copy(this.target.clone().setY(this.model.center.y));
+                         
+                        //for多楼层 且 让模型刚好适应屏幕
+                        
+                        /* var box = this.model.boundingBox.clone();
+                            box.applyMatrix4(this.camera.matrixWorld);//将 boundingbox、也就是模型, 转换到当前相机朝向
+                        var boxSize = box.size() //其中boxSize.x是模型在当前相机视角下的横向宽度,当飞出后,该宽度要刚好占满窗口宽度
+                        
+                        var fov = A.getHFOVFromVFOV(k.insideFOV, camera.aspect, 1); //获得在当前窗口的横向的fov
+                        var distance = Math.abs(boxSize.x) / 2 / Math.tan(THREE.Math.degToRad(fov / 2))//根据上面获得的参数得到target到相机的距离
+                        
+                        console.log(boxSize.x,distance, boxSize.length() / 2)
+                        
+                        distance +=  boxSize.length() / 2   //由于此时模型从中心向相机的部分由于近大远小仍超出屏幕,所以将target放在靠近模型靠近相机的这一端,故而再加上box的对角线长度的一半, 虽然本该加上Math.sqrt(boxSize.z*boxSize.z +boxSize.y+boxSize.y)/2,但是这样模型显得比较满
+                         
+                        if(this.mode === V.PANORAMA){
+                            control.target.copy(this.model.center); 
+                            var vec = this.getDirection().negate().setY(1).normalize()//获得朝向
+                        }else{
+                            control.target.copy(this.target.clone().setY(this.model.center.y))
+                            var vec = T.DOWN.clone().applyQuaternion(this.quaternion).setY(1).normalize()
+                        }                       
+                          
+                        vec.multiplyScalar(distance )
+                        camera.position.copy(control.target.clone().add(vec))  */
+                         
+                    }if(mode == V.FLOORPLAN){ 
+                        if(!target){
+                            control.target.copy(this.model.center).setY(0)  
+                        } 
+                        if(!position){
+                            camera.position.copy(control.target).setY(k.floorplan.cameraHeight), 
+                            control.rotateToView(this.model.size, this.getDirection())
+                        }
+                        
+                        if(currentScale){
+                            control.currentScale = control.absoluteScale = currentScale
+                        }else if (fitBoundSize) {
+                            control.zoomToContain(fitBoundSize)
+                        }else{ 
+                            control.zoomToContain(this.model.size)
+                        } 
+                            
+                    }
                 }
-                i.update(0)
+                control.update(0)
             }
             ,
             t.prototype.update = (new B.Vector3,
@@ -21807,10 +21828,9 @@ function o(a, s, l) {
                     this.emit(W.FlyingStarted, n.position, _, n, b);
                     
                     
-                    
-                    //this.updateHotVisible(n); //更新热点显示
+                     
                     this.transitionPos({type:"beforeFlytopano", pano:n, dur:p})//add 
-                    Hot.updateVisibles([this.currentPano, n])
+                    Hot.updateVisibles([this.currentPano, n],'every')
                     
                     
                     
@@ -21969,8 +21989,9 @@ function o(a, s, l) {
                     
                     //if(hot.usingTransformData || !useCustom){
                         var pos = useCustom ? hot.info.position : panoData.pos;
-                        //var qua = hot.isSprite ? null : (useCustom  ? hot.quaternion : panoData.qua);
-                        begin(hot, pos/* , qua  */ )
+                        var qua = hot.isSprite ? null : (useCustom  ? hot.info.quaternion : panoData.qua);
+                        var scale = useCustom ? hot.info.scale : panoData.scale;
+                        begin(hot, pos , qua,   scale )
                     //}
                     //hot.usingTransformData = !useCustom;
                 }
@@ -22331,8 +22352,23 @@ function o(a, s, l) {
                 n && (this.currentPano = n)
                 
                 
+                //----------改----------
+                let target,position,currentScale,fitBoundSize
+                if(editTool.hotpoint.editSpot){//focus
+                    target = editTool.hotpoint.editSpot.position.clone()
+                    let bound = editTool.hotpoint.editSpot.info.modelBound?.bound
+                    if(bound){
+                        bound = new THREE.Box3().copy(bound).applyMatrix4(editTool.hotpoint.editSpot.children[0].matrixWorld)
+                        fitBoundSize = bound.size()
+                    }else{
+                        fitBoundSize = new THREE.Vector3(5,5,5)
+                    } 
+                }
+                
+                this.switchCameraMode(i, l, target, position, {currentScale, fitBoundSize})
+                
+                //----------------------
                 
-                this.switchCameraMode(i, l)
                 
                 G.cancelById(q.LookTransition);
                 
@@ -22695,9 +22731,7 @@ function o(a, s, l) {
             }
             ,
             t.prototype.getCurrentNodePanos = function(e) {
-                if (this.model.panos.map,
-                e.length = 0,
-                this.path.nodes)
+                if (this.model.panos.map, e.length = 0, this.path.nodes)
                     for (var t = 0; t < this.path.nodes.length; t++) {
                         var i = this.path.nodes[t];
                         e.push(this.model.panos.get(i))
@@ -25900,7 +25934,7 @@ function o(a, s, l) {
                     e.autoload = void 0 === e.autoload || e.autoload;
                     var t = a.parseSidUrl(e.url);
                     e.urlBase = t.urlBase,
-                    e.urlModel = t.urlModel,
+                    e.urlModel = /* 'data/1081/', */ t.urlModel,
                     e.urlFiles = t.urlFiles;
                     var i = this._getPlatformError();
                     return i ? $.Deferred().reject(i).promise() : (this.options = e,

+ 36 - 27
js/main_2020_show.js

@@ -4704,7 +4704,8 @@ window.Modernizr = function(n, e, t) {
                 this.nextFunc = e
             }
             ,
-            n.prototype.interrupt = function(e, t) {
+            n.prototype.interrupt = function(e, t) {//滑动屏幕或按下键盘等
+                 
                 return !!this.wouldInterrupt() && (this.tourIsPlaying && (this.player.zoomEnabled = this.wasZoomEnabled),
                 this.tourIsPlaying = !1,
 				//this.bgmReplay(),//xzw
@@ -9075,12 +9076,12 @@ window.Modernizr = function(n, e, t) {
             P.forEach(function(e) {
                 b.addEventListener(e, u.bind(this, !1), !0),
                 w.addEventListener(e, u.bind(this, !0), !0),
-                E.addEventListener(e, o, !0) 
+                E.addEventListener(e, stopTour2, !0) 
                                
                 S.forEach(function(t) {//会触发导览停止  
-                    t.addEventListener(e, a, !0)
+                    t.addEventListener(e, stopTour, !0)
                 }) 
-                $("#drawer img").on(e, a)
+                $("#drawer img").on(e, stopTour)
             }) 
             document.addEventListener("keydown", u.bind(this, !1), !0) 
              
@@ -9088,14 +9089,14 @@ window.Modernizr = function(n, e, t) {
                 E.classList.add("playing")
             })
         }
-        function r() {
+        function play() {//r
             // C.playTour(),
             C.playTourNearBy(),
             I && clearTimeout(I),
             d(),
             _.removeClass("fadeIn")
         }
-        function o() {
+        function stopTour2() {//o
             E.classList.contains("playing") && (C.stopTour(),
             _.addClass("fadeIn"),
             setTimeout(function() {
@@ -9105,15 +9106,15 @@ window.Modernizr = function(n, e, t) {
             I = setTimeout(h, p.tourInteraction.showModal)),
             setTimeout(function() {
                 E.classList.remove("playing")
-            }, p.tourInteraction.allowNextClick))
+            }, p.tourInteraction.allowNextClick)) 
         }
-        function a() {
+        function stopTour() { //a
             C.tourInProgress && (C.stopTour(),
             C.endTourProgress(),
-            E.classList.remove("playing"))
+            E.classList.remove("playing")) 
         }
-        function s() {
-            T.is(":visible") ? r() : o()
+        function togglePlay() {//s
+            T.is(":visible") ? play() : stopTour2()
         }
         function l() {
             x.hasClass("playing") && (clearTimeout(I),
@@ -9144,11 +9145,12 @@ window.Modernizr = function(n, e, t) {
                   
                 i && n || e || (O = !0),
                 C.atEndOfTour() && d(),
-                !C.tourIsPlaying && C.tourInProgress && (_.removeClass("fadeIn"),
-                d(),
-                t.which !== f.SPACE && a()),
-                i && n && s() 
-            }
+                
+                !C.tourIsPlaying && C.tourInProgress && (_.removeClass("fadeIn"), d(), t.which !== f.SPACE && stopTour()),
+                
+                i && n && togglePlay()  //空格键播放或暂停
+                
+            } 
         }
         function d() {
             M.removeClass("fadeIn")
@@ -9176,10 +9178,10 @@ window.Modernizr = function(n, e, t) {
           , P = ["touchstart", "mousedown", "pointerdown"]
           , O = !1;
         t.exports.init = n,
-        t.exports.play = r,
-        t.exports.pause = o,
-        t.exports.pauseWithoutCTA = a,
-        t.exports.togglePlay = s,
+        t.exports.play = play,
+        t.exports.pause = stopTour2,
+        t.exports.pauseWithoutCTA = stopTour,
+        t.exports.togglePlay = togglePlay,
         t.exports.stopTour = l,
         t.exports.dismissModal = d
     }
@@ -19520,7 +19522,7 @@ window.Modernizr = function(n, e, t) {
             }(),
             n.prototype.placeMarker = function() {
                 this.marker && (this.marker.position.copy(this.floorPosition),
-                this.marker.position.y += .05,
+                this.marker.position.y += .1,   //经常有marker比地面低,所以多往上调5cm
                 this.marker.lookAt(new r.Vector3(0,1,0).add(this.marker.position)))
             }
             ,
@@ -22461,9 +22463,13 @@ window.Modernizr = function(n, e, t) {
                     return !0;
                 if (this.handleLongTap())
                     return !0;
+                
+                /* if(this.director.tourIsPlaying){
+                    return !0;
+                } */ 
                 if (this.mouseCouldBeClickToMove) {
                     if (this.flying)
-                        return this.path.activeTransType === x.WALK && this.emit(w.WarpInterruptedWithFlyTo, this.path.activeTransType),
+                        return this.path.activeTransType === x.WALK && this.emit(w.WarpInterruptedWithFlyTo, this.path.activeTransType), //停止导览
                         !0;
                         
                     //add----  
@@ -23417,9 +23423,9 @@ window.Modernizr = function(n, e, t) {
                     
                     
                      //---------before fly--------------- add
-                    //this.updateHotVisible(i); //更新热点显示
+                    
                     this.transitionPos({type:"beforeFlytopano", pano:i, dur:I})//add 
-                    Hot.updateVisibles([this.currentPano, i])
+                    Hot.updateVisibles([this.currentPano, i],'every')
                     
                     //地标变化
                     if(this.model.floorLogos){
@@ -23594,9 +23600,12 @@ window.Modernizr = function(n, e, t) {
                     
                     //if(hot.usingTransformData || !useCustom){
                         var pos = useCustom ? hot.info.position : panoData.pos;
-                        begin(hot, pos/* , qua */  )
+                        var qua = hot.isSprite ? null : (useCustom  ? hot.info.quaternion : panoData.qua);
+                        var scale = useCustom ? hot.info.scale : panoData.scale;
+                        begin(hot, pos , qua,   scale )
                     //}
-                 }
+                    //hot.usingTransformData = !useCustom;
+                }
             
             }
             
@@ -24396,7 +24405,7 @@ window.Modernizr = function(n, e, t) {
             ,
             n.prototype.getCurrentNodePanos = function(e) {
                 this.model.panos.map;
-                if (e.length = 0, this.path.nodes.length){
+                if (e.length = 0, this.path.nodes){
                     
                     var momentTour = this.director.getMomentTour(this.director.destinationItem)  
                     if(momentTour == 'black'){ //改 upcomingPanos如果是black的只需要起点和终点

+ 85 - 7
js/manage.js

@@ -1634,6 +1634,90 @@ function initByTHREE(THREE){
 
     
     
+
+    class HistoryRecord extends THREE.EventDispatcher{
+        
+        constructor(o){ 
+            super()
+            
+            this.undoList = []   
+            this.redoList = [] 
+            this.applyData = o.applyData    //应用数据的方法
+            this.getData = o.getData        //获取数据的方法
+            
+            this.dataBefore 
+         
+   
+            window.addEventListener('keydown',(e)=>{ 
+                if(e.keyCode == 90 && e.ctrlKey){//Z
+                    this.undo()
+                }else if(e.keyCode == 89 && e.ctrlKey){//Y
+                    this.redo()
+                }  
+            })
+            
+            
+        }
+        
+        undo(){//回退 
+            let length = this.undoList.length
+             
+            if(length>0){  
+                let unExist 
+                let last = this.undoList.pop(); 
+                this.applyData && (unExist = !this.applyData(last.before)) 
+                unExist || this.redoList.push(last); 
+                unExist && this.undo()//找不到就回退下一个。
+                this.dispatchEvent('undo')
+                //console.log('undo',last)
+            } 
+        }
+        
+        
+        redo(){//撤销回退 
+            let length = this.undoList.length
+            let last = this.redoList.pop();
+            if(last){
+                //注意:每行的顺序不能乱
+                this.undoList.push(last)  
+                this.applyData && this.applyData(last.after) 
+                this.dispatchEvent('redo')
+                //console.log('redo',last)
+            }
+        }
+         
+        
+        beforeChange(o){//在变化之前(可能执行好几次直到变化完,但只有第一次有效)。 o的内容完全根据getData怎么定义
+            if(!this.dataBefore){
+                let data = this.getData(o)
+                data && (this.dataBefore = data)
+            } 
+        } 
+        
+        afterChange(o){//变化结束,从beforeChange到此算一次操作。
+            if(this.dataBefore){
+                this.writeIn({before:this.dataBefore, after:this.getData(o)}     ) //写入某物体变化前和变化后的状态
+                this.dataBefore = null  
+            } 
+        }
+        
+        writeIn(data ){ 
+            this.redoList.length = 0; //一旦录入新的操作,就不允许undo了
+             
+            this.undoList.push(data );
+            //console.log('新增undo', data)    
+        }
+        
+        
+        clear(){ 
+            this.redoList.length = 0 
+            this.undoList.length = 0 
+            this.dataBefore = null
+        } 
+        
+    }
+    window.HistoryRecord = HistoryRecord
+
     
     /* class VideoPlayer extends THREE.EventDispatcher{
         constructor(player) {
@@ -2173,13 +2257,7 @@ var CursorDeal = {
 
 
 
-
-
-
-
-
-
-
+