diff --git a/packages/frontend-misskey-world-engine/src/PlayerContainer.ts b/packages/frontend-misskey-world-engine/src/PlayerContainer.ts index d8aea3bd67..5eb291d92e 100644 --- a/packages/frontend-misskey-world-engine/src/PlayerContainer.ts +++ b/packages/frontend-misskey-world-engine/src/PlayerContainer.ts @@ -47,7 +47,8 @@ export class PlayerContainer { public id: string; private profile: PlayerProfile; private root: BABYLON.TransformNode; - private modelRootContainerForAnim: BABYLON.TransformNode; + private subRootContainerForAnim: BABYLON.TransformNode; + private subRoot: BABYLON.TransformNode; private modelRoot: BABYLON.TransformNode | null = null; private sr: BABYLON.SnapshotRenderingHelper; private scene: BABYLON.Scene; @@ -63,8 +64,10 @@ export class PlayerContainer { this.root = new BABYLON.TransformNode(`player:${this.id}`, params.scene); this.root.rotationQuaternion = null; - this.modelRootContainerForAnim = new BABYLON.TransformNode(`player:${this.id}:modelRootContainerForAnim`, params.scene); - this.modelRootContainerForAnim.parent = this.root; + this.subRootContainerForAnim = new BABYLON.TransformNode(`player:${this.id}:subRootContainerForAnim`, params.scene); + this.subRootContainerForAnim.parent = this.root; + this.subRoot = new BABYLON.TransformNode(`player:${this.id}:subRoot`, params.scene); + this.subRoot.parent = this.subRootContainerForAnim; if (params.state) this.applyState(params.state, true); } @@ -77,7 +80,7 @@ export class PlayerContainer { // meshじゃなくtransform nodeにしてパフォーマンス向上 this.modelRoot = new BABYLON.TransformNode('__root__', this.scene); - this.modelRoot.parent = this.modelRootContainerForAnim; + this.modelRoot.parent = this.subRoot; this.modelRoot.scaling.x = -1; this.modelRoot.scaling = this.modelRoot.scaling.scale(WORLD_SCALE);// cmをmに @@ -171,11 +174,11 @@ export class PlayerContainer { { frame: 90, value: cm(2) }, { frame: 120, value: cm(0) }, ]); - this.modelRootContainerForAnim.animations = [anim]; + this.subRootContainerForAnim.animations = [anim]; this.animationObserver = this.scene.onAfterAnimationsObservable.add(() => { - this.sr.updateMesh(this.modelRootContainerForAnim.getChildMeshes(), false); + this.sr.updateMesh(this.subRootContainerForAnim.getChildMeshes(), false); }); - this.scene.beginAnimation(this.modelRootContainerForAnim, 0, 120, true); + this.scene.beginAnimation(this.subRootContainerForAnim, 0, 120, true); } private async loadAccessory(args: { @@ -205,6 +208,8 @@ export class PlayerContainer { await container.load(); + container.root.parent = this.subRoot; + return container; } diff --git a/packages/frontend-misskey-world-engine/src/avatars/accessories/mug.ts b/packages/frontend-misskey-world-engine/src/avatars/accessories/mug.ts index 99b86df18d..4b91e0fe7d 100644 --- a/packages/frontend-misskey-world-engine/src/avatars/accessories/mug.ts +++ b/packages/frontend-misskey-world-engine/src/avatars/accessories/mug.ts @@ -7,15 +7,38 @@ import * as BABYLON from '@babylonjs/core'; import { cm } from 'misskey-world/src/utility.js'; import { mug_schema } from 'misskey-world/src/room/objects/mug.schema.js'; import { defineAccessory } from '../accessory.js'; -import { yuge } from '../utility.js'; export const mug = defineAccessory(mug_schema, { createInstance: ({ scene, root, sr }) => { - const yugeDispose = yuge(scene, root, new BABYLON.Vector3(0, cm(5), 0), sr); + const emitter = new BABYLON.TransformNode('emitter', scene); + emitter.parent = root; + emitter.position = new BABYLON.Vector3(0, cm(5), 0); + const ps = new BABYLON.ParticleSystem('steamParticleSystem', 8, scene); + ps.particleTexture = new BABYLON.Texture('/client-assets/world/avatar-accessories/mug/steam.png'); + ps.emitter = emitter; + ps.minEmitBox = new BABYLON.Vector3(cm(-1), 0, cm(-1)); + ps.maxEmitBox = new BABYLON.Vector3(cm(1), 0, cm(1)); + ps.minEmitPower = cm(10); + ps.maxEmitPower = cm(12); + ps.minLifeTime = 2; + ps.maxLifeTime = 3; + ps.addSizeGradient(0, cm(10), cm(12)); + ps.addSizeGradient(1, cm(18), cm(20)); + ps.direction1 = new BABYLON.Vector3(-0.3, 1, 0.3); + ps.direction2 = new BABYLON.Vector3(0.3, 1, -0.3); + ps.emitRate = 0.5; + ps.blendMode = BABYLON.ParticleSystem.BLENDMODE_ADD; + ps.color1 = new BABYLON.Color4(1, 1, 1, 0.3); + ps.color2 = new BABYLON.Color4(1, 1, 1, 0.2); + ps.colorDead = new BABYLON.Color4(1, 1, 1, 0); + ps.preWarmCycles = Math.random() * 1000; + ps.start(); + sr.fixParticleSystem(ps); return { dispose: () => { - yugeDispose?.(); + ps.stop(); + emitter.dispose(); }, }; }, diff --git a/packages/frontend-misskey-world-engine/src/avatars/accessory.ts b/packages/frontend-misskey-world-engine/src/avatars/accessory.ts index 0a4fa569cb..044f36120f 100644 --- a/packages/frontend-misskey-world-engine/src/avatars/accessory.ts +++ b/packages/frontend-misskey-world-engine/src/avatars/accessory.ts @@ -39,6 +39,6 @@ export function defineAccessorySchema>(schema: Schema, def: Pick, 'path' | 'createInstance'>): AccessoryDef { +export function defineAccessory>(schema: Schema, def: Pick, 'path' | 'createInstance'>): AvatarAccessoryDef { return { ...schema, ...def }; } diff --git a/packages/frontend/assets/world/avatar-accessories/mug/steam.png b/packages/frontend/assets/world/avatar-accessories/mug/steam.png new file mode 100644 index 0000000000..d088cd71cf Binary files /dev/null and b/packages/frontend/assets/world/avatar-accessories/mug/steam.png differ