Trim needless comments and fix the picker width
Remove comments that only restate the code, keeping the section banners and the notes that carry a reason, a measured fact or an external contract. ButtonOptions.width claimed to be a fixed width but only set minWidth, so the Graph and Texture pickers grew with the name they showed. It is now what it promises, with a separate minWidth for the buttons that have two forms. Narrow buttons shrink their padding, otherwise a 24px icon button had 8px left for its glyph and truncate dropped it entirely. __gm.labelsDropped() guards that class: the overflow guard only saw text that was too wide, never a label truncated to nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f16801aef3
commit
4d84231b9f
115 files changed
+707
-1564
No files matched your search
@@ -2,16 +2,11 @@ import type { Asset } from '../model/Asset';
|
||||
import { type AssetType, isPlaceableType } from '../model/AssetTypes';
|
||||
import type { PropertyBag, PropertyValue } from '../model/Properties';
|
||||
|
||||
/**
|
||||
* Declarative description of one editable property. The inspector is generated from
|
||||
* these entries, so adding a property to a type is a single line in a schema below.
|
||||
*/
|
||||
/** The inspector is generated from these entries, so a new property is one line in a schema below. */
|
||||
export type PropertyDef =
|
||||
/**
|
||||
* `decimals` is the number of places the field displays; it belongs only on properties that
|
||||
* are integral by their meaning (counts, indices). Geometry does not qualify: dragging in the
|
||||
* viewport puts fractions into a position or a size, and a field that hid them would commit
|
||||
* the rounded number back into the project.
|
||||
* `decimals` belongs only on properties that are integral by meaning (counts, indices), not on
|
||||
* geometry: dragging produces fractions, and a field that hid them would commit the rounded value.
|
||||
*/
|
||||
| {
|
||||
key: string;
|
||||
@@ -26,40 +21,28 @@ export type PropertyDef =
|
||||
| { key: string; label: string; kind: 'text'; default: string }
|
||||
| { key: string; label: string; kind: 'color'; default: number }
|
||||
| { key: string; label: string; kind: 'boolean'; default: boolean }
|
||||
/** One of a fixed set of string values, shown as a dropdown. */
|
||||
| { key: string; label: string; kind: 'enum'; default: string; options: { value: string; label: string }[] }
|
||||
/** A keyboard key name (`KeyboardEvent.key`), captured by pressing it. */
|
||||
| { key: string; label: string; kind: 'key'; default: string }
|
||||
/**
|
||||
* A reference to another asset, stored as its id (`''` = none) and picked from a
|
||||
* searchable dropdown. `assetTypes` limits what the picker offers; without it every
|
||||
* placeable asset is offered, which is what graph nodes acting on an object want.
|
||||
*
|
||||
* The id is not validated on load – a reference can dangle, exactly like a graph node's
|
||||
* asset parameter, and the places that read one have to cope with that.
|
||||
* An asset id (`''` = none); without `assetTypes` the picker offers every placeable asset.
|
||||
* Ids are not validated on load, so a reference can dangle and readers must cope.
|
||||
*/
|
||||
| { key: string; label: string; kind: 'asset'; default: string; assetTypes?: readonly AssetType[] }
|
||||
/**
|
||||
* A picture: the id of a texture asset (the whole image) or of one of its frames. Its own
|
||||
* kind rather than an `asset` reference with `assetTypes: ['texture']`, because a frame is
|
||||
* not an asset – it is a rectangle inside one, and the picker has to offer both.
|
||||
*
|
||||
* Like an asset reference the id is not validated on load and may dangle; everything that
|
||||
* reads one falls back to drawing no picture.
|
||||
* The id of a texture asset or of one of its frames. Its own kind rather than an `asset`
|
||||
* reference, because a frame is not an asset and the picker has to offer both. May dangle.
|
||||
*/
|
||||
| { key: string; label: string; kind: 'texture'; default: string };
|
||||
|
||||
export type PropertySchema = readonly PropertyDef[];
|
||||
|
||||
/** Kinds a behavior variable may have (what the node graph can compute with). */
|
||||
export const VARIABLE_KINDS = ['number', 'boolean', 'text'] as const;
|
||||
export type VariableKind = (typeof VARIABLE_KINDS)[number];
|
||||
|
||||
/**
|
||||
* Properties every *placeable* asset has, whatever its type. `enabled` is the master switch:
|
||||
* a disabled object is not drawn, does not collide and its behavior does not run – and the
|
||||
* same goes for everything parented below it. Assets default to on, so switching a single
|
||||
* instance off is an ordinary override. Scenes have no such switch (they are not placed).
|
||||
* Properties every placeable asset has. A disabled object is not drawn, does not collide and its
|
||||
* behavior does not run – and the same goes for everything parented below it.
|
||||
*/
|
||||
export const COMMON_PROPS: PropertySchema = [
|
||||
{ key: 'enabled', label: 'Enabled', kind: 'boolean', default: true },
|
||||
@@ -67,12 +50,11 @@ export const COMMON_PROPS: PropertySchema = [
|
||||
|
||||
const COMMON_KEYS = new Set(COMMON_PROPS.map((d) => d.key));
|
||||
|
||||
/** Whether a key belongs to the common properties (the inspector groups those separately). */
|
||||
export function isCommonProp(key: string): boolean {
|
||||
return COMMON_KEYS.has(key);
|
||||
}
|
||||
|
||||
/** Property schema per asset type. Position is deliberately absent: it belongs to scene objects. */
|
||||
/** Position is deliberately absent: it belongs to scene objects, not to asset types. */
|
||||
const ASSET_SCHEMAS: Record<AssetType, PropertySchema> = {
|
||||
scene: [{ key: 'backgroundColor', label: 'Background', kind: 'color', default: 0x2a2d34 }],
|
||||
camera: [
|
||||
@@ -83,20 +65,11 @@ const ASSET_SCHEMAS: Record<AssetType, PropertySchema> = {
|
||||
sprite: [
|
||||
{ key: 'width', label: 'Width', kind: 'number', default: 100, min: 1, step: 1 },
|
||||
{ key: 'height', label: 'Height', kind: 'number', default: 100, min: 1, step: 1 },
|
||||
/*
|
||||
* The colour of the sprite: the fill of the box while it has no picture, and a multiplier
|
||||
* on the picture once it has one. White therefore means "no tint" – which is why it is the
|
||||
* default. A coloured default would silently stain every texture the moment it is applied,
|
||||
* and the first thing anyone would do is set it back to white.
|
||||
*
|
||||
* Tinting is worth keeping rather than suppressing for textured sprites: it is how one
|
||||
* white coin picture becomes ten differently coloured coins, per instance, for free.
|
||||
*/
|
||||
// The fill while there is no picture, and a tint multiplier once there is one: white = no tint.
|
||||
{ key: 'color', label: 'Color', kind: 'color', default: 0xffffff },
|
||||
{ key: 'texture', label: 'Texture', kind: 'texture', default: '' },
|
||||
],
|
||||
// The picture itself is intrinsic data on the asset (see TextureAsset), not a property:
|
||||
// only how it is sampled is worth deciding, and that decision is the whole schema.
|
||||
// The picture itself is intrinsic data on the asset (see TextureAsset), not a property.
|
||||
texture: [
|
||||
{
|
||||
key: 'filter',
|
||||
@@ -125,7 +98,6 @@ const ASSET_SCHEMAS: Record<AssetType, PropertySchema> = {
|
||||
{ key: 'width', label: 'Width', kind: 'number', default: 100, min: 1, step: 1 },
|
||||
{ key: 'height', label: 'Height', kind: 'number', default: 100, min: 1, step: 1 },
|
||||
{ key: 'radius', label: 'Radius', kind: 'number', default: 50, min: 1, step: 1 },
|
||||
// Triggers report collisions but never block a colliding `Move`; solid colliders do both.
|
||||
{ key: 'isTrigger', label: 'Trigger (no blocking)', kind: 'boolean', default: false },
|
||||
],
|
||||
// A container is pure structure: its content is the template, not a property.
|
||||
@@ -148,11 +120,6 @@ const ASSET_SCHEMAS: Record<AssetType, PropertySchema> = {
|
||||
],
|
||||
};
|
||||
|
||||
/**
|
||||
* Type schema with the common properties in front – the effective schema of an asset type.
|
||||
* Only placeable types get them: `enabled` switches off a placed object, and a scene or a
|
||||
* texture is never placed, so the switch would have nothing to act on.
|
||||
*/
|
||||
const FULL_SCHEMAS: Record<AssetType, PropertySchema> = Object.fromEntries(
|
||||
(Object.keys(ASSET_SCHEMAS) as AssetType[]).map((type) => [
|
||||
type,
|
||||
@@ -160,17 +127,15 @@ const FULL_SCHEMAS: Record<AssetType, PropertySchema> = Object.fromEntries(
|
||||
]),
|
||||
) as Record<AssetType, PropertySchema>;
|
||||
|
||||
/** Schema shared by every asset of a type (common properties first). */
|
||||
export function schemaFor(type: AssetType): PropertySchema {
|
||||
return FULL_SCHEMAS[type];
|
||||
}
|
||||
|
||||
/** The effective schema of one asset: the type schema, plus declared variables for behaviors. */
|
||||
/** The type schema, or for behaviors their declared variables. */
|
||||
export function schemaForAsset(asset: Asset): PropertySchema {
|
||||
return asset.type === 'behavior' ? [...COMMON_PROPS, ...asset.variables] : FULL_SCHEMAS[asset.type];
|
||||
}
|
||||
|
||||
/** The definition of `key` in the effective schema of `asset`, if it has one. */
|
||||
export function propDef(asset: Asset, key: string): PropertyDef | undefined {
|
||||
return schemaForAsset(asset).find((d) => d.key === key);
|
||||
}
|
||||
@@ -186,7 +151,6 @@ export function defaultsOf(schema: PropertySchema): PropertyBag {
|
||||
return bag;
|
||||
}
|
||||
|
||||
/** Builds a variable definition of the given kind with the kind's natural default. */
|
||||
export function variableDef(key: string, kind: VariableKind, defaultValue?: PropertyValue): PropertyDef {
|
||||
switch (kind) {
|
||||
case 'number':
|
||||
@@ -198,7 +162,7 @@ export function variableDef(key: string, kind: VariableKind, defaultValue?: Prop
|
||||
}
|
||||
}
|
||||
|
||||
/** Clamp / coerce a raw value so it satisfies the definition. */
|
||||
/** Clamps / coerces a raw value so it satisfies the definition. */
|
||||
export function coerceValue(def: PropertyDef, value: PropertyValue): PropertyValue {
|
||||
switch (def.kind) {
|
||||
case 'number': {
|
||||
@@ -214,8 +178,6 @@ export function coerceValue(def: PropertyDef, value: PropertyValue): PropertyVal
|
||||
}
|
||||
case 'boolean':
|
||||
return Boolean(value);
|
||||
// An asset or texture reference is an id like the other two are plain strings; whether it
|
||||
// still resolves is not decidable from a single property definition.
|
||||
case 'text':
|
||||
case 'key':
|
||||
case 'asset':
|
||||
|
||||
Reference in new issue
Block a user