diff --git a/eslint.config.js b/eslint.config.js index e1d5f91..aef40fc 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -7,7 +7,7 @@ import tseslint from "typescript-eslint"; import { defineConfig, globalIgnores } from "eslint/config"; export default defineConfig([ - globalIgnores(["dist", "POC-grass"]), + globalIgnores(["dist"]), { files: ["**/*.{ts,tsx}"], extends: [ diff --git a/public/map.json b/public/map.json index bc281c5..a50a559 100644 --- a/public/map.json +++ b/public/map.json @@ -40201,7 +40201,7 @@ "scale": [1, 1, 1], "children": [ { - "name": "panneauxcentre", + "name": "panneauclassique", "type": "Object3D", "role": "group", "position": [0, 0, 0], @@ -40209,40 +40209,30 @@ "scale": [1, 1, 1], "children": [ { - "name": "panneauxcentre", + "name": "panneauclassique", "type": "Object3D", "position": [-35.2895, 3.8515, 40.1864], "rotation": [-3.0988, 0.9934, -3.1367], "scale": [1, 1, 1], "children": [ { - "name": "panneauxcentre", + "name": "panneauclassique", "type": "Mesh", "position": [-35.2895, 3.8515, 40.1864], "rotation": [-3.0988, 0.9934, -3.1367], "scale": [1, 1, 1] } ] - } - ] - }, - { - "name": "panneauxdomaine", - "type": "Object3D", - "role": "group", - "position": [0, 0, 0], - "rotation": [0, 0, 0], - "scale": [1, 1, 1], - "children": [ + }, { - "name": "panneauxdomaine", + "name": "panneauclassique", "type": "Object3D", "position": [-2.4347, 3.7803, -56.1439], "rotation": [0.0474, 0.2148, -0.0027], "scale": [1, 1, 1], "children": [ { - "name": "panneauxdomaine", + "name": "panneauclassique", "type": "Mesh", "position": [-2.4347, 3.7803, -56.1439], "rotation": [0.0474, 0.2148, -0.0027], @@ -40253,7 +40243,7 @@ ] }, { - "name": "panneaudirresidences2", + "name": "panneaufleche", "type": "Object3D", "role": "group", "position": [0, 0, 0], @@ -40261,118 +40251,78 @@ "scale": [1, 1, 1], "children": [ { - "name": "panneaudirresidences2", + "name": "panneaufleche", "type": "Object3D", "position": [30.1743, 7.1944, -13.5781], "rotation": [0.0374, -1.297, -0.0099], "scale": [1, 1, 1], "children": [ { - "name": "panneaudirresidences2", + "name": "panneaufleche", "type": "Mesh", "position": [30.1743, 7.1944, -13.5781], "rotation": [0.0374, -1.297, -0.0099], "scale": [1, 1, 1] } ] - } - ] - }, - { - "name": "panneaudirdomaine", - "type": "Object3D", - "role": "group", - "position": [0, 0, 0], - "rotation": [0, 0, 0], - "scale": [1, 1, 1], - "children": [ + }, { - "name": "panneaudirdomaine", + "name": "panneaufleche", "type": "Object3D", "position": [8.1032, 7.1918, -23.0004], "rotation": [0.0462, -0.2443, -0.0027], "scale": [1, 1, 1], "children": [ { - "name": "panneaudirdomaine", + "name": "panneaufleche", "type": "Mesh", "position": [8.1032, 7.1918, -23.0004], "rotation": [0.0462, -0.2443, -0.0027], "scale": [1, 1, 1] } ] - } - ] - }, - { - "name": "panneaudirresidences1", - "type": "Object3D", - "role": "group", - "position": [0, 0, 0], - "rotation": [0, 0, 0], - "scale": [1, 1, 1], - "children": [ + }, { - "name": "panneaudirresidences1", + "name": "panneaufleche", "type": "Object3D", "position": [-10.1125, 7.2582, -11.4511], "rotation": [0.0478, 0.3436, -0.0028], "scale": [1, 1, 1], "children": [ { - "name": "panneaudirresidences1", + "name": "panneaufleche", "type": "Mesh", "position": [-10.1125, 7.2582, -11.4511], "rotation": [0.0478, 0.3436, -0.0028], "scale": [1, 1, 1] } ] - } - ] - }, - { - "name": "panneaudircentre", - "type": "Object3D", - "role": "group", - "position": [0, 0, 0], - "rotation": [0, 0, 0], - "scale": [1, 1, 1], - "children": [ + }, { - "name": "panneaudircentre", + "name": "panneaufleche", "type": "Object3D", "position": [-10.5207, 7.0874, 19.3819], "rotation": [-3.1416, 1.5139, -3.0947], "scale": [1, 1, 1], "children": [ { - "name": "panneaudircentre", + "name": "panneaufleche", "type": "Mesh", "position": [-10.5207, 7.0874, 19.3819], "rotation": [-3.1416, 1.5139, -3.0947], "scale": [1, 1, 1] } ] - } - ] - }, - { - "name": "panneaudirfabrik", - "type": "Object3D", - "role": "group", - "position": [0, 0, 0], - "rotation": [0, 0, 0], - "scale": [1, 1, 1], - "children": [ + }, { - "name": "panneaudirfabrik", + "name": "panneaufleche", "type": "Object3D", "position": [29.0899, 6.9811, 23.4988], "rotation": [3.1416, -0.8852, 3.1253], "scale": [1, 1, 1], "children": [ { - "name": "panneaudirfabrik", + "name": "panneaufleche", "type": "Mesh", "position": [29.0899, 6.9811, 23.4988], "rotation": [3.1416, -0.8852, 3.1253], diff --git a/scripts/transformMap.cjs b/scripts/transformMap.cjs index cc119f8..798a91e 100644 --- a/scripts/transformMap.cjs +++ b/scripts/transformMap.cjs @@ -10,6 +10,13 @@ const MESH_NAME_MAPPINGS = { eoliennes: "eolienne", immeuble_1: "immeuble1", buissons: "buisson", + panneauxcentre: "panneauclassique", + panneauxdomaine: "panneauclassique", + panneaudircentre: "panneaufleche", + panneaudirdomaine: "panneaufleche", + panneaudirfabrik: "panneaufleche", + panneaudirresidences1: "panneaufleche", + panneaudirresidences2: "panneaufleche", panneauxquartier: "panneauaffichage", }; diff --git a/src/data/world/terrainConfig.ts b/src/data/world/terrainConfig.ts index fb6edb8..b2f358c 100644 --- a/src/data/world/terrainConfig.ts +++ b/src/data/world/terrainConfig.ts @@ -1,108 +1,58 @@ +import type { TerrainSurfaceColorConfig } from "@/types/world/terrainSurface"; + +export const TERRAIN_SURFACE_COLOR_TOLERANCE = 15; +export const TERRAIN_WATER_HEIGHT = 0; +export const TERRAIN_TILE_SIZE = 1; +export const GRASS_BASE_COLOR = "#1a3a1a"; + export const TERRAIN_COLORS = { grass1: { hex: "#84C66B", rgb: [132, 198, 107] as const, - type: "grass" as const, + kind: "grass", grassTipColor: "#84C66B", }, grass2: { hex: "#67B058", rgb: [103, 176, 88] as const, - type: "grass" as const, + kind: "grass", grassTipColor: "#67B058", }, grass3: { hex: "#A3CA5B", rgb: [163, 202, 91] as const, - type: "grass" as const, + kind: "grass", grassTipColor: "#A3CA5B", }, potager: { hex: "#342420", rgb: [52, 36, 32] as const, - type: "tile" as const, - tileModel: "/models/potager/potager.gltf", - tileSize: 1, + kind: "garden", + modelPath: "/models/potager/potager.gltf", + tileSize: TERRAIN_TILE_SIZE, }, terre: { hex: "#513E2C", rgb: [81, 62, 44] as const, - type: "none" as const, + kind: "dirt", }, chemin: { hex: "#F5D896", rgb: [245, 216, 150] as const, - type: "tile" as const, - tileModel: "/models/chemins/model.gltf", - tileSize: 1, + kind: "path", + modelPath: "/models/chemins/model.gltf", + tileSize: TERRAIN_TILE_SIZE, }, eau: { hex: "#91DAF5", rgb: [145, 218, 245] as const, - type: "water" as const, + kind: "water", }, cailloux: { hex: "#B6D3DE", rgb: [182, 211, 222] as const, - type: "none" as const, + kind: "rock", }, -} as const; +} satisfies Record; export type TerrainColorKey = keyof typeof TERRAIN_COLORS; -export type TerrainType = "grass" | "tile" | "water" | "none"; - -export const GRASS_BASE_COLOR = "#1a3a1a"; - -export const COLOR_TOLERANCE = 15; - -export function colorMatchesTerrain( - r: number, - g: number, - b: number, - targetRgb: readonly [number, number, number], - tolerance: number = COLOR_TOLERANCE, -): boolean { - return ( - Math.abs(r - targetRgb[0]) <= tolerance && - Math.abs(g - targetRgb[1]) <= tolerance && - Math.abs(b - targetRgb[2]) <= tolerance - ); -} - -export function getTerrainTypeFromColor( - r: number, - g: number, - b: number, -): TerrainColorKey | null { - for (const [key, config] of Object.entries(TERRAIN_COLORS)) { - if (colorMatchesTerrain(r, g, b, config.rgb)) { - return key as TerrainColorKey; - } - } - return null; -} - -export function isGrassZone(r: number, g: number, b: number): boolean { - return ( - colorMatchesTerrain(r, g, b, TERRAIN_COLORS.grass1.rgb) || - colorMatchesTerrain(r, g, b, TERRAIN_COLORS.grass2.rgb) || - colorMatchesTerrain(r, g, b, TERRAIN_COLORS.grass3.rgb) - ); -} - -export function getGrassTipColor( - r: number, - g: number, - b: number, -): string | null { - if (colorMatchesTerrain(r, g, b, TERRAIN_COLORS.grass1.rgb)) { - return TERRAIN_COLORS.grass1.grassTipColor; - } - if (colorMatchesTerrain(r, g, b, TERRAIN_COLORS.grass2.rgb)) { - return TERRAIN_COLORS.grass2.grassTipColor; - } - if (colorMatchesTerrain(r, g, b, TERRAIN_COLORS.grass3.rgb)) { - return TERRAIN_COLORS.grass3.grassTipColor; - } - return null; -} diff --git a/src/types/world/terrainSurface.ts b/src/types/world/terrainSurface.ts new file mode 100644 index 0000000..ec625c2 --- /dev/null +++ b/src/types/world/terrainSurface.ts @@ -0,0 +1,18 @@ +export type TerrainSurfaceKind = + | "grass" + | "path" + | "water" + | "garden" + | "dirt" + | "rock"; + +export type TerrainSurfaceRgb = readonly [number, number, number]; + +export interface TerrainSurfaceColorConfig { + hex: string; + rgb: TerrainSurfaceRgb; + kind: TerrainSurfaceKind; + grassTipColor?: string; + modelPath?: string; + tileSize?: number; +} diff --git a/src/utils/world/terrainSurfaceColor.ts b/src/utils/world/terrainSurfaceColor.ts new file mode 100644 index 0000000..277c4d5 --- /dev/null +++ b/src/utils/world/terrainSurfaceColor.ts @@ -0,0 +1,51 @@ +import { + TERRAIN_COLORS, + TERRAIN_SURFACE_COLOR_TOLERANCE, + type TerrainColorKey, +} from "@/data/world/terrainConfig"; +import type { TerrainSurfaceRgb } from "@/types/world/terrainSurface"; + +export function colorMatchesTerrainSurface( + r: number, + g: number, + b: number, + targetRgb: TerrainSurfaceRgb, + tolerance: number = TERRAIN_SURFACE_COLOR_TOLERANCE, +): boolean { + return ( + Math.abs(r - targetRgb[0]) <= tolerance && + Math.abs(g - targetRgb[1]) <= tolerance && + Math.abs(b - targetRgb[2]) <= tolerance + ); +} + +export function getTerrainColorKeyFromRgb( + r: number, + g: number, + b: number, +): TerrainColorKey | null { + for (const [key, config] of Object.entries(TERRAIN_COLORS)) { + if (colorMatchesTerrainSurface(r, g, b, config.rgb)) { + return key as TerrainColorKey; + } + } + + return null; +} + +export function isGrassTerrainColor(r: number, g: number, b: number): boolean { + const key = getTerrainColorKeyFromRgb(r, g, b); + return key !== null && TERRAIN_COLORS[key].kind === "grass"; +} + +export function getGrassTipColorFromRgb( + r: number, + g: number, + b: number, +): string | null { + const key = getTerrainColorKeyFromRgb(r, g, b); + if (key === null) return null; + + const terrainColor = TERRAIN_COLORS[key]; + return "grassTipColor" in terrainColor ? terrainColor.grassTipColor : null; +}