52 lines
1.7 KiB
TypeScript
52 lines
1.7 KiB
TypeScript
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<AssetType, string> = {
|
||
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<AssetType, Asset[]>();
|
||
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]));
|
||
}
|