1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-05-13 15:15:45 +02:00
This commit is contained in:
syuilo
2026-04-11 18:28:31 +09:00
parent 938dc5ce40
commit 9fe161ec7c
3 changed files with 98 additions and 3 deletions

View File

@@ -3,18 +3,99 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import * as BABYLON from '@babylonjs/core';
import { defineObject } from '../engine.js';
import { createPlaneUvMapper, normalizeUvToSquare } from '../utility.js';
export const djPlayer = defineObject({
id: 'djPlayer',
name: 'djPlayer',
options: {
schema: {},
default: {},
schema: {
screenBrightness: {
type: 'range',
label: 'Screen brightness',
min: 0,
max: 1,
step: 0.01,
},
customPicture: {
type: 'image',
label: 'Custom picture',
},
fit: {
type: 'enum',
label: 'Custom picture fit',
enum: ['cover', 'contain', 'stretch'],
},
},
default: {
screenBrightness: 0.35,
customPicture: null,
fit: 'cover',
},
},
placement: 'top',
createInstance: () => {
createInstance: async ({ model, options, scene }) => {
const screenMesh = model.findMesh('__X_SCREEN__');
const screenMaterial = model.findMaterial('__X_SCREEN__');
const defaultScreenTexture = screenMaterial.emissiveTexture;
normalizeUvToSquare(screenMesh);
const updateUv = createPlaneUvMapper(screenMesh);
const applyFit = () => {
const tex = screenMaterial.emissiveTexture;
if (tex == null) return;
const srcAspect = tex.getSize().width / tex.getSize().height;
const targetAspect = 15.6 / 8.33;
updateUv(srcAspect, targetAspect, options.fit);
model.updated();
};
applyFit();
const applyCustomPicture = () => new Promise<void>((resolve) => {
if (options.customPicture != null && options.customPicture !== '') {
const tex = new BABYLON.Texture(options.customPicture, scene, false, false);
tex.wrapU = BABYLON.Texture.MIRROR_ADDRESSMODE;
tex.wrapV = BABYLON.Texture.MIRROR_ADDRESSMODE;
tex.level = 0.5;
screenMaterial.unfreeze();
screenMaterial.emissiveTexture = tex;
tex.onLoadObservable.addOnce(() => {
applyFit();
resolve();
});
} else {
screenMaterial.emissiveTexture = defaultScreenTexture;
applyFit();
resolve();
}
});
await applyCustomPicture();
const applyScreenBrightness = () => {
const b = options.screenBrightness;
screenMaterial.emissiveColor = new BABYLON.Color3(b, b, b);
};
applyScreenBrightness();
return {
onOptionsUpdated: ([k, v]) => {
switch (k) {
case 'screenBrightness': applyScreenBrightness(); break;
case 'customPicture': applyCustomPicture(); break;
case 'fit': applyFit(); break;
}
},
interactions: {},
};
},

View File

@@ -376,6 +376,20 @@ export function getPlaneUvIndexes(mesh: BABYLON.Mesh) {
return [aIndex, bIndex, cIndex, dIndex];
}
export function normalizeUvToSquare(mesh: BABYLON.Mesh) {
const uvs = mesh.getVerticesData(BABYLON.VertexBuffer.UVKind)!;
const uvIndexes = getPlaneUvIndexes(mesh);
uvs[uvIndexes[0]] = 0;
uvs[uvIndexes[0] + 1] = 0;
uvs[uvIndexes[1]] = 1;
uvs[uvIndexes[1] + 1] = 0;
uvs[uvIndexes[2]] = 0;
uvs[uvIndexes[2] + 1] = 1;
uvs[uvIndexes[3]] = 1;
uvs[uvIndexes[3] + 1] = 1;
mesh.updateVerticesData(BABYLON.VertexBuffer.UVKind, uvs);
}
export function createPlaneUvMapper(mesh: BABYLON.Mesh) {
mesh.markVerticesDataAsUpdatable(BABYLON.VertexBuffer.UVKind, true);