- Wall N
- { update({ walls: { ...options.walls, n: v } }); }">
+ Walls
+
+
+
+ Wall N
+ { update({ walls: { ...options.walls, n: v } }); }">
+
+
+
+ Wall S
+ { update({ walls: { ...options.walls, s: v } }); }">
+
+
+
+ Wall W
+ { update({ walls: { ...options.walls, w: v } }); }">
+
+
+
+ Wall E
+ { update({ walls: { ...options.walls, e: v } }); }">
+
+
- Wall S
- { update({ walls: { ...options.walls, s: v } }); }">
-
+
Pillars
-
- Wall W
- { update({ walls: { ...options.walls, w: v } }); }">
-
+
+
+ Pillar NW
+ { update({ pillars: { ...options.pillars, nw: v } }); }">
+
-
- Wall E
- { update({ walls: { ...options.walls, e: v } }); }">
+
+ Pillar NE
+ { update({ pillars: { ...options.pillars, ne: v } }); }">
+
+
+
+ Pillar SW
+ { update({ pillars: { ...options.pillars, sw: v } }); }">
+
+
+
+ Pillar SE
+ { update({ pillars: { ...options.pillars, se: v } }); }">
+
+
@@ -64,6 +96,7 @@ SPDX-License-Identifier: AGPL-3.0-only
+
+
diff --git a/packages/frontend/src/pages/room.vue b/packages/frontend/src/pages/room.vue
index f4f4e313eb..b781384ec1 100644
--- a/packages/frontend/src/pages/room.vue
+++ b/packages/frontend/src/pages/room.vue
@@ -207,6 +207,28 @@ const data = localStorage.getItem('roomData') != null ? JSON.parse(localStorage.
withHabaki: false,
},
},
+ pillars: {
+ nw: {
+ material: null,
+ color: [0.9, 0.9, 0.9],
+ show: false,
+ },
+ ne: {
+ material: null,
+ color: [0.9, 0.9, 0.9],
+ show: false,
+ },
+ sw: {
+ material: null,
+ color: [0.9, 0.9, 0.9],
+ show: false,
+ },
+ se: {
+ material: null,
+ color: [0.9, 0.9, 0.9],
+ show: false,
+ },
+ },
flooring: {
material: 'wood',
color: [0.9, 0.9, 0.9],
@@ -257,6 +279,30 @@ if (data.heya.options.walls == null) {
},
};
}
+if (data.heya.options.pillars == null) {
+ data.heya.options.pillars = {
+ nw: {
+ material: null,
+ color: [0.9, 0.9, 0.9],
+ show: false,
+ },
+ ne: {
+ material: null,
+ color: [0.9, 0.9, 0.9],
+ show: false,
+ },
+ sw: {
+ material: null,
+ color: [0.9, 0.9, 0.9],
+ show: false,
+ },
+ se: {
+ material: null,
+ color: [0.9, 0.9, 0.9],
+ show: false,
+ },
+ };
+}
let latestData = deepClone(data);
diff --git a/packages/frontend/src/world/room/heya.ts b/packages/frontend/src/world/room/heya.ts
index ad08cdbfb9..a77cddd1a5 100644
--- a/packages/frontend/src/world/room/heya.ts
+++ b/packages/frontend/src/world/room/heya.ts
@@ -1,3 +1,4 @@
+/* eslint-disable id-denylist */
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
@@ -26,24 +27,22 @@ export abstract class HeyaManager {
abstract dispose(): void;
}
-type SimpleHeyaWallBase = {
- material: null | 'wood' | 'concrete';
- color: [number, number, number];
- withHari: boolean;
- hariMaterial: null | 'wood' | 'concrete';
- hariColor: [number, number, number];
- withHabaki: boolean;
-};
-
export type SimpleHeyaOptions = {
dimension: [number, number];
window: 'none' | 'kosidakamado' | 'demado' | 'hakidasimado';
- walls: {
- n: SimpleHeyaWallBase;
- s: SimpleHeyaWallBase;
- w: SimpleHeyaWallBase;
- e: SimpleHeyaWallBase;
- };
+ walls: Record<'n' | 's' | 'w' | 'e', {
+ material: null | 'wood' | 'concrete';
+ color: [number, number, number];
+ withHari: boolean;
+ hariMaterial: null | 'wood' | 'concrete';
+ hariColor: [number, number, number];
+ withHabaki: boolean;
+ }>;
+ pillars: Record<'nw' | 'ne' | 'sw' | 'se', {
+ material: null | 'wood' | 'concrete';
+ color: [number, number, number];
+ show: boolean;
+ }>;
flooring: {
material: null | 'wood' | 'concrete';
color: [number, number, number];
@@ -58,27 +57,16 @@ export type JapaneseHeyaOptions = {
window: 'none' | 'kosidakamado' | 'demado' | 'hakidasimado';
};
+// TODO: マテリアルは必要になるまで作成しないようにする
+
export class SimpleHeyaManager extends HeyaManager {
private loaderResult: BABYLON.ISceneLoaderAsyncResult | null = null;
private meshes: BABYLON.Mesh[] = [];
- private wallRoots: {
- n: BABYLON.TransformNode;
- s: BABYLON.TransformNode;
- w: BABYLON.TransformNode;
- e: BABYLON.TransformNode;
- } | null = null;
- private wallMaterials: {
- n: BABYLON.PBRMaterial;
- s: BABYLON.PBRMaterial;
- w: BABYLON.PBRMaterial;
- e: BABYLON.PBRMaterial;
- } | null = null;
- private wallHariMaterials: {
- n: BABYLON.PBRMaterial;
- s: BABYLON.PBRMaterial;
- w: BABYLON.PBRMaterial;
- e: BABYLON.PBRMaterial;
- } | null = null;
+ private wallRoots: Record<'n' | 's' | 'w' | 'e', BABYLON.TransformNode> = null as any;
+ private wallMaterials: Record<'n' | 's' | 'w' | 'e', BABYLON.PBRMaterial> | null = null;
+ private wallHariMaterials: Record<'n' | 's' | 'w' | 'e', BABYLON.PBRMaterial> | null = null;
+ private pillarRoots: Record<'nw' | 'ne' | 'sw' | 'se', BABYLON.TransformNode> | null = null;
+ private pillarMaterials: Record<'nw' | 'ne' | 'sw' | 'se', BABYLON.PBRMaterial> | null = null;
private ceilingMaterial: BABYLON.PBRMaterial | null = null;
private floorMaterial: BABYLON.PBRMaterial | null = null;
@@ -121,6 +109,13 @@ export class SimpleHeyaManager extends HeyaManager {
e: this.loaderResult.transformNodes.find(t => t.name.includes('__WALL_E__'))!,
};
+ this.pillarRoots = {
+ nw: this.loaderResult.transformNodes.find(t => t.name.includes('__PILLAR_NW__'))!,
+ ne: this.loaderResult.transformNodes.find(t => t.name.includes('__PILLAR_NE__'))!,
+ sw: this.loaderResult.transformNodes.find(t => t.name.includes('__PILLAR_SW__'))!,
+ se: this.loaderResult.transformNodes.find(t => t.name.includes('__PILLAR_SE__'))!,
+ };
+
const wallMaterial = findMaterial(this.meshes[0], '__X_WALL__');
this.wallMaterials = {
n: wallMaterial.clone('wallNMaterial'),
@@ -137,6 +132,14 @@ export class SimpleHeyaManager extends HeyaManager {
e: hariMaterial.clone('wallEHariMaterial'),
};
+ const pillarMaterial = findMaterial(this.meshes[0], '__X_PILLAR__');
+ this.pillarMaterials = {
+ nw: pillarMaterial.clone('pillarNWMaterial'),
+ ne: pillarMaterial.clone('pillarNEMaterial'),
+ sw: pillarMaterial.clone('pillarSWMaterial'),
+ se: pillarMaterial.clone('pillarSEMaterial'),
+ };
+
for (const [k, v] of Object.entries(this.wallRoots)) {
for (const m of v.getChildMeshes().filter(m => m.material === wallMaterial)) {
m.material = this.wallMaterials[k];
@@ -145,6 +148,11 @@ export class SimpleHeyaManager extends HeyaManager {
m.material = this.wallHariMaterials[k];
}
}
+ for (const [k, v] of Object.entries(this.pillarRoots)) {
+ for (const m of v.getChildMeshes().filter(m => m.material === pillarMaterial)) {
+ m.material = this.pillarMaterials[k];
+ }
+ }
this.ceilingMaterial = findMaterial(this.meshes[0], '__X_CEILING__');
this.floorMaterial = findMaterial(this.meshes[0], '__X_FLOOR__');
@@ -161,9 +169,9 @@ export class SimpleHeyaManager extends HeyaManager {
for (const mesh of wallRoot.getChildMeshes()) {
if (mesh.name.includes('__X_HARI__')) {
- mesh.isVisible = wallOptions.withHari;
+ mesh.setEnabled(wallOptions.withHari);
} else if (mesh.name.includes('__X_HABAKI__')) {
- mesh.isVisible = wallOptions.withHabaki;
+ mesh.setEnabled(wallOptions.withHabaki);
}
}
@@ -208,6 +216,31 @@ export class SimpleHeyaManager extends HeyaManager {
}
}
+ for (const type of ['nw', 'ne', 'sw', 'se'] as const) {
+ const pillarRoot = this.pillarRoots[type];
+ const pillarOptions = options.pillars[type];
+
+ pillarRoot.setEnabled(pillarOptions.show);
+
+ const targetMaterial = this.pillarMaterials[type];
+
+ targetMaterial.unfreeze();
+ targetMaterial.albedoColor = new BABYLON.Color3(...pillarOptions.color);
+
+ const texPath = pillarOptions.material === 'wood' ? '/client-assets/room/textures/wall-wood2.png'
+ : pillarOptions.material === 'concrete' ? '/client-assets/room/textures/wall-concrete.png'
+ : null;
+
+ if (texPath != null) {
+ const tex = new BABYLON.Texture(texPath, this.meshes[0].getScene(), false, false);
+ targetMaterial.albedoTexture = tex;
+ } else {
+ targetMaterial.albedoTexture = null;
+ }
+
+ targetMaterial.freeze();
+ }
+
{
this.ceilingMaterial.unfreeze();
this.ceilingMaterial.albedoColor = new BABYLON.Color3(...options.ceiling.color);
@@ -250,14 +283,14 @@ export class SimpleHeyaManager extends HeyaManager {
public dispose() {
if (this.loaderResult != null) {
for (const m of this.loaderResult.meshes) {
- m.dispose();
+ m.dispose(false, true);
}
for (const t of this.loaderResult.transformNodes) {
- t.dispose();
+ t.dispose(false, true);
}
}
for (const m of this.meshes) {
- m.dispose();
+ m.dispose(false, true);
}
for (const m of Object.values(this.wallMaterials ?? {})) {
m.dispose();
@@ -265,5 +298,8 @@ export class SimpleHeyaManager extends HeyaManager {
for (const m of Object.values(this.wallHariMaterials ?? {})) {
m.dispose();
}
+ for (const m of Object.values(this.pillarMaterials ?? {})) {
+ m.dispose();
+ }
}
}