mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-05-14 07:35:35 +02:00
wip
This commit is contained in:
@@ -6,10 +6,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
<template>
|
<template>
|
||||||
<div :class="$style.root" class="_pageScrollable">
|
<div :class="$style.root" class="_pageScrollable">
|
||||||
<canvas ref="canvas" :class="$style.canvas"></canvas>
|
<canvas ref="canvas" :class="$style.canvas"></canvas>
|
||||||
<div class="_buttons" :class="$style.controls">
|
<div v-if="engine != null" class="_buttons" :class="$style.controls">
|
||||||
<MkButton @click="grab">Grab</MkButton>
|
<MkButton @click="grab">Grab</MkButton>
|
||||||
<MkButton @click="toggleLight">Toggle Light</MkButton>
|
<MkButton @click="toggleLight">Toggle Light</MkButton>
|
||||||
<MkButton @click="toggleGridSnapping">Grid Snap: {{ gridSnapping }}</MkButton>
|
<MkButton :primary="engine.enableGridSnapping.value" @click="toggleGridSnapping">Grid Snap: {{ engine.enableGridSnapping.value ? 'on' : 'off' }}</MkButton>
|
||||||
|
<MkButton v-if="engine.enableGridSnapping.value" :primary="engine.gridSnappingScale.value === 1" @click="engine.gridSnappingScale.value = 1">Snap: 1cm</MkButton>
|
||||||
|
<MkButton v-if="engine.enableGridSnapping.value" :primary="engine.gridSnappingScale.value === 2" @click="engine.gridSnappingScale.value = 2">Snap: 2cm</MkButton>
|
||||||
|
<MkButton v-if="engine.enableGridSnapping.value" :primary="engine.gridSnappingScale.value === 4" @click="engine.gridSnappingScale.value = 4">Snap: 4cm</MkButton>
|
||||||
|
<MkButton v-if="engine.enableGridSnapping.value" :primary="engine.gridSnappingScale.value === 8" @click="engine.gridSnappingScale.value = 8">Snap: 8cm</MkButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -24,14 +28,14 @@ import { RoomEngine } from '@/utility/room/engine.js';
|
|||||||
|
|
||||||
const canvas = useTemplateRef('canvas');
|
const canvas = useTemplateRef('canvas');
|
||||||
|
|
||||||
let engine: RoomEngine;
|
const engine = shallowRef<RoomEngine | null>(null);
|
||||||
|
|
||||||
function resize() {
|
function resize() {
|
||||||
if (engine != null) engine.resize();
|
if (engine.value != null) engine.value.resize();
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
engine = new RoomEngine({
|
engine.value = new RoomEngine({
|
||||||
roomType: 'default',
|
roomType: 'default',
|
||||||
objects: [{
|
objects: [{
|
||||||
id: 'a',
|
id: 'a',
|
||||||
@@ -192,7 +196,7 @@ onMounted(() => {
|
|||||||
canvas: canvas.value!,
|
canvas: canvas.value!,
|
||||||
});
|
});
|
||||||
|
|
||||||
engine.init();
|
engine.value.init();
|
||||||
|
|
||||||
canvas.value!.focus();
|
canvas.value!.focus();
|
||||||
|
|
||||||
@@ -200,26 +204,23 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
engine.destroy();
|
engine.value.destroy();
|
||||||
|
|
||||||
window.removeEventListener('resize', resize);
|
window.removeEventListener('resize', resize);
|
||||||
});
|
});
|
||||||
|
|
||||||
function grab() {
|
function grab() {
|
||||||
engine.toggleGrab();
|
engine.value.toggleGrab();
|
||||||
canvas.value!.focus();
|
canvas.value!.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleLight() {
|
function toggleLight() {
|
||||||
engine.toggleRoomLight();
|
engine.value.toggleRoomLight();
|
||||||
canvas.value!.focus();
|
canvas.value!.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
const gridSnapping = ref(false);
|
|
||||||
|
|
||||||
function toggleGridSnapping() {
|
function toggleGridSnapping() {
|
||||||
gridSnapping.value = !gridSnapping.value;
|
engine.value.enableGridSnapping.value = !engine.value.enableGridSnapping.value;
|
||||||
engine.enableGridSnapping = gridSnapping.value;
|
|
||||||
canvas.value!.focus();
|
canvas.value!.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ import * as BABYLON from '@babylonjs/core';
|
|||||||
import { AxesViewer } from '@babylonjs/core/Debug/axesViewer';
|
import { AxesViewer } from '@babylonjs/core/Debug/axesViewer';
|
||||||
import { registerBuiltInLoaders } from '@babylonjs/loaders/dynamic';
|
import { registerBuiltInLoaders } from '@babylonjs/loaders/dynamic';
|
||||||
import { BoundingBoxRenderer } from '@babylonjs/core/Rendering/boundingBoxRenderer';
|
import { BoundingBoxRenderer } from '@babylonjs/core/Rendering/boundingBoxRenderer';
|
||||||
|
import { GridMaterial } from '@babylonjs/materials';
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
import * as sound from '@/utility/sound.js';
|
import * as sound from '@/utility/sound.js';
|
||||||
|
|
||||||
type RoomDef = {
|
type RoomDef = {
|
||||||
@@ -442,17 +444,20 @@ export class RoomEngine {
|
|||||||
isMainLight: boolean;
|
isMainLight: boolean;
|
||||||
} | null = null;
|
} | null = null;
|
||||||
private selectedObjectId: string | null = null;
|
private selectedObjectId: string | null = null;
|
||||||
private time: 0 | 1 | 2 = 0; // 0: 昼, 1: 夕, 2: 夜
|
private time: 0 | 1 | 2 = 2; // 0: 昼, 1: 夕, 2: 夜
|
||||||
private roomCollisionMeshes: BABYLON.AbstractMesh[] = [];
|
private roomCollisionMeshes: BABYLON.AbstractMesh[] = [];
|
||||||
private def: RoomDef;
|
private def: RoomDef;
|
||||||
public enableGridSnapping = false;
|
public enableGridSnapping = ref(true);
|
||||||
public gridSnappingScale = 10/*cm*/;
|
public gridSnappingScale = ref(8/*cm*/);
|
||||||
private putParticleSystem: BABYLON.ParticleSystem;
|
private putParticleSystem: BABYLON.ParticleSystem;
|
||||||
private envMapIndoor: BABYLON.CubeTexture;
|
private envMapIndoor: BABYLON.CubeTexture;
|
||||||
private envMapOutdoor: BABYLON.CubeTexture;
|
private envMapOutdoor: BABYLON.CubeTexture;
|
||||||
private reflectionProbe: BABYLON.ReflectionProbe;
|
private reflectionProbe: BABYLON.ReflectionProbe;
|
||||||
private roomLight: BABYLON.SpotLight;
|
private roomLight: BABYLON.SpotLight;
|
||||||
private enableReflectionProbe = false;
|
private enableReflectionProbe = false;
|
||||||
|
private xGridPreviewPlane: BABYLON.Mesh;
|
||||||
|
private yGridPreviewPlane: BABYLON.Mesh;
|
||||||
|
private zGridPreviewPlane: BABYLON.Mesh;
|
||||||
|
|
||||||
constructor(def: RoomDef, options: {
|
constructor(def: RoomDef, options: {
|
||||||
canvas: HTMLCanvasElement;
|
canvas: HTMLCanvasElement;
|
||||||
@@ -617,6 +622,32 @@ export class RoomEngine {
|
|||||||
this.putParticleSystem.colorDead = new BABYLON.Color4(1, 1, 1, 0);
|
this.putParticleSystem.colorDead = new BABYLON.Color4(1, 1, 1, 0);
|
||||||
this.putParticleSystem.targetStopDuration = 0.05;
|
this.putParticleSystem.targetStopDuration = 0.05;
|
||||||
|
|
||||||
|
const gridMaterial = new GridMaterial('grid', this.scene);
|
||||||
|
gridMaterial.lineColor = new BABYLON.Color3(0.5, 0.5, 0.5);
|
||||||
|
gridMaterial.mainColor = new BABYLON.Color3(0, 0, 0);
|
||||||
|
gridMaterial.minorUnitVisibility = 1;
|
||||||
|
gridMaterial.opacity = 0.5;
|
||||||
|
watch(this.gridSnappingScale, (v) => {
|
||||||
|
gridMaterial.gridRatio = v;
|
||||||
|
}, { immediate: true });
|
||||||
|
|
||||||
|
this.xGridPreviewPlane = BABYLON.MeshBuilder.CreatePlane('xGridPreviewPlane', { width: 1000/*cm*/, height: 1000/*cm*/ }, this.scene);
|
||||||
|
this.xGridPreviewPlane.rotation = new BABYLON.Vector3(0, 0, Math.PI / 2);
|
||||||
|
this.xGridPreviewPlane.material = gridMaterial;
|
||||||
|
this.xGridPreviewPlane.isPickable = false;
|
||||||
|
this.xGridPreviewPlane.isVisible = false;
|
||||||
|
|
||||||
|
this.yGridPreviewPlane = BABYLON.MeshBuilder.CreatePlane('yGridPreviewPlane', { width: 1000/*cm*/, height: 1000/*cm*/ }, this.scene);
|
||||||
|
this.yGridPreviewPlane.rotation = new BABYLON.Vector3(Math.PI / 2, 0, 0);
|
||||||
|
this.yGridPreviewPlane.material = gridMaterial;
|
||||||
|
this.yGridPreviewPlane.isPickable = false;
|
||||||
|
this.yGridPreviewPlane.isVisible = false;
|
||||||
|
|
||||||
|
this.zGridPreviewPlane = BABYLON.MeshBuilder.CreatePlane('zGridPreviewPlane', { width: 1000/*cm*/, height: 1000/*cm*/ }, this.scene);
|
||||||
|
this.zGridPreviewPlane.material = gridMaterial;
|
||||||
|
this.zGridPreviewPlane.isPickable = false;
|
||||||
|
this.zGridPreviewPlane.isVisible = false;
|
||||||
|
|
||||||
let isDragging = false;
|
let isDragging = false;
|
||||||
|
|
||||||
this.canvas.addEventListener('pointerdown', (ev) => {
|
this.canvas.addEventListener('pointerdown', (ev) => {
|
||||||
@@ -795,10 +826,10 @@ export class RoomEngine {
|
|||||||
grabbing.ghost.position = this.camera.position.add(dir.scale(grabbing.distance)).add(grabbing.startOffset);
|
grabbing.ghost.position = this.camera.position.add(dir.scale(grabbing.distance)).add(grabbing.startOffset);
|
||||||
grabbing.ghost.rotation = new BABYLON.Vector3(0, this.camera.rotation.y + grabbing.startRotationY + grabbing.rotation, 0);
|
grabbing.ghost.rotation = new BABYLON.Vector3(0, this.camera.rotation.y + grabbing.startRotationY + grabbing.rotation, 0);
|
||||||
|
|
||||||
if (this.enableGridSnapping) {
|
if (this.enableGridSnapping.value) {
|
||||||
grabbing.ghost.position.x = Math.round(grabbing.ghost.position.x / this.gridSnappingScale) * this.gridSnappingScale;
|
grabbing.ghost.position.x = Math.round(grabbing.ghost.position.x / this.gridSnappingScale.value) * this.gridSnappingScale.value;
|
||||||
grabbing.ghost.position.y = Math.round(grabbing.ghost.position.y / this.gridSnappingScale) * this.gridSnappingScale;
|
grabbing.ghost.position.y = Math.round(grabbing.ghost.position.y / this.gridSnappingScale.value) * this.gridSnappingScale.value;
|
||||||
grabbing.ghost.position.z = Math.round(grabbing.ghost.position.z / this.gridSnappingScale) * this.gridSnappingScale;
|
grabbing.ghost.position.z = Math.round(grabbing.ghost.position.z / this.gridSnappingScale.value) * this.gridSnappingScale.value;
|
||||||
grabbing.ghost.rotation.y = Math.round(grabbing.ghost.rotation.y / (Math.PI / 8)) * (Math.PI / 8);
|
grabbing.ghost.rotation.y = Math.round(grabbing.ghost.rotation.y / (Math.PI / 8)) * (Math.PI / 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -848,8 +879,18 @@ export class RoomEngine {
|
|||||||
if (newPos.y > 250/*cm*/) newPos.y = 250/*cm*/;
|
if (newPos.y > 250/*cm*/) newPos.y = 250/*cm*/;
|
||||||
} else if (placement === 'ceiling') {
|
} else if (placement === 'ceiling') {
|
||||||
newPos.y = 250/*cm*/;
|
newPos.y = 250/*cm*/;
|
||||||
|
|
||||||
|
if (this.enableGridSnapping.value) {
|
||||||
|
this.yGridPreviewPlane.position = new BABYLON.Vector3(grabbing.mesh.position.x, 250/*cm*/ - 0.1/*cm*/, grabbing.mesh.position.z);
|
||||||
|
this.yGridPreviewPlane.isVisible = true;
|
||||||
|
}
|
||||||
} else if (placement === 'floor') {
|
} else if (placement === 'floor') {
|
||||||
newPos.y = 0;
|
newPos.y = 0;
|
||||||
|
|
||||||
|
if (this.enableGridSnapping.value) {
|
||||||
|
this.yGridPreviewPlane.position = new BABYLON.Vector3(grabbing.mesh.position.x, 0.1/*cm*/, grabbing.mesh.position.z);
|
||||||
|
this.yGridPreviewPlane.isVisible = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// 下に向かってレイを飛ばす
|
// 下に向かってレイを飛ばす
|
||||||
const ray = new BABYLON.Ray(grabbing.ghost.position, new BABYLON.Vector3(0, -1, 0), 1000/*cm*/);
|
const ray = new BABYLON.Ray(grabbing.ghost.position, new BABYLON.Vector3(0, -1, 0), 1000/*cm*/);
|
||||||
@@ -859,6 +900,11 @@ export class RoomEngine {
|
|||||||
sticky = hit.pickedMesh.metadata?.objectId ?? null;
|
sticky = hit.pickedMesh.metadata?.objectId ?? null;
|
||||||
}
|
}
|
||||||
if (newPos.y < 0) newPos.y = 0;
|
if (newPos.y < 0) newPos.y = 0;
|
||||||
|
|
||||||
|
if (this.enableGridSnapping.value) {
|
||||||
|
this.yGridPreviewPlane.position = new BABYLON.Vector3(grabbing.mesh.position.x, grabbing.mesh.position.y + 0.1/*cm*/, grabbing.mesh.position.z);
|
||||||
|
this.yGridPreviewPlane.isVisible = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sticky != null) {
|
if (sticky != null) {
|
||||||
@@ -1038,13 +1084,18 @@ export class RoomEngine {
|
|||||||
this.grabbing = null;
|
this.grabbing = null;
|
||||||
this.selectObject(null);
|
this.selectObject(null);
|
||||||
|
|
||||||
|
this.xGridPreviewPlane.isVisible = false;
|
||||||
|
this.yGridPreviewPlane.isVisible = false;
|
||||||
|
this.zGridPreviewPlane.isVisible = false;
|
||||||
|
|
||||||
|
this.putParticleSystem.emitter = pos;
|
||||||
|
this.putParticleSystem.start();
|
||||||
|
|
||||||
sound.playUrl('/client-assets/room/sfx/put.mp3', {
|
sound.playUrl('/client-assets/room/sfx/put.mp3', {
|
||||||
volume: 1,
|
volume: 1,
|
||||||
playbackRate: 1,
|
playbackRate: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.putParticleSystem.emitter = pos;
|
|
||||||
this.putParticleSystem.start();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user