InputHandlerNew.js 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454
  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. //恢复
  601. if(prop.pos3d){
  602. viewport.view.applyToCamera(camera)
  603. this.pointer.copy(prop.pointer)
  604. this.mouse.copy(prop.mouse)
  605. }
  606. }
  607. let canUseDepthTex = !Potree.settings.unableUseDepTexPick && (Potree.settings.displayMode == 'showPanos' || useDepthTex)
  608. && viewer.images360.currentPano.pointcloud.hasDepthTex && viewport == viewer.mainViewport && !usePointcloud
  609. if(canUseDepthTex)getByDepthTex()
  610. else getByCloud()
  611. /* if(canUseDepthTex && !this.isMeasuring){
  612. getByDepthTex()
  613. }else{
  614. getByCloud()
  615. if(!intersectPoint && canUseDepthTex ){ //若在测量,先尝试点云,再用全景 //后来发现有深度图的点云全景visibleNode为空,pick不到的
  616. getByDepthTex()
  617. }
  618. } */
  619. //console.log(viewport.name , intersectPoint && intersectPoint.location )
  620. let intersect
  621. let intersectOnModel, allElements
  622. if(Potree.settings.intersectOnObjs && !dontIntersect){
  623. if(prop.point){
  624. raycaster = new THREE.Raycaster()
  625. var dir = new THREE.Vector3().subVectors(prop.point, camera.position).normalize()
  626. raycaster.set(camera.position, dir) //var origin = new THREE.Vector3(pointer.x, pointer.y, -1).unproject(camera),
  627. }
  628. allElements = this.getHoveredElements(viewer.objs.children, true, raycaster)
  629. if(allElements[0]){
  630. intersectOnModel = {//模拟点云的intersectPoint的结构写法
  631. hoveredElement : allElements[0] ,
  632. location: allElements[0].point,
  633. //point: {normal: allElements[0].face.normal },
  634. normal: allElements[0].face && allElements[0].face.normal,
  635. distance: allElements[0].distance,
  636. object: allElements[0].object
  637. }
  638. }
  639. }
  640. if(intersectPoint && intersectOnModel){
  641. if(intersectPoint.distance < intersectOnModel.distance){
  642. intersect = intersectPoint
  643. }else{
  644. intersect = intersectOnModel
  645. }
  646. }else{
  647. intersect = intersectOnModel || intersectPoint
  648. }
  649. if(viewport.camera.type == 'OrthographicCamera'/* == 'mapViewport' */){
  650. let pos3d = new THREE.Vector3(this.pointer.x,this.pointer.y,-1).unproject(viewport.camera); //z:-1朝外
  651. if(!intersect){
  652. intersect = {}
  653. }
  654. intersect.orthoIntersect = pos3d.clone()
  655. }
  656. //记录全部hover到的:
  657. if(intersect){
  658. intersect.allElements = allElements
  659. intersect.pointclouds = intersectPoint ? intersectPoint.pointclouds : []
  660. }
  661. viewer.addTimeMark('getIntersect','end')
  662. //点云费时:2-15ms
  663. //深度图费时: 0.1-0.2ms
  664. this.viewer.dispatchEvent({type:'getIntersect', intersect})
  665. if(onlyGetIntersect){
  666. return intersect
  667. }
  668. if (intersect) {
  669. if(viewer.showCoordType){ //显示坐标位置时
  670. let pos = intersect.point.position.toArray()
  671. if(viewer.showCoordType == "local"){
  672. }else if(viewer.showCoordType == "lonlat"){
  673. pos = viewer.transform.lonlatToLocal.inverse(pos)
  674. }else{
  675. pos = viewer.transform.lonlatToLocal.inverse(pos)
  676. pos = viewer.transform.lonlatTo4550.forward(pos)
  677. }
  678. viewer.dispatchEvent({
  679. type : "coordinateChange", pos
  680. })
  681. }
  682. }
  683. //console.log('getIntersect', !!intersectPoint)
  684. this.intersect = intersect
  685. intersect && (this.hoverViewport.lastIntersect = intersect)
  686. return intersect
  687. }
  688. onMouseMove (e) {
  689. return this.dealPointerMove( e )
  690. }
  691. dealPointerMove(e, isTouch){
  692. if(this.interactHistory.move) return //一帧只触发一次
  693. this.interactHistory.move = 1
  694. if(isTouch){
  695. var { camera, viewport } = this.updateTouchesInfo(e)
  696. }else {
  697. var { camera, viewport } = this.getPointerInViewport(e.clientX, e.clientY, this.dragViewport)
  698. }
  699. this.hoverViewport = viewport
  700. if(!viewport)return//刚变化viewport时会找不到
  701. let isFlying = this.viewer.viewports.some(e=>e.view.isFlying()) || viewer.scene.cameraAnimations.some(c=>c.onUpdate)
  702. let intersect
  703. if(e.onlyGetIntersect || Potree.settings.intersectWhenHover && (!this.drag || this.drag.object || viewport.alignment ) ){ //没有拖拽物体,但按下鼠标了的话,不intersect。触屏的就能直接避免intersect
  704. let dontIntersect = this.drag && viewport.alignment || isFlying /* viewer.images360.flying */ // flying 时可能卡顿
  705. //console.log('dontIntersectPointcloud',dontIntersectPointcloud)
  706. intersect = this.getIntersect(viewport, e.onlyGetIntersect, e.pickWindowSize, !!dontIntersect, e.whichPointcloud || e.usePointcloud || this.drag) //深度图不准,尽量用点云
  707. //console.log('intersectPoint', intersectPoint)
  708. }
  709. if(e.onlyGetIntersect){
  710. /* if(Potree.settings.intersectOnObjs){
  711. let hoveredElements = this.getHoveredElements() //应该不用发送mouseover事件吧
  712. let intersect = this.getWholeIntersect(hoveredElements, intersectPoint)
  713. return intersect
  714. }
  715. return intersectPoint */
  716. return intersect
  717. }
  718. e.preventDefault();
  719. /* if(intersectPoint && intersectPoint.pointcloud){
  720. console.log(intersectPoint.pointcloud.name)
  721. } */
  722. if (this.drag) {//有拖拽(不一定拖拽了物体, 也不一定按下了鼠标)
  723. this.drag.mouse = isTouch ? 1 : e.buttons;
  724. //add:
  725. //this.drag.pointer = this.pointer.clone();
  726. //this.drag.hoverViewport = this.hoverViewport
  727. this.drag.pointerDelta.subVectors(this.pointer, this.drag.end)
  728. this.drag.end.copy(this.pointer)
  729. if (this.drag.object && (e.buttons == Buttons.NONE || !this.drag.notPressMouse )){//如果是本不需要按鼠标的拖拽,但按下了鼠标,就不执行这段(改为拖拽场景,如添加测量时突然拖拽画面)
  730. if (this.logMessages) console.log(this.constructor.name + ': drag: ' + this.drag.object.name);
  731. this.drag.object.dispatchEvent($.extend(
  732. this.getEventDesc(e,isTouch),
  733. {
  734. type: 'drag', //拖拽物体
  735. }
  736. ))
  737. viewer.dispatchEvent('content_changed')
  738. } else {
  739. if (this.logMessages) console.log(this.constructor.name + ': drag: ');
  740. let dragConsumed = false;
  741. this.viewer.dispatchEvent($.extend(
  742. this.getEventDesc(e,isTouch),
  743. {
  744. type: 'global_drag', //拖拽画面
  745. consume: () => {dragConsumed = true;}
  746. }
  747. ))
  748. }
  749. }
  750. if(!isTouch || e.touches.length == 1){
  751. if((!this.drag || this.drag.notPressMouse || Potree.settings.intersectOnObjs && this.drag.object) && !isFlying){
  752. /* let blacklist = this.drag && this.drag */
  753. let hoveredElements = this.getHoveredElements( );
  754. if(hoveredElements.length > 0){
  755. let names = hoveredElements.map(h => h.object.name).join(", ");
  756. if (this.logMessages) console.log(`${this.constructor.name}: onMouseMove; hovered: '${names}'`);
  757. }
  758. let curr = hoveredElements.map(a => a.object).find(a => true);//只取第一个
  759. let prev = this.lastMouseoverElement //this.hoveredElements.map(a => a.object).find(a => true);
  760. if(curr !== prev){
  761. if(curr){
  762. if (this.logMessages) console.log(`${this.constructor.name}: mouseover: ${curr.name}`);
  763. curr.dispatchEvent({
  764. type: 'mouseover',
  765. object: curr,
  766. });
  767. }
  768. if(prev){
  769. if (this.logMessages) console.log(`${this.constructor.name}: mouseleave: ${prev.name}`);
  770. prev.dispatchEvent({
  771. type: 'mouseleave',
  772. object: prev,
  773. });
  774. }
  775. this.lastMouseoverElement = curr
  776. viewer.dispatchEvent('content_changed')
  777. }
  778. if(hoveredElements.length > 0){
  779. let object = hoveredElements
  780. .map(e => e.object)
  781. .find(e => (e._listeners && e._listeners['mousemove']));
  782. if(object){
  783. object.dispatchEvent({
  784. type: 'mousemove',
  785. object: object
  786. });
  787. }
  788. }
  789. this.hoveredElements = hoveredElements
  790. }
  791. //this.intersect = this.getWholeIntersect()
  792. this.viewer.dispatchEvent($.extend(
  793. this.getEventDesc(e,isTouch),
  794. {
  795. type: 'global_mousemove',
  796. }
  797. ))
  798. }
  799. }
  800. onMouseWheel(e){
  801. if(!this.enabled) return;
  802. if(this.logMessages) console.log(this.constructor.name + ": onMouseWheel");
  803. e.preventDefault();
  804. let delta = 0;
  805. if (e.wheelDelta !== undefined) { // WebKit / Opera / Explorer 9
  806. delta = e.wheelDelta;
  807. } else if (e.detail !== undefined) { // Firefox
  808. delta = -e.detail;
  809. }
  810. let ndelta = Math.sign(delta);
  811. // this.wheelDelta += Math.sign(delta);
  812. if(!this.hoverViewport){//调试手机版时会无
  813. var { viewport } = this.getPointerInViewport(e.clientX, e.clientY )
  814. this.hoverViewport = viewport
  815. }
  816. if (this.hoveredElement) {
  817. this.hoveredElement.object.dispatchEvent($.extend(
  818. this.getEventDesc(e,isTouch),
  819. {
  820. type: 'mousewheel',
  821. delta: ndelta,
  822. object: this.hoveredElement.object
  823. }
  824. ));
  825. } else {
  826. this.viewer.dispatchEvent($.extend(
  827. this.getEventDesc(e),
  828. {
  829. type: 'global_mousewheel',
  830. delta: ndelta,
  831. }
  832. ));
  833. }
  834. setTimeout(()=>{
  835. this.dealPointerMove(e )//add 在更新完view后重新获取intersect 和 drag
  836. },1)//只延迟1会崩溃吗
  837. }
  838. startDragging (object, args = null) {
  839. let name = object ? object.name : "no name";
  840. if (this.logMessages) console.log(`${this.constructor.name}: startDragging: '${name}'`);
  841. this.drag = {
  842. start: this.pointer.clone(),
  843. end: this.pointer.clone(),
  844. pointerDelta: new THREE.Vector2(0, 0),
  845. object: object,
  846. hoverViewport: this.hoverViewport, //会变化
  847. dragViewport: this.hoverViewport, //不变
  848. };
  849. if (args) {
  850. for (let key of Object.keys(args)) {
  851. this.drag[key] = args[key];
  852. }
  853. }
  854. if(object){
  855. object.dispatchEvent($.extend(
  856. this.getEventDesc(),
  857. {
  858. type: 'startDragging'
  859. }
  860. ));
  861. }
  862. }
  863. /* getMousePointCloudIntersection (mouse) {
  864. return Utils.getMousePointCloudIntersection(
  865. this.mouse,
  866. this.scene.getActiveCamera(),
  867. this.viewer,
  868. this.scene.pointclouds);
  869. } */
  870. toggleSelection (object) {
  871. let oldSelection = this.selection;
  872. let index = this.selection.indexOf(object);
  873. if (index === -1) {
  874. this.selection.push(object);
  875. object.dispatchEvent({
  876. type: 'select'
  877. });
  878. } else {
  879. this.selection.splice(index, 1);
  880. object.dispatchEvent({
  881. type: 'deselect'
  882. });
  883. }
  884. this.dispatchEvent({
  885. type: 'selection_changed',
  886. oldSelection: oldSelection,
  887. selection: this.selection
  888. });
  889. viewer.dispatchEvent('content_changed')
  890. }
  891. deselect(object){
  892. let oldSelection = this.selection;
  893. let index = this.selection.indexOf(object);
  894. if(index >= 0){
  895. this.selection.splice(index, 1);
  896. object.dispatchEvent({
  897. type: 'deselect'
  898. });
  899. this.dispatchEvent({
  900. type: 'selection_changed',
  901. oldSelection: oldSelection,
  902. selection: this.selection
  903. });
  904. }
  905. viewer.dispatchEvent('content_changed')
  906. }
  907. deselectAll () {
  908. for (let object of this.selection) {
  909. object.dispatchEvent({
  910. type: 'deselect'
  911. });
  912. }
  913. let oldSelection = this.selection;
  914. if (this.selection.length > 0) {
  915. this.selection = [];
  916. this.dispatchEvent({
  917. type: 'selection_changed',
  918. oldSelection: oldSelection,
  919. selection: this.selection
  920. });
  921. }
  922. viewer.dispatchEvent('content_changed')
  923. }
  924. isSelected (object) {
  925. let index = this.selection.indexOf(object);
  926. return index !== -1;
  927. }
  928. registerInteractiveObject(object){
  929. this.interactiveObjects.add(object);
  930. }
  931. removeInteractiveObject(object){
  932. this.interactiveObjects.delete(object);
  933. }
  934. registerInteractiveScene (scene) {
  935. let index = this.interactiveScenes.indexOf(scene);
  936. if (index === -1) {
  937. this.interactiveScenes.push(scene);
  938. }
  939. }
  940. unregisterInteractiveScene (scene) {
  941. let index = this.interactiveScenes.indexOf(scene);
  942. if (index > -1) {
  943. this.interactiveScenes.splice(index, 1);
  944. }
  945. }
  946. getHoveredElement () {
  947. let hoveredElements = this.getHoveredElements();
  948. if (hoveredElements.length > 0) {
  949. return hoveredElements[0];
  950. } else {
  951. return null;
  952. }
  953. }
  954. getHoveredElements (interactables, dontCheckDis, raycaster) {
  955. if(!interactables){
  956. let scenes = this.hoverViewport.interactiveScenes || this.interactiveScenes.concat(this.scene);
  957. let interactableListeners = ['mouseup', 'mousemove', 'mouseover', 'mouseleave', 'drag', 'drop', 'click', 'select', 'deselect'];
  958. interactables = []
  959. for (let scene of scenes) {
  960. scene.traverseVisible(node => {//检测加了侦听的object
  961. if (node._listeners && node.visible && !this.blacklist.has(node) ) {
  962. let hasInteractableListener = interactableListeners.filter((e) => {
  963. return node._listeners[e] !== undefined;
  964. }).length > 0;
  965. if (hasInteractableListener) {
  966. interactables.push(node);
  967. }
  968. }
  969. });
  970. }
  971. }
  972. let camera = this.hoverViewport.camera
  973. if(!raycaster){
  974. let ray = Utils.mouseToRay(this.pointer, camera );
  975. raycaster = new THREE.Raycaster();
  976. raycaster.ray.set(ray.origin, ray.direction);
  977. raycaster.camera = camera //add
  978. }
  979. if(camera.type == "OrthographicCamera"){//使无论多远,threshold区域都是一样宽的
  980. raycaster.params.Line.threshold = 20/camera.zoom
  981. }else{
  982. raycaster.params.Line.threshold = 0.04; //相对长度
  983. }
  984. raycaster.params.Line2 = {threshold :20 } //拓宽的lineWidth
  985. //raycaster.layers.enableAll()//add
  986. Potree.Utils.setCameraLayers(raycaster, //设置能识别到的layers(如空间模型里只有mapViewer能识别到marker)
  987. ['sceneObjects','mapObjects','measure', 'transformationTool', 'model'],
  988. this.hoverViewport && this.hoverViewport.extraEnableLayers
  989. )
  990. //this.hoverViewport.beforeRender && this.hoverViewport.beforeRender()
  991. viewer.dispatchEvent( {type:'raycaster', viewport: this.hoverViewport})//add
  992. let intersections = raycaster.intersectObjects(interactables.filter(o => o.visible), true, null, true); //原本是false 检测不到children
  993. let intersectionsCopy = intersections.slice()
  994. if(this.intersect && this.intersect.distance != void 0 && !dontCheckDis){//add
  995. intersections = intersections.filter(e=>{
  996. let material = e.object.material
  997. return e.object.pickDontCheckDis || ( material.depthTest == false || material.depthWrite == false) && !material.realUseDepth //!material.depthTestWhenPick
  998. || ( material.useDepth ? e.distance < this.intersect.distance + material.uniforms.occlusionDistance.value : e.distance < this.intersect.distance )
  999. })
  1000. }
  1001. intersections = intersections.map(e=>{//add 转化为interactables
  1002. var object = e.object;
  1003. do{
  1004. if(interactables.includes(object)) {
  1005. e.oriObject = e.object;
  1006. e.object = object;
  1007. break
  1008. }
  1009. object = object.parent
  1010. }while(object)
  1011. return e
  1012. })
  1013. //add for测量线,在检测到sphere时优先选中sphere而非线
  1014. //intersections = intersections.sort(function(a,b){return b.object.renderOrder-a.object.renderOrder}) // 降序
  1015. intersections = intersections.sort(function(a,b){
  1016. let order2 = b.object.pickOrder || 0
  1017. let order1 = a.object.pickOrder || 0
  1018. return order2-order1
  1019. }) // 降序
  1020. /* if(intersections.length == 0){
  1021. console.log('no')
  1022. } */
  1023. //console.log('getHoveredElement ', intersections)
  1024. return intersections;
  1025. }
  1026. /* setScene (scene) {
  1027. this.deselectAll();
  1028. this.scene = scene;
  1029. } */
  1030. update (delta) {
  1031. }
  1032. /*getNormalizedDrag () {
  1033. if (!this.drag) {
  1034. return new THREE.Vector2(0, 0);
  1035. }
  1036. let diff = new THREE.Vector2().subVectors(this.drag.end, this.drag.start);
  1037. diff.x = diff.x / this.domElement.clientWidth;
  1038. diff.y = diff.y / this.domElement.clientHeight;
  1039. return diff;
  1040. }
  1041. getNormalizedLastDrag () {
  1042. if (!this.drag) {
  1043. return new THREE.Vector2(0, 0);
  1044. }
  1045. let mouseDelta = this.drag.mouseDelta.clone();
  1046. mouseDelta.x = mouseDelta.x / this.domElement.clientWidth;
  1047. mouseDelta.y = mouseDelta.y / this.domElement.clientHeight;
  1048. return mouseDelta;
  1049. } */
  1050. getMouseDirection(pointer) {//add
  1051. pointer = pointer || this.pointer
  1052. let camera = this.hoverViewport.camera
  1053. var t = new THREE.Vector3(pointer.x, pointer.y, -1).unproject(camera),
  1054. i = new THREE.Vector3(pointer.x, pointer.y, 1).unproject(camera);
  1055. return {origin: t, direction:i.clone().sub(t).normalize() }
  1056. }
  1057. }