diff --git a/src/components/ObjectView.tsx b/src/components/ObjectView.tsx index cd6cf07..90be0b2 100644 --- a/src/components/ObjectView.tsx +++ b/src/components/ObjectView.tsx @@ -1,7 +1,7 @@ import { observer } from "mobx-react-lite"; import type { ObjectInstance } from "../types"; import { useEffect, useRef, type RefObject } from "react"; -import type { Group, Mesh } from "three"; +import type { Group } from "three"; import { Edges, TransformControls } from "@react-three/drei"; import type { ThreeEvent } from "@react-three/fiber"; import { state } from "../state"; diff --git a/src/components/SceneView.tsx b/src/components/SceneView.tsx new file mode 100644 index 0000000..3013c45 --- /dev/null +++ b/src/components/SceneView.tsx @@ -0,0 +1,18 @@ +import { observer } from "mobx-react-lite"; +import type { Scene } from "../types"; +import { CharacterView } from "./CharacterView"; +import { ObjectView } from "./ObjectView"; + +type SceneViewProps = { + scene: Scene, +} + +export const SceneView = observer(function ({ scene }: SceneViewProps) { + return (<> + + + {Object.values(scene.objects).map((obj) => + )} + + ); +}); diff --git a/src/components/WorldView.tsx b/src/components/WorldView.tsx index c6c2e98..e4b7437 100644 --- a/src/components/WorldView.tsx +++ b/src/components/WorldView.tsx @@ -4,8 +4,7 @@ import { useFrame } from '@react-three/fiber'; import { OrbitControls } from '@react-three/drei'; import { observer } from 'mobx-react-lite'; import { state } from '../state'; -import { ObjectView } from './ObjectView'; -import { CharacterView } from './CharacterView'; +import { SceneView } from './SceneView'; export const WorldView = observer(function () { const world = state.world; @@ -34,9 +33,6 @@ export const WorldView = observer(function () { makeDefault enableDamping={false} /> - - - {Object.values(world.currentScene.objects).map((obj) => )} - + ) }); diff --git a/src/model/objectPrefabs/wolf.ts b/src/model/objectPrefabs/wolf.ts new file mode 100644 index 0000000..65a5fa9 --- /dev/null +++ b/src/model/objectPrefabs/wolf.ts @@ -0,0 +1,62 @@ +import type { Voxel } from "../../types/voxel"; + +const G = '#808080'; // gray fur +const L = '#d0c8b8'; // light beige-gray (snout / face) +const D = '#484040'; // dark gray (outer ear) +const E = '#e8b820'; // amber (eyes) +const N = '#181414'; // near-black (nose, pupils) +const P = '#c06858'; // pink (inner ear) + +function v(x: number, y: number, z: number, color: string): Voxel { + return { typeId: 'stone', position: [x, y, z], color }; +} + +// Wolf faces +Z (nose at Z=6). Head spans 7×7×7. +export const wolf: Voxel[] = [ + // ── Back of skull Z=0 ─────────────────────────────────────────── + v(2,3,0,G), v(3,3,0,G), v(4,3,0,G), + v(2,4,0,G), v(3,4,0,G), v(4,4,0,G), + v(2,5,0,G), v(3,5,0,G), v(4,5,0,G), + + // ── Skull Z=1 ─────────────────────────────────────────────────── + v(1,3,1,G), v(2,3,1,G), v(3,3,1,G), v(4,3,1,G), v(5,3,1,G), + v(1,4,1,G), v(2,4,1,G), v(3,4,1,G), v(4,4,1,G), v(5,4,1,G), + v(1,5,1,G), v(2,5,1,G), v(3,5,1,G), v(4,5,1,G), v(5,5,1,G), + v(2,6,1,G), v(3,6,1,G), v(4,6,1,G), + + // ── Skull + ear bases Z=2 ─────────────────────────────────────── + v(1,3,2,G), v(2,3,2,G), v(3,3,2,G), v(4,3,2,G), v(5,3,2,G), + v(1,4,2,G), v(2,4,2,G), v(3,4,2,G), v(4,4,2,G), v(5,4,2,G), + v(0,5,2,G), v(1,5,2,G), v(2,5,2,G), v(3,5,2,G), v(4,5,2,G), v(5,5,2,G), v(6,5,2,G), + v(1,6,2,G), v(2,6,2,G), v(3,6,2,G), v(4,6,2,G), v(5,6,2,G), + v(0,6,2,D), v(6,6,2,D), + + // ── Face + ears Z=3 ───────────────────────────────────────────── + v(1,3,3,L), v(2,3,3,L), v(3,3,3,L), v(4,3,3,L), v(5,3,3,L), + v(1,4,3,G), v(2,4,3,G), v(3,4,3,G), v(4,4,3,G), v(5,4,3,G), + // ears: dark outer, pink inner + v(0,5,3,D), v(1,5,3,P), v(2,5,3,G), v(3,5,3,G), v(4,5,3,G), v(5,5,3,P), v(6,5,3,D), + v(0,6,3,D), v(1,6,3,P), v(2,6,3,G), v(3,6,3,G), v(4,6,3,G), v(5,6,3,P), v(6,6,3,D), + // snout start + v(2,1,3,L), v(3,1,3,L), v(4,1,3,L), + v(2,2,3,L), v(3,2,3,L), v(4,2,3,L), + + // ── Face + amber eyes + snout Z=4 ─────────────────────────────── + v(1,3,4,L), v(2,3,4,L), v(3,3,4,L), v(4,3,4,L), v(5,3,4,L), + v(1,4,4,G), v(2,4,4,E), v(3,4,4,G), v(4,4,4,E), v(5,4,4,G), + v(1,5,4,G), v(2,5,4,G), v(3,5,4,G), v(4,5,4,G), v(5,5,4,G), + v(2,1,4,L), v(3,1,4,L), v(4,1,4,L), + v(2,2,4,L), v(3,2,4,L), v(4,2,4,L), + + // ── Front face + pupils + snout Z=5 ───────────────────────────── + v(1,3,5,L), v(2,3,5,L), v(3,3,5,L), v(4,3,5,L), v(5,3,5,L), + v(1,4,5,G), v(2,4,5,N), v(3,4,5,G), v(4,4,5,N), v(5,4,5,G), + v(1,5,5,G), v(2,5,5,G), v(3,5,5,G), v(4,5,5,G), v(5,5,5,G), + v(2,1,5,L), v(3,1,5,L), v(4,1,5,L), + v(2,2,5,L), v(3,2,5,L), v(4,2,5,L), + + // ── Snout tip + nose Z=6 ──────────────────────────────────────── + v(2,2,6,L), v(3,2,6,L), v(4,2,6,L), + v(2,1,6,L), v(3,1,6,L), v(4,1,6,L), + v(2,3,6,N), v(3,3,6,N), v(4,3,6,N), // nose +]; diff --git a/src/state/world.ts b/src/state/world.ts index c10a886..b98606f 100644 --- a/src/state/world.ts +++ b/src/state/world.ts @@ -7,6 +7,7 @@ import { clone } from "../utils"; import type { VoxelType } from "../types/voxel"; import { state } from "./root"; import { DEFAULT_VOXEL_TYPES } from "../model/defaultVoxelTypes"; +import { wolf } from "../model/objectPrefabs/wolf"; export class WorldState { public data: World = WorldFactory.create(); @@ -23,22 +24,14 @@ export class WorldState { } public loadMock() { - const objTypeId = 'test1'; - const voxelTypeId = 'glass'; const objectId1 = 'object1'; - const objectId2 = 'object2'; this.data = { objectTypes: { - [objTypeId]: { - id: objTypeId, - name: 'Test Object', - voxels: [ - { - typeId: voxelTypeId, - position: [0, 0, 0], - }, - ], + wolf: { + id: 'wolf', + name: 'Wolf', + voxels: wolf, }, }, voxelTypes: DEFAULT_VOXEL_TYPES, @@ -54,18 +47,12 @@ export class WorldState { objects: { [objectId1]: { id: objectId1, - typeId: objTypeId, + typeId: 'wolf', position: [0, 0, 0], rotation: [0, 0, 0], scale: [1, 1, 1], }, - [objectId2]: { - id: objectId2, - typeId: objTypeId, - position: [1, 0, 0], - rotation: [0, 0, 0], - scale: [1, 1, 1], - }, + }, }, gameRules: {