123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623 |
- const log$a = new Logger("xverse-bus")
- class EngineProxy{
- constructor(e) {
- E(this, "_tvs", []);
- E(this, "isRenderFirstFrame", !1);
- E(this, "_idleTime", 0);
- E(this, "renderTimer");
- E(this, "lightManager");
- E(this, "_checkSceneNotReadyCount", 0);
- E(this, "_checkSceneDurationFrameNum", 0);
- E(this, "_checkSceneFrameCount", 0);
- E(this, "timeoutCircularArray", new CircularArray(120,!1,[]));
- E(this, "frameCircularArray", new CircularArray(120,!1,[]));
- E(this, "interFrameCircularArray", new CircularArray(120,!1,[]));
- E(this, "drawCallCntCircularArray", new CircularArray(120,!1,[]));
- E(this, "activeFacesCircularArray", new CircularArray(120,!1,[]));
- E(this, "renderTimeCircularArray", new CircularArray(120,!1,[]));
- E(this, "drawCallTimeCircularArray", new CircularArray(120,!1,[]));
- E(this, "animationCircularArray", new CircularArray(120,!1,[]));
- E(this, "meshSelectCircularArray", new CircularArray(120,!1,[]));
- E(this, "renderTargetCircularArray", new CircularArray(120,!1,[]));
- E(this, "regBeforeRenderCircularArray", new CircularArray(120,!1,[]));
- E(this, "regAfterRenderCircularArray", new CircularArray(120,!1,[]));
- E(this, "renderCnt", 0);
- E(this, "renderErrorCount", 0);
- E(this, "engineSloppyCnt", 0);
- E(this, "systemStuckCnt", 0);
- E(this, "frameRenderNumber", 0);
- E(this, "_setFPS", (e,t=25)=>{
- log$a.info("Set fps to", t);
- const r = t > 60 ? 60 : t < 24 ? 24 : t;
- e.Engine.stopRenderLoop();
- const n = 1e3 / r;
- let o = Date.now()
- , a = Date.now()
- , s = n
- , l = 1;
- const u = ()=>{
- var T;
- const c = Date.now()
- , h = c - o
- , f = c - a;
- a = c,
- this.frameCircularArray.add(f),
- h - s > n && (this.systemStuckCnt += 1);
- const d = h / s;
- l = .9 * l + .1 * d;
- const _ = Date.now();
- let g = 0
- , m = 0;
- if (this.room.isUpdatedRawYUVData || this.room.isPano) {
- if (this.isRenderFirstFrame = !0,
- this._checkSceneDurationFrameNum > 0)
- this._checkSceneFrameCount++,
- this.room.sceneManager.isReadyToRender({}) && this._checkSceneDurationFrameNum--,
- this._checkSceneFrameCount > ye._CHECK_DURATION && (this._checkSceneDurationFrameNum = ye._CHECK_DURATION,
- this._checkSceneFrameCount = 0,
- this._checkSceneNotReadyCount++,
- (this._checkSceneNotReadyCount == 1 || this._checkSceneNotReadyCount % 100 == 0) && log$a.error(`[SDK] Scene not ready, skip render. loop: ${this._checkSceneNotReadyCount}`),
- this._checkSceneNotReadyCount > 10 && (log$a.error("[SDK] Scene not ready, reload later"),
- this.room.proxyEvents("renderError", {
- error: new Error("[SDK] Scene not ready, skip render and reload.")
- })),
- this.room.stats.assign({
- renderErrorCount: this._checkSceneNotReadyCount
- }),
- log$a.infoAndReportMeasurement({
- value: 0,
- startTime: Date.now(),
- metric: "renderError",
- error: new Error("[SDK] Scene not ready, skip render and reload."),
- reportOptions: {
- sampleRate: .1
- }
- }));
- else
- try {
- e.render()
- } catch (C) {
- this.renderErrorCount++,
- this.renderErrorCount > 10 && this.room.proxyEvents("renderError", {
- error: C
- }),
- this.room.stats.assign({
- renderErrorCount: this.renderErrorCount
- }),
- log$a.infoAndReportMeasurement({
- value: 0,
- startTime: Date.now(),
- metric: "renderError",
- error: C,
- reportOptions: {
- sampleRate: .1
- }
- })
- }
- g = Date.now() - _,
- this.frameRenderNumber < 1e3 && this.frameRenderNumber++,
- this.room.networkController.rtcp.workers.UpdateYUV(),
- m = Date.now() - _ - g
- }
- this.isRenderFirstFrame || this.room.networkController.rtcp.workers.UpdateYUV();
- const y = Date.now() - _;
- o = c + y,
- s = Math.min(Math.max((n - y) / l, 5), 200),
- y > n && (s = 10,
- this.engineSloppyCnt += 1),
- this._idleTime = s;
- const b = s;
- if (s > 150 && console.log("lastGap is ", s, ", ratio is ", l, ", usedTimeMs is ", y, ", cpuRenderTime is ", g, ", cpuUpdateYUVTime is ", m),
- this.timeoutCircularArray.add(b),
- this.renderCnt % 25 == 0) {
- const C = this.frameCircularArray.getAvg()
- , A = this.timeoutCircularArray.getAvg()
- , S = this.frameCircularArray.getMax()
- , P = this.timeoutCircularArray.getMax();
- (T = this.room.stats) == null || T.assign({
- avgFrameTime: C,
- avgTimeoutTime: A,
- maxFrameTime: S,
- maxTimeoutTime: P,
- systemStuckCnt: this.systemStuckCnt
- })
- }
- this.renderTimer = window.setTimeout(u, s)
- }
- ;
- this.renderTimer = window.setTimeout(u, n / l)
- }
- );
- E(this, "updateStats", ()=>{
- var e;
- (e = this.room.stats) == null || e.assign({
- renderFrameTime: this.renderTimeCircularArray.getAvg(),
- maxRenderFrameTime: this.renderTimeCircularArray.getMax(),
- interFrameTime: this.interFrameCircularArray.getAvg(),
- animationTime: this.animationCircularArray.getAvg(),
- meshSelectTime: this.meshSelectCircularArray.getAvg(),
- drawcallTime: this.drawCallTimeCircularArray.getAvg(),
- idleTime: this._idleTime,
- registerBeforeRenderTime: this.regBeforeRenderCircularArray.getAvg(),
- registerAfterRenderTime: this.regAfterRenderCircularArray.getAvg(),
- renderTargetRenderTime: this.renderTargetCircularArray.getAvg(),
- fps: (1e3 / (this.renderTimeCircularArray.getAvg() + this.interFrameCircularArray.getAvg())).toFixed(2),
- drawcall: this.drawCallCntCircularArray.getAvg(),
- engineSloppyCnt: this.engineSloppyCnt,
- maxInterFrameTime: this.interFrameCircularArray.getMax(),
- maxDrawcallTime: this.drawCallTimeCircularArray.getMax(),
- maxMeshSelectTime: this.meshSelectCircularArray.getMax(),
- maxAnimationTime: this.animationCircularArray.getMax(),
- maxRegisterBeforeRenderTime: this.regBeforeRenderCircularArray.getMax(),
- maxRegisterAfterRenderTime: this.regAfterRenderCircularArray.getMax(),
- maxRenderTargetRenderTime: this.renderTargetCircularArray.getMax(),
- avgFrameTime: this.frameCircularArray.getAvg(),
- avgTimeoutTime: this.timeoutCircularArray.getAvg(),
- maxFrameTime: this.frameCircularArray.getMax(),
- maxTimeoutTime: this.timeoutCircularArray.getMax()
- })
- }
- );
- this.room = e
- }
- async initEngine(e) {
- await this.updateBillboard(),
- log$a.info("engine version:", VERSION$1);
- const t = new Logger("engine");
- t.setLevel(LoggerLevels.Warn);
- const r = {
- videoResOriArray: [{
- width: 720,
- height: 1280
- }, {
- width: 1280,
- height: 720
- }, {
- width: 480,
- height: 654
- }, {
- width: 654,
- height: 480
- }, {
- width: 1920,
- height: 1080
- }, {
- width: 1080,
- height: 1920
- }, {
- width: 414,
- height: 896
- }],
- forceKeepVertical: this.room.options.objectFit !== "cover",
- panoInfo: {
- dynamicRange: 1,
- width: 4096,
- height: 2048
- },
- shaderMode: EShaderMode.videoAndPano,
- yuvInfo: {
- width: 1280,
- height: 720,
- fov: e.fov || DEFAULT_MAIN_CAMERA_FOV
- },
- cameraParam: {
- maxZ: 1e4
- },
- urlTransformer,
- logger: t,
- disableWebGL2: this.room.options.disableWebGL2 || !1
- }
- , n = this.room.options.resolution;
- n && (r.videoResOriArray.some(l=>l.width === n.width && l.height === n.height) || r.videoResOriArray.push(n));
- const o = this.room.sceneManager = getSceneManager(this.room.canvas, r);
- this.room.setPictureQualityLevel(this.room.options.pictureQualityLevel || "high"),
- this.room.sceneManager.staticmeshComponent.setRegionLodRule([2, 2, -1, -1, -1]),
- this.room.scene = o.Scene,
- this.room.breathPointManager = o.breathPointComponent,
- this.lightManager = o.lightComponent,
- this.registerStats(),
- this.setEnv(e),
- await this.room.avatarManager.init();
- const a = this._createAssetList(e);
- await this.loadAssets(a, ""),
- this._setFPS(o)
- }
- pause() {
- clearTimeout(this.renderTimer),
- log$a.info("Invoke room.pause to pause render");
- const e = {
- roomId: this.room.id,
- effects: [],
- lowPolyModels: [],
- breathPointsConfig: [],
- skinId: this.room.skinId
- };
- return this.loadAssets(e, this.room.skinId)
- }
- async resume() {
- this._setFPS(this.room.sceneManager),
- this.room.sceneManager.cameraComponent.cameraFovChange(this.room.sceneManager.yuvInfo),
- log$a.info("Invoke room.resume to render");
- const e = this._createAssetList(this.room.skin);
- await this.loadAssets(e, "")
- }
- setEnv(e) {
- var r;
- this.lightManager || (this.lightManager = this.room.sceneManager.lightComponent),
- e = e || this.room.skin;
- const t = ModelManager.findModel(e.models, AssetTypeName.Config, AssetClassName.Env);
- return t ? (r = this.lightManager) == null ? void 0 : r.setIBL(t.modelUrl) : (log$a.error("env file not found"),
- Promise.resolve())
- }
- async _parseModelsAndLoad(e, t, r) {
- log$a.info("Invoke _parseModelsAndLoad start", t);
- const n = ["airship", "balloon", "default", "ground_feiting", "ground_reqiqiu"]
- , o = new Map;
- r == null && (r = "xxxx");
- let a = !0;
- for (let u = 0; u < e.length; ++u) {
- a = !0;
- for (let c = 0; c < n.length; ++c)
- if (e[u].modelUrl.toLowerCase().indexOf(n[c]) >= 0) {
- const h = o.get(n[c]);
- h ? (h.push(e[u]),
- o.set(n[c], h)) : o.set(n[c], [e[u]]),
- a = !1;
- break
- }
- if (a) {
- const c = o.get("default");
- c ? (c.push(e[u]),
- o.set("default", c)) : o.set("default", [e[u]])
- }
- }
- let s = o.get(t) || [];
- if (this.room.viewMode === "simple" && (s = s.filter(u=>!u.modelUrl.endsWith("zip"))),
- !s)
- return Promise.reject(`no invalid scene model with group name: ${t}`);
- const l = [];
- for (let u = 0; u < s.length; ++u) {
- const c = s[u];
- if (c.modelUrl.toLowerCase().endsWith("zip"))
- c.modelUrl.toLowerCase().endsWith("zip") && l.push(this.room.sceneManager.addNewLowPolyMesh({
- url: c.modelUrl,
- skinInfo: r
- }));
- else {
- const h = t;
- l.push(this.room.sceneManager.addNewLowPolyMesh({
- url: c.modelUrl,
- group: h,
- pick: !0,
- skinInfo: r
- }))
- }
- }
- return Promise.all(l)
- }
- async _deleteAssetsLowpolyModel(e) {
- this.room.sceneManager.staticmeshComponent.deleteMeshesBySkinInfo(e),
- this.room.sceneManager.breathPointComponent.clearBreathPointsBySkinInfo(e),
- this.room.sceneManager.decalComponent.deleteDecalBySkinInfo(e);
- const t = [];
- this.room.sceneManager.Scene.meshes.forEach(r=>{
- r.xskinInfo == e && t.push(r)
- }
- ),
- t.forEach(r=>{
- r.dispose(!1, !1)
- }
- )
- }
- async loadLandAssets() {
- const e = this._createAssetList(this.room.skin);
- return this.loadAssets(e, this.room.skinId).catch(()=>this.loadAssets(e, this.room.skinId))
- }
- async loadAssets(e, t="", r=8e3) {
- const n = Date.now();
- return this._loadAssets(e, t)._timeout(r, new InitEngineTimeoutError(`loadAssets timeout(${r}ms)`)).then(o=>(log$a.infoAndReportMeasurement({
- tag: "loadAssets",
- startTime: n,
- metric: "loadAssets"
- }),
- o)).catch(o=>(log$a.infoAndReportMeasurement({
- tag: "loadAssets",
- startTime: n,
- metric: "loadAssets",
- error: o
- }),
- Promise.reject(o)))
- }
- async _loadAssets(e, t="") {
- try {
- const r = [];
- r.push(this._loadAssetsLowpolyModel(e, t)),
- await Promise.all(r),
- await this.setEnv(),
- this._checkSceneDurationFrameNum = ye._CHECK_DURATION,
- this._checkSceneNotReadyCount = 0,
- this._checkSceneFrameCount = 0,
- this.updateAnimationList(),
- this.room.loadAssetsHook()
- } catch (r) {
- return Promise.reject(r)
- }
- }
- updateAnimationList() {
- if (this.room.avatarManager && this.room.avatarManager.xAvatarManager) {
- const e = this.room.skin.animationList;
- if (!e)
- return;
- e.forEach(t=>{
- this.room.avatarManager.xAvatarManager.updateAnimationLists(t.animations, t.avatarId)
- }
- )
- }
- }
- async _loadAssetsLowpolyModel(e, t="") {
- const r = []
- , n = []
- , o = [];
- e.lowPolyModels.forEach(f=>{
- f.group === "TV" ? n.push({
- id: "",
- name: "",
- thumbnailUrl: "",
- typeName: AssetTypeName.Model,
- className: AssetClassName.Tv,
- modelUrl: f.url
- }) : f.group === "\u544A\u767D\u5899" ? o.push({
- id: "",
- name: "",
- thumbnailUrl: "",
- typeName: AssetTypeName.Model,
- className: AssetClassName.Lpm,
- modelUrl: f.url
- }) : r.push({
- id: "",
- name: "",
- thumbnailUrl: "",
- typeName: AssetTypeName.Model,
- className: AssetClassName.Lpm,
- modelUrl: f.url
- })
- }
- ),
- t != "" && t != null && this._deleteAssetsLowpolyModel(t);
- const a = e.skinId;
- log$a.info("====> from ", t, " to ", a),
- this._tvs.forEach(f=>f.clean()),
- this._tvs = [];
- let s = EFitMode.cover;
- a == "10048" && (s = EFitMode.contain),
- Array.isArray(n) && n.forEach((f,d)=>{
- this._tvs.push(new TV("squareTv" + d,f.modelUrl,this.room,{
- fitMode: s
- }))
- }
- ),
- e.breathPointsConfig.forEach(async f=>{
- let d;
- try {
- d = await urlTransformer(f.imageUrl)
- } catch (_) {
- d = f.imageUrl,
- log$a.error("urlTransformer error", _)
- }
- this.room.breathPointManager.addBreathPoint({
- id: f.id,
- position: f.position,
- spriteSheet: d,
- rotation: f.rotation || {
- pitch: 0,
- yaw: 270,
- roll: 0
- },
- billboardMode: !0,
- type: f.type || "no_type",
- spriteWidthNumber: f.spriteWidthNum || 1,
- spriteHeightNumber: f.spriteHeightNum || 1,
- maxVisibleRegion: f.maxVisibleRegion || 150,
- width: f.width,
- height: f.height,
- skinInfo: f.skinId
- })
- }
- ),
- o.forEach(f=>{
- this.room.sceneManager.decalComponent.addDecal({
- id: f.id || "gbq",
- meshPath: f.modelUrl,
- skinInfo: a
- })
- }
- );
- const u = this.room.sceneManager.staticmeshComponent.lowModel_group
- , c = Array.from(u.keys()).filter(f=>!f.startsWith("region_"))
- , h = ["airship", "balloon", "ground_feiting", "ground_reqiqiu", "default"];
- return new Promise((f,d)=>{
- Promise.all(h.map(_=>this._parseModelsAndLoad(r, _, a))).then(()=>{
- let _ = !1;
- r.forEach(v=>{
- v.modelUrl.endsWith("zip") && (_ = !0)
- }
- ),
- _ == !1 && this.room.sceneManager.staticmeshComponent.deleteLastRegionMesh(),
- this.room.sceneManager.staticmeshComponent.lowModel_group;
- const g = Array.from(u.keys()).filter(v=>!v.startsWith("region_"))
- , m = c.filter(v=>g.indexOf(v) < 0);
- m.length > 0 && m.forEach(v=>{
- this.room.sceneManager.staticmeshComponent.deleteMeshesByGroup(v)
- }
- ),
- f(!0)
- }
- ).catch(_=>{
- d(_)
- }
- )
- }
- )
- }
- async _updateSkinAssets(e) {
- const t = this.room.lastSkinId
- , r = await this.room.getSkin(e)
- , n = this._createAssetList(r);
- try {
- await this.loadAssets(n, t),
- this.room.updateCurrentState({
- versionId: r.versionId,
- skinId: r.id,
- skin: r
- })
- } catch {
- await this.loadAssets(n, t),
- this.room.updateCurrentState({
- versionId: r.versionId,
- skinId: r.id,
- skin: r
- })
- }
- this.setEnv(r)
- }
- _createAssetList(e) {
- const t = []
- , r = []
- , n = [];
- let o = e.models;
- const a = this.room.modelManager.config.preload;
- return this.room.viewMode === "simple" ? a && (o = a.baseUrls.map(l=>(l.modelUrl = l.url,
- l))) : this.room.viewMode,
- ModelManager.findModels(o, AssetTypeName.Effects, AssetClassName.Effects).forEach(l=>{
- t.push({
- url: l.modelUrl,
- group: l.className,
- name: l.name
- })
- }
- ),
- ModelManager.findModels(o, AssetTypeName.Model, AssetClassName.Lpm).forEach(l=>{
- r.push({
- url: l.modelUrl,
- group: l.className
- })
- }
- ),
- ModelManager.findModels(o, AssetTypeName.Model, AssetClassName.Gbq).forEach(l=>{
- r.push({
- url: l.modelUrl,
- group: l.className
- })
- }
- ),
- ModelManager.findModels(o, AssetTypeName.Model, AssetClassName.Tv).forEach(l=>{
- r.push({
- url: l.modelUrl,
- group: l.className
- })
- }
- ),
- [].forEach(l=>{
- l.skinId == e.id && n.push(l)
- }
- ),
- {
- roomId: this.room.id,
- effects: t,
- lowPolyModels: r,
- breathPointsConfig: n,
- skinId: e.id
- }
- }
- registerStats() {
- const e = this.room.sceneManager;
- this.room.scene.registerAfterRender(()=>{
- var I;
- const t = e.statisticComponent.getInterFrameTimeCounter()
- , r = e.statisticComponent.getDrawCall()
- , n = e.statisticComponent.getActiveFaces()
- , o = e.statisticComponent.getFrameTimeCounter()
- , a = e.statisticComponent.getDrawCallTime()
- , s = e.statisticComponent.getAnimationTime()
- , l = e.statisticComponent.getActiveMeshEvaluationTime()
- , u = e.statisticComponent.getRenderTargetRenderTime()
- , c = e.statisticComponent.getRegisterBeforeRenderTime()
- , h = e.statisticComponent.getRegisterAfterRenderTime()
- , f = e.statisticComponent.getActiveParticles()
- , d = e.statisticComponent.getActiveBones()
- , _ = e.Scene._activeAnimatables.length
- , g = e.statisticComponent.getTotalRootNodes()
- , m = e.Scene.geometries.length
- , v = e.Scene.onBeforeRenderObservable.observers.length
- , y = e.Scene.onAfterRenderObservable.observers.length
- , b = e.statisticComponent.getTotalMeshes()
- , T = e.statisticComponent.getTotalTextures()
- , C = e.statisticComponent.getTotalMaterials()
- , A = e.statisticComponent.getSystemInfo()
- , S = A.resolution
- , P = A.driver;
- A.vender;
- const R = A.version
- , M = A.hardwareScalingLevel
- , x = S + "_" + P + "_" + R + "_" + M;
- this.interFrameCircularArray.add(t),
- this.renderTimeCircularArray.add(o),
- this.animationCircularArray.add(s),
- this.meshSelectCircularArray.add(l),
- this.drawCallTimeCircularArray.add(a),
- this.regAfterRenderCircularArray.add(h),
- this.regBeforeRenderCircularArray.add(c),
- this.renderTargetCircularArray.add(u),
- this.drawCallCntCircularArray.add(r),
- this.renderCnt += 1,
- this.renderCnt % 25 == 0 && ((I = this.room.stats) == null || I.assign({
- renderFrameTime: this.renderTimeCircularArray.getAvg(),
- maxRenderFrameTime: this.renderTimeCircularArray.getMax(),
- interFrameTime: this.interFrameCircularArray.getAvg(),
- animationTime: this.animationCircularArray.getAvg(),
- meshSelectTime: this.meshSelectCircularArray.getAvg(),
- drawcallTime: this.drawCallTimeCircularArray.getAvg(),
- idleTime: this._idleTime,
- registerBeforeRenderTime: this.regBeforeRenderCircularArray.getAvg(),
- registerAfterRenderTime: this.regAfterRenderCircularArray.getAvg(),
- renderTargetRenderTime: this.renderTargetCircularArray.getAvg(),
- fps: (1e3 / (this.renderTimeCircularArray.getAvg() + this.interFrameCircularArray.getAvg())).toFixed(2),
- drawcall: this.drawCallCntCircularArray.getAvg(),
- triangle: n.toString(),
- engineSloppyCnt: this.engineSloppyCnt,
- maxInterFrameTime: this.interFrameCircularArray.getMax(),
- maxDrawcallTime: this.drawCallTimeCircularArray.getMax(),
- maxMeshSelectTime: this.meshSelectCircularArray.getMax(),
- maxAnimationTime: this.animationCircularArray.getMax(),
- maxRegisterBeforeRenderTime: this.regBeforeRenderCircularArray.getMax(),
- maxRegisterAfterRenderTime: this.regAfterRenderCircularArray.getMax(),
- maxRenderTargetRenderTime: this.renderTargetCircularArray.getMax(),
- activeParticles: f,
- activeBones: d,
- activeAnimation: _,
- totalMeshes: b,
- totalRootNodes: g,
- totalGeometries: m,
- totalTextures: T,
- totalMaterials: C,
- registerBeforeCount: v,
- registerAfterCount: y,
- hardwareInfo: x
- }))
- }
- )
- }
- async updateBillboard() {
- const {options: {skinId: e}} = this.room
- , r = (await this.room.modelManager.findAssetList(e)).filter(a=>a.typeName === AssetTypeName.Textures && a.className === AssetClassName.SayBubble)
- , n = ["bubble01", "bubble02", "bubble03"]
- , o = ["bubble01_npc", "bubble02_npc", "bubble03_npc"];
- if (r.length) {
- const a = r.filter(l=>n.includes(l.name)).map(l=>l.url)
- , s = r.filter(l=>o.includes(l.name)).map(l=>l.url);
- a.length && (XBillboardManager.userBubbleUrls = a),
- s.length && (XBillboardManager.npcBubbleUrls = s)
- }
- }
- }
- ;
|