XAvatarBillboardComponent.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. import EMeshType from "./enum/EMeshType.js"
  2. import BillboardStatus from "./enum/BillboardStatus.js"
  3. import Logger from "./Logger.js"
  4. const logger = new Logger('CharacterBillboardComponent')
  5. export default class XAvatarBillboardComponent {
  6. constructor(e) {
  7. E(this, "_nickName", "");
  8. E(this, "_words", "");
  9. E(this, "_isNameVisible", !0);
  10. E(this, "_isBubbleVisible", !0);
  11. E(this, "_isGiftButtonsVisible", !1);
  12. E(this, "withinVisualRange", !1);
  13. E(this, "_bubble");
  14. E(this, "_nameBoard");
  15. E(this, "_giftButtons", new Map);
  16. E(this, "_buttonTex", new Map);
  17. E(this, "_nameLinesLimit", 2);
  18. E(this, "_nameLengthPerLine", 16);
  19. E(this, "_scene");
  20. E(this, "_pickBbox", null);
  21. E(this, "bbox");
  22. E(this, "_height", .26);
  23. E(this, "_attachmentObservers", new Map);
  24. E(this, "attachToAvatar", (e,t,r=!1,n={
  25. x: 0,
  26. y: 0,
  27. z: 0
  28. },o=!1,a,s)=>{
  29. const l = e.rootNode;
  30. if (this.bbox || e.getBbox(),
  31. t && l) {
  32. const u = a || t.uniqueId;
  33. let c = this._attachmentObservers.get(u);
  34. if (c)
  35. if (o)
  36. this._scene.onBeforeRenderObservable.remove(c),
  37. this._attachmentObservers.delete(u);
  38. else
  39. return;
  40. const h = ue4Position2Xverse(n);
  41. r ? (t.setParent(l),
  42. t.position = h) : (c = this._scene.onBeforeRenderObservable.add(()=>{
  43. let f = 0;
  44. s ? (f = e.rootNode.rotation.y / Math.PI * 180 + 90,
  45. e.rootNode.rotation.y && (t.rotation.y = e.rootNode.rotation.y)) : f = e.avatarManager.sceneManager.cameraComponent.getCameraPose().rotation.yaw,
  46. f || (f = 0);
  47. const d = new BABYLON.Vector3(0,this._height,0);
  48. e.controller && e.controller.activeAnimation() && e.controller.activeAnimation().animatables[0] && (this._height = d.y = (e.controller.activeAnimation().animatables[0].target.position.y * .01 - .66) * e.scale),
  49. d.y < .07 * e.scale && (d.y = 0),
  50. t.position.x = l.position.x + h.x * Math.sin(f * Math.PI / 180) + h.z * Math.cos(f * Math.PI / 180),
  51. t.position.z = l.position.z + h.x * Math.cos(f * Math.PI / 180) - h.z * Math.sin(f * Math.PI / 180),
  52. t.position.y = l.position.y + this.bbox.maximum.y + h.y + d.y
  53. }
  54. ),
  55. this._attachmentObservers.set(u, c))
  56. } else
  57. logger.error("avatar or attachment not found!")
  58. }
  59. );
  60. E(this, "detachFromAvatar", (e,t,r=!1)=>{
  61. const n = this._attachmentObservers.get(t.uniqueId);
  62. n && this._scene.onBeforeRenderObservable.remove(n),
  63. e.rootNode ? (t.setEnabled(!1),
  64. t.parent = null,
  65. r && t.dispose()) : logger.error("avatar not found!")
  66. }
  67. );
  68. E(this, "getBbox", (e,t={})=>{
  69. const {isConst: r=!1, changeWithAvatar: n=!1} = t;
  70. let {localCenter: o={
  71. x: 0,
  72. y: 0,
  73. z: 75
  74. }, width: a=1.32, height: s=1.5, depth: l=.44} = t;
  75. if (n) {
  76. const u = e.scale;
  77. o = {
  78. x: o.x * u,
  79. y: o.y * u,
  80. z: o.z * u
  81. },
  82. a *= u,
  83. s *= u,
  84. l *= u
  85. }
  86. if (e.rootNode) {
  87. let u = new BABYLON.Vector3(0,0,0)
  88. , c = new BABYLON.Vector3(0,0,0);
  89. if (r) {
  90. const f = ue4Position2Xverse(o);
  91. u = u.add(f.add(new BABYLON.Vector3(-a / 2,-s / 2,-l / 2))),
  92. c = c.add(f.add(new BABYLON.Vector3(a / 2,s / 2,l / 2)))
  93. } else if (u = u.add(new BABYLON.Vector3(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY)),
  94. c = c.add(new BABYLON.Vector3(Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY)),
  95. e.isRender) {
  96. e.rootNode.getChildMeshes().forEach(_=>{
  97. const g = _.getBoundingInfo().boundingBox.minimum
  98. , m = _.getBoundingInfo().boundingBox.maximum;
  99. u.x = Math.min(u.x, g.x),
  100. c.x = Math.max(c.x, m.x),
  101. u.y = Math.min(u.y, g.y),
  102. c.y = Math.max(c.y, m.y),
  103. u.z = Math.min(u.z, g.z),
  104. c.z = Math.max(c.z, m.z)
  105. }
  106. );
  107. const f = c.x - u.x
  108. , d = c.z - u.z;
  109. u.x -= e.scale * f / 2,
  110. c.x += e.scale * f / 2,
  111. c.y *= e.scale,
  112. u.z -= e.scale * d / 2,
  113. c.z += e.scale * d / 2
  114. } else {
  115. const f = e.avatarManager.getMainAvatar();
  116. f && f.bbComponent.bbox && (u.x = f.bbComponent.bbox.minimum.x,
  117. c.x = f.bbComponent.bbox.maximum.x,
  118. u.y = f.bbComponent.bbox.minimum.y,
  119. c.y = f.bbComponent.bbox.maximum.y,
  120. u.z = f.bbComponent.bbox.minimum.z,
  121. c.z = f.bbComponent.bbox.maximum.z)
  122. }
  123. const h = e.rootNode.computeWorldMatrix(!0);
  124. if (this.bbox ? this.bbox.reConstruct(u, c, h) : this.bbox = new BABYLON.BoundingBox(u,c,h),
  125. this._pickBbox == null) {
  126. const f = this.createPickBoundingbox(e, this.bbox);
  127. this.attachToAvatar(e, f.data, !1, {
  128. x: 0,
  129. y: 0,
  130. z: 0
  131. }, !1, "pickbox"),
  132. this._pickBbox = f
  133. }
  134. } else
  135. logger.error("avatar not found!")
  136. }
  137. );
  138. this._scene = e
  139. }
  140. get isNameVisible() {
  141. return this._isNameVisible
  142. }
  143. get isBubbleVisible() {
  144. return this._isBubbleVisible
  145. }
  146. get isGiftButtonsVisible() {
  147. return this._isGiftButtonsVisible
  148. }
  149. get words() {
  150. return this._words
  151. }
  152. get nickName() {
  153. return this._nickName
  154. }
  155. get giftButtons() {
  156. return this._giftButtons
  157. }
  158. get bubble() {
  159. return this._bubble
  160. }
  161. get nameBoard() {
  162. return this._nameBoard
  163. }
  164. setNicknameStatus(e) {
  165. if (this.nameBoard && this.nameBoard.setStatus(e),
  166. e == BillboardStatus.DISPOSE) {
  167. const t = this._attachmentObservers.get("nickname");
  168. t && (this._scene.onBeforeRenderObservable.remove(t),
  169. this._attachmentObservers.delete("nickname"))
  170. }
  171. }
  172. setBubbleStatus(e) {
  173. if (this.bubble && this.bubble.setStatus(e),
  174. e == BillboardStatus.DISPOSE) {
  175. const t = this._attachmentObservers.get("bubble");
  176. t && (this._scene.onBeforeRenderObservable.remove(t),
  177. this._attachmentObservers.delete("bubble"))
  178. }
  179. }
  180. setButtonsStatus(e) {
  181. this.giftButtons && this.giftButtons.size != 0 && this.giftButtons.forEach(t=>{
  182. if (t.setStatus(e),
  183. e == BillboardStatus.DISPOSE && t.getMesh()) {
  184. const r = "button_" + t.getMesh().xid
  185. , n = this._attachmentObservers.get(r);
  186. n && (this._scene.onBeforeRenderObservable.remove(n),
  187. this._attachmentObservers.delete(r))
  188. }
  189. }
  190. )
  191. }
  192. setGiftButtonsVisible(e) {
  193. this.setButtonsStatus(e ? BillboardStatus.SHOW : BillboardStatus.DISPOSE)
  194. }
  195. dispose(e) {
  196. this._attachmentObservers.forEach(t=>{
  197. this._scene.onBeforeRenderObservable.remove(t)
  198. }
  199. ),
  200. this._attachmentObservers.clear(),
  201. this.updateBillboardStatus(e, BillboardStatus.DISPOSE),
  202. this._buttonTex.clear(),
  203. this._pickBbox && (e.avatarManager.bboxMeshPool.release(this._pickBbox),
  204. this._pickBbox = null)
  205. }
  206. updateBillboardStatus(e, t) {
  207. this.bbox || e.getBbox(),
  208. e.isRender ? (e.setBubbleStatus(t),
  209. e.setButtonsStatus(t),
  210. e.setNicknameStatus(t)) : (e.setBubbleStatus(BillboardStatus.DISPOSE),
  211. e.setButtonsStatus(BillboardStatus.DISPOSE),
  212. e.enableNickname ? e.setNicknameStatus(t) : e.setNicknameStatus(BillboardStatus.DISPOSE))
  213. }
  214. disposeBillBoard(e) {
  215. this._attachmentObservers.forEach(t=>{
  216. this._scene.onBeforeRenderObservable.remove(t)
  217. }
  218. ),
  219. this._attachmentObservers.clear(),
  220. this.updateBillboardStatus(e, BillboardStatus.DISPOSE),
  221. this._buttonTex.clear(),
  222. this._pickBbox && (e.avatarManager.bboxMeshPool.release(this._pickBbox),
  223. this._pickBbox = null)
  224. }
  225. setPickBoxScale(e) {
  226. this._pickBbox && this._pickBbox.data && (this._pickBbox.data.scaling = new BABYLON.Vector3(e,e,e))
  227. }
  228. setIsPickable(e, t) {
  229. e.rootNode && e.rootNode.getChildMeshes().forEach(r=>{
  230. r.isPickable = t
  231. }
  232. ),
  233. this._pickBbox && this._pickBbox.data && (this._pickBbox.data.isPickable = t)
  234. }
  235. initNameboard(e, t=1) {
  236. this._nameBoard == null && (this._nameBoard = e.avatarManager.sceneManager.billboardComponent.addBillboard("name-" + e.id, !1, !0)),
  237. this._nameBoard.init("nickname", t / 300, t / 300)
  238. }
  239. initBubble(e, t=1) {
  240. this._bubble == null && (this._bubble = e.avatarManager.sceneManager.billboardComponent.addBillboard("bubble-" + e.id, !1, !0)),
  241. e.isRender && this._bubble.init("bubble", t / 250, t / 250)
  242. }
  243. say(e, t=this._words, {id: r, isUser: n, background: o, font: a="Arial", fontsize: s=38, fontcolor: l="#ffffff", fontstyle: u="bold", linesize: c=22, linelimit: h, offsets: f={
  244. x: 0,
  245. y: 0,
  246. z: 40
  247. }, scale: d, compensationZ: _=11.2, reregistAnyway: g=!0}) {
  248. (!this.bubble || this.bubble.getMesh() == null) && e.initBubble(),
  249. this._words = t;
  250. let m;
  251. n != null && (m = n ? XBillboardManager.userBubbleUrls : XBillboardManager.npcBubbleUrls),
  252. this._bubble && (this._bubble.DEFAULT_CONFIGS = {
  253. id: r,
  254. isUser: n,
  255. background: o || m,
  256. font: a,
  257. fontsize: s,
  258. fontcolor: l,
  259. fontstyle: u,
  260. linesize: c,
  261. linelimit: h,
  262. offsets: f,
  263. scale: d,
  264. compensationZ: _,
  265. reregistAnyway: g
  266. },
  267. this._bubble.getMesh() && (this._bubble.drawBillboard({
  268. imageList: o || m
  269. }, {
  270. texts: this._words,
  271. font: a,
  272. fontsize: s,
  273. fontcolor: l,
  274. fontstyle: u,
  275. linesize: c
  276. }, {
  277. offsets: f,
  278. scale: d,
  279. compensationZ: _
  280. }),
  281. this.attachToAvatar(e, this._bubble.getMesh(), !1, this._bubble.offsets, g, "bubble"),
  282. r && this._bubble.setId(r))),
  283. this.setButtonsStatus(BillboardStatus.DISPOSE)
  284. }
  285. silent() {
  286. this.setBubbleStatus(BillboardStatus.DISPOSE),
  287. this._words = ""
  288. }
  289. setNickName(e, t, {id: r, isUser: n, background: o, font: a="Arial", fontsize: s=40, fontcolor: l="#ffffff", fontstyle: u="bold", linesize: c=22, linelimit: h, offsets: f={
  290. x: 0,
  291. y: 0,
  292. z: 15
  293. }, scale: d, compensationZ: _=0, reregistAnyway: g=!1}) {
  294. this._nickName = t,
  295. (!this.nameBoard || this.nameBoard.getMesh() == null) && this.initNameboard(e),
  296. this._nameBoard && this._nameBoard.getMesh() && (this._nameBoard.DEFAULT_CONFIGS = {
  297. id: r,
  298. isUser: n,
  299. background: o,
  300. font: a,
  301. fontsize: s,
  302. fontcolor: l,
  303. fontstyle: u,
  304. linesize: c,
  305. linelimit: h,
  306. offsets: f,
  307. scale: d,
  308. compensationZ: _,
  309. reregistAnyway: g
  310. },
  311. this._nameBoard.drawBillboard({}, {
  312. texts: this._nickName,
  313. font: a,
  314. fontsize: s,
  315. fontcolor: l,
  316. fontstyle: u,
  317. linesize: c,
  318. linelimit: h
  319. }, {
  320. offsets: f,
  321. scale: d,
  322. compensationZ: 0
  323. }),
  324. this.attachToAvatar(e, this._nameBoard.getMesh(), !1, this._nameBoard.offsets, g, "nickname"),
  325. r && this._nameBoard.setId(r))
  326. }
  327. generateButtons(e, t=null, r, n=85) {
  328. if (t && (this._buttonTex = t,
  329. this.clearButtons()),
  330. this._buttonTex.size == 0)
  331. return;
  332. let o = (this._buttonTex.size - 1) / 2;
  333. this._buttonTex.forEach((a,s)=>{
  334. let l = this._giftButtons.get(s);
  335. l || (l = e.avatarManager.sceneManager.billboardComponent.addBillboard("button-" + s + e.id, !0, !1),
  336. l.init(s, r / 240, r / 240));
  337. const u = {
  338. x: r * o * 70,
  339. y: 0,
  340. z: r * (n - 20 * (o * o))
  341. };
  342. l.drawBillboard({
  343. imageList: [a]
  344. }, {}, {
  345. offsets: u,
  346. scale: r
  347. }),
  348. this.attachToAvatar(e, l.getMesh(), !1, l.offsets, !0, "button_" + s),
  349. this._giftButtons.set(s, l),
  350. o -= 1
  351. }
  352. ),
  353. this.setBubbleStatus(BillboardStatus.DISPOSE)
  354. }
  355. clearButtons() {
  356. this._giftButtons.forEach(e=>{
  357. e.dispose()
  358. }
  359. ),
  360. this._giftButtons.clear()
  361. }
  362. createPickBoundingbox(e, t) {
  363. const r = t.extendSize.x * 2
  364. , n = t.extendSize.y * 2
  365. , o = t.extendSize.z * 2
  366. , a = this._scene
  367. , s = Math.max(r, o)
  368. , l = e.avatarManager.bboxMeshPool.getFree(a, s, n, s)
  369. , u = l.data;
  370. return u && (u.position = t.centerWorld,
  371. u.setEnabled(!1),
  372. u.isPickable = !0,
  373. u.xtype = EMeshType.XAvatar,
  374. u.xid = e.id),
  375. l
  376. }
  377. }