import type { Asset } from '../../core/model/Asset'; import type { AssetType } from '../../core/model/AssetTypes'; /** * Group headings of the asset panel. Plural, because a heading names what is under it – and so no * heading reads like the `+` menu entry that creates one of its kind. */ export const ASSET_GROUP_LABELS: Record = { scene: 'Scenes', camera: 'Cameras', sprite: 'Sprites', text: 'Texts', behavior: 'Behaviors', variables: 'Variables', collider: 'Colliders', rigidbody: 'Rigidbodies', container: 'Containers', texture: 'Textures', animation: 'Animations', tile: 'Tiles', tilemap: 'Tilemaps', statemachine: 'State machines', shader: 'Shaders', font: 'Fonts', sound: 'Sounds', particles: 'Particles', }; export interface AssetGroup { type: AssetType; assets: Asset[]; } /** Case aside and digits as numbers, so `Level 2` comes before `Level 10`. */ const collator = new Intl.Collator('en', { numeric: true, sensitivity: 'base' }); /** * The asset panel's rows (#176): one group per type that has assets, groups and the assets in * each alphabetical. Equal names keep the project's order, so a row does not jump on a rebuild. */ export function groupAssets(assets: readonly Asset[]): AssetGroup[] { const byType = new Map(); for (const asset of assets) { const list = byType.get(asset.type); if (list) list.push(asset); else byType.set(asset.type, [asset]); } return [...byType] .map(([type, list]) => ({ type, assets: list.sort((a, b) => collator.compare(a.name, b.name)) })) .sort((a, b) => collator.compare(ASSET_GROUP_LABELS[a.type], ASSET_GROUP_LABELS[b.type])); }