XBreathPointManager.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. import XStaticMesh from "./XStaticMesh.js"
  2. import EMeshType from "./enum/EMeshType.js"
  3. import BreathPoint from "./BreathPoint.js"
  4. import Logger from "./Logger.js"
  5. import XBreathPointError from "./Error/XBreathPointError.js"
  6. const logger = new Logger('XBreathPointManager')
  7. export default class XBreathPointManager {
  8. constructor(e) {
  9. E(this, "_scene");
  10. E(this, "materialMap", new Map);
  11. E(this, "breathPoints", new Map);
  12. E(this, "_sceneManager");
  13. E(this, "_allIds", new Set);
  14. E(this, "_loopBPKeys", []);
  15. E(this, "addBreathPoint", async info=>{
  16. const t = [{
  17. // url: "https://static.xverse.cn/qqktv/texture.png"
  18. url: "./assets/textures/breathPoint/texture.png"
  19. }];
  20. if (t.length <= 0) {
  21. logger.warn("[Engine] BreathPoint get texture list error: textureList.length <= 0"),
  22. new XBreathPointError("[Engine] BreathPoint get texture list error!");
  23. return
  24. }
  25. const r = t[0]
  26. , {
  27. id, spriteSheet=r.url, spriteWidthNumber=20, spriteHeightNumber=1, position, rotation={ pitch: -90, yaw: 270, roll: 0 },
  28. size=.6, width=-1, height=-1, fps=30, billboardMode=!1, forceLeaveGround=!1, type="default", lifeTime=-1, backfaceculling=!0,
  29. maxVisibleRegion=-1, skinInfo="default"
  30. } = info;
  31. if (this.breathPoints.get(id)) {
  32. logger.warn("[Engine] Cannot add breathPoint with an existing id: [" + id + "]"),
  33. new XBreathPointError("[Engine] Cannot add breathPoint with an existing id: [" + id + "]");
  34. return
  35. }
  36. if (forceLeaveGround) {
  37. const I = this.castRay(new BABYLON.Vector3(position.x, position.y, position.z)) * scaleFromUE4toXverse;
  38. I != 0 ? position.z = position.z - I + 1 : position.z = position.z + 1
  39. }
  40. let mat;
  41. if (this.materialMap.get(type)) {
  42. const I = this.materialMap.get(type);
  43. I.count = I.count + 1,
  44. mat = I.mat
  45. } else {
  46. const texture = new BABYLON.Texture(spriteSheet, this._scene, !0, !0, BABYLON.Texture.BILINEAR_SAMPLINGMODE, null, ()=>{
  47. logger.error("[Engine] Breathpoint create texture error."),
  48. new XBreathPointError("[Engine] Breathpoint create texture error.")
  49. } ,null, !0);
  50. texture.name = "TexBreathPoint_" + id,
  51. mat = new BABYLON.StandardMaterial(`MaterialBreathPoint_${id}`,this._scene),
  52. mat.alpha = 1,
  53. mat.emissiveTexture = texture,
  54. mat.backFaceCulling = backfaceculling,
  55. mat.diffuseTexture = texture,
  56. mat.diffuseTexture.hasAlpha = !0,
  57. mat.useAlphaFromDiffuseTexture = !0,
  58. this.materialMap.set(type, {
  59. mat,
  60. count: 1,
  61. lastRenderTime: Date.now(),
  62. fps,
  63. spriteWidthNumber,
  64. spriteHeightNumber,
  65. spriteSheet,
  66. texture
  67. })
  68. }
  69. const faceUV = new Array(6);
  70. for (let i = 0; i < 6; i++) faceUV[i] = new BABYLON.Vector4(0,0,0,0);
  71. faceUV[0] = new BABYLON.Vector4(0, 0, 1 / spriteWidthNumber, 1 / spriteHeightNumber),
  72. faceUV[1] = new BABYLON.Vector4(0, 0, 1 / spriteWidthNumber, 1 / spriteHeightNumber);
  73. let options = {};
  74. width > 0 && height > 0 ? options = {
  75. width,
  76. height,
  77. depth: .01,
  78. faceUV
  79. } : options = {
  80. size,
  81. depth: .01,
  82. faceUV
  83. };
  84. const mesh = BABYLON.MeshBuilder.CreateBox(id, options, this._scene);
  85. mesh.material = mat;
  86. const xMesh = new XStaticMesh({
  87. id,
  88. mesh,
  89. xtype: EMeshType.XBreathPoint,
  90. skinInfo
  91. });
  92. let rota = rotation;
  93. billboardMode && (
  94. mesh.billboardMode = BABYLON.Mesh.BILLBOARDMODE_ALL,
  95. xMesh.allowMove(),
  96. rota = {
  97. pitch: 0,
  98. yaw: 270,
  99. roll: 0
  100. }
  101. );
  102. const breathPoint = new BreathPoint({
  103. type,
  104. mesh: xMesh,
  105. id,
  106. position,
  107. rotation: rota,
  108. mat,
  109. maxVisibleRegion,
  110. scene: this._scene,
  111. skinInfo
  112. });
  113. this.breathPoints.set(id, breathPoint),
  114. this._allIds.add(id),
  115. lifeTime > 0 && setTimeout(()=>{
  116. this.clearBreathPoints(id)
  117. }, lifeTime * 1e3)
  118. });
  119. E(this, "reg_breathpoint_update", ()=>{
  120. const e = new Date().getTime();
  121. if (this.materialMap != null)
  122. for (const [t,r] of this.materialMap)
  123. e - r.lastRenderTime > 1e3 / r.fps && (r.lastRenderTime = e,
  124. Math.abs(r.mat.diffuseTexture.uOffset - (1 - 1 / r.spriteWidthNumber)) < 1e-6 ? (r.mat.diffuseTexture.uOffset = 0,
  125. Math.abs(r.mat.diffuseTexture.vOffset - (1 - 1 / r.spriteHeightNumber)) < 1e-6 ? r.mat.diffuseTexture.vOffset = 0 : r.mat.diffuseTexture.vOffset += 1 / r.spriteHeightNumber) : r.mat.diffuseTexture.uOffset += 1 / r.spriteWidthNumber)
  126. }
  127. );
  128. E(this, "reg_breathpoint_autovisible", ()=>{
  129. if (this._scene.getFrameId() % 2 == 0)
  130. if (this._loopBPKeys.length == 0)
  131. this._loopBPKeys = Array.from(this._allIds);
  132. else {
  133. const e = this._getMainPlayerPosition();
  134. for (let t = 0; t < 5 && this._loopBPKeys.length > 0; ++t) {
  135. const r = this._loopBPKeys.pop();
  136. if (r != null) {
  137. const n = this.getBreathPoint(r);
  138. if (n != null && n.maxvisibleregion >= 0 && n.mesh.visibility == 1) {
  139. const o = n.mesh.position;
  140. calcDistance3DVector(e, o) >= n.maxvisibleregion ? n == null || n.removeFromScene() : n == null || n.addToScene()
  141. }
  142. }
  143. }
  144. }
  145. }
  146. );
  147. this._sceneManager = e,
  148. this._scene = e.Scene,
  149. this._scene.registerBeforeRender(this.reg_breathpoint_update),
  150. this._scene.registerBeforeRender(this.reg_breathpoint_autovisible)
  151. }
  152. setAllBreathPointVisibility(e) {
  153. for (const [t,r] of this.breathPoints.entries())
  154. r.toggleVisibility(e)
  155. }
  156. toggleBPVisibilityBySkinInfo(e, t) {
  157. for (const [r,n] of this.breathPoints.entries())
  158. n.skinInfo == e && n.toggleVisibility(t)
  159. }
  160. toggleBPVisibilityById(e, t) {
  161. const r = this.getBreathPoint(e);
  162. r != null && r.toggleVisibility(t)
  163. }
  164. getBreathPointBySkinInfo(e) {
  165. const t = [];
  166. for (const [r,n] of this.breathPoints.entries())
  167. n.skinInfo == e && t.push(n);
  168. return t
  169. }
  170. getAllBreathPoint() {
  171. return this.breathPoints
  172. }
  173. getBreathPoint(e) {
  174. return this.breathPoints.get(e)
  175. }
  176. delete(e) {
  177. const t = this.breathPoints.get(e);
  178. if (t != null) {
  179. t.dispose(),
  180. this._allIds.delete(e);
  181. const r = this.materialMap.get(t._type);
  182. r != null && (r.count = r.count - 1,
  183. r.count <= 0 && (r.count = 0,
  184. r.texture.dispose(),
  185. r.mat.dispose(!0, !0),
  186. this.materialMap.delete(t._type))),
  187. this.breathPoints.delete(e)
  188. }
  189. }
  190. castRay(e) {
  191. var s;
  192. e = ue4Position2Xverse({
  193. x: e.x,
  194. y: e.y,
  195. z: e.z
  196. });
  197. const t = new BABYLON.Vector3(0,-1,0)
  198. , r = new BABYLON.Ray(e,t,length)
  199. , n = []
  200. , o = (s = this._sceneManager) == null ? void 0 : s.getGround({
  201. x: e.x,
  202. y: e.y,
  203. z: e.z
  204. });
  205. let a = r.intersectsMeshes(o);
  206. if (a.length > 0) {
  207. const l = a[0];
  208. if (l && l.pickedMesh) {
  209. const u = l.distance;
  210. t.y = 1;
  211. const c = r.intersectsMeshes(n);
  212. let h = 1e8;
  213. if (c.length > 0) {
  214. const f = c[0];
  215. return f && f.pickedMesh && (h = -f.distance),
  216. h == 1e8 ? u : Math.abs(h) < Math.abs(u) ? h : u
  217. }
  218. }
  219. } else if (t.y = 1,
  220. a = r.intersectsMeshes(n),
  221. a.length > 0) {
  222. const l = a[0];
  223. if (l && l.pickedMesh)
  224. return l.distance
  225. }
  226. return 0
  227. }
  228. changePickable(e) {
  229. for (const [t,r] of this.breathPoints.entries())
  230. r.changePickable(e)
  231. }
  232. clearBreathPoints(e) {
  233. logger.info(`[Engine] clearBreathPoints: ${e}`);
  234. for (const [t,r] of this.breathPoints.entries())
  235. (r._type == e || r._id == e) && this.delete(r._id)
  236. }
  237. clearBreathPointsBySkinInfo(e) {
  238. logger.info(`[Engine] clearBreathPointsBySkinInfo: ${e}`);
  239. for (const [t,r] of this.breathPoints.entries())
  240. r.skinInfo == e && this.delete(r._id)
  241. }
  242. clearAllBreathPoints() {
  243. logger.info("[Engine] ClearAllBreathPoints");
  244. for (const [e,t] of this.breathPoints.entries())
  245. this.delete(t._id)
  246. }
  247. _getMainPlayerPosition() {
  248. var r;
  249. const e = this._sceneManager.cameraComponent.MainCamera.position
  250. , t = this._sceneManager.avatarComponent.getMainAvatar();
  251. if (t != null && t != null) {
  252. const n = (r = t == null ? void 0 : t.rootNode) == null ? void 0 : r.position;
  253. if (n != null)
  254. return n
  255. }
  256. return e
  257. }
  258. changeBreathPointPose(e, t, r) {
  259. const n = new BABYLON.Vector3(e.position.x,e.position.y,e.position.z);
  260. if (this.breathPoints.get(r) != null) {
  261. logger.info(`[Engine] changeBreathPointPose, id:${r}`);
  262. const o = this.breathPoints.get(r)
  263. , a = o.mesh.position;
  264. let s = a.subtract(n);
  265. s = BABYLON.Vector3.Normalize(s);
  266. const l = BABYLON.Vector3.Distance(a, n)
  267. , u = new Ray(n,s,l)
  268. , c = this._scene.multiPickWithRay(u);
  269. if (c) {
  270. for (let h = 0; h < c.length; h++)
  271. if (c[h].pickedMesh != null && t.mesh.name.indexOf(c[h].pickedMesh.name) >= 0) {
  272. const f = c[h].pickedPoint;
  273. o.mesh.position = n.add(f.subtract(n).scale(.99)),
  274. this.breathPoints.set(r, o)
  275. }
  276. }
  277. } else
  278. logger.warn(`[Engine] changeBreathPointPose, id:${r} is not existing!`)
  279. }
  280. }