InputHandlerNew.js 47 KB

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