mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-06-11 12:24:11 +02:00
wip
This commit is contained in:
@@ -17,18 +17,20 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<template #header><i class="ti ti-box"></i> カタログ</template>
|
||||
|
||||
<div :class="$style.root">
|
||||
<div :class="$style.container">
|
||||
<div :class="$style.menu">
|
||||
<div
|
||||
v-for="def in OBJECT_DEFS"
|
||||
:key="def.id"
|
||||
:class="[$style.catalogItem, { [$style.selected]: selectedId === def.id }]"
|
||||
@click="selectedId = def.id"
|
||||
>
|
||||
<div>{{ def.name }}</div>
|
||||
</div>
|
||||
<div :class="$style.catalogItems">
|
||||
<div
|
||||
v-for="def in OBJECT_DEFS"
|
||||
:key="def.id"
|
||||
:class="[$style.catalogItem, { [$style.selected]: selectedId === def.id }]"
|
||||
@click="selectedId = def.id"
|
||||
>
|
||||
<img :class="$style.catalogItemThumbnail" :src="`/client-assets/room/object-thumbs/${camelToKebab(def.id)}.png`"/>
|
||||
<div :class="$style.catalogItemName">{{ def.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="selectedId != null" :class="$style.preview" class="_panel">
|
||||
<canvas ref="canvas" :class="$style.canvas"></canvas>
|
||||
<button :class="$style.unselectButton" @click="selectedId = null">x</button>
|
||||
</div>
|
||||
</div>
|
||||
</MkModalWindow>
|
||||
@@ -41,6 +43,7 @@ import MkModalWindow from '@/components/MkModalWindow.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { OBJECT_DEFS } from '@/world/room/object-defs.js';
|
||||
import { createRoomObjectPreviewEngine, RoomObjectPreviewEngine } from '@/world/room/previewEngine.js';
|
||||
import { camelToKebab } from '@/world/utility.js';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'ok', id: string): void;
|
||||
@@ -86,15 +89,14 @@ async function cancel() {
|
||||
.root {
|
||||
container-type: inline-size;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 100%;
|
||||
.catalogItems {
|
||||
display: grid;
|
||||
grid-template-columns: 400px 1fr;
|
||||
}
|
||||
|
||||
.menu {
|
||||
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
||||
grid-gap: 12px;
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
@@ -109,9 +111,33 @@ async function cancel() {
|
||||
background-color: var(--MI_THEME-accentedBg);
|
||||
}
|
||||
|
||||
.catalogItemThumbnail {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.catalogItemName {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.preview {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.unselectButton {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -30,6 +30,7 @@ export class RoomObjectPreviewEngine {
|
||||
private camera: BABYLON.ArcRotateCamera;
|
||||
private objectMesh: BABYLON.Mesh | null = null;
|
||||
private objectInstance: RoomObjectInstance<any> | null = null;
|
||||
private objectType: string | null = null;
|
||||
private envMapIndoor: BABYLON.CubeTexture;
|
||||
private roomLight: BABYLON.SpotLight;
|
||||
private zGridPreviewPlane: BABYLON.Mesh;
|
||||
@@ -86,6 +87,42 @@ export class RoomObjectPreviewEngine {
|
||||
this.zGridPreviewPlane = BABYLON.MeshBuilder.CreatePlane('zGridPreviewPlane', { width: cm(1000), height: cm(1000) }, this.scene);
|
||||
this.zGridPreviewPlane.material = gridMaterial;
|
||||
this.zGridPreviewPlane.rotation = new BABYLON.Vector3(Math.PI / 2, 0, 0);
|
||||
|
||||
if (_DEV_) {
|
||||
window.takeScreenshot = () => {
|
||||
const def = getObjectDef(this.objectType);
|
||||
|
||||
const boundingInfo = getMeshesBoundingBox(this.objectMesh!.getChildMeshes().filter(m => m.isEnabled() && m.isVisible));
|
||||
|
||||
const camera = new BABYLON.ArcRotateCamera('camera', Math.PI / 4, Math.PI / 2.5, cm(300), new BABYLON.Vector3(0, cm(90), 0), this.scene);
|
||||
camera.inputs.clear();
|
||||
camera.minZ = cm(1);
|
||||
camera.maxZ = cm(100000);
|
||||
camera.mode = BABYLON.Camera.ORTHOGRAPHIC_CAMERA;
|
||||
camera.setTarget(boundingInfo.center);
|
||||
if (def.placement === 'wall' || def.placement === 'side') {
|
||||
} else if (def.placement === 'ceiling' || def.placement === 'bottom') {
|
||||
camera.beta = Math.PI / 1.75;
|
||||
} else {
|
||||
}
|
||||
|
||||
// zoom to fit
|
||||
const size = boundingInfo.extendSize;
|
||||
const distance = Math.max(size.x, size.y, size.z) * 3;
|
||||
camera.orthoTop = (distance / 2);
|
||||
camera.orthoBottom = -(distance / 2);
|
||||
camera.orthoLeft = -(distance / 2);
|
||||
camera.orthoRight = (distance / 2);
|
||||
|
||||
this.scene.activeCamera = camera;
|
||||
|
||||
this.zGridPreviewPlane.isVisible = false;
|
||||
|
||||
window.setTimeout(() => {
|
||||
BABYLON.Tools.CreateScreenshotUsingRenderTarget(this.engine, camera, { width: 256, height: 256 }, undefined, undefined, undefined, true, `${camelToKebab(this.objectType!)}.png`);
|
||||
}, 100);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public async init() {
|
||||
@@ -276,6 +313,7 @@ export class RoomObjectPreviewEngine {
|
||||
|
||||
model.bakeMesh();
|
||||
|
||||
this.objectType = args.type;
|
||||
this.objectInstance = objectInstance;
|
||||
this.objectMesh = root;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user