bill 3 роки тому
батько
коміт
f45d7b824c

Різницю між файлами не показано, бо вона завелика
+ 220 - 203
public/lib/potree/potree.js


Різницю між файлами не показано, бо вона завелика
+ 1 - 1
public/lib/potree/potree.js.map


+ 2 - 2
src/components/bill-ui/components/slide/index.vue

@@ -6,8 +6,8 @@
             </GateContent>
         </Gate>
         <template v-if="showCtrl">
-            <span class="left" @click="prevHandler"><UIIcon type="left" /></span>
-            <span class="right" @click="nextHandler"><UIIcon type="pull-more" /></span>
+            <span class="left" @click="prevHandler"><UIIcon type="left1" /></span>
+            <span class="right" @click="nextHandler"><UIIcon type="right" /></span>
         </template>
         <slot name="attach" :active="items[index]" />
 

+ 20 - 6
src/components/tagging/sign.vue

@@ -5,12 +5,16 @@
     :style="posStyle" 
     @mouseenter="isHover = true"
     @mouseleave="isHover = false"
+    :class="{active: showContent}"
   >
-    <img 
-      :src="getResource(taggingStyle.icon)" 
-      @click="iconClickHandler" 
-      v-if="taggingStyle" 
-    />
+    <ui-tip :tip="tagging.title" foreShow tipV="top" class="tag-tip">
+      <img 
+        class="tag-img"
+        :src="getResource(taggingStyle.icon)" 
+        @click="iconClickHandler" 
+        v-if="taggingStyle" 
+      />
+    </ui-tip>
     <div @click.stop>
       <UIBubble
         class="hot-bubble pc" 
@@ -111,7 +115,7 @@ const iconClickHandler = () => {
   transform: translate(-50%, -50%);
   cursor: pointer;
 
-  > img {
+  .tag-img {
     width: 32px;
     height: 32px;
   }
@@ -165,4 +169,14 @@ const iconClickHandler = () => {
   }
 }
 
+</style>
+
+<style>
+.tag-tip {
+  z-index: 8 !important;
+}
+.tag-tip p {
+  padding: 6px 10px !important;
+  margin: 5px 0 !important;
+}
 </style>

+ 4 - 4
src/layout/model-list/sign.vue

@@ -1,8 +1,8 @@
 <template>
-  <div class="model-header" :class="{disabled: model.error}" @click="$emit('click')">
+  <div class="model-header" @click="!model.error && $emit('click')">
     <p>{{ model.title }}</p>
     <div class="model-action" @click.stop>
-        <ui-input type="checkbox" v-model="show" />
+      <ui-input type="checkbox" v-model="show" :class="{disabled: model.error}"/>
       <ui-icon 
         v-if="model.type !== SceneType.SWSS && custom.modelsChangeStore" 
         type="del" 
@@ -11,8 +11,8 @@
       />
     </div>
   </div>
-  <div class="model-desc" @click="$emit('click')">
-    <p><span>数据来源:</span>{{ SceneTypeDesc[model.type] }}</p>
+  <div class="model-desc" @click="$emit('click')" v-if="custom.currentModel === model">
+    <p><span>数据来源:</span>{{ ModelTypeDesc[model.type] }}</p>
     <p><span>数据大小:</span>{{ model.size }}</p>
     <p v-if="model.type === SceneType.SWSS"><span>拍摄时间:</span>{{ model.time }}</p>
   </div>

+ 10 - 3
src/sdk/association.ts

@@ -13,11 +13,17 @@ import {
 
 import TaggingComponent from '@/components/tagging/list.vue'
 
+export const modelRange: ModelAttrRange  = {
+  opacityRange: { min: 0, max: 100, step: 0.1 },
+  bottomRange: { min: -30, max: 70, step: 0.1 },
+  scaleRange: { min: 0, max: 200, step: 0.1 }
+}
+
 import type { SDK, SceneModel, SceneGuidePath } from '.'
-import { FuseModel, Tagging } from '@/store'
+import { Model, Tagging } from '@/store'
 
-const sceneModelMap = new WeakMap<FuseModel, SceneModel>()
-export const getSceneModel = (model: FuseModel | null) => model && sceneModelMap.get(toRaw(model))
+const sceneModelMap = new WeakMap<Model, SceneModel>()
+export const getSceneModel = (model: Model | null) => model && sceneModelMap.get(toRaw(model))
 
 const associationModels = (sdk: SDK) => {
   const getModels = () => fuseModels.value
@@ -31,6 +37,7 @@ const associationModels = (sdk: SDK) => {
       const itemRaw = toRaw(item)
       const sceneModel = sdk.addModel({
         ...itemRaw,
+        ...modelRange,
         type: item.type === SceneType.SWSS ? 'laser' : 'glb',
         url: item.type === SceneType.SWSS ? item.url : getResource(item.url)
       })

+ 39 - 17
src/sdk/cover/index.js

@@ -3,7 +3,7 @@ import mitt from 'mitt'
 import axios from 'axios' //{ axios } from '@/api'
 
 
-export const enter = (dom) => {
+export const enter = (dom, isLocal) => {
     
     Potree.settings.isOfficial = true //标记为正式、非测试版本 
     //Potree.fileServer = axios 
@@ -25,8 +25,8 @@ export const enter = (dom) => {
     window.THREE = THREE
      
     let autoLoads = [] 
-    let autoLoads2 = []
-    
+    let autoLoadsDone = []
+   
     
     let sdk = {
         sceneBus,
@@ -323,28 +323,42 @@ export const enter = (dom) => {
         },
         
         
+        //scaleRange: { min, max }, opacityRange: { min, max }, bottomRange: { min, max } })
+        
         addModel(props){ 
             let bus = mitt()  
-            console.log('addModel',props)
+            //console.log('addModel',props)
             props.isFirstLoad = props.bottom == void 0 //在编辑时用户添加的
             if(props.opacity == void 0)  props.opacity = 1
-            
-            
+            props.scale /= 100
+            var oneByOne = !!isLocal;
+             
             if(!props.isFirstLoad){
                 autoLoads.push(props) 
             }
+            
+            let startLoad = (prop)=>{
+                Potree.addModel(prop,  prop.done , prop.progressFun, prop.onError)
+                console.log('startLoad', prop)
+            }
+            
             let spliceFromArr = (model,loaded)=>{
                 let index = autoLoads.indexOf(props)
                 if(index>-1){
                     autoLoads.splice(index,1)
+                     
                     if(loaded){
-                        autoLoads2.push(model)
-                    }
-                      
-                    if(autoLoads.length == 0){//设置相机位置:当自动开始加载第一个模型时(其余的也跟着自动加载),等这批加载完后;  
-                        MergeEditor.focusOn(autoLoads2, 1000)
+                        autoLoadsDone.push(model)
                     }
-                } 
+                }
+
+                if(oneByOne && autoLoads[0]){
+                    startLoad(autoLoads[0])
+                     
+                    //this.addModel(autoLoads[0])
+                }else if(autoLoads.length == 0 && autoLoadsDone.length>0){//设置相机位置:当自动开始加载第一个模型时(其余的也跟着自动加载),等这批加载完后;  
+                    MergeEditor.focusOn(autoLoadsDone, 1000)
+                }  
             }
             
             let model
@@ -358,7 +372,7 @@ export const enter = (dom) => {
                 model.addEventListener('transformChanged',(e)=>{
                     bus.emit('transformChanged', {
                         position : model.position.clone(),
-                        scale: model.scale.x,
+                        scale: model.scale.x * 100,
                         rotation: model.rotation.clone(),
                         bottom: model.btmHeight
                     })
@@ -375,7 +389,7 @@ export const enter = (dom) => {
             let onError = function ( xhr ) {
                 bus.emit('loadError', xhr)
                 spliceFromArr(model,false)
-                console.log('loadError!!!!!!!!!',  props.url) 
+                console.log('loadError!!!!!!!!!',  props.url, props.size, xhr) 
             }
             
             if(props.type == "glb"){////////////////////////////test
@@ -383,12 +397,19 @@ export const enter = (dom) => {
                     props.url = '/lib/potree/resources/models/glb/coffeemat.glb' 
                                      
                 }
-                
+                //props.url += '5'
                 //props.url = 'http://localhost:5173/api/profile/datav1/1537680519838306304/data/glb/cloud_glb_24.glb'   
             }
-           
             
-            Potree.addModel(props,  done , progressFun, onError)
+            
+            props.done = done; props.progressFun = progressFun; props.onError = onError
+            
+            
+            
+            if(!oneByOne || autoLoads.length==1){
+                startLoad(props)
+            }                
+            
             
             let result = {  
                 bus,
@@ -407,6 +428,7 @@ export const enter = (dom) => {
                 },
                 changeScale(s){
                     if(model){
+                        s /= 100
                         model.scale.set(s,s,s)
                         model.dispatchEvent("scale_changed")
                     }

+ 14 - 3
src/sdk/sdk.ts

@@ -29,8 +29,19 @@ export type SceneModel = ToChangeAPI<Omit<SceneModelAttrs, 'position' | 'rotatio
     leaveTransform: () => void
   }
 
+export type ModelAttrRange = {
+  [key in 'opacity' | 'bottom' | 'scale' as `${key}Range`]: {
+    min: number,
+    max: number,
+    step: number
+  }
+}
+
+export type AddModelProps = Pick<FuseModel, 'url' | 'id'> 
+  & FuseModelAttrs 
+  & { type: 'laser' | 'glb' }
+  & ModelAttrRange
 
-export type addModelProps = Pick<FuseModel, 'url' | 'id'> & FuseModelAttrs & { type: 'laser' | 'glb' }
 
 export type SceneGuidePath = Pick<GuidePath, 'position' | 'target' | 'speed' | 'time'>
 export interface SceneGuide {
@@ -60,7 +71,7 @@ export type CalcPathProps = [[SceneGuidePath, SceneGuidePath], Partial<Pick<Scen
 export interface SDK {
   layout: HTMLDivElement,
   sceneBus: Emitter<{ 'cameraChange': void }>
-  addModel: (props: addModelProps) => SceneModel
+  addModel: (props: AddModelProps) => SceneModel
   calcPathInfo: (paths: CalcPathProps[0], info: CalcPathProps[1]) => Required<CalcPathProps[1]>
   getPositionByScreen: (screenPos: ScreenLocalPos, modelId?: FuseModel['id']) => ScenePos | null
   getScreenByPosition: (localPos: SceneLocalPos, modelId?: FuseModel['id']) => ScreenPos | null
@@ -87,7 +98,7 @@ export const initialSDK = async (props: InialSDKProps) => {
   await Promise.all(libs.map(loadLib))
   await loadLib(`./lib/potree/potree.js`)
 
-  const localSdk = cover(props.layout) as unknown as SDK
+  const localSdk = cover(props.layout, true) as unknown as SDK
 
   sdk = localSdk
   sdk.layout = props.layout

+ 1 - 1
src/views/guide/edit-paths.vue

@@ -19,7 +19,7 @@
     <div class="info" v-if="paths.length">
       <div class="meta">
         <div class="length">
-          <span>视频时长</span>
+          <span>视频时长</span>{{paths.reduce((t, c) => t + c.time, 0).toFixed(1)}}s
         </div>
         <div 
           class="fun-ctrl clear" 

+ 4 - 7
src/views/merge/index.vue

@@ -8,17 +8,17 @@
         <!-- <template #icon>
           <a href="">设置比例</a>
         </template> -->
-        <ui-input type="range" v-model="custom.currentModel.scale" v-bind="scaleOption" width="100%">
+        <ui-input type="range" v-model="custom.currentModel.scale" v-bind="modelRange.scaleRange" :ctrl="false" width="100%">
           <template #icon>%</template>
         </ui-input>
       </ui-group-option>
       <ui-group-option label="离地高度">
-        <ui-input type="range" v-model="custom.currentModel.bottom" v-bind="bottomOption" width="100%">
+        <ui-input type="range" v-model="custom.currentModel.bottom" v-bind="modelRange.bottomRange" :ctrl="false" width="100%">
           <template #icon>m</template>
         </ui-input>
       </ui-group-option>
       <ui-group-option label="模型不透明度">
-        <ui-input type="range" v-model="custom.currentModel.opacity" v-bind="opacityOption" width="100%">
+        <ui-input type="range" v-model="custom.currentModel.opacity" v-bind="modelRange.opacityRange" :ctrl="false" width="100%">
           <template #icon>%</template>
         </ui-input>
       </ui-group-option>
@@ -37,7 +37,7 @@ import { RightPano } from '@/layout'
 import { autoSaveFuseModels, defaultFuseModelAttrs } from '@/store'
 import { togetherCallback } from '@/utils'
 import Actions from '@/components/actions/index.vue'
-import { getSceneModel } from '@/sdk'
+import { getSceneModel, modelRange } from '@/sdk'
 import { useViewStack } from '@/hook'
 import { showLeftCtrlPanoStack, showLeftPanoStack, custom, modelsChangeStoreStack } from '@/env'
 import { ref, nextTick } from 'vue'
@@ -50,9 +50,6 @@ useViewStack(() => {
   active.value = true
   return () => active.value = false
 })
-const opacityOption = { min: 0, max: 100, step: 0.01, ctrl: false }
-const bottomOption = { min: -30, max: 70, step: 0.1, ctrl: false }
-const scaleOption = { min: 0, max: 200, step: 0.01, ctrl: false }
 const actionItems: ActionsProps['items'] = [
   {
     icon: 'move',

+ 1 - 5
src/views/tagging/edit.vue

@@ -185,14 +185,10 @@ const delImageHandler = async (file: Tagging['images'][number]) => {
   z-index: 2000;
   padding: 20px;
   overflow-y: auto;
-  text-align: center;
 }
 
 .edit-hot-item {
-  display: inline-block;
-  text-align: left;
-  margin-top: 100px;
-  margin-bottom: 20px;
+  margin: 100px auto 20px;
   width: 400px;
   padding: 20px;
   background: rgba(27, 27, 28, 0.8);

+ 20 - 12
src/views/tagging/index.vue

@@ -49,9 +49,9 @@ import Edit from './edit.vue'
 import TagingSign from './sign.vue'
 import { Message } from 'bill/index'
 import { RightFillPano } from '@/layout'
-import { togetherCallback } from '@/utils'
+import { asyncTimeout, togetherCallback } from '@/utils'
 import { useViewStack } from '@/hook'
-import { computed, ref, watch } from 'vue';
+import { computed, nextTick, ref, watch } from 'vue';
 import { sdk } from '@/sdk'
 import { 
   taggings, 
@@ -65,7 +65,8 @@ import {
   getTaggingPositions,
   taggingPositions,
   createTaggingPosition,
-  FuseModel
+FuseModel,
+fuseModels
 } from '@/store'
 import { 
   custom, 
@@ -93,6 +94,8 @@ const saveHandler = (tagging: Tagging) => {
 
 const deleteTagging = (tagging: Tagging) => {
   const index = taggings.value.indexOf(tagging)
+  const positions = getTaggingPositions(tagging)
+  taggingPositions.value = taggingPositions.value.filter(position => !positions.includes(position))
   taggings.value.splice(index, 1)
 }
 
@@ -161,22 +164,27 @@ watch(selectTagging, (a, b, onCleanup) => {
     const pop = togetherCallback([
       showLeftCtrlPanoStack.push(ref(true)), 
       showLeftPanoStack.push(ref(true)),
-      currentModelStack.push(ref(currentModel)),
       showRightCtrlPanoStack.push(ref(false)),
       showRightPanoStack.push(ref(false))
     ])
 
-    const clickHandler = (ev: MouseEvent) => {
-      const position = sdk.getPositionByScreen({
-        x: ev.clientX,
-        y: ev.clientY
-      }, custom.currentModel?.id)
-
-      if (!position) {
+    const clickHandler = async (ev: MouseEvent) => {
+      await nextTick()
+      await asyncTimeout()
+      const positions = fuseModels.value.
+        map(model => 
+          sdk.getPositionByScreen({
+            x: ev.clientX,
+            y: ev.clientY
+          }, model.id)
+        )
+        .filter(pos => pos)
+
+      if (!positions.length) {
         Message.error('当前位置无法添加')
       } else if (selectTagging.value) {
         const storePosition = createTaggingPosition({
-          ...position,
+          ...positions[0],
           taggingId: selectTagging.value.id
         })
         taggingPositions.value.push(storePosition)