InputHandlerNew.js 47 KB

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