InputHandlerNew.js 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584
  1. /**
  2. * @author mschuetz / http://mschuetz.at
  3. *
  4. *
  5. */
  6. import * as THREE from "../../libs/three.js/build/three.module.js";
  7. import {KeyCodes} from "../KeyCodes.js";
  8. import {Utils} from "../utils.js";
  9. import Common from "../custom/utils/Common.js";
  10. import DepthBasicMaterial from '../custom/materials/DepthBasicMaterial.js'
  11. import browser from "../custom/utils/browser.js";
  12. import math from "../custom/utils/math.js";
  13. let {Buttons} = Potree.defines
  14. export class InputHandler extends THREE.EventDispatcher {
  15. constructor (viewer,scene) {
  16. super();
  17. this.viewer = viewer;
  18. this.renderer = viewer.renderer;
  19. this.domElement = this.renderer.domElement;
  20. this.enabled = true;
  21. this.scene = scene;
  22. this.interactiveScenes = [];
  23. this.interactiveObjects = new Set();
  24. this.inputListeners = [];
  25. this.blacklist = new Set();
  26. this.drag = null;
  27. this.mouse = new THREE.Vector2(0, 0);
  28. //add:
  29. this.pointer = new THREE.Vector2(0, 0); //交互点的屏幕坐标,有别于DOM坐标,在此存放NDC坐标。(NDC,三维常用坐标系,二维坐标,整个屏幕映射范围(-1,1),屏幕中心为原点,+Y朝上,+X朝右)
  30. this.mouseDownMouse = new THREE.Vector2(0, 0);
  31. this.selection = [];
  32. this.hoveredElements = [];
  33. this.pressedKeys = {};
  34. this.wheelDelta = 0;
  35. this.speed = 1;
  36. this.logMessages = false;
  37. if (this.domElement.tabIndex === -1) {
  38. this.domElement.tabIndex = 2222;
  39. }
  40. this.lastPointerUpTime = 0
  41. this.touches = []
  42. this.interactHistory = {move:0} //add
  43. this.hoverViewport = viewer.viewports[0]
  44. document.addEventListener('mouseup', function (event) {
  45. event.preventDefault();
  46. }, { passive: false });
  47. this.domElement.addEventListener('contextmenu', (event) => { event.preventDefault(); }, false);
  48. this.domElement.addEventListener('click', this.onMouseClick.bind(this), false);
  49. this.domElement.addEventListener('mousedown', this.onMouseDown.bind(this), {passive:false, useCapture:false});
  50. window.addEventListener('mouseup', this.onMouseUp.bind(this), {passive:false, useCapture:false});
  51. if(Potree.isIframeChild){//子页面的话在父页面也要加侦听(应该不会有多层吧?否则要一直加到最外层)
  52. //window.parent.addEventListener('mouseup', this.onMouseUp.bind(this), false); //可能跨域
  53. //window.parent.postMessage('listenMouseup', '*');
  54. window.addEventListener('mouseout', this.onMouseUp.bind(this), false); //cancel drag
  55. }
  56. this.domElement.addEventListener('mouseout', ()=>{
  57. this.containsMouse = false
  58. }, false);
  59. this.domElement.addEventListener('mousemove', this.onMouseMove.bind(this), {passive:false, useCapture:false});
  60. //add
  61. /* this.domElement.addEventListener("pointerout", this.onMouseUp.bind(this)),
  62. this.domElement.addEventListener("pointercancel", this.onMouseUp.bind(this)),
  63. */
  64. this.domElement.addEventListener('mousewheel', this.onMouseWheel.bind(this), false);
  65. this.domElement.addEventListener('DOMMouseScroll', this.onMouseWheel.bind(this), false); // Firefox
  66. //this.domElement.addEventListener('dblclick', this.onDoubleClick.bind(this)); //因为双击时间间隔是跟随系统的所以不好判断
  67. window.addEventListener('keydown', this.onKeyDown.bind(this));//原先是this.domElement,这样的话一开始要点击屏幕后才能监听到
  68. window.addEventListener('keyup', this.onKeyUp.bind(this));
  69. window.addEventListener('blur',this.onKeyUp.bind(this)); //add
  70. this.domElement.addEventListener('touchstart', this.onTouchStart.bind(this));
  71. this.domElement.addEventListener('touchend', this.onTouchEnd.bind(this));
  72. this.domElement.addEventListener('touchmove', this.onTouchMove.bind(this));
  73. {
  74. this.measuring = [] //正在编辑的measure
  75. //let mesureInfo = new THREE.EventDispatcher()
  76. this.addEventListener('measuring',(e)=>{
  77. //true优先级高于false, 正在添加时dropMarker也不会停止
  78. //Potree.Utils.updateVisible(mesureInfo, e.situation, e.v, 0, e.v?'add':'cancel' )//借用该函数,使true优先级高于false,防止正在添加时dropMarker而停止
  79. if(e.v){
  80. this.measuring.includes(e.object) || this.measuring.push(e.object)
  81. }else{
  82. let index = this.measuring.indexOf(e.object)
  83. index > -1 && this.measuring.splice(index, 1)
  84. }
  85. if(this.measuring.length == 0 && this.measuring.length>0 ){
  86. this.viewer.viewports.forEach((viewport)=>{
  87. this.collectClosePoints(viewport, true )//forceUpdate
  88. })
  89. }
  90. //console.log('measuring',e.v, e.cause, e.situation, this.measuring.length )
  91. })
  92. }
  93. window.viewer.addEventListener('loopStart',()=>{
  94. this.interactHistory = {} //清空
  95. })
  96. }
  97. /* addInputListener (listener) {
  98. this.inputListeners.push(listener);
  99. }
  100. removeInputListener (listener) {
  101. this.inputListeners = this.inputListeners.filter(e => e !== listener);
  102. }
  103. getSortedListeners(){
  104. return this.inputListeners.sort( (a, b) => {
  105. let ia = (a.importance !== undefined) ? a.importance : 0;
  106. let ib = (b.importance !== undefined) ? b.importance : 0;
  107. return ib - ia;
  108. });
  109. } */
  110. //统一跟第一个触碰的viewport相同
  111. updateTouchesInfo(e){
  112. var viewport, pointer, camera
  113. let oldTouches = this.touches
  114. let changedTouches = Array.from(e.changedTouches).filter(e=>e.target == this.domElement )
  115. let touches = Array.from(e.touches).filter(e=>e.target == this.domElement )
  116. this.touches = touches.map(touch=>{
  117. let touch_ = oldTouches.find(a=>a.touch.identifier == touch.identifier)
  118. let pointer = touch_ && touch_.pointer //复制原先的值
  119. //let isAtDomElement = touch.target == this.domElement
  120. return {
  121. touch, pointer, //isAtDomElement
  122. }
  123. })
  124. if(touches.length > 0){
  125. let newTouches = touches.filter(e=>!
  126. oldTouches.some(a=>a.touch.identifier == e.identifier) && !changedTouches.some(a=>a.identifier == e.identifier)
  127. ) //从按钮处划过时e.touches中会出现this.touches和changedTouches中都没有的identifier
  128. if(newTouches.length>0){
  129. console.warn('has new',newTouches.map(e=>e.identifier))
  130. }
  131. newTouches.concat(changedTouches).forEach(touch=>{ //修改changedTouches的
  132. let touch_ = this.touches.find(a=>a.touch.identifier == touch.identifier)
  133. if(touch_){
  134. let a = this.getPointerInViewport(touch.pageX, touch.pageY, this.dragViewport||viewport, new THREE.Vector2)
  135. touch_.pointer = a.pointer.clone()
  136. viewport = a.viewport; camera = a.camera
  137. }
  138. })
  139. //使用当前touches的平均
  140. if(touches.length > 1){
  141. let pageX = Common.average(touches, "pageX")
  142. let pageY = Common.average(touches, "pageY")
  143. let a = this.getPointerInViewport(pageX, pageY, viewport, new THREE.Vector2)
  144. this.pointer.copy(a.pointer)
  145. }else{
  146. this.pointer = this.touches[0].pointer.clone() //更新,使用当前touches中的第一个
  147. }
  148. //console.log('touchesInfo', this.pointer.x.toPrecision(2), this.pointer.y.toPrecision(2) , this.touches.length)
  149. /* if(this.touches.find(e=>!e.pointer)){
  150. console.error(' touches has no pointer', oldTouches.map(e=>e.touch.identifier),
  151. Array.from(e.touches).map(e=>e.identifier), Array.from(e.changedTouches).map(e=>e.identifier) )
  152. } */
  153. //console.log(this.touches)
  154. //console.log('更新pointer1',this.pointer.toArray())
  155. return {viewport, camera/* , pointer:this.pointer */}
  156. }
  157. }
  158. onTouchStart (e) {
  159. if (this.logMessages) console.log(this.constructor.name + ': onTouchStart');
  160. e.preventDefault();
  161. /* if (e.touches.length === 1 || !this.drag) { //!this.drag代表一次性下了两个指头
  162. let rect = this.domElement.getBoundingClientRect();
  163. let x = e.touches[0].pageX
  164. let y = e.touches[0].pageY
  165. this.dealPointerDown(x,y,e,true)
  166. }else{
  167. this.updateTouchesInfo(e)
  168. this.drag.end.copy(this.pointer)
  169. } */
  170. this.dealPointerDown(e,true)
  171. this.viewer.dispatchEvent($.extend(
  172. this.getEventDesc(e,true),
  173. {
  174. type: 'global_' + e.type,
  175. changedTouches: e.changedTouches
  176. }
  177. ));
  178. /* console.log('targetTouches :', Array.from(e.targetTouches).map(e=>'| identifier: '+ e.identifier),
  179. 'changedTouches :', Array.from(e.changedTouches).map(e=>'| identifier: '+ e.identifier)
  180. ) */
  181. //console.log('')
  182. }
  183. onTouchMove (e) {
  184. if (this.logMessages) console.log(this.constructor.name + ': onTouchMove');
  185. e.preventDefault();
  186. /* if (e.touches.length === 1) {
  187. let rect = this.domElement.getBoundingClientRect();
  188. let x = e.touches[0].pageX;
  189. let y = e.touches[0].pageY;
  190. }else{
  191. this.updateTouchesInfo(e)
  192. this.drag.pointerDelta.subVectors(this.pointer, this.drag.end)
  193. this.drag.end.copy(this.pointer)
  194. }
  195. */
  196. this.dealPointerMove(e, true)
  197. this.viewer.dispatchEvent($.extend(
  198. this.getEventDesc(e,true),
  199. {
  200. type: 'global_' + e.type,
  201. changedTouches: e.changedTouches
  202. }
  203. ));
  204. /* console.log('targetTouches :', Array.from(e.targetTouches).map(e=>'| identifier: '+ e.identifier),
  205. 'changedTouches :', Array.from(e.changedTouches).map(e=>'| identifier: '+ e.identifier)
  206. ) */
  207. }
  208. onTouchEnd (e) {
  209. if (this.logMessages) console.log(this.constructor.name + ': onTouchEnd');
  210. e.preventDefault();
  211. //console.log('onTouchEnd')
  212. this.updateTouchesInfo(e)
  213. /* if (e.touches.length === 0) {
  214. let rect = this.domElement.getBoundingClientRect();
  215. let x = e.changedTouches[0].pageX //万一一次松开两个指头的怎么办
  216. let y = e.changedTouches[0].pageY
  217. this.dealPointerUp(x,y,e,true)
  218. }else {
  219. this.drag.end.copy(this.pointer)
  220. } */
  221. this.dealPointerUp(e,true)
  222. this.viewer.dispatchEvent($.extend(
  223. this.getEventDesc(e,true),
  224. {
  225. type: 'global_' + e.type,
  226. }
  227. ));
  228. //console.log('touchend length '+e.touches.length, this.touches.length)
  229. }
  230. onKeyDown (e) {
  231. if (this.logMessages) console.log(this.constructor.name + ': onKeyDown');
  232. if(e.target.nodeName == 'INPUT' || e.target.nodeName == 'TEXTAREA') return //正在输入文字 或e.srcElement
  233. if(!this.containsMouse)return //在别的ui上无效
  234. // DELETE
  235. /* if (e.keyCode === KeyCodes.DELETE && this.selection.length > 0) {
  236. this.dispatchEvent({
  237. type: 'delete',
  238. selection: this.selection
  239. });
  240. this.deselectAll();
  241. } */
  242. this.dispatchEvent({
  243. type: 'keydown',
  244. keyCode: e.keyCode,
  245. event: e
  246. });
  247. // for(let l of this.getSortedListeners()){
  248. // l.dispatchEvent({
  249. // type: "keydown",
  250. // keyCode: e.keyCode,
  251. // event: e
  252. // });
  253. // }
  254. this.pressedKeys[e.keyCode] = true;
  255. // e.preventDefault();
  256. }
  257. onKeyUp (e) {
  258. if (this.logMessages) console.log(this.constructor.name + ': onKeyUp');
  259. if(e.keyCode != void 0){
  260. delete this.pressedKeys[e.keyCode];
  261. }else{
  262. this.pressedKeys = {}
  263. }
  264. e.preventDefault();
  265. }
  266. onDoubleClick (e) {
  267. if (this.logMessages) console.log(this.constructor.name + ': onDoubleClick');
  268. let consumed = false;
  269. for (let hovered of this.hoveredElements) {
  270. if (hovered._listeners && hovered._listeners['dblclick']) {
  271. hovered.object.dispatchEvent({
  272. type: 'dblclick',
  273. mouse: this.mouse,
  274. object: hovered.object
  275. });
  276. consumed = true;
  277. break;
  278. }
  279. }
  280. if (!consumed) {
  281. /* for (let inputListener of this.getSortedListeners()) {
  282. inputListener. */this.viewer.dispatchEvent({
  283. type: 'global_dblclick',
  284. mouse: this.mouse,
  285. object: null
  286. });
  287. //}
  288. }
  289. this.needSingleClick = false//add
  290. e.preventDefault();
  291. }
  292. onMouseClick (e) {
  293. if (this.logMessages) console.log(this.constructor.name + ': onMouseClick');
  294. e.preventDefault();
  295. }
  296. dealPointerDown(e,isTouch){
  297. e.preventDefault();
  298. //重新获取一下pointer, 因点击了浏览器的按钮展开列表时 move回来不会触发onmousemove,所以pointer是旧的
  299. if(isTouch){
  300. var { camera, viewport } = this.updateTouchesInfo(e)
  301. if(this.drag){
  302. //因为触屏在按下前缺少pointermove所以要更新下
  303. this.drag.end = this.pointer.clone()
  304. }
  305. }else{
  306. var { camera, viewport } = this.getPointerInViewport(e.clientX, e.clientY )
  307. }
  308. this.dragViewport = this.hoverViewport = viewport
  309. //if(isTouch || !Potree.settings.intersectWhenHover ){
  310. if(isTouch || !this.dragViewport.view.isFlying() && !Potree.settings.intersectWhenHover && Potree.settings.editType != 'pano' ){//漫游点编辑如果拖拽前getIntersect旋转会延迟
  311. //isTouch必须更新 否则是旧的
  312. this.hoveredElements = this.getHoveredElements();
  313. let dontIntersect = false
  314. this.intersect = this.getIntersect({viewport, dontIntersect, clientX:e.clientX, clientY:e.clientY}) //更新intersect,避免在没有mousemove但flyToPano后intersect未更新。
  315. //this.intersect = this.getWholeIntersect()
  316. }
  317. if(!viewport)return //why add this?
  318. if (!this.drag) {
  319. let target = (isTouch||e.button == THREE.MOUSE.LEFT) && this.hoveredElements.find(el => (//只有左键能拖拽
  320. el.object._listeners &&
  321. el.object._listeners['drag'] &&
  322. el.object._listeners['drag'].length > 0));
  323. if (target) {
  324. this.startDragging(target.object, {location: target.point});
  325. } else {
  326. this.startDragging(null);
  327. }
  328. }
  329. this.drag.intersectStart = this.intersect;
  330. if(!isTouch || e.touches.length == 1){
  331. let consumed = false;
  332. let consume = () => { return consumed = true; };
  333. //if (this.hoveredElements.length === 0) {
  334. this.viewer.dispatchEvent($.extend(
  335. this.getEventDesc(e,isTouch),
  336. {
  337. type: 'global_mousedown'
  338. }
  339. ));
  340. for(let hovered of this.hoveredElements){
  341. let object = hovered.object;
  342. object.dispatchEvent({
  343. type: 'mousedown',
  344. viewer: this.viewer,
  345. consume: consume
  346. });
  347. if(consumed){
  348. break;
  349. }
  350. }
  351. }
  352. this.mouseDownMouse = this.mouse.clone()
  353. this.pointerDownTime = Date.now()
  354. }
  355. onMouseDown (e) {
  356. if (this.logMessages) console.log(this.constructor.name + ': onMouseDown');
  357. this.dealPointerDown(e)
  358. }
  359. /* getWholeIntersect(hoveredElements, intersectPoint){//add
  360. hoveredElements = hoveredElements || this.hoveredElements
  361. intersectPoint = intersectPoint || this.intersectPoint
  362. if(Potree.settings.intersectOnObjs && hoveredElements[0] && hoveredElements[0].object.isModel){
  363. return {//模拟点云的intersectPoint的结构写法
  364. hoveredElement : hoveredElements[0] ,
  365. location: hoveredElements[0].point,
  366. point: {normal: hoveredElements[0].face.normal },
  367. distance: hoveredElements[0].distance,
  368. object: hoveredElements[0].object
  369. }
  370. }else return intersectPoint
  371. } */
  372. getEventDesc(e,isTouch){//搜集dispatchEvent要给的一般数据
  373. let o = {
  374. viewer: this.viewer,
  375. mouse: this.mouse,
  376. pointer:this.pointer,
  377. drag :this.drag,
  378. isTouch,
  379. dragViewport : this.dragViewport,
  380. hoverViewport: this.hoverViewport,
  381. // button: isTouch ? 0 : e.button,
  382. //intersectPoint:this.intersectPoint,
  383. hoveredElement: this.hoveredElements[0],
  384. intersect: this.intersect//this.getWholeIntersect() , //可能包含mesh上的,针对融合页面
  385. }
  386. if(e){
  387. o.isAtDomElement = e.target == this.domElement
  388. }
  389. if(isTouch){
  390. o.touches = this.touches
  391. }else if(e){
  392. o.button = e.button
  393. o.buttons = e.buttons
  394. }
  395. return o;
  396. }
  397. dealPointerUp(e,isTouch){
  398. if(!this.drag){// 在canvas外mousedown
  399. return
  400. }
  401. this.drag.end.copy(this.pointer)
  402. if(isTouch && e.touches.length >= 1){
  403. return
  404. }
  405. let now = Date.now()
  406. if (this.logMessages) console.log(this.constructor.name + ': onMouseUp');
  407. e.preventDefault();
  408. let pressDistance = this.mouseDownMouse.distanceTo(this.mouse);
  409. let pressTime = now - this.pointerDownTime;
  410. let noMovement = this.drag.pointerDelta.length() == 0//this.getNormalizedDrag().length() === 0;
  411. let consumed = false;
  412. let consume = () => { return consumed = true; };
  413. this.viewer.dispatchEvent($.extend(
  414. this.getEventDesc(e,isTouch),
  415. {
  416. type: 'global_mouseup',
  417. pressDistance,
  418. consume,
  419. }
  420. ));
  421. if (this.hoveredElements.length > 0) {
  422. let hovered = this.hoveredElements
  423. .map(e => e.object)
  424. .find(e => (e._listeners && e._listeners['mouseup']));
  425. if(hovered){
  426. hovered.dispatchEvent({
  427. type: 'mouseup',
  428. viewer: this.viewer,
  429. consume: consume
  430. });
  431. }
  432. }
  433. if (this.drag) {
  434. //拖拽结束
  435. if (this.drag.object/* && e.button == THREE.MOUSE.LEFT */) {//add LEFT
  436. if (this.logMessages) console.log(`${this.constructor.name}: drop ${this.drag.object.name}`);
  437. this.drag.object.dispatchEvent($.extend(
  438. this.getEventDesc(e,isTouch),
  439. {
  440. type: 'drop',
  441. pressDistance,
  442. }
  443. ));
  444. } else {
  445. this.viewer.dispatchEvent($.extend(
  446. this.getEventDesc(e,isTouch),
  447. {
  448. type: 'global_drop',
  449. pressDistance
  450. }
  451. ));
  452. }
  453. // check for a click
  454. if(!Potree.settings.disableClick && pressDistance < Potree.config.clickMaxDragDis && pressTime<Potree.config.clickMaxPressTime && !e.unableClick){
  455. let clickElement
  456. if(this.hoveredElements){
  457. clickElement = this.hoveredElements.find(e=>e.object._listeners['click'])
  458. if(clickElement){
  459. let canceled
  460. let cancel = () => { return canceled = true; };
  461. //console.log('clickElement',clickElement)
  462. if (this.logMessages) console.log(`${this.constructor.name}: click ${clickElement.name}`);
  463. clickElement.object.dispatchEvent($.extend(
  464. this.getEventDesc(e,isTouch),
  465. {
  466. type: 'click',
  467. pressDistance ,
  468. cancel ,
  469. consume
  470. }
  471. ));
  472. if(canceled){//比如只需要右键的话,可以忽视左键的点击
  473. clickElement = null
  474. }
  475. }
  476. }
  477. let selectable
  478. if(/* !consumed && */ !this.fixSelection){
  479. if (e.button === THREE.MOUSE.LEFT) {
  480. //if (noMovement) {
  481. selectable = this.hoveredElements.find(el => el.object._listeners && el.object._listeners['select']);
  482. if (selectable) {
  483. selectable = selectable.object;
  484. if (this.isSelected(selectable)) {
  485. this.deselectAll();
  486. } else {
  487. this.deselectAll();
  488. this.toggleSelection(selectable);
  489. }
  490. consumed = true //add
  491. } else {
  492. if(this.selection.length>0)consumed = true //add 取消选择后,阻断后续
  493. this.deselectAll();
  494. }
  495. //}
  496. } else if ((e.button === THREE.MOUSE.RIGHT) /* && noMovement */) {
  497. this.deselectAll();
  498. }
  499. }
  500. let desc = this.getEventDesc(e,isTouch)
  501. if(!consumed){
  502. this.viewer.dispatchEvent($.extend(
  503. desc,
  504. {
  505. type: 'global_click',
  506. pressDistance,
  507. clickElement:clickElement/* || selectable */,
  508. consume
  509. }
  510. ));
  511. }
  512. //增加 单击:
  513. this.needSingleClick = true;
  514. consumed || setTimeout(()=>{
  515. if(this.needSingleClick){
  516. this.viewer.dispatchEvent($.extend(
  517. desc,
  518. {
  519. type: 'global_single_click',
  520. pressDistance,
  521. clickElement
  522. }
  523. ));
  524. }
  525. }, Potree.config.doubleClickTime+1)
  526. //自行执行双击:
  527. if(!consumed && now - this.lastClickTime < Potree.config.doubleClickTime){
  528. this.onDoubleClick(e)
  529. }
  530. consumed || (this.lastClickTime = now)
  531. }
  532. this.drag = null;
  533. }
  534. this.dragViewport = null
  535. }
  536. onMouseUp (e) {
  537. this.dealPointerUp( e )
  538. }
  539. getPointerInViewport(clientX, clientY, viewForceAt, pointer ){
  540. let rect = this.domElement.getBoundingClientRect();
  541. let x = clientX - rect.left;
  542. let y = clientY - rect.top;
  543. let camera
  544. let viewport
  545. pointer = pointer ||this.pointer
  546. //if(this.viewer.viewports || viewForceAt){
  547. var getDimension = (view)=>{
  548. var left = Math.ceil(this.domElement.clientWidth * view.left)
  549. , bottom = Math.ceil(this.domElement.clientHeight * view.bottom)
  550. , width = Math.ceil(this.domElement.clientWidth * view.width)
  551. , height = Math.ceil(this.domElement.clientHeight * view.height)
  552. , top = this.domElement.clientHeight - bottom - height
  553. return {left, bottom, width, height, top}
  554. }
  555. var getView = (view, left, bottom, width, height, top)=>{
  556. this.mouse.set(x-left, y - top )
  557. Utils.convertScreenPositionToNDC(pointer, this.mouse, width, height);
  558. //console.log('更新pointer2',this.pointer.toArray())
  559. camera = view.camera;
  560. viewport = view
  561. }
  562. if(viewForceAt){
  563. let {left, bottom, width, height, top} = getDimension(viewForceAt)
  564. getView(viewForceAt, left, bottom, width, height, top)
  565. }else{
  566. var length = this.viewer.viewports.length;
  567. //var getif = false
  568. for(var i=0;i<length;i++){
  569. var view = this.viewer.viewports[i];
  570. if(!view.active)continue
  571. var {left, bottom, width, height, top} = getDimension(view)
  572. if(x >= left && x <= left + width && y >= top && y <= top + height){
  573. getView(view, left, bottom, width, height, top)
  574. //getif = true
  575. break;
  576. }
  577. }
  578. }
  579. return {
  580. camera, viewport, pointer
  581. }
  582. }
  583. ifBlockedByIntersect({point, margin=0, cameraPos, pickWindowSize, pano, useDepthTex, viewport}={}){//某点是否被遮挡(不允许camera修改位置, 因为depthTex不好置换)
  584. viewport = viewport || this.hoverViewport || viewer.mainViewport
  585. let intersect = this.getIntersect({viewport, onlyGetIntersect:true, pickWindowSize, useDepthTex, point, cameraPos, pano })
  586. let cameraPos_ = (!cameraPos && pano) ? pano.position : (cameraPos||viewport.view.position)
  587. if(intersect && intersect.distance+margin <= point.distanceTo(cameraPos_)){
  588. return intersect //被遮挡
  589. }
  590. //点云模式,对没加载出的点云不准确。 尤其是需要修改相机位置时,因临时修改并不能使点云加载。
  591. }
  592. collectClosePoints(viewport, forceUpdate){//获取吸附点
  593. if(!Potree.settings.adsorption)return
  594. let point2ds = []
  595. //吸附测量线端点
  596. viewer.scene.measurements.forEach(e=>{
  597. if(this.measuring.includes(e)) return//不吸附到正在拖拽的自身
  598. point2ds.push(...e.getPointsPos2d(viewport, forceUpdate))
  599. })
  600. return point2ds
  601. }
  602. getIntersect({viewport,onlyGetIntersect, pickWindowSize, dontIntersect, usePointcloud, useDepthTex, all, highLevelCloud, cameraPos, pointSize, pointclouds, point, pano, clientX, clientY, resolution}={}){// usePointcloud:必须使用点云
  603. let intersect, intersectPoint, intersectOnModel, allElements
  604. let camera = viewport.camera
  605. let raycaster
  606. if(Potree.settings.pauseIntersect)return
  607. viewer.addTimeMark('getIntersect','start')
  608. let getByDepthTex = ()=>{
  609. let intersect
  610. if(point){
  611. let cameraPos = pano ? pano.position : camera.position
  612. let dir = new THREE.Vector3().subVectors(point, cameraPos).normalize();
  613. intersect = {dir}
  614. }else{
  615. intersect = Utils.getIntersect(camera, [viewer.images360.cube], this.pointer, raycaster)
  616. }
  617. intersectPoint = viewer.images360.depthSampler.sample(intersect, pano, !!point) //可能不准确, 因pano可能未加载depthTex
  618. if(intersectPoint && Potree.settings.depTexLocBindDataset){
  619. intersectPoint.pointcloud = ( pano || viewer.images360.currentPano).pointcloud
  620. //在全景模式下,虽然深度图上的点可能对应别的pointcloud,但因为是在当前全景图处得到的,所以即使将原本对应的点云移走,该点也不移动是有道理的。它可以永远跟着该全景图。
  621. }
  622. }
  623. let getByCloud = ()=>{
  624. let pointer, mouse, ifCenter
  625. if(point){//指定了目标点,而非只是用pointer所在位置
  626. cameraPos && camera.position.copy( cameraPos)
  627. camera.lookAt(point)
  628. camera.updateMatrixWorld()
  629. ifCenter = true
  630. //pointer = this.pointer.clone()
  631. //mouse = this.mouse.clone()
  632. //this.pointer.set(0,0) //画布中心
  633. //this.mouse.set(Math.round(viewport.resolution.x/2), Math.round(viewport.resolution.y/2))
  634. }
  635. intersectPoint = (viewport.noPointcloud || dontIntersect )? null : Utils.getMousePointCloudIntersection(
  636. viewport,
  637. this.mouse,
  638. this.pointer,
  639. camera,
  640. this.viewer,
  641. pointclouds || this.viewer.scene.pointclouds,
  642. {pickClipped: true, ifCenter, all, measuring: this.measuring.length>0 || highLevelCloud, pickWindowSize, cameraChanged: !!point,
  643. pointSize , resolution }
  644. );
  645. //恢复
  646. if(point){
  647. viewport.view.applyToCamera(camera)
  648. //this.pointer.copy(pointer)
  649. //this.mouse.copy(mouse)
  650. }
  651. }
  652. if(this.measuring.length && Potree.settings.adsorption ){//吸附
  653. let points = this.collectClosePoints(viewport)
  654. let points2 = points.filter(e=>e.trueSide && e.inSight
  655. && math.closeTo(this.mouse, e.posInViewport, Potree.config.measure.adsorptMinDis)
  656. )
  657. let disArr = points2.map(e=> e.pos.distanceToSquared(this.mouse) )
  658. let min = points2.slice().sort((a,b)=>disArr[points.indexOf(a)] - disArr[points.indexOf(b)])
  659. if(min[0]){
  660. intersect = {
  661. //hoveredElement
  662. location: min[0].pos3d,
  663. //point: {normal: allElements[0].face.normal },
  664. //normal
  665. //distance
  666. object: min[0].object,
  667. adsorption:true
  668. }
  669. console.log('找到吸附点', min[0].pos3d, min[0].object.uuid)
  670. }
  671. }
  672. if(!intersect){
  673. let canUseDepthTex = (Potree.settings.displayMode == 'showPanos' || useDepthTex)
  674. && viewer.images360.currentPano.pointcloud.hasDepthTex && viewport == viewer.mainViewport && !usePointcloud
  675. if(canUseDepthTex)getByDepthTex()
  676. else if(Potree.settings.mergeType2 && Potree.settings.displayMode == 'showPanos' && !viewer.images360.currentPano.pointcloud.isPointcloud){} //融合页面进入非点云的场景的全景模式不用pick
  677. else getByCloud()
  678. /* if(canUseDepthTex && this.measuring.length){
  679. getByDepthTex()
  680. }else{
  681. getByCloud()
  682. if(!intersectPoint && canUseDepthTex ){ //若在测量,先尝试点云,再用全景 //后来发现有深度图的点云全景visibleNode为空,pick不到的
  683. getByDepthTex()
  684. }
  685. } */
  686. //console.log(viewport.name , intersectPoint && intersectPoint.location )
  687. if(Potree.settings.intersectOnObjs && !dontIntersect){
  688. if(point){
  689. raycaster = new THREE.Raycaster()
  690. var dir = new THREE.Vector3().subVectors(point, camera.position).normalize()
  691. raycaster.set(camera.position, dir) //var origin = new THREE.Vector3(pointer.x, pointer.y, -1).unproject(camera),
  692. }
  693. allElements = this.getHoveredElements(viewer.objs.children, true, raycaster)
  694. if(allElements[0]){
  695. let normal, localNormal
  696. if(allElements[0].object.fileType == '3dgs' ){
  697. normal = allElements[0].normal
  698. }else{
  699. localNormal = allElements[0].face && allElements[0].face.normal
  700. if(localNormal){
  701. let quaternion = new THREE.Quaternion
  702. allElements[0].oriObject.matrixWorld.decompose( new THREE.Vector3, quaternion, new THREE.Vector3 )
  703. normal = localNormal.clone().applyQuaternion(quaternion)
  704. allElements[0].object.matrix.decompose( new THREE.Vector3, quaternion, new THREE.Vector3 )
  705. localNormal = normal.clone().applyQuaternion(quaternion.invert()) //改为在最外层model上无旋转时的normal
  706. }
  707. }
  708. intersectOnModel = {//模拟点云的intersectPoint的结构写法
  709. hoveredElement : allElements[0] ,
  710. location: allElements[0].point,
  711. localNormal,
  712. normal,
  713. distance: allElements[0].distance,
  714. object: allElements[0].object
  715. }
  716. }
  717. }
  718. if(intersectPoint && intersectOnModel){
  719. if(intersectPoint.distance < intersectOnModel.distance){
  720. intersect = intersectPoint
  721. }else{
  722. intersect = intersectOnModel
  723. }
  724. }else{
  725. intersect = intersectOnModel || intersectPoint
  726. }
  727. if(intersect?.normal){ //尤其是点云屋顶上的normal都指向屋内了,需要根据站位反向一下
  728. if (viewport.view.direction.angleTo(intersect.normal) < Math.PI / 2) {
  729. intersect.normal.negate()
  730. intersect.localNormal?.negate()
  731. }
  732. }
  733. }
  734. if(viewport.camera.type == 'OrthographicCamera'/* == 'mapViewport' */){
  735. let pos3d = new THREE.Vector3(this.pointer.x,this.pointer.y,-1).unproject(viewport.camera); //z:-1朝外
  736. if(!intersect){
  737. intersect = {}
  738. }
  739. intersect.orthoIntersect = pos3d.clone()
  740. }
  741. //记录全部hover到的:
  742. if(intersect){
  743. intersect.allElements = allElements
  744. intersect.pointclouds = intersectPoint ? intersectPoint.pointclouds : []
  745. }
  746. viewer.addTimeMark('getIntersect','end')
  747. //点云费时:2-15ms
  748. //深度图费时: 0.1-0.2ms
  749. /*
  750. intersect && intersect.location && intersect.location.applyMatrix4(viewer.scene.scene.matrix)//add
  751. */
  752. if(onlyGetIntersect){
  753. return intersect
  754. }
  755. if (intersect) {
  756. if(viewer.showCoordType){ //显示坐标位置时
  757. let pos = intersect.point.position.toArray()
  758. if(viewer.showCoordType == "local"){
  759. }else if(viewer.showCoordType == "lonlat"){
  760. pos = viewer.transform.lonlatToLocal.inverse(pos)
  761. }else{
  762. pos = viewer.transform.lonlatToLocal.inverse(pos)
  763. pos = viewer.transform.lonlatTo4550.forward(pos)
  764. }
  765. viewer.dispatchEvent({
  766. type : "coordinateChange", pos
  767. })
  768. }
  769. }
  770. //console.log('getIntersect', !!intersectPoint)
  771. this.intersect = intersect
  772. intersect && (this.hoverViewport.lastIntersect = intersect)
  773. return intersect
  774. }
  775. onMouseMove (e) {
  776. return this.dealPointerMove( e )
  777. }
  778. dealPointerMove(e, isTouch){
  779. if(this.interactHistory.move) return //一帧只触发一次
  780. this.interactHistory.move = 1
  781. if(isTouch){
  782. var { camera, viewport } = this.updateTouchesInfo(e)
  783. }else {
  784. var { camera, viewport } = this.getPointerInViewport(e.clientX, e.clientY, this.dragViewport)
  785. }
  786. this.hoverViewport = viewport
  787. if(!viewport)return//刚变化viewport时会找不到
  788. let isFlying = this.viewer.viewports.some(e=>e.view.isFlying()) || viewer.scene.cameraAnimations.some(c=>c.onUpdate)
  789. let intersect
  790. if(e.onlyGetIntersect || (!this.drag || this.drag.object || viewport.alignment ) ){ //没有拖拽物体,但按下鼠标了的话,不intersect。触屏的就能直接避免intersect
  791. let dontIntersect = this.drag && viewport.alignment || isFlying || !Potree.settings.intersectWhenHover // flying 时可能卡顿
  792. //console.log('dontIntersectPointcloud',dontIntersectPointcloud)
  793. intersect = this.getIntersect(Object.assign({}, e, {viewport, dontIntersect, clientX:e.clientX, clientY:e.clientY })) //数据集多的时候卡顿
  794. }
  795. if(e.onlyGetIntersect){
  796. return intersect
  797. }
  798. e.preventDefault();
  799. if (this.drag) {//有拖拽(不一定拖拽了物体, 也不一定按下了鼠标)
  800. this.drag.mouse = isTouch ? 1 : e.buttons;
  801. //add:
  802. //this.drag.pointer = this.pointer.clone();
  803. //this.drag.hoverViewport = this.hoverViewport
  804. this.drag.pointerDelta.subVectors(this.pointer, this.drag.end)
  805. this.drag.end.copy(this.pointer)
  806. let dragConsumed = false;
  807. if (this.drag.object && (e.buttons == Buttons.NONE || !this.drag.notPressMouse )){//如果是本不需要按鼠标的拖拽,但按下了鼠标,就不执行这段(改为拖拽场景,如添加测量时突然拖拽画面)
  808. if (this.logMessages) console.log(this.constructor.name + ': drag: ' + this.drag.object.name);
  809. let refused
  810. this.drag.object.dispatchEvent($.extend(
  811. this.getEventDesc(e,isTouch),
  812. {
  813. type: 'drag', //拖拽物体
  814. refuse: () => {refused = true;}
  815. }
  816. ))
  817. if(!refused)dragConsumed = true
  818. viewer.dispatchEvent('content_changed')
  819. }
  820. if(!dragConsumed){
  821. if (this.logMessages) console.log(this.constructor.name + ': drag: ');
  822. this.viewer.dispatchEvent($.extend(
  823. this.getEventDesc(e,isTouch),
  824. {
  825. type: 'global_drag', //拖拽画面
  826. //consume: () => {dragConsumed = true;}
  827. }
  828. ))
  829. }
  830. }
  831. if(!isTouch || e.touches.length == 1){
  832. if((!this.drag || this.drag.notPressMouse || Potree.settings.intersectOnObjs && this.drag.object) && !isFlying){
  833. /* let blacklist = this.drag && this.drag */
  834. let hoveredElements = this.getHoveredElements( );
  835. if(hoveredElements.length > 0){
  836. let names = hoveredElements.map(h => h.object.name).join(", ");
  837. if (this.logMessages) console.log(`${this.constructor.name}: onMouseMove; hovered: '${names}'`);
  838. }
  839. let cur = hoveredElements.find(a => a.object)
  840. let curr = cur && cur.object//hoveredElements.map(a => a.object).find(a => true);//只取第一个
  841. let prev = this.lastMouseoverElement //this.hoveredElements.map(a => a.object).find(a => true);
  842. if(curr !== prev){
  843. if(curr){
  844. if (this.logMessages) console.log(`${this.constructor.name}: mouseover: ${curr.name}`);
  845. curr.dispatchEvent({
  846. type: 'mouseover',
  847. object: curr,
  848. hoveredElement:cur
  849. });
  850. }
  851. if(prev){
  852. if (this.logMessages) console.log(`${this.constructor.name}: mouseleave: ${prev.name}`);
  853. prev.dispatchEvent({
  854. type: 'mouseleave',
  855. object: prev,
  856. });
  857. }
  858. this.lastMouseoverElement = curr
  859. viewer.dispatchEvent('content_changed')
  860. }
  861. if(curr?._listeners?.mousemove){
  862. if(curr){ //xzw改为只取第一个
  863. curr.dispatchEvent($.extend(
  864. this.getEventDesc(e),
  865. {
  866. type: 'mousemove',
  867. hoveredElement: cur
  868. }
  869. ));
  870. }
  871. }
  872. /* if(hoveredElements.length > 0){
  873. let object = hoveredElements
  874. .map(e => e.object)
  875. .find(e => (e._listeners && e._listeners['mousemove']));
  876. if(object){
  877. object.dispatchEvent($.extend(
  878. this.getEventDesc(e),
  879. {
  880. type: 'mousemove',
  881. hoveredElement: hoveredElements.find(e=>e.object == object)
  882. }
  883. ));
  884. }
  885. } */
  886. this.hoveredElements = hoveredElements
  887. }
  888. //this.intersect = this.getWholeIntersect()
  889. this.viewer.dispatchEvent($.extend(
  890. this.getEventDesc(e,isTouch),
  891. {
  892. type: 'global_mousemove',
  893. }
  894. ))
  895. this.containsMouse = true
  896. }
  897. }
  898. onMouseWheel(e){
  899. if(!this.enabled) return;
  900. if(this.logMessages) console.log(this.constructor.name + ": onMouseWheel");
  901. e.preventDefault();
  902. let delta = 0;
  903. if (e.wheelDelta !== undefined) { // WebKit / Opera / Explorer 9
  904. delta = e.wheelDelta;
  905. } else if (e.detail !== undefined) { // Firefox
  906. delta = -e.detail;
  907. }
  908. let ndelta = Math.sign(delta);
  909. // this.wheelDelta += Math.sign(delta);
  910. if(!this.hoverViewport){//调试手机版时会无
  911. var { viewport } = this.getPointerInViewport(e.clientX, e.clientY )
  912. this.hoverViewport = viewport
  913. }
  914. if (this.hoveredElement) {
  915. this.hoveredElement.object.dispatchEvent($.extend(
  916. this.getEventDesc(e,isTouch),
  917. {
  918. type: 'mousewheel',
  919. delta: ndelta,
  920. object: this.hoveredElement.object
  921. }
  922. ));
  923. } else {
  924. this.viewer.dispatchEvent($.extend(
  925. this.getEventDesc(e),
  926. {
  927. type: 'global_mousewheel',
  928. delta: ndelta,
  929. }
  930. ));
  931. }
  932. setTimeout(()=>{
  933. this.dealPointerMove(e )//add 在更新完view后重新获取intersect 和 drag
  934. },1)//只延迟1会崩溃吗
  935. }
  936. startDragging (object, args = null) {
  937. let name = object ? object.name : "no name";
  938. if (this.logMessages) console.log(`${this.constructor.name}: startDragging: '${name}'`);
  939. this.drag = {
  940. start: this.pointer.clone(),
  941. end: this.pointer.clone(),
  942. pointerDelta: new THREE.Vector2(0, 0),
  943. object: object,
  944. hoverViewport: this.hoverViewport, //会变化
  945. dragViewport: this.hoverViewport, //不变
  946. };
  947. if (args) {
  948. for (let key of Object.keys(args)) {
  949. this.drag[key] = args[key];
  950. }
  951. }
  952. if(object){
  953. object.dispatchEvent($.extend(
  954. this.getEventDesc(),
  955. {
  956. type: 'startDragging'
  957. }
  958. ));
  959. }
  960. }
  961. /* getMousePointCloudIntersection (mouse) {
  962. return Utils.getMousePointCloudIntersection(
  963. this.mouse,
  964. this.scene.getActiveCamera(),
  965. this.viewer,
  966. this.scene.pointclouds);
  967. } */
  968. toggleSelection (object) {
  969. let oldSelection = this.selection;
  970. let index = this.selection.indexOf(object);
  971. if (index === -1) {
  972. this.selection.push(object);
  973. object.dispatchEvent({
  974. type: 'select'
  975. });
  976. } else {
  977. this.selection.splice(index, 1);
  978. object.dispatchEvent({
  979. type: 'deselect'
  980. });
  981. }
  982. this.dispatchEvent({
  983. type: 'selection_changed',
  984. oldSelection: oldSelection,
  985. selection: this.selection
  986. });
  987. viewer.dispatchEvent('content_changed')
  988. }
  989. deselect(object){
  990. let oldSelection = this.selection;
  991. let index = this.selection.indexOf(object);
  992. if(index >= 0){
  993. this.selection.splice(index, 1);
  994. object.dispatchEvent({
  995. type: 'deselect'
  996. });
  997. this.dispatchEvent({
  998. type: 'selection_changed',
  999. oldSelection: oldSelection,
  1000. selection: this.selection
  1001. });
  1002. }
  1003. viewer.dispatchEvent('content_changed')
  1004. }
  1005. deselectAll () {
  1006. for (let object of this.selection) {
  1007. object.dispatchEvent({
  1008. type: 'deselect'
  1009. });
  1010. }
  1011. let oldSelection = this.selection;
  1012. if (this.selection.length > 0) {
  1013. this.selection = [];
  1014. this.dispatchEvent({
  1015. type: 'selection_changed',
  1016. oldSelection: oldSelection,
  1017. selection: this.selection
  1018. });
  1019. }
  1020. viewer.dispatchEvent('content_changed')
  1021. }
  1022. isSelected (object) {
  1023. let index = this.selection.indexOf(object);
  1024. return index !== -1;
  1025. }
  1026. registerInteractiveObject(object){
  1027. this.interactiveObjects.add(object);
  1028. }
  1029. removeInteractiveObject(object){
  1030. this.interactiveObjects.delete(object);
  1031. }
  1032. registerInteractiveScene (scene) {
  1033. let index = this.interactiveScenes.indexOf(scene);
  1034. if (index === -1) {
  1035. this.interactiveScenes.push(scene);
  1036. }
  1037. }
  1038. unregisterInteractiveScene (scene) {
  1039. let index = this.interactiveScenes.indexOf(scene);
  1040. if (index > -1) {
  1041. this.interactiveScenes.splice(index, 1);
  1042. }
  1043. }
  1044. getHoveredElement () {
  1045. let hoveredElements = this.getHoveredElements();
  1046. if (hoveredElements.length > 0) {
  1047. return hoveredElements[0];
  1048. } else {
  1049. return null;
  1050. }
  1051. }
  1052. getHoveredElements (interactables, dontCheckDis, raycaster) {
  1053. if(!interactables){
  1054. let scenes = this.hoverViewport.interactiveScenes || this.interactiveScenes.concat(this.scene);
  1055. let interactableListeners = ['mouseup', 'mousemove', 'mouseover', 'mouseleave', 'drag', 'drop', 'click', 'select', 'deselect'];
  1056. interactables = []
  1057. for (let scene of scenes) {
  1058. scene.traverseVisible(node => {//检测加了侦听的object
  1059. if (node._listeners && node.visible && !this.blacklist.has(node) ) {
  1060. let hasInteractableListener = interactableListeners.filter((e) => {
  1061. return node._listeners[e] !== undefined;
  1062. }).length > 0;
  1063. if (hasInteractableListener) {
  1064. interactables.push(node);
  1065. }
  1066. }
  1067. });
  1068. }
  1069. }else interactables = interactables.filter(e=>e.visible)
  1070. let camera = this.hoverViewport.camera
  1071. if(!raycaster){
  1072. let ray = Utils.mouseToRay(this.pointer, camera );
  1073. raycaster = new THREE.Raycaster();
  1074. raycaster.ray.set(ray.origin, ray.direction);
  1075. raycaster.camera = camera //add
  1076. }
  1077. if(camera.type == "OrthographicCamera"){//使无论多远,threshold区域都是一样宽的
  1078. raycaster.params.Line.threshold = 20/camera.zoom
  1079. }else{
  1080. raycaster.params.Line.threshold = 0.04; //相对长度
  1081. }
  1082. raycaster.params.Line2 = {threshold : browser.isMobile()?100:20 } //拓宽的lineWidth
  1083. //raycaster.layers.enableAll()//add
  1084. let layers = ['sceneObjects','mapObjects',/* 'measure', */ 'transformationTool', 'model', 'bothMapAndScene'] //设置能识别到的layers(如空间模型里只有mapViewer能识别到marker)
  1085. if(Potree.settings.mergeType2 && Potree.settings.modelSkybox && Potree.settings.displayMode == 'showPanos' && !viewer.images360.currentPano.pointcloud.hasDepthTex) layers.push('skybox')//model变成skybox了
  1086. Potree.Utils.setCameraLayers(raycaster, layers, this.hoverViewport && this.hoverViewport.extraEnableLayers)
  1087. //this.hoverViewport.beforeRender && this.hoverViewport.beforeRender()
  1088. viewer.dispatchEvent( {type:'raycaster', viewport: this.hoverViewport, raycaster, viewer:this.viewer, interactables })//add
  1089. let intersections = raycaster.intersectObjects(interactables , true, null, true); //原本是false 检测不到children
  1090. let intersectionsCopy = intersections.slice()
  1091. if(this.intersect && this.intersect.distance != void 0 && !dontCheckDis){//add
  1092. intersections = intersections.filter(e=>{
  1093. if( this.intersect.hoveredElement && this.intersect.hoveredElement.oriObject == e.object)return true
  1094. let material = e.object.material
  1095. return e.object.pickDontCheckDis ||
  1096. ( material.defines?.FadeFar == void 0 || e.distance < material.uniforms.fadeFar.value * 1.2 ) && (//在几乎完全消失的距离内
  1097. ( material.depthTest == false || material.depthWrite == false) && !material.realUseDepth //!material.depthTestWhenPick
  1098. || ( material.useDepth ? e.distance <= this.intersect.distance + material.uniforms.clipDistance.value : e.distance <= this.intersect.distance ))
  1099. //maxClipFactor是否需要考虑?
  1100. })
  1101. }
  1102. intersections = intersections.map(e=>{//add 转化为interactables
  1103. var object = e.object;
  1104. do{
  1105. if(interactables.includes(object)) {
  1106. e.oriObject = e.object;
  1107. e.object = object;
  1108. break
  1109. }
  1110. object = object.parent
  1111. }while(object)
  1112. return e
  1113. })
  1114. //add for测量线,在检测到sphere时优先选中sphere而非线
  1115. //intersections = intersections.sort(function(a,b){return b.object.renderOrder-a.object.renderOrder}) // 降序
  1116. intersections = intersections.sort(function(a,b){
  1117. let order2 = b.object.pickOrder || 0
  1118. let order1 = a.object.pickOrder || 0
  1119. return order2-order1
  1120. }) // 降序
  1121. //console.log('getHoveredElement ', intersections)
  1122. return intersections;
  1123. }
  1124. /* setScene (scene) {
  1125. this.deselectAll();
  1126. this.scene = scene;
  1127. } */
  1128. update (delta) {
  1129. }
  1130. /*getNormalizedDrag () {
  1131. if (!this.drag) {
  1132. return new THREE.Vector2(0, 0);
  1133. }
  1134. let diff = new THREE.Vector2().subVectors(this.drag.end, this.drag.start);
  1135. diff.x = diff.x / this.domElement.clientWidth;
  1136. diff.y = diff.y / this.domElement.clientHeight;
  1137. return diff;
  1138. }
  1139. getNormalizedLastDrag () {
  1140. if (!this.drag) {
  1141. return new THREE.Vector2(0, 0);
  1142. }
  1143. let mouseDelta = this.drag.mouseDelta.clone();
  1144. mouseDelta.x = mouseDelta.x / this.domElement.clientWidth;
  1145. mouseDelta.y = mouseDelta.y / this.domElement.clientHeight;
  1146. return mouseDelta;
  1147. } */
  1148. getMouseDirection(pointer) {//add
  1149. pointer = pointer || this.pointer
  1150. let camera = this.hoverViewport.camera
  1151. var t = new THREE.Vector3(pointer.x, pointer.y, -1).unproject(camera),
  1152. i = new THREE.Vector3(pointer.x, pointer.y, 1).unproject(camera);
  1153. return {origin: t, direction:i.clone().sub(t).normalize() }
  1154. }
  1155. }