diff --git a/README.md b/README.md index 4df4527ab..0a9f8e357 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,12 @@ is neither mapped to a slot nor listed in ignoredObjects in theme-slots.json. - **Add a slot to the root `theme-slots.json` only for a genuinely new role.** Every theme is missing it until someone fills it in the assets repository: those objects keep their placeholder art in the meantime, which is not an - error. + error. Give it a `description` saying what its objects do in the starters + and what fits it: the authors of themes choose its asset from it (the gun of + the FPS starters must shoot, a crop must grow from the soil). +- **Map an object only to a slot whose description fits what it does.** A seed + planted in a plot is not a small rock: every theme would show a rock (or a + bone, or a wheel) instead. List it in `ignoredObjects` if no slot fits. - **List in `ignoredObjects`** what is not meant to be seen as art: the camera anchor cube, an invisible collision helper, the faceless player of a first person game. diff --git a/examples/starting-expanded-first-person-farming/theme-slots.json b/examples/starting-expanded-first-person-farming/theme-slots.json index 1740da005..039606a98 100644 --- a/examples/starting-expanded-first-person-farming/theme-slots.json +++ b/examples/starting-expanded-first-person-farming/theme-slots.json @@ -12,8 +12,6 @@ "scene:Game Scene/Beet": "crop.b", "scene:Game Scene/Harvest_Seed_Beet": "prop.container", "scene:Game Scene/Harvest_Seed_Carrot": "prop.container", - "scene:Game Scene/Seed_Beet": "nature.rock.small", - "scene:Game Scene/Seed_Carrot": "nature.rock.small", "scene:Game Scene/Barn": "building.tower", "scene:Game Scene/SmallBarn": "building.tower", "scene:Game Scene/ChickenCoop": "building.tower", @@ -69,6 +67,8 @@ "object:Water3D::Water3D/AreaPlaceholder", "object:Terrain3D::Terrain3D/AreaPlaceholder", "object:Terrain3D::TerrainGrass/AreaPlaceholder", - "object:Terrain3D::ScatteredModels/AreaPlaceholder" + "object:Terrain3D::ScatteredModels/AreaPlaceholder", + "scene:Game Scene/Seed_Beet", + "scene:Game Scene/Seed_Carrot" ] } diff --git a/examples/starting-first-person-farming/theme-slots.json b/examples/starting-first-person-farming/theme-slots.json index 92d6fc8a2..647bcb506 100644 --- a/examples/starting-first-person-farming/theme-slots.json +++ b/examples/starting-first-person-farming/theme-slots.json @@ -15,8 +15,6 @@ "scene:Game Scene/Beet": "crop.b", "scene:Game Scene/Harvest_Seed_Beet": "prop.container", "scene:Game Scene/Harvest_Seed_Carrot": "prop.container", - "scene:Game Scene/Seed_Beet": "nature.rock.small", - "scene:Game Scene/Seed_Carrot": "nature.rock.small", "scene:Game Scene/Walls": { "front": "env.wall", "left": "env.wall", @@ -29,6 +27,8 @@ "effect:Game Scene//Effect2": "sky.day" }, "ignoredObjects": [ - "scene:Game Scene/Player" + "scene:Game Scene/Player", + "scene:Game Scene/Seed_Beet", + "scene:Game Scene/Seed_Carrot" ] } diff --git a/scripts/lib/ThemeSlots.js b/scripts/lib/ThemeSlots.js index e752cb1bc..42c427aa7 100644 --- a/scripts/lib/ThemeSlots.js +++ b/scripts/lib/ThemeSlots.js @@ -3,10 +3,11 @@ const path = require('path'); const fs = require('fs').promises; /** - * The vocabulary of slots a theme can fill, shared by every starter. + * The vocabulary of slots a theme can fill, shared by every starter. The + * description of a slot is what the authors of themes read to choose its asset. * @typedef {{ * version: number, - * slots: Array<{id: string, kind: ThemeSlotKind, label: string}>, + * slots: Array<{id: string, kind: ThemeSlotKind, label: string, description: string}>, * }} ThemeSlotsVocabulary * * @typedef {'model' | 'texture' | 'material' | 'skybox' | 'color'} ThemeSlotKind diff --git a/scripts/lib/__tests__/ThemeSlots.spec.js b/scripts/lib/__tests__/ThemeSlots.spec.js index 14134a2e7..f5d520e89 100644 --- a/scripts/lib/__tests__/ThemeSlots.spec.js +++ b/scripts/lib/__tests__/ThemeSlots.spec.js @@ -11,13 +11,48 @@ const { const vocabulary = { version: 1, slots: [ - { id: 'character.player', kind: 'model', label: 'Player character' }, - { id: 'nature.tree', kind: 'model', label: 'Tree' }, - { id: 'env.ground', kind: 'texture', label: 'Ground' }, - { id: 'env.wall', kind: 'texture', label: 'Wall' }, - { id: 'sky.day', kind: 'skybox', label: 'Daytime sky' }, - { id: 'terrain.ground', kind: 'material', label: 'Terrain ground' }, - { id: 'terrain.grass.tip', kind: 'color', label: 'Grass tip color' }, + { + id: 'character.player', + kind: 'model', + label: 'Player character', + description: 'The character the player controls.', + }, + { + id: 'nature.tree', + kind: 'model', + label: 'Tree', + description: 'The trees.', + }, + { + id: 'env.ground', + kind: 'texture', + label: 'Ground', + description: 'The texture of the ground.', + }, + { + id: 'env.wall', + kind: 'texture', + label: 'Wall', + description: 'The texture of the walls.', + }, + { + id: 'sky.day', + kind: 'skybox', + label: 'Daytime sky', + description: 'The sky.', + }, + { + id: 'terrain.ground', + kind: 'material', + label: 'Terrain ground', + description: 'The main ground of a terrain.', + }, + { + id: 'terrain.grass.tip', + kind: 'color', + label: 'Grass tip color', + description: 'The color of the grass blades at their tip.', + }, ], }; diff --git a/theme-slots.json b/theme-slots.json index 0835de675..a5e011451 100644 --- a/theme-slots.json +++ b/theme-slots.json @@ -4,222 +4,266 @@ { "id": "character.player", "kind": "model", - "label": "Player character" + "label": "Player character", + "description": "The character the player controls: walks, runs and jumps in the platformer, GTA, endless runner, RPG and point-and-click starters, or a unit selected and moved in the RTS and tile starters. A rigged character with Idle, Walk, Run, Jump and Death animations." }, { "id": "character.enemy", "kind": "model", - "label": "Enemy character" + "label": "Enemy character", + "description": "An opponent the player fights: it chases the player and is shot in the FPS with enemies and the vampire survivor, and it is the target blown away by the tank. A rigged character with Idle, Walk or Run and Death animations, recognizable as hostile." }, { "id": "character.npc", "kind": "model", - "label": "NPC or ally character" + "label": "NPC or ally character", + "description": "A friendly character the player walks to and talks to (RPG, point-and-click): it stands and opens a dialog. A rigged character with an Idle animation, recognizable as friendly." }, { "id": "character.monster", "kind": "model", - "label": "Monster or creature" + "label": "Monster or creature", + "description": "The creature hunting the player in the horror starters: it roams, chases the player and ends the game when it catches them, and is shot in the FPS horror. A rigged creature with Idle and Walk or Run animations, scarier than character.enemy." }, { "id": "vehicle.car", "kind": "model", - "label": "Drivable ground vehicle" + "label": "Drivable ground vehicle", + "description": "The vehicle the player drives on the ground (driving, racing, GTA): a car, kart, truck, tractor or sled. Not a boat or an aircraft." }, { "id": "vehicle.aircraft.player", "kind": "model", - "label": "Player aircraft" + "label": "Player aircraft", + "description": "The flying vehicle the player pilots (flight simulator, shoot'em up, twin-stick shooter): a plane, spaceship or any flying vessel." }, { "id": "vehicle.aircraft.enemy", "kind": "model", - "label": "Enemy aircraft" + "label": "Enemy aircraft", + "description": "The flying vehicles the player shoots down in the shoot'em up and the twin-stick shooter." }, { "id": "vehicle.tank.base", "kind": "model", - "label": "Turret vehicle base" + "label": "Turret vehicle base", + "description": "The hull of the tank, which drives. Fill the three tank slots from the same model set." }, { "id": "vehicle.tank.turret", "kind": "model", - "label": "Turret vehicle turret" + "label": "Turret vehicle turret", + "description": "The turret of the tank, which rotates on the hull. Fill the three tank slots from the same model set." }, { "id": "vehicle.tank.cannon", "kind": "model", - "label": "Turret vehicle cannon" + "label": "Turret vehicle cannon", + "description": "The barrel of the tank, which aims up and down and fires. Fill the three tank slots from the same model set." }, { "id": "weapon.handheld", "kind": "model", - "label": "First person weapon" + "label": "First person weapon", + "description": "The gun held in first-person view in the FPS starters: the player aims it with the crosshair and fires it, and its bullets hit what it points at. It must shoot: a pistol, rifle, shotgun, blaster, crossbow or bow. Never a melee weapon or a tool (sword, axe, shovel, candy cane)." }, { "id": "projectile.player", "kind": "model", - "label": "Player projectile" + "label": "Player projectile", + "description": "What the player fires: the bullets of the shoot'em up, twin-stick shooter and vampire survivor, and the tank shell, which explodes where it lands. Small and flying: a bullet, arrow, cannonball, fireball or snowball." }, { "id": "projectile.enemy", "kind": "model", - "label": "Enemy projectile" + "label": "Enemy projectile", + "description": "What the enemies fire at the player in the shoot'em up. Small and flying, and different from projectile.player." }, { "id": "pickup.coin", "kind": "model", - "label": "Coin or currency pickup" + "label": "Coin or currency pickup", + "description": "A collectible the player picks up by walking into it, counted as a score (the coins of the platformer). Small and rewarding: a coin, gem, star or fruit." }, { "id": "hazard.spike", "kind": "model", - "label": "Hazard or trap" + "label": "Hazard or trap", + "description": "A trap the player must avoid in the endless runner: touching it fails the run. Clearly dangerous: spikes, a saw, fire or a mine." }, { "id": "nature.tree", "kind": "model", - "label": "Tree" + "label": "Tree", + "description": "The trees: scattered by the thousands in the forests of the expanded starters, where the player and vehicles collide with their trunks, and placed on tiles in the tile placement starters. Something tall growing from the ground, in the style of the setting: a pine, palm, dead tree or alien plant." }, { "id": "nature.grass", "kind": "model", - "label": "Grass or bush" + "label": "Grass or bush", + "description": "Small vegetation scattered densely on the ground of the expanded starters, which the player walks through (it has no collision), and the decorative grass of the RPG, RTS and point-and-click starters. Low and small: grass, a bush, flowers or mushrooms. Not a tree or an object." }, { "id": "nature.rock.big", "kind": "model", - "label": "Large rock" + "label": "Large rock", + "description": "Large rocks scattered on the terrain of the expanded starters, where the player and vehicles collide with them: boulders that block the way." }, { "id": "nature.rock.small", "kind": "model", - "label": "Small rock" + "label": "Small rock", + "description": "Small stones scattered densely on the ground of the expanded starters, walked over: pebbles and small rocks." }, { "id": "resource.log", "kind": "model", - "label": "Log or raw resource" + "label": "Log or raw resource", + "description": "A raw material lying on the ground: the logs harvested and carried in the survival crafting starters, and the fallen logs of the horror forests. A log, branch, plank or bundle of material." }, { "id": "crop.a", "kind": "model", - "label": "First crop or food item" + "label": "First crop or food item", + "description": "The first crop of the farming starters: it grows from a seed planted in a dirt plot, and is picked up when grown. Something grown from the soil: a vegetable, fruit, pumpkin or mushroom. Not cooked food or an object. Different from crop.b." }, { "id": "crop.b", "kind": "model", - "label": "Second crop or food item" + "label": "Second crop or food item", + "description": "The second crop of the farming starters: it grows from a seed planted in a dirt plot, and is picked up when grown. Something grown from the soil: a vegetable, fruit, pumpkin or mushroom. Not cooked food or an object. Different from crop.a." }, { "id": "prop.container", "kind": "model", - "label": "Bag, crate or chest" + "label": "Bag, crate or chest", + "description": "A container: the seed bags the player clicks to get seeds in the farming starters, and the crates and shipping containers used as cover in the FPS with enemies and the tank. A bag, crate, barrel or chest." }, { "id": "building.tower", "kind": "model", - "label": "Tower or placeable building" + "label": "Tower or placeable building", + "description": "A building: the tower placed on a tile in the tile placement starters, and the houses of the villages of the expanded starters. A building or tower of the setting, standing on its own." }, { "id": "prop.obstacle", "kind": "model", - "label": "Road or track obstacle" + "label": "Road or track obstacle", + "description": "A light obstacle on a road or track: the traffic cones the car knocks away, the barriers along the racing track. Something a vehicle hits and pushes: a cone, barrier, fence piece or crate." }, { "id": "env.ground", "kind": "texture", - "label": "Ground" + "label": "Ground", + "description": "The texture of flat ground boxes: the ground of the starters without a terrain." }, { "id": "env.ground.tiled", "kind": "texture", - "label": "Ground with a tile grid" + "label": "Ground with a tile grid", + "description": "The texture of floors and grounds with a visible tile grid: the floor of the camera monitoring building, and the grounds of the RTS, flight simulator, shoot'em up and point-and-click starters." }, { "id": "env.wall", "kind": "texture", - "label": "Wall and building faces" + "label": "Wall and building faces", + "description": "The texture of walls, platforms and building faces made of boxes." }, { "id": "env.road", "kind": "texture", - "label": "Road or track surface" + "label": "Road or track surface", + "description": "The texture of roads and tracks made of boxes (driving, racing, tank)." }, { "id": "env.water", "kind": "texture", - "label": "Water or lava" + "label": "Water or lava", + "description": "The texture of water areas made of boxes (or lava, in a fiery setting)." }, { "id": "env.tiles", "kind": "texture", - "label": "Placement grid overlay" + "label": "Placement grid overlay", + "description": "The texture of the placement grid of the tile placement starters." }, { "id": "env.crate", "kind": "texture", - "label": "Pushable box faces" + "label": "Pushable box faces", + "description": "The texture of pushable boxes and furniture: a crate, wooden or metal box." }, { "id": "env.finish", "kind": "texture", - "label": "Finish line" + "label": "Finish line", + "description": "The texture of the finish line of the racing starters: a checkered or striped band." }, { "id": "env.dirt", "kind": "texture", - "label": "Farm plot or diggable ground" + "label": "Farm plot or diggable ground", + "description": "The texture of the farm plots where seeds are planted: tilled soil." }, { "id": "terrain.ground", "kind": "material", - "label": "Main ground of a terrain (grass, sand, snow...)" + "label": "Main ground of a terrain (grass, sand, snow...)", + "description": "The main ground of a 3D terrain, covering most of it: grass, sand, snow, dirt." }, { "id": "terrain.dirt", "kind": "material", - "label": "Paths, trails and fields of a terrain" + "label": "Paths, trails and fields of a terrain", + "description": "The paths, trails and fields painted on a 3D terrain." }, { "id": "terrain.road", "kind": "material", - "label": "Paved roads of a terrain" + "label": "Paved roads of a terrain", + "description": "The paved roads painted on a 3D terrain." }, { "id": "terrain.rock", "kind": "material", - "label": "Cliffs and steep slopes of a terrain" + "label": "Cliffs and steep slopes of a terrain", + "description": "The cliffs and steep slopes of a 3D terrain." }, { "id": "terrain.sand", "kind": "material", - "label": "Shores and beaches of a terrain" + "label": "Shores and beaches of a terrain", + "description": "The shores and beaches of a 3D terrain." }, { "id": "terrain.pavement", "kind": "material", - "label": "Sidewalks and squares of a terrain" + "label": "Sidewalks and squares of a terrain", + "description": "The sidewalks and squares of a 3D terrain." }, { "id": "terrain.grass.base", "kind": "color", - "label": "Color of the grass blades at their base" + "label": "Color of the grass blades at their base", + "description": "The color of the grass blades at their base, close to the color of terrain.ground." }, { "id": "terrain.grass.tip", "kind": "color", - "label": "Color of the grass blades at their tip" + "label": "Color of the grass blades at their tip", + "description": "The color of the grass blades at their tip, lighter than terrain.grass.base." }, { "id": "sky.day", "kind": "skybox", - "label": "Daytime sky" + "label": "Daytime sky", + "description": "The sky of most starters, around the whole scene." }, { "id": "sky.dark", "kind": "skybox", - "label": "Night or gloomy sky" + "label": "Night or gloomy sky", + "description": "The night or gloomy sky of the horror starters." } ] -} \ No newline at end of file +}