misskey/packages/frontend-misskey-world-engine/src/room/furnitures/allInOnePc.ts
2026-06-15 16:18:20 +09:00

97 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import * as BABYLON from '@babylonjs/core/pure.js';
import { cm, WORLD_SCALE } from 'misskey-world/src/utility.js';
import { allInOnePc_schema } from 'misskey-world/src/room/furnitures/allInOnePc.schema.js';
import { createTextureManager, defineFurniture } from '../furniture.js';
import { getLightRangeFactorByGraphicsQuality } from '../utility.js';
export const allInOnePc = defineFurniture(allInOnePc_schema, {
createInstance: async ({ lc, scene, options, model, graphicsQuality }) => {
const matrix = model.root.getWorldMatrix(true);
const scale = new BABYLON.Vector3();
matrix.decompose(scale);
// TODO: graphicsQualityがLOWならそもそも追加しない
const light = new BABYLON.SpotLight('', new BABYLON.Vector3(cm(0), cm(30) / Math.abs(scale.y), 0), new BABYLON.Vector3(0, 0, 1), Math.PI / 1, 2, scene, lc != null);
light.parent = model.root;
light.diffuse = new BABYLON.Color3(1.0, 1.0, 1.0);
light.range = cm(100) * getLightRangeFactorByGraphicsQuality(graphicsQuality);
light.radius = cm(20);
if (lc != null) lc.addLight(light);
const screenMesh = model.findMesh('__X_SCREEN__');
const bodyMaterial = model.findMaterial('__X_BODY__');
const bezelMaterial = model.findMaterial('__X_BEZEL__');
const screenMaterial = model.findMaterial('__X_SCREEN__');
screenMaterial.ambientColor = new BABYLON.Color3(0, 0, 0);
screenMaterial.albedoColor = new BABYLON.Color3(0, 0, 0);
screenMaterial.emissiveColor = new BABYLON.Color3(1, 1, 1);
screenMaterial.roughness = 0;
screenMaterial.metallic = 0;
const textureManager = createTextureManager(screenMesh, () => 50 / 27.5, scene);
const applyScreenBrightness = () => {
const b = options.screenBrightness;
screenMaterial.emissiveIntensity = b * 2;
light.intensity = (5 * b) * WORLD_SCALE * WORLD_SCALE;
};
applyScreenBrightness();
const applyImage = () => {
screenMaterial.unfreeze();
let url: string | null = null;
if (options.image.type === '_custom_') {
url = options.image.custom?.url ?? null;
} else if (options.image.type === 'desktop') {
url = '/assets/objects/all-in-one-pc/desktop.png';
}
return textureManager.change(url, options.image.fit, options.image.rotation).then((tex) => {
screenMaterial.emissiveTexture = tex;
});
};
await applyImage();
const applyBodyMat = () => {
bodyMaterial.albedoColor = new BABYLON.Color3(options.bodyMat.color[0], options.bodyMat.color[1], options.bodyMat.color[2]);
bodyMaterial.roughness = options.bodyMat.roughness;
bodyMaterial.metallic = options.bodyMat.metallic;
};
const applyBezelMat = () => {
bezelMaterial.albedoColor = new BABYLON.Color3(options.bezelMat.color[0], options.bezelMat.color[1], options.bezelMat.color[2]);
bezelMaterial.roughness = options.bezelMat.roughness;
bezelMaterial.metallic = options.bezelMat.metallic;
};
applyBodyMat();
applyBezelMat();
return {
onOptionsUpdated: ([k, v]) => {
switch (k) {
case 'bodyMat': applyBodyMat(); break;
case 'bezelMat': applyBezelMat(); break;
case 'screenBrightness': applyScreenBrightness(); break;
case 'image': applyImage(); break;
}
},
interactions: {},
dispose: () => {
light.dispose();
if (lc != null) lc.removeLight(light);
scene.removeLight(light); // lc使用時はsceneには追加してないはずだが、これがないとクラッシュする babylonのバグ
textureManager.dispose();
},
};
},
});