mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-06-06 04:04:18 +02:00
wip
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -5,22 +5,28 @@ 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" @keypress="onKeypress" @wheel="onWheel"></canvas>
|
<div :class="$style.screen">
|
||||||
<div v-if="engine != null" class="_buttons" :class="$style.controls">
|
<canvas ref="canvas" :class="$style.canvas" @keydown="onKeydown" @wheel="onWheel"></canvas>
|
||||||
<!--<MkButton v-for="action in actions" :key="action.key" @click="action.fn">{{ action.label }}{{ hotkeyToLabel(action.hotkey) }}</MkButton>-->
|
<div v-if="engine != null" class="_buttonsCenter" :class="$style.overlayControls">
|
||||||
<MkButton @click="toggleLight">Toggle Light</MkButton>
|
|
||||||
<MkButton :primary="engine.isEditMode.value" @click="toggleEditMode">Edit mode: {{ engine.isEditMode.value ? 'on' : 'off' }}</MkButton>
|
|
||||||
<template v-if="engine.isEditMode.value">
|
<template v-if="engine.isEditMode.value">
|
||||||
<MkButton v-if="engine.ui.isGrabbing" @click="endGrabbing">Put (E)</MkButton>
|
<MkButton v-if="engine.ui.isGrabbing" @click="endGrabbing">Put (E)</MkButton>
|
||||||
<MkButton v-else-if="engine.ui.isGrabbingForInstall" @click="endGrabbing">Install (E)</MkButton>
|
<MkButton v-else-if="engine.ui.isGrabbingForInstall" @click="endGrabbing">Install (E)</MkButton>
|
||||||
<MkButton v-else @click="beginSelectedInstalledObjectGrabbing">Grab (E)</MkButton>
|
<MkButton v-else @click="beginSelectedInstalledObjectGrabbing">Grab (E)</MkButton>
|
||||||
|
|
||||||
|
<MkButton v-if="engine.ui.isGrabbing || engine.ui.isGrabbingForInstall" @click="rotate">Rotate (R)</MkButton>
|
||||||
|
|
||||||
<MkButton :primary="engine.enableGridSnapping.value" @click="showSnappingMenu">Grid Snap: {{ engine.enableGridSnapping.value ? 'on' : 'off' }}</MkButton>
|
<MkButton :primary="engine.enableGridSnapping.value" @click="showSnappingMenu">Grid Snap: {{ engine.enableGridSnapping.value ? 'on' : 'off' }}</MkButton>
|
||||||
</template>
|
</template>
|
||||||
<MkButton v-if="engine.isSitting.value" @click="engine.standUp()">降りる (Q)</MkButton>
|
<MkButton v-if="engine.isSitting.value" @click="engine.standUp()">降りる (Q)</MkButton>
|
||||||
<template v-for="interaction in interacions" :key="interaction.id">
|
<template v-for="interaction in interacions" :key="interaction.id">
|
||||||
<MkButton @click="interaction.fn()">{{ interaction.label }}</MkButton>
|
<MkButton inline @click="interaction.fn()">{{ interaction.label }}{{ interaction.isPrimary ? ' (E)' : '' }}</MkButton>
|
||||||
</template>
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="engine != null" class="_buttons" :class="$style.controls">
|
||||||
|
<!--<MkButton v-for="action in actions" :key="action.key" @click="action.fn">{{ action.label }}{{ hotkeyToLabel(action.hotkey) }}</MkButton>-->
|
||||||
|
<MkButton @click="toggleLight">Toggle Light</MkButton>
|
||||||
|
<MkButton :primary="engine.isEditMode.value" @click="toggleEditMode">Edit mode: {{ engine.isEditMode.value ? 'on' : 'off' }}</MkButton>
|
||||||
<MkButton @click="addObject">addObject</MkButton>
|
<MkButton @click="addObject">addObject</MkButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -44,6 +50,7 @@ const engine = shallowRef<RoomEngine | null>(null);
|
|||||||
const interacions = shallowRef<{
|
const interacions = shallowRef<{
|
||||||
id: string;
|
id: string;
|
||||||
label: string;
|
label: string;
|
||||||
|
isPrimary: boolean;
|
||||||
fn: () => void;
|
fn: () => void;
|
||||||
}[]>([]);
|
}[]>([]);
|
||||||
|
|
||||||
@@ -97,36 +104,38 @@ const actions = computed<Action[]>(() => {
|
|||||||
return actions;
|
return actions;
|
||||||
});
|
});
|
||||||
|
|
||||||
function onKeypress(ev: KeyboardEvent) {
|
function onKeydown(ev: KeyboardEvent) {
|
||||||
if (engine.value == null) return;
|
if (engine.value == null) return;
|
||||||
|
|
||||||
/* todo
|
|
||||||
if (ev.code === 'KeyE') {
|
if (ev.code === 'KeyE') {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
if (engine.value.isEditMode.value) {
|
if (engine.value.isEditMode.value) {
|
||||||
if (engine.value.ui.isGrabbing || engine.value.ui.isGrabbingForInstall) {
|
if (engine.value.ui.isGrabbing || engine.value.ui.isGrabbingForInstall) {
|
||||||
this.endGrabbing();
|
endGrabbing();
|
||||||
} else {
|
} else {
|
||||||
this.beginSelectedInstalledObjectGrabbing();
|
beginSelectedInstalledObjectGrabbing();
|
||||||
}
|
}
|
||||||
} else if (this.selectedObjectId.value != null) {
|
} else if (engine.value.selectedObjectId.value != null) {
|
||||||
this.interact(this.selectedObjectId.value);
|
engine.value.interact(engine.value.selectedObjectId.value);
|
||||||
}
|
}
|
||||||
} else if (ev.code === 'KeyR') {
|
} else if (ev.code === 'KeyR') {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
if (this.grabbingCtx != null) {
|
if (engine.value.ui.isGrabbing || engine.value.ui.isGrabbingForInstall) {
|
||||||
this.grabbingCtx.rotation += Math.PI / 8;
|
rotate();
|
||||||
}
|
}
|
||||||
} else if (ev.code === 'KeyQ') {
|
} else if (ev.code === 'KeyQ') {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
if (this.isSitting.value) {
|
if (engine.value.isSitting.value) {
|
||||||
this.standUp();
|
engine.value.standUp();
|
||||||
}
|
}
|
||||||
|
} else if (ev.code === 'Tab') {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
toggleEditMode();
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onWheel(ev: WheelEvent) {
|
function onWheel(ev: WheelEvent) {
|
||||||
@@ -217,7 +226,12 @@ onMounted(() => {
|
|||||||
type: 'tabletopDigitalClock',
|
type: 'tabletopDigitalClock',
|
||||||
position: [-35, 90, 175],
|
position: [-35, 90, 175],
|
||||||
rotation: [0, Math.PI, 0],
|
rotation: [0, Math.PI, 0],
|
||||||
options: {},
|
options: {
|
||||||
|
bodyStyle: {
|
||||||
|
type: 'color',
|
||||||
|
value: [0.45, 0.8, 1],
|
||||||
|
},
|
||||||
|
},
|
||||||
}, {
|
}, {
|
||||||
id: 'f3',
|
id: 'f3',
|
||||||
type: 'snakeplant',
|
type: 'snakeplant',
|
||||||
@@ -421,6 +435,7 @@ onMounted(() => {
|
|||||||
interacions.value = Object.entries(obji.interactions).map(([interactionId, interactionInfo]) => ({
|
interacions.value = Object.entries(obji.interactions).map(([interactionId, interactionInfo]) => ({
|
||||||
id: interactionId,
|
id: interactionId,
|
||||||
label: interactionInfo.label,
|
label: interactionInfo.label,
|
||||||
|
isPrimary: obji.primaryInteraction === interactionId,
|
||||||
fn: interactionInfo.fn,
|
fn: interactionInfo.fn,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -477,8 +492,8 @@ function showSnappingMenu(ev: PointerEvent) {
|
|||||||
}], ev.currentTarget ?? ev.target);
|
}], ev.currentTarget ?? ev.target);
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleGridSnapping() {
|
function rotate() {
|
||||||
engine.value.enableGridSnapping.value = !engine.value.enableGridSnapping.value;
|
engine.value.changeGrabbingRotationY(Math.PI / 8);
|
||||||
canvas.value!.focus();
|
canvas.value!.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,6 +525,12 @@ definePage(() => ({
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.screen {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 90cqh;
|
||||||
|
}
|
||||||
|
|
||||||
.canvas {
|
.canvas {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -518,9 +539,13 @@ definePage(() => ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
.controls {
|
.controls {
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlayControls {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 16px;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
z-index: 1;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -854,7 +854,7 @@ export class RoomEngine {
|
|||||||
const objectInstance = def.createInstance({
|
const objectInstance = def.createInstance({
|
||||||
room: this,
|
room: this,
|
||||||
root,
|
root,
|
||||||
options: args.options,
|
options: args.options, // todo: merge with default options
|
||||||
loaderResult: loaderResult,
|
loaderResult: loaderResult,
|
||||||
meshUpdated: () => {
|
meshUpdated: () => {
|
||||||
meshUpdated(this.objectMeshs.get(args.id)!.getChildMeshes() as BABYLON.Mesh[]);
|
meshUpdated(this.objectMeshs.get(args.id)!.getChildMeshes() as BABYLON.Mesh[]);
|
||||||
@@ -998,7 +998,7 @@ export class RoomEngine {
|
|||||||
this.zGridPreviewPlane.isVisible = false;
|
this.zGridPreviewPlane.isVisible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private interact(oid: string) {
|
public interact(oid: string) {
|
||||||
const o = this.roomState.installedObjects.find(o => o.id === oid)!;
|
const o = this.roomState.installedObjects.find(o => o.id === oid)!;
|
||||||
const mesh = this.objectMeshs.get(o.id)!;
|
const mesh = this.objectMeshs.get(o.id)!;
|
||||||
const objDef = getObjectDef(o.type);
|
const objDef = getObjectDef(o.type);
|
||||||
@@ -1150,6 +1150,11 @@ export class RoomEngine {
|
|||||||
if (this.grabbingCtx.distance < 5/*cm*/) this.grabbingCtx.distance = 5/*cm*/;
|
if (this.grabbingCtx.distance < 5/*cm*/) this.grabbingCtx.distance = 5/*cm*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public changeGrabbingRotationY(delta: number) {
|
||||||
|
if (this.grabbingCtx == null) return;
|
||||||
|
this.grabbingCtx.rotation += delta;
|
||||||
|
}
|
||||||
|
|
||||||
public resize() {
|
public resize() {
|
||||||
this.engine.resize();
|
this.engine.resize();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,16 +5,30 @@
|
|||||||
|
|
||||||
import * as BABYLON from '@babylonjs/core';
|
import * as BABYLON from '@babylonjs/core';
|
||||||
import { defineObject } from '../engine.js';
|
import { defineObject } from '../engine.js';
|
||||||
import { get7segMeshesOfCurrentTime, yuge } from '../utility.js';
|
import { get7segMeshesOfCurrentTime } from '../utility.js';
|
||||||
|
|
||||||
export const tabletopDigitalClock = defineObject({
|
export const tabletopDigitalClock = defineObject({
|
||||||
id: 'tabletopDigitalClock',
|
id: 'tabletopDigitalClock',
|
||||||
defaultOptions: {},
|
defaultOptions: {
|
||||||
|
bodyStyle: {
|
||||||
|
type: 'color',
|
||||||
|
value: [0.45, 0.8, 0],
|
||||||
|
} as { type: 'color'; value: [number, number, number] } | { type: 'wood'; } | null,
|
||||||
|
},
|
||||||
placement: 'top',
|
placement: 'top',
|
||||||
createInstance: ({ room, root }) => {
|
createInstance: ({ room, options, root }) => {
|
||||||
return {
|
return {
|
||||||
onInited: () => {
|
onInited: () => {
|
||||||
const meshes = {
|
const bodyMesh = root.getChildMeshes().find(m => m.name.includes('__X_BODY__')) as BABYLON.Mesh;
|
||||||
|
|
||||||
|
const bodyMaterial = bodyMesh.material as BABYLON.PBRMaterial;
|
||||||
|
|
||||||
|
if (options.bodyStyle?.type === 'color') {
|
||||||
|
const [r, g, b] = options.bodyStyle.value;
|
||||||
|
bodyMaterial.albedoColor = new BABYLON.Color3(r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
const segmentMeshes = {
|
||||||
'1a': root.getChildMeshes().find(m => m.name.includes('__TIME_7SEG_1A__')),
|
'1a': root.getChildMeshes().find(m => m.name.includes('__TIME_7SEG_1A__')),
|
||||||
'1b': root.getChildMeshes().find(m => m.name.includes('__TIME_7SEG_1B__')),
|
'1b': root.getChildMeshes().find(m => m.name.includes('__TIME_7SEG_1B__')),
|
||||||
'1c': root.getChildMeshes().find(m => m.name.includes('__TIME_7SEG_1C__')),
|
'1c': root.getChildMeshes().find(m => m.name.includes('__TIME_7SEG_1C__')),
|
||||||
@@ -48,9 +62,9 @@ export const tabletopDigitalClock = defineObject({
|
|||||||
const colonMeshes = root.getChildMeshes().filter(m => m.name.includes('__TIME_7SEG_COLON__'));
|
const colonMeshes = root.getChildMeshes().filter(m => m.name.includes('__TIME_7SEG_COLON__'));
|
||||||
|
|
||||||
room.intervalIds.push(window.setInterval(() => {
|
room.intervalIds.push(window.setInterval(() => {
|
||||||
const onMeshes = get7segMeshesOfCurrentTime(meshes);
|
const onMeshes = get7segMeshesOfCurrentTime(segmentMeshes);
|
||||||
|
|
||||||
for (const mesh of Object.values(meshes)) {
|
for (const mesh of Object.values(segmentMeshes)) {
|
||||||
mesh.isVisible = onMeshes.includes(mesh);
|
mesh.isVisible = onMeshes.includes(mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user