'))
div.addClass('slider')
if(o.unitStr){
div.find(".BarTxt").append($('
'+ o.unitStr +''));
}
o.root.append(div);
this.line = $(".scrollBar", div);
this.knot = $(".scroll_Thumb", div);
o.noValue || (this.textArea = $(".scrollBarTxt", div));
this.track = $(".scroll_Track", div);
this.unitStr = o.unitStr;//unitStr是单位字符串,比如角度的°。不能是数字
this.onchange = o.onchange;
this.percent = null;
this.dragStart = false;
this.offsetToBody = null;
this.getOffset();
this.checkError();
this.percent = this.getPercent();
o.noValue || this.displayValue();
this.moveKnot();
this.knotWidth = 0;
this.lineWidth = 0;
//this.waitValue;//等待要触发事件的值,防止崩溃
this.avoidCrash = o.avoidCrash;
this.realMax = !this.noValue ? o.realMax : null;//如果传入realMax,代表可以通过输入数字修改最大值范围,最大值不可以超过realMax。
this.scrollUnit = (scope.max - scope.min) * 0.001;
if(this.precision != void 0){
var prec = Math.pow(10,-this.precision);
this.scrollUnit < prec && (this.scrollUnit = prec);
}else{//默认化为整数
this.scrollUnit < 1 && (this.scrollUnit = 1);
}
this.dragStartEvent = o.dragStartEvent;
this.line.on( "mousedown touchstart", function (event) {
scope.dragStart = true;
scope.dragChange(event);
if(scope.dragStartEvent)scope.dragStartEvent()
//if(o.avoidCrash && isMobile)scope.dealInterval();
});
!window.isMobile && this.line.on( "mousewheel DOMMouseScroll wheel", function (event) {
event.preventDefault();
var v = event.originalEvent.deltaY>0 ? -scope.scrollUnit : scope.scrollUnit;
scope.setValue(scope.value + v);
});
this.dragEndEvent = o.dragEndEvent;
var stop = function(){
if (scope.dragStart) {
scope.dragStart = false;
if(scope.dragEndEvent)scope.dragEndEvent()
}
}
$(document).on("mouseup touchend",stop)
/* isMobile || */$("#player").on("mouseup",stop)
var lastChangeTime = 0;
$(document).on("mousemove touchmove",function(){
if (scope.dragStart) {
/* if(isMobile && o.avoidCrash){
scope.lastDragEvent = event;
}else */scope.dragChange(event);
}
})
o.noValue || this.textArea.on("change", function () {
var v = parseFloat(scope.textArea.val());
if (v != v)//NaN
return;
scope.setValueFromOutside(v);
});
}
SlideBar.prototype.dealInterval = function(){
this.interval = setInterval(function(){
this.lastDragEvent && this.dragChange(this.lastDragEvent);
this.lastDragEvent = null
if(!this.dragStart) clearInterval(this.interval)
}.bind(this),90)
}
SlideBar.prototype.changeLimit = function (o) {
if(o.min) this.min = o.min;
if(o.max) this.max = o.max;
}
SlideBar.prototype.getOffset = function () { //为了检测鼠标位置需要获得相对body的offset
var left = this.line[0].offsetLeft;
var element = this.line[0];
while (element = element.offsetParent) {
left += element.offsetLeft;
}
this.offsetToBody = (left == 0) ? (this.offsetToBody || 0) : left;
//如果left为0,很可能是它不可见,那么最好使用旧的offsetToBody
}
SlideBar.prototype.InitOffset = function () {
//如果一开始scroller没有显示,要在显示时获取一下offset
this.getOffset();
this.getWidth();
this.moveKnot();
}
SlideBar.prototype.checkError = function () {
if (this.min >= this.max) {
console.log("scrollbar值有误 " + name);
return;
}
}
SlideBar.prototype.getPercent = function () {
return (this.value - this.min) / (this.max - this.min);
}
SlideBar.prototype.displayValue = function (value) {
//this.textArea.val(this.value + (this.unitStr ? " " + this.unitStr : ""));
if(value != void 0)this.value = value;
this.textArea.val(this.value)
}
SlideBar.prototype.getWidth = function () {
this.knotWidth = this.knot.width();
this.lineWidth = this.line.width() - this.knotWidth
}
SlideBar.prototype.moveKnot = function () {
//this.getWidth();
var width = this.percent * this.lineWidth;
this.knot.css('left',width + "px")
if (this.track)this.track.css('width', (width + this.knotWidth / 2) + "px")
}
SlideBar.prototype.bind = function (f) {
this.onchange = f;
}
SlideBar.prototype.setValue = function (v, noEvent, changeMax) {//设置数值并改变knot位置 noEvent为true的话就可以不触发回调函数,仅仅改变显示
//if(this.value==v)return; //因为换选材质需要执行后面onchange才会带动preview的改变,所以这里一样还是执行,而拉动滑动条的部分值不变就不执行
if(this.precision != void 0){
this.value = parseFloat(v.toFixed(this.precision))
}else{//默认化为整数
this.value = Math.round(v);
}
if(changeMax && this.realMax!=void 0){
if(this.value>this.oriMax){
this.value = Math.min(this.value, this.realMax);
this.changeLimit({max:this.value})
}else{
this.changeLimit({max:this.oriMax})
}
}
this.percent = this.getPercent();
var makeit = true;
if (this.onchange && !noEvent ){
var result = this.onchange(this.value); //如果执行的函数不允许这个值,就不能变
if(result === false){
makeit = false;
}
}
if(makeit){
this.moveKnot();
//console.log("SlideBarV-"+this.name + " : "+this.value)
this.noValue || this.displayValue();
}
}
SlideBar.prototype.dragChange = function (event) {//拖动时触发 计算数值
//this.getWidth();
//if(!this.offsetToBody || isNaN(this.offsetToBody)this.getOffset();
if (event.clientX != void 0) {
this.percent = (event.clientX - this.knotWidth / 2 - this.offsetToBody) / this.lineWidth;
} else {
if(event.touches != void 0){
this.percent = (event.touches[0].clientX - this.knotWidth / 2 - this.offsetToBody) / this.lineWidth;
}
else this.percent = (event.originalEvent.touches[0].clientX - this.knotWidth / 2 - this.offsetToBody) / this.lineWidth;
}
if (this.percent < 0)
this.percent = 0;
else if (this.percent > 1)
this.percent = 1;
//var v = this.percent * this.max;
var v = this.percent * (this.max - this.min) + this.min;
//var v = Math.round(this.percent * this.max * 10)/10; //精度为0.1
if (this.value == v)
return;
this.setValue(v);
}
SlideBar.prototype.setValueFromOutside = function (v) { //外面的事件触发的
if (this.line.width() == 0)
return;
//不可见就不执行。
//v = Math.round(v*10)/10;
if(this.realMax!=void 0){
v = THREE.Math.clamp(v, this.min, this.realMax);
if(v>this.max)this.changeLimit({max:v});
}else v = THREE.Math.clamp(v, this.min, this.max);
this.setValue(v);
}
//-----------------------------------------------------
var LineDraw = {
createLine: function (posArr, o) {
var e = new THREE.BufferGeometry
, p = new Float32Array(6);
e.addAttribute("position", new THREE.BufferAttribute(p, 3));
//这句新旧版写法不同 旧版这样:e.addAttribute("position",Float32Array,2,3);
var p = e.attributes.position.array;
for (var i = 0; i < 2; i++) {
p[i * 3] = posArr[i].x;
p[i * 3 + 1] = posArr[i].y;
p[i * 3 + 2] = posArr[i].z;
}
var mat = new THREE[o.deshed ? "LineDashedMaterial" : "LineBasicMaterial"]({
linewidth: o.width || 1,
//windows无效。 似乎mac/ios上粗细有效 ?
color: o.color || defaultColor,
transparent: o.dontAlwaysSeen ? false : true,
depthTest: o.dontAlwaysSeen ? true : false
})
var line = new THREE.Line(e, mat);
line.renderOrder = o.renderOrder || 4
//同tagStem; //如果不加高,可能会部分被model遮住
return line;
}
}
var toPrecision = function(e, t) {
function i(e, t) {
var i = Math.pow(10, t);
return Math.round(e * i) / i
}
if (e instanceof Array) {
for (var n = 0; n < e.length; n++)
e[n] = i(e[n], t);
return e
}
return i(e, t)
}
var transformControls;
var initTransformCtl = function(THREE){
TransformControls.init(THREE)
TransformControls.prototype.transCtlChangeMode = function(mode){
//if(!this.editing)return;
if(mode && this.mode != mode){
this.mode = mode;
$(".MenuOptions[name='transform'] li").removeClass("chosen");
$(".MenuOptions[name='transform'] li[index='"+ mode +"']").addClass("chosen");
}
},
transformControls = new TransformControls( player.camera, player.domElement, {
player:player,
dontHideWhenFaceCamera:true,
scaleAxis:["x","y"], //隐藏了z轴。虽然参数没用上
NoScaleZ:true//整体缩放时只缩放xy轴。
});
transformControls.setSize(1.5)
player.model.add(transformControls)
$(".MenuOptions[name='transform'] li").on("click",(e)=>{
transformControls.transCtlChangeMode($(e.target).attr("index"))
})
}
var EditOverlay = {
editing: false,
overlayMaxCount: 10,
scroller:{
videoDepth : new SlideBar({
root: $('#videoDepth').eq(0),
value: settings.overlay.depth * 100,
min: 0 * 100,
max: 1 * 100,
name: "videoDepth",
unitStr:"cm",
avoidCrash:true,
onchange:function (s) {
if(s == 0){
EditOverlay.editPlane.addBox(false)
}else{
EditOverlay.editPlane.addBox(true)
EditOverlay.editPlane.scale.z = s/100 / settings.overlay.depth ;
}
},
dragEndEvent:function(){
}
})
},
init: function(THREE){
var mat = new THREE.MeshBasicMaterial({wireframe:true, opacity:0.5, color:"#57e4f3", transparent:true})
var wireframeModel = this.wireframeModel = new THREE.Object3D; wireframeModel.name = 'wireframeModel'
player.model.chunks.forEach((mesh)=>{
var chunk = mesh.clone();
chunk.material = mat;
wireframeModel.add(chunk)
})
wireframeModel.visible = false
player.model.add(wireframeModel)
//------------------------------
$('.overlay .addBtn button').on("click",this.beginToAddPlane.bind(this))
$("#overlayProp a.close").on("click",()=>{this.closeOverlayPanel("cancel")})
$("#overlayProp button.submit").on("click",(e)=>{
this.SaveOverlay()
})
$("#overlayProp button.delete").on("click",(e)=>{
this.DeleteOverlay();
})
$('#overlayUpload [name="useImgRatio"] button').on("click", this.useImgRatio.bind(this));
var uploadInput = $('
');
$('#overlayUpload [name="upload"] button').on('click',()=>{
uploadInput.click()
})
uploadInput.on("change", (e)=>{
inputMedia({
enableTypes:[/* "photo", */"video"],
videoDone:(file, video)=>{
var plane = this.editPlane.plane
$(video).css('width','100%')
$(video).css('height','100%')
plane.material.map = new THREE.VideoTexture( video );
plane.material.map.image.play();
plane.material.map.minFilter = THREE.LinearFilter;
this.editPlane.overlayType = "video";
$('#overlayUpload .preview video').remove();
//$('#overlayUpload .preview').css('background-image',"").append($(video));
video.autoplay = true;
video.loop = true;
video.volume = 0
video.muted = true
this.useImgRatio() //自适应比例
this.editPlane.file = file;
plane.material.opacity = 1;
plane.material.color = new THREE.Color(1,1,1)
plane.material.needsUpdate = true;
}
}, "video", e);
})
player.overlayGroup.children.forEach((overlay)=>{
this.getOverlayInfo(overlay)
this.addToList(overlay)
})
},
enter : function(){
this.editing = true;
this.wireframeModel.visible = true;
},
leave : function(){
if(!this.editing)return;
this.editing = false
$("#overlayProp a.close").click();
this.endAddPlane();
this.wireframeModel.visible = false;
},
beginToAddPlane: function(){
player.reticule.visible = false;
this.objCursorType = 'overlay';
player.currentCursor = 'url(images/edit/box_video.png), auto'
$('#player').css('cursor', player.currentCursor)
$('.overlay .addBtn button').addClass("unable")//可以加多个视频时的按钮
},
endAddPlane : function(){
this.objCursorType = null;
player.currentCursor = '';
$('#player').css('cursor','')
$('.overlay .addBtn button').removeClass("unable")
player.reticule.visible = true
},
addPlane : function(o){
var pos = o.intersect.point;
var overlay = new Overlay({sid:new Date().getTime()+""})
overlay.position.copy(pos);
if(player.getMouseDirection().angleTo(o.intersect.face.normal) < Math.PI/2) {
overlay.lookAt(o.intersect.face.normal.clone().negate().add(pos));
overlay.position.add(o.intersect.face.normal.clone().negate().multiplyScalar(0.01))//avoid mesh crash with chunks 模型的精度可能和floorplan的不一样,所以chunk即使材质经过处理还是会闪烁但是wallmesh不会
}else{
overlay.lookAt(o.intersect.face.normal.clone().add(pos));
overlay.position.add(o.intersect.face.normal.clone().multiplyScalar(0.01))
}
overlay.isNew = true
player.clickOverlay(overlay)
transformControls.transCtlChangeMode("translate")
this.addToList(overlay)
},
updateOverlayScaleDisplay : function(){
var overlay = this.editPlane;
var maxWidth = 193, maxHeight = maxWidth//maxWidth/2;
var ratioW = Math.abs(overlay.width) / maxWidth;
var ratioH = Math.abs(overlay.height) / maxHeight;
var ratio = 1/Math.max(ratioW,ratioH);//缩放比例
var w = Math.round(Math.abs(overlay.width)*ratio)
var h = Math.round(Math.abs(overlay.height)*ratio)
$('#overlayUpload .preview').css({
"width": w + 'px',
"height": h + 'px',
});
$('#overlayUpload .preview [attr-type="width"]').text(toPrecision(overlay.width, 2))
$('#overlayUpload .preview [attr-type="height"]').text(toPrecision(overlay.height, 2))
}
,
updateOverlayPanel : function(overlay){
this.editPlane = overlay;
var plane = overlay.plane
var src = plane.material.map && plane.material.map.image.src;
$('#overlayUpload .preview video').remove();
if(overlay.overlayType == "video"){
var video = plane.material.map.image
$('#overlayUpload .preview').css('background-image',"").append(video);
}else{
$('#overlayUpload .preview').css({
'background-image': src ? ("url(" + src + ")") : ""
})
}
if(overlay.overlayType){
$('#overlayUpload [name="useImgRatio"]').removeClass("hide")
$('#overlayUpload .preview').addClass('uploaded')
}else{
$('#overlayUpload [name="useImgRatio"]').addClass("hide")
$('#overlayUpload .preview').removeClass('uploaded')
}
this.updateOverlayScaleDisplay()
if(overlay.hasBox){
this.scroller.videoDepth.setValue(overlay.scale.z * settings.overlay.depth * 100,true)
}else{
this.scroller.videoDepth.setValue(0,true)
}
setTimeout(()=>{
this.scroller.videoDepth.InitOffset()
},201)
}
,
closeOverlayPanel : function(type){
if(!this.editPlane)return;
if(type == 'cancel'){
if(!this.editPlane.isNew && !this.editPlane.needDelete)this.editPlane.setFromInfo(this.editPlane.info) //this.setOverlayFromInfo(this.editPlane, this.editPlane.info);//恢复
else this.disposeOverlay(this.editPlane); //删除
}
this.editPlane = null;
transformControls.detach()
$("#overlayProp").addClass("atRight");
//if(player.model.overlayPlanes.length < this.overlayMaxCount) this.beginToAddPlane()
}
,
useImgRatio : function(o){
var plane = this.editPlane.plane;
if(!plane.material.map)return;
var img = plane.material.map.image;
var mintranRatio = 200;//default is 200 , 防止图片太小时在墙上依旧很大
var width = this.editPlane.overlayType == "video" ? img.videoWidth : img.width;
var height = this.editPlane.overlayType == "video" ? img.videoHeight : img.height;
if(o == "suitSize"){
var boundWidth = Math.min(Math.max(width,height)/mintranRatio, 1)
if(width > height){
var w = boundWidth;
var h = boundWidth * height / width
}else{
var h = boundWidth;
var w = boundWidth * width / height;
}
}else{
//假设不变总面积
var k = Math.sqrt(Math.abs(this.editPlane.width * this.editPlane.height) / (width * height))
var w = k * width * (this.editPlane.width<0?-1:1);
var h = k * height * (this.editPlane.height<0?-1:1);
}
this.editPlane.scale.setX(w/settings.overlay.width)
this.editPlane.scale.setY(h/settings.overlay.height)
this.editPlane.width = w;
this.editPlane.height = h;
this.updateOverlayPanel(this.editPlane)
},
getOverlayInfo : function(overlay){
//2 编辑前, 从当前状态获取info
var plane = overlay.plane;
overlay.info = {
width: overlay.width,
height: overlay.height,
depth: settings.overlay.depth * overlay.scale.z,
pos: overlay.position.clone(),
qua: overlay.quaternion.clone(),
media: plane.material.map.image,
file: overlay.file,
type: overlay.overlayType,
hasBox: overlay.hasBox
}
}
,
getSavingInfo : function(overlay){
if(!overlay.file && (!overlay.plane.material.map ||!overlay.plane.material.map.image)){
return;
}
var info = {
width: toPrecision(overlay.width, 4),
height: toPrecision(overlay.height, 4),
depth: toPrecision(settings.overlay.depth * overlay.scale.z, 4),
pos: toPrecision(overlay.position.toArray(),4),
qua: toPrecision(overlay.quaternion.toArray(),4),
sid: overlay.sid,
hasBox: overlay.hasBox ? 1 : 0,
media: [overlay.overlayType],
file: overlay.fileSrc || overlay.plane.material.map.image.src
}
return info
},
SaveOverlay : function(){
var overlay = this.editPlane;
if(!overlay.file && (!overlay.plane.material.map ||!overlay.plane.material.map.image)){
alert("请上传视频");return;
}
var saveInfo = ()=>{
//overlay.savingInfo = JSON.stringify(info)//准备写入的info
//saveDone:
overlay.isNew = false;
this.getOverlayInfo(overlay);
this.closeOverlayPanel()
$('.waiting').removeClass('showloading');
}
if(!overlay.info || overlay.file != overlay.info.file){
$('.waiting').addClass('showloading');
uploadFile(overlay.file, 'overlay', function (rs) {
if (rs.code === 0) {
overlay.fileSrc = rs.data;
saveInfo()
};
} )
}else saveInfo();
}
,
disposeOverlay : function(overlay){
var plane = overlay.plane
if(overlay == player.hoveringPlane){
player.hoverOverlay(null,"soon");
}
if(plane.material.map){//删除视频src
//overlay.info && common.destroyBlob(overlay.info.media.src)
//common.destroyBlob(plane.material.map.image.src)
}
plane.material.dispose();
overlay.parent.remove(overlay);
this.removeFromList(overlay)
//this.beginToAddPlane()
}
,
DeleteOverlay : function(){
var overlay = this.editPlane;
if(!overlay.isNew){
if(confirm("确定删除该视频?")){
overlay.needDelete = true;
$("#overlayProp a.close").click()//this.closeOverlayPanel()
}
}else{//刚创建时的删除按钮等同于取消按钮
$("#overlayProp a.close").click()//this.closeOverlayPanel()
}
}
,
addToList : function(overlay){
var li = $(`
${overlay.sid}
`)
$(".overlayList ul").append(li);
li.on("click",()=>{
player.clickOverlay(overlay)
})
overlay.domLi = li;
},
removeFromList : function(overlay){
overlay.domLi.remove();
}
}
//----------------漫游可见性---------------------------------
var panoVisiSet = {
setPanoVisible : false,
//漫游可见性
panoVLines : {},//线条
panoVTemp:null, //修改后还没保存的临时数据
//热点可见性
$confirmSnap : $("#camera-start"),
colors:{green: "#00c8ae"},
init : function(){
this.meshGroup = new THREE.Object3D; this.meshGroup.name = "setVisible-group"
player.model.add(this.meshGroup)
},
beginSetPanoVisible : function () {
if (this.setPanoVisible ) return;
$(".toolLeft").removeClass("unable")
this.setPanoVisible = true;
this.panoVTemp = {};
this.SetOnePanoVisible(player.currentPano)//先设置currentPano
this.$confirmSnap.text('保存当前设置').removeClass("hide")
//objects.tagManager.hideAllTags();
this.updateFootIconSize()//更新一下大小,尤其是上次换了中心点然后退出又进入但是镜头没有变化的话
},
SetOnePanoVisible : function (pano) { //点击某个pano后就对该pano点进行设置
if (this.panoVsetting == pano) return;
//if (this.panoVsetting) saveLastPanoVi(this.panoVsetting);
this.panoVsetting = pano; //记录正在修改的
this.delVisibleLines(); //删除线
this.showFootIcons(pano, true);
this.createPanoVisiLines(pano); //创线
},
saveLastPanoVi : function () { //保存刚设置过的pano
var change = [];
for (var r in this.panoVLines) {
var line = this.panoVLines[r];
if (line.name.indexOf("new") > -1 && line.visible) { //新设置为visible且没有取消
change.push({
type: "add",
id: r
})
} else if (line.name.indexOf("new") == -1 && !line.visible) { //旧的且已经取消
change.push({
type: "sub",
id: r
})
}
}
if (change.length) { //添加双向的neighbour:
var self = this.searchNeib(this.panoVsetting.id)
//var seeMarkers_self = self.seeMarkers;
var neighbourUUIDs_self = self.neighbourUUIDs
var neighbourPanos_self = self.neighbourPanos;
for (var i = 0; i < change.length; i++) {
var other = this.searchNeib(change[i].id)
//var seeMarkers = other.seeMarkers;
var neighbourUUIDs = other.neighbourUUIDs;
var neighbourPanos = other.neighbourPanos;
if (change[i].type == "add") {
//seeMarkers.push(this.panoVsetting.id);
neighbourUUIDs.push(this.panoVsetting.id);
neighbourPanos[this.panoVsetting.id] = true;
//seeMarkers_self.push(change[i].id);
neighbourUUIDs_self.push(change[i].id);
neighbourPanos_self[change[i].id] = true;
} else {
//var index = seeMarkers.indexOf(this.panoVsetting.id);
//index > -1 && seeMarkers.splice(index, 1);
var index = neighbourUUIDs.indexOf(this.panoVsetting.id);
index > -1 && neighbourUUIDs.splice(index, 1);
neighbourPanos[this.panoVsetting.id] = false;
//var index = seeMarkers_self.indexOf(change[i].id);
//index > -1 && seeMarkers_self.splice(index, 1);
var index = neighbourUUIDs_self.indexOf(change[i].id);
index > -1 && neighbourUUIDs_self.splice(index, 1);
neighbourPanos_self[change[i].id] = false;
}
this.panoVTemp[change[i].id] = { //后面两个是作为保存到后台的数据存储,临时需要用到的是第一个
neighbourPanos: neighbourPanos,
//seeMarkers: seeMarkers,
neighbourUUIDs: neighbourUUIDs
}
}
this.panoVTemp[this.panoVsetting.id] = {//加上自己
neighbourPanos: neighbourPanos_self,
//seeMarkers: seeMarkers_self,
neighbourUUIDs: neighbourUUIDs_self
}
}
},
pauseSetPanoVisible : function (type) { //暂停 因为点击了保存设置 但没有退出设置
if (!this.setPanoVisible) return;
if(type == "unsaved"){//中途点击pano从而停止一个热点的设置
this.saveLastPanoVi();
}else{
this.panoVTemp = {}; //清空数据
}
this.delVisibleLines();
this.showFootIcons();//清空选择
var lastPanoSetting = this.panoVsetting;
this.panoVsetting = null;
lastPanoSetting && this.changeFIconState2(lastPanoSetting.footIcon, this.checkHasNeighbor(lastPanoSetting))//这句要放在this.panoVsetting = null后。 根据可见性更改透明度
},
//按理说改变了neighbourPano,tag的初始visible也要改。但是这样还要考虑已经改过的tag。。很麻烦
finishSetPanoVisible : function () { //结束 退出这个设置
if (!this.setPanoVisible)
return; //否则会加多个侦听
this.setPanoVisible = false;
this.hideFootIcons();
this.delVisibleLines();
//objects.tagManager.showAllTags();
this.recoverAllState2();
this.panoVsetting = null;
this.panoVTemp = {};
player.flyoutType = null
this.$confirmSnap.addClass("hide")
},
recoverAllState2 : function(){//为了热点可视恢复成pano全部可见
for (var i = 0; i < this.footIcons.length; i++) {
this.footIcons[i].material.uniforms.opacity.value = 1;
this.footIcons[i].material.uniforms.map.value = footTex1;
}
},
afterSavePanoVisibles : function(){ //实施:
var panos = player.model.panos;
for (var i in this.panoVTemp) {
var pano = panos.index[i];
//pano.seeMarkers = this.panoVTemp[i].seeMarkers;
pano.neighbourUUIDs = this.panoVTemp[i].neighbourUUIDs;
pano.neighbourPanos = this.panoVTemp[i].neighbourPanos;
}
if(!this.checkHasNeighbor(player.currentPano)){//currentPano变为孤立点 就要换一个防止飞入
var list = panos.sortByScore([pano=>{return this.checkHasNeighbor(pano)}],
[function(pano){return -pano.position.distanceTo(player.currentPano.position)}])
if(list && list.length){
player.currentPano = list[0].pano;//找最近的一非孤立点
//this.noPanoHasNeighbor = false; //更新状态
}else{
//this.noPanoHasNeighbor = true; //更新状态
}
}else{
//this.noPanoHasNeighbor = false; //更新状态
}
//dataDeal.done();
//暂时:
this.pauseSetPanoVisible()
this.updateFootIconSize()//更新一下center大小 写在最后
},
//最佳推荐操作顺序: 先设置pano可见性 再创建热点 这样热点的visible正确些,否则之后再设置热点可见性会改更多
savePanoVisibles : function () { //保存
if (this.panoVsetting) this.saveLastPanoVi(this.panoVsetting); //获取最后设置的那个热点的改动
var PanoData = [];
for (var i in this.panoVTemp) {
PanoData.push({//希望算法部不会更改index排序,或者更改后能将visible信息一并更改
panoID: i,
//visibles: this.turnToPanoIndex(this.panoVTemp[i].seeMarkers),
visibles3: this.turnToPanoIndex(this.panoVTemp[i].neighbourUUIDs)
})
}
if (PanoData.length == 0) {//没改变
alert("保存成功")
return;
}
/* this.afterSavePanoVisibles()
alert("保存成功")
console.log(JSON.stringify(PanoData)) */
$.ajax({
method: 'POST',
url: ceshi + '/cms/scene/roamViable',
headers:{
'Content-Type':'application/json',
token:token
},
contentType:'application/json',
data: JSON.stringify({
data: JSON.stringify(PanoData),
sceneCode: window.number
}),
success: (data)=>{
if (data.code === 0) {
this.afterSavePanoVisibles()
alert("保存漫游可行成功")
} else alert("保存漫游可行失败")
if (data.code === 5001) {
alert('请重新登录')
localStorage.dcj_token = ''
window.location.href('/bigscene/')
}
},
fail:function(){
alert("保存漫游可行失败")
}
})
/* var o = {
name_t: "panoVisible",
f: this.pauseSetPanoVisible,
url: Config.prefixEditProPCApi+"/saveLinkPano",
dialog: i18n.get('设置'),
data: { data: JSON.stringify(PanoData) }
}
var dataDeal = uploadsSaving.saveFucforPC(o);
dataDeal.group[0] = function () {
//实施:
for (var i in player.panoVTemp) {
var pano = player.model.panos.index[i];
pano.seeMarkers = player.panoVTemp[i].seeMarkers;
pano.neighbourUUIDs = player.panoVTemp[i].neighbourUUIDs;
pano.neighbourPanos = player.panoVTemp[i].neighbourPanos;
}
if(!player.model.checkHasNeighbor(player.currentPano)){//currentPano变为孤立点 就要换一个防止飞入
var list = player.model.panos.sortByScore([function(pano){return player.model.checkHasNeighbor(pano)}],
[function(pano){return -pano.position.distanceTo(player.currentPano.position)}])
if(list && list.length){
player.currentPano = list[0].pano;//找最近的一非孤立点
player.model.noPanoHasNeighbor = false; //更新状态
}else{
player.model.noPanoHasNeighbor = true; //更新状态
}
}else{
player.model.noPanoHasNeighbor = false; //更新状态
}
dataDeal.done();
player.model.updateFootIconSize(player.cameraControls.activeControl)//更新一下center大小 写在最后
} */
},
searchNeib : function (panoId) {//寻找某pano的相关neighbour 可能是修改过的
var panos = player.model.panos;
var o = {};
if (this.panoVTemp[panoId]) {
//o.seeMarkers = this.panoVTemp[panoId].seeMarkers;
o.neighbourUUIDs = this.panoVTemp[panoId].neighbourUUIDs;
o.neighbourPanos = this.panoVTemp[panoId].neighbourPanos;
} else {
//o.seeMarkers = panos.index[panoId].seeMarkers.slice(0);
o.neighbourUUIDs = panos.index[panoId].neighbourUUIDs.slice(0);
o.neighbourPanos = CloneObject(panos.index[panoId].neighbourPanos);
}
return o;
},
turnToPanoIndex : function (panoArr) {
var panos = player.model.panos;
var array = [];
for (var i = 0; i < panoArr.length; i++) {
var pano = panos.index[panoArr[i]];
var index = panos.list.indexOf(pano)
array.push(index);
}
return array;
},
setDisplay : function(state){
var panos = player.model.panos;
if(state){
player.model.panos.forEach((pano)=>{
if(pano.hasVideo){
pano.marker.visible = false;
pano.flagSpot.disc.visible = false;
pano.flagSpot.markGroup.hide();
}
})
player.model.cadFloorPlane.changeCadVisible(false)
}else{
player.model.panos.forEach((pano)=>{
if(pano.hasVideo){
pano.marker.visible = true;
pano.flagSpot.disc.visible = true;
pano.flagSpot.markGroup.show();
}
})
player.model.cadFloorPlane.changeCadVisible(null,{autoJudge:true})
}
player.defaultRoomLabels.forEach(function(label){ label.update()})
player.path.currentPanoMarker.mesh.visible = !state;
objects.overlayManager.group.visible = !state;
player.reticule.visible = !state;
},
delVisibleLines : function () {
//xzw add 所有线都删除
for (var i in this.tagsVLines) {
this.tagsVLines[i].geometry.dispose();
this.tagsVLines[i].material.dispose();
this.meshGroup.remove(this.tagsVLines[i]);
delete this.tagsVLines[i];
}
for (var i in this.panoVLines) {
this.panoVLines[i].geometry.dispose();
this.panoVLines[i].material.dispose();
this.meshGroup.remove(this.panoVLines[i]);
delete this.panoVLines[i];
}
},
//--------panoVisible
createPanoVisiLines : function (pano) {
// pano可见性线条
var neighbours = this.panoVTemp[pano.id] && this.panoVTemp[pano.id].neighbourPanos || pano.neighbourPanos;
for (var r in neighbours) {
if (neighbours[r] && r != pano.id) {
this.createPanoSingleLine(pano, "old", r)
}
}
},
createPanoSingleLine : function (pano, type, id) {//pano是中心
var panos = player.model.panos;
var p2 = panos.index[id].floorPosition.clone()/* .sub(player.model.position) */
var line = LineDraw.createLine([pano.floorPosition.clone()/* .sub(this.position) */, p2], {
color: this.colors.green
});
this.meshGroup.add(line);
line.name = "PanoVL-" + type + "-" + id;
this.panoVLines[id] = line;
this.changeFIconState(panos.index[id].footIcon, "linked")
},
dealPanoVisible : function (id) { //外部调用
var panos = player.model.panos;
if (this.panoVsetting) {
if (id == this.panoVsetting.id) {//关闭当前pano设置
this.pauseSetPanoVisible('unsaved')
}else{
var link;//结果是否连接
if(this.panoVLines[id]){
this.panoVLines[id].visible = !this.panoVLines[id].visible;
link = this.panoVLines[id].visible;
this.changeFIconState(panos.index[id].footIcon, this.panoVLines[id].visible?"linked":false)
}else{
this.createPanoSingleLine(this.panoVsetting, "new", id)
link = true;
}
if(link){//如果连接上了,直接判断该点是可见的(有附近点),(不能通过checkHasNeighbor来判断,因为新增的线条可能不在它的neighbour中
this.changeFIconState2(panos.index[id].footIcon, true)
this.changeFIconState2(panos.index[this.panoVsetting.id].footIcon, true)
}else{//否则需要checkHasNeighbor
this.changeFIconState2(panos.index[id].footIcon, this.checkHasNeighbor(panos.index[id]))
this.changeFIconState2(panos.index[this.panoVsetting.id].footIcon, this.checkHasNeighbor(this.panoVsetting))
}
}
}else {//点击开始设置要设置的pano
this.SetOnePanoVisible(panos.index[id])
}
this.updateFootIconSize()
},
showFootIcons : function (pano, isPanovisible) {
if (!this.footIcons) {
footTex1 = Texture.load("images/edit/End_128.png"); //Store.FootIcon);
footTex2 = Texture.load("images/edit/End_unable_128.png"); //Store.FootIcon_unable);
this.footIcons = [];
var scale = 0.4;
scale *= 40 / Math.sqrt(Math.min($("#player").width(), $("#player").height()));//屏幕越小,放得越大
scale = THREE.Math.clamp(scale, 0.3, 0.7)
//console.log("scale"+scale)
var geo = new THREE.PlaneGeometry(scale, scale, 1, 1)
var panos = player.model.panos;
for (var r in panos.index) {
var t = THREE.UniformsUtils.clone(shaders.waypoint.uniforms);
t.map.value = footTex1
t.color.value.set("#ffffff");
var mat = new THREE.RawShaderMaterial({
vertexShader: shaders.waypoint.vertexShader,
fragmentShader: shaders.waypoint.fragmentShader,
uniforms: t,
side: THREE.DoubleSide,
transparent: !0,
depthWrite: !1,
depthTest: false,
name: "footIcon"
})
var foot = new THREE.Mesh(geo, mat)
foot.position.copy(panos.index[r].floorPosition.clone()/* .sub(player.model.position) */)
foot.lookAt(foot.position.clone().add(new THREE.Vector3(0, 1, 0)));
foot.name = panos.index[r].id;
foot.visible = false;
foot.renderOrder = 6,
panos.index[r].footIcon = foot;
this.meshGroup.add(foot);
this.footIcons.push(foot)
}
}
for (var i = 0; i < this.footIcons.length; i++) {
this.footIcons[i].visible = true;
this.changeFIconState(this.footIcons[i], false)
var panos = player.model.panos;
if(isPanovisible){
this.changeFIconState2(this.footIcons[i], this.checkHasNeighbor(panos.index[this.footIcons[i].name], "showFoot"))
}
if (pano && (this.footIcons[i].name == pano.id)) {
//pano为中心 或者 currentPano 所以放大一点
this.footIcons[i].oriScale = new THREE.Vector3(1.5, 1.5, 1.5)
if (isPanovisible) {
//currentPano特殊些:
this.changeFIconState(this.footIcons[i], "center")
//this.footIcons[i].Unclick = true;//不让点击和hover
}
} else {
this.footIcons[i].oriScale = new THREE.Vector3(1, 1, 1)
}
}
},
checkHasNeighbor : function(pano, state){ //检查当前状态pano点是否有可通行点
var neighbours = this.panoVTemp && this.panoVTemp[pano.id] ? this.panoVTemp[pano.id].neighbourPanos : pano.neighbourPanos;
if(state != "showFoot" && pano == this.panoVsetting){//是中心点的话。state == "showFoot"代表是showFootIcon时, 这时候线还没创建,无法用线判断中心点有几个相邻点,直接用neighbourPanos
for(var i in this.panoVLines){
if(this.panoVLines[i].visible){
return true; //有一条线即可
}
}
return;
}
for(var i in neighbours ){
if(i == pano.id)continue;
if(neighbours[i]){
if(this.panoVsetting && this.panoVsetting.id == i && this.panoVLines[pano.id] && !this.panoVLines[pano.id].visible) continue;
return true;
}
}
return false;
},
/* ifAllPanoNoNeighbor : function(){//检查是否全是孤立点
var panos = player.model.panos;
for(var i in panos.index){
if(this.checkHasNeighbor(panos.index[i])){
return false;
}
}
this.noPanoHasNeighbor = true;
return true;//是全部没有neighbour
}, */
changeFIconState : function (footIcon, state) {
var color = state == "linked" ? this.colors.green :(state == "center" ? /* "#d7f244" */ "#d5f12e": "#ffffff") ;
footIcon.material.uniforms.color.value.set(color)
},
changeFIconState2 : function(footIcon, state){//是可见点还是不可见点
if(state){
footIcon.material.uniforms.map.value = footTex1;
if(this.panoVsetting){
if(this.panoVsetting.id != footIcon.name){
footIcon.material.uniforms.opacity.value = 1;
}else{
//this.changeVisiBtnState(true)
}
}
}else{//不可见
footIcon.material.uniforms.map.value = footTex2;
if(!this.panoVsetting || this.panoVsetting.id != footIcon.name){//非中心点时
footIcon.material.uniforms.opacity.value = 0.5;
}else{//变为中心点时
footIcon.material.uniforms.opacity.value = 1;
//this.changeVisiBtnState(false)
}
}
},
hideFootIcons : function () {
if (!this.footIcons) return;
for (var i = 0; i < this.footIcons.length; i++) {
this.footIcons[i].visible = false;
}
},
updateFootIconSize : function () {//根据相机位置 改变footIcon大小,使在范围内看到的热点大小一致,防止太小点击不到
if (!this.footIcons) return;
var s = player.cameraControls.controls.floorplan.absoluteScale * 2.8;
s = THREE.Math.clamp(s, 0.5, 1.4);
this.footIcons.forEach(function (f) {
try{
f.scale.copy(f.oriScale).multiplyScalar(s);
}catch(e){console.log(e)}
})
}
}
function permitTranMode(state){
state ? $(".pinBottom.left").removeClass('hide') : $(".pinBottom.left").addClass('hide');
}
CloneObject = function (copyObj, result, isSimpleCopy) {//isSimpleCopy只复制最外层
//复制json result的可能:普通数字或字符串、普通数组、复杂对象
result = result || {};
if (copyObj instanceof Array) {
if (copyObj[0] instanceof Object) {
//不支持含有 [[Object]] 这样二级数组里面还是复杂数据的,普通和复杂的数据混合可能也不支持
console.error("不支持含有 [[Object]] 这样二级数组里面还是复杂数据的...")
}
return copyObj.slice(0);
//如果是数组,直接复制返回(排除数组内是object
}
for (var key in copyObj) {
if (copyObj[key] instanceof Object && !isSimpleCopy)
result[key] = CloneObject(copyObj[key]);
else
result[key] = copyObj[key];
//如果是函数类同基本数据,即复制引用
}
return result;
};
function randomWord(randomFlag, min, max) {//随机字符串
var str = "",
range = min,
arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
if (randomFlag) { // 随机长度
range = Math.round(Math.random() * (max - min)) + min;
}
for (var i = 0; i < range; i++) {
var pos = Math.round(Math.random() * (arr.length - 1));
str += arr[pos];
}
return str;
}
function getRandomSid() {//5-7位随机字符串 + 6位时间 为热点准备
var pre = randomWord(true, 5, 7);
var post = new Date().getTime() + "";
var len = post.length;
post = post.substring(len - 8, len - 5) + post.substring(len - 3, len)//其实还是有可能重复的....
return pre + post;
}
//})();