From 7dff4a1238bd7919e676e517f7196397a1810ed3 Mon Sep 17 00:00:00 2001 From: Tom Boullay Date: Mon, 1 Jun 2026 00:09:39 +0200 Subject: [PATCH] feat(characters): populate residential zones --- src/components/three/models/AnimatedModel.tsx | 16 ++-- src/data/world/characters/characterConfig.ts | 77 ++++++++++++++++++- 2 files changed, 85 insertions(+), 8 deletions(-) diff --git a/src/components/three/models/AnimatedModel.tsx b/src/components/three/models/AnimatedModel.tsx index 02e149a..2cb429c 100644 --- a/src/components/three/models/AnimatedModel.tsx +++ b/src/components/three/models/AnimatedModel.tsx @@ -1,5 +1,6 @@ -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import { useAnimations } from "@react-three/drei"; +import { SkeletonUtils } from "three-stdlib"; import type { AnimationAction } from "three"; import { AnimatedModelContext, @@ -43,7 +44,8 @@ export function AnimatedModel({ rotation, scale, }); - const { actions, names, mixer } = useAnimations(animations, scene); + const model = useMemo(() => SkeletonUtils.clone(scene), [scene]); + const { actions, names, mixer } = useAnimations(animations, model); const [currentAnim, setCurrentAnim] = useState(defaultAnimation); const isReady = names.length > 0; @@ -154,21 +156,21 @@ export function AnimatedModel({ }; useEffect(() => { - scene.position.set(...position); - scene.rotation.set(rotation[0], rotation[1], rotation[2]); + model.position.set(...position); + model.rotation.set(rotation[0], rotation[1], rotation[2]); const parsedScale = typeof scale === "number" ? [scale, scale, scale] : (scale ?? [1, 1, 1]); - scene.scale.set( + model.scale.set( parsedScale[0] ?? 1, parsedScale[1] ?? 1, parsedScale[2] ?? 1, ); - }, [scene, position, rotation, scale]); + }, [model, position, rotation, scale]); return ( - + {children} ); diff --git a/src/data/world/characters/characterConfig.ts b/src/data/world/characters/characterConfig.ts index 0390a61..579cb55 100644 --- a/src/data/world/characters/characterConfig.ts +++ b/src/data/world/characters/characterConfig.ts @@ -1,6 +1,15 @@ import type { Vector3Tuple } from "@/types/three/three"; -export type CharacterId = "electricienne" | "gerant" | "fermier"; +export type CharacterId = + | "electricienne" + | "gerant" + | "fermier" + | "zone1_habitant1" + | "zone1_habitant2" + | "zone2_habitant1" + | "zone2_habitant2" + | "zone3_habitant1" + | "zone3_habitant2"; export interface CharacterConfig { id: CharacterId; @@ -44,10 +53,76 @@ export const CHARACTER_CONFIGS = { animations: ["idle", "walk"], defaultAnimation: "idle", }, + zone1_habitant1: { + id: "zone1_habitant1", + label: "Zone 1 - Habitant 1", + modelPath: "/models/habitant1-animated/model.gltf", + position: [-43.64, 0, -16.72], + rotation: [0, -1.23, 0], + scale: [1.55, 1.55, 1.55], + animations: ["idle", "walk"], + defaultAnimation: "idle", + }, + zone1_habitant2: { + id: "zone1_habitant2", + label: "Zone 1 - Habitant 2", + modelPath: "/models/habitant2-animated/model.gltf", + position: [-43.46, 0, -4.93], + rotation: [0, -2.42, 0], + scale: [1.55, 1.55, 1.55], + animations: ["idle", "walk"], + defaultAnimation: "idle", + }, + zone2_habitant1: { + id: "zone2_habitant1", + label: "Zone 2 - Habitant 1", + modelPath: "/models/habitant1-animated/model.gltf", + position: [-3.41, 0, 73.01], + rotation: [0, 1.97, 0], + scale: [1.55, 1.55, 1.55], + animations: ["idle", "walk"], + defaultAnimation: "idle", + }, + zone2_habitant2: { + id: "zone2_habitant2", + label: "Zone 2 - Habitant 2", + modelPath: "/models/habitant2-animated/model.gltf", + position: [-2.22, 0, 60.59], + rotation: [0, 0.86, 0], + scale: [1.55, 1.55, 1.55], + animations: ["idle", "walk"], + defaultAnimation: "idle", + }, + zone3_habitant1: { + id: "zone3_habitant1", + label: "Zone 3 - Habitant 1", + modelPath: "/models/habitant1-animated/model.gltf", + position: [82.52, 0, -29.01], + rotation: [0, -0.89, 0], + scale: [1.55, 1.55, 1.55], + animations: ["idle", "walk"], + defaultAnimation: "idle", + }, + zone3_habitant2: { + id: "zone3_habitant2", + label: "Zone 3 - Habitant 2", + modelPath: "/models/habitant2-animated/model.gltf", + position: [92.95, 0, -18.1], + rotation: [0, -1.59, 0], + scale: [1.55, 1.55, 1.55], + animations: ["idle", "walk"], + defaultAnimation: "idle", + }, } satisfies Record; export const CHARACTER_IDS = [ "electricienne", "gerant", "fermier", + "zone1_habitant1", + "zone1_habitant2", + "zone2_habitant1", + "zone2_habitant2", + "zone3_habitant1", + "zone3_habitant2", ] as const satisfies readonly CharacterId[];