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
+14
-30
@@ -4,13 +4,8 @@ import type { SceneObject } from './SceneObject';
|
||||
import { descendantsBelow, parentChain, sumAlongChain } from './walk';
|
||||
|
||||
/**
|
||||
* Parent/child structure of a scene. `scene.objects` stays a flat list (storage order =
|
||||
* creation order); the tree is implied by `SceneObject.parentId`. Positions are local to
|
||||
* the parent, so the world position is the sum along the chain – there is no rotation or
|
||||
* scale yet, which keeps this trivially invertible.
|
||||
*
|
||||
* The helpers work on anything that holds a flat object list – a scene, or the template
|
||||
* inside a container asset.
|
||||
* `objects` stays a flat list in creation order; the tree is implied by `SceneObject.parentId`.
|
||||
* Anything holding such a list fits – a scene, or the template inside a container asset.
|
||||
*/
|
||||
export interface ObjectTree {
|
||||
objects: SceneObject[];
|
||||
@@ -24,12 +19,11 @@ function childrenOf(tree: ObjectTree, parentId: string): SceneObject[] {
|
||||
return tree.objects.filter((o) => o.parentId === parentId);
|
||||
}
|
||||
|
||||
/** The parent of an object, or undefined for a top-level one (and for a dangling link). */
|
||||
function parentOf(tree: ObjectTree, object: SceneObject): SceneObject | undefined {
|
||||
return object.parentId ? findObject(tree, object.parentId) : undefined;
|
||||
}
|
||||
|
||||
/** All objects below `id`, depth-first, parents before children. */
|
||||
/** Depth-first, parents before children. */
|
||||
export function descendantsOf(tree: ObjectTree, id: string): SceneObject[] {
|
||||
return descendantsBelow(
|
||||
id,
|
||||
@@ -38,7 +32,6 @@ export function descendantsOf(tree: ObjectTree, id: string): SceneObject[] {
|
||||
);
|
||||
}
|
||||
|
||||
/** The ids of `rootIds` and of everything below them – what group operations act on. */
|
||||
export function subtreeIds(tree: ObjectTree, rootIds: Iterable<string>): Set<string> {
|
||||
const ids = new Set<string>();
|
||||
for (const rootId of rootIds) {
|
||||
@@ -48,18 +41,18 @@ export function subtreeIds(tree: ObjectTree, rootIds: Iterable<string>): Set<str
|
||||
return ids;
|
||||
}
|
||||
|
||||
/** Takes the subtrees of `rootIds` out of the tree; returns them with their former indices (see `restoreAt`). */
|
||||
/** Returns the removed objects with their former indices (see `restoreAt`). */
|
||||
export function removeSubtrees(tree: ObjectTree, rootIds: readonly string[]): Removed<SceneObject>[] {
|
||||
const ids = subtreeIds(tree, rootIds);
|
||||
return removeWhere(tree.objects, (o) => ids.has(o.id));
|
||||
}
|
||||
|
||||
/** An object and every parent above it, nearest first. Stops at a cycle (defensive). */
|
||||
/** An object and every parent above it, nearest first. */
|
||||
export function chainOf(tree: ObjectTree, object: SceneObject): SceneObject[] {
|
||||
return [...parentChain(object, (o) => parentOf(tree, o))];
|
||||
}
|
||||
|
||||
/** Ids of the ancestors of `id`, nearest parent first. Empty for a top-level object. */
|
||||
/** Nearest parent first. */
|
||||
export function ancestorIdsOf(tree: ObjectTree, id: string): string[] {
|
||||
const object = findObject(tree, id);
|
||||
return object
|
||||
@@ -69,16 +62,12 @@ export function ancestorIdsOf(tree: ObjectTree, id: string): string[] {
|
||||
: [];
|
||||
}
|
||||
|
||||
/** Whether `ancestorId` is `objectId` itself or one of its ancestors. */
|
||||
export function isSelfOrAncestor(tree: ObjectTree, ancestorId: string, objectId: string): boolean {
|
||||
const object = findObject(tree, objectId);
|
||||
return object !== undefined && chainOf(tree, object).some((o) => o.id === ancestorId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Of the given ids, those that have no ancestor among the ids themselves – the tops of the
|
||||
* selected subtrees. Whole subtrees are what group operations (move, remove, group) act on.
|
||||
*/
|
||||
/** Of the given ids, those with no ancestor among the ids themselves. */
|
||||
export function subtreeRoots(tree: ObjectTree, ids: readonly string[]): string[] {
|
||||
const set = new Set(ids);
|
||||
return ids.filter((id) => !ancestorIdsOf(tree, id).some((ancestorId) => set.has(ancestorId)));
|
||||
@@ -95,15 +84,13 @@ function positionAlongChain(tree: ObjectTree, object: SceneObject, withEditorOff
|
||||
);
|
||||
}
|
||||
|
||||
/** Position of an object in world units (all local positions along the chain summed up). */
|
||||
export function worldPosition(tree: ObjectTree, object: SceneObject): Position {
|
||||
return positionAlongChain(tree, object, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Where the scene view draws an object: its world position plus the editor offsets along the
|
||||
* chain, so shifting a parent shifts everything below it. This is a view aid only – nothing
|
||||
* in the game, in collisions or in the graph ever sees it (they all use `worldPosition`).
|
||||
* World position plus the editor offsets along the chain. A view aid only – the game, collisions
|
||||
* and the graph all use `worldPosition`.
|
||||
*/
|
||||
export function editorPosition(tree: ObjectTree, object: SceneObject): Position {
|
||||
return positionAlongChain(tree, object, true);
|
||||
@@ -123,8 +110,8 @@ export interface TreeEntry {
|
||||
}
|
||||
|
||||
/**
|
||||
* Objects in tree order: top-level objects in storage order, each followed by its subtree.
|
||||
* This is the order the hierarchy panel shows and the tie-break order for equal `z`.
|
||||
* Top-level objects in storage order, each followed by its subtree – the order the hierarchy panel
|
||||
* shows and the tie-break order for equal `z`.
|
||||
*/
|
||||
export function treeOrder(tree: ObjectTree): TreeEntry[] {
|
||||
const result: TreeEntry[] = [];
|
||||
@@ -137,7 +124,7 @@ export function treeOrder(tree: ObjectTree): TreeEntry[] {
|
||||
}
|
||||
};
|
||||
visit('', 0);
|
||||
// Objects whose parent is missing (should not happen after loading) are listed at the top level.
|
||||
// Objects whose parent is missing are listed at the top level rather than dropped.
|
||||
for (const object of tree.objects) {
|
||||
if (object.parentId && !ids.has(object.parentId) && !result.some((e) => e.object === object))
|
||||
result.push({ object, depth: 0 });
|
||||
@@ -146,15 +133,12 @@ export function treeOrder(tree: ObjectTree): TreeEntry[] {
|
||||
}
|
||||
|
||||
export interface VisibleEntry extends TreeEntry {
|
||||
/** Whether the object has children at all – only those rows offer an expand/collapse chevron. */
|
||||
hasChildren: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tree order with the subtrees of collapsed objects left out: a row is shown when *every*
|
||||
* ancestor is expanded. Expansion is a view state (which ids are open), never stored in the
|
||||
* project – anything not listed counts as collapsed, so a freshly loaded scene shows only its
|
||||
* top level.
|
||||
* Tree order with the subtrees of collapsed objects left out. Anything not in `expanded` counts as
|
||||
* collapsed, so a freshly loaded scene shows only its top level.
|
||||
*/
|
||||
export function visibleTreeOrder(tree: ObjectTree, expanded: ReadonlySet<string>): VisibleEntry[] {
|
||||
const parents = new Set(tree.objects.map((o) => o.parentId).filter(Boolean));
|
||||
|
||||
Reference in new issue
Block a user