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:
rootandClaude Opus 5 committed 2026-09-08 15:52:05 +02:00
1 parent f16801aef3
commit 4d84231b9f
115 files changed
+707 -1564

No files matched your search

+13 -12
View File
@@ -1,8 +1,6 @@
/**
* One table covering every built-in node that has a `run`, plus a guard that keeps it that way:
* adding a node without a case here fails `covers every built-in node`. Nodes without `run`
* (the events) are seeded by the interpreter, so they are listed with the test that drives them
* and checked in tests/core/behavior-events.test.ts.
* One table covering every built-in node that has a `run`: adding a node without a case here
* fails `covers every built-in node`. The run-less event nodes are listed in `EVENT_NODES`.
*/
import { describe, expect, it } from 'vitest';
import { BUILT_IN_NODES } from '../../src/core/graph/nodes';
@@ -29,7 +27,6 @@ const run = (type: string, c: Case): { result: RunResult; ctx: FakeContext } =>
return { result: requireNodeDef(type).run!(ctx, c.inputs ?? {}, c.params ?? {}), ctx };
};
/** A handle with a fixed position, for the geometry nodes. */
const at = (name: string, x: number, y: number) => ({ ...fakeEntity(name), x, y });
const pointer = (overrides: Partial<NodeContext['pointer']>): Partial<NodeContext> => ({
@@ -38,6 +35,7 @@ const pointer = (overrides: Partial<NodeContext['pointer']>): Partial<NodeContex
const CASES: Record<string, Case[]> = {
// --- flow ------------------------------------------------------------------------------------
Branch: [
{ name: 'true takes then', inputs: { condition: true }, next: 'then' },
{ name: 'false takes else', inputs: { condition: false }, next: 'else' },
@@ -47,6 +45,7 @@ const CASES: Record<string, Case[]> = {
Sequence: [{ name: 'runs all three outputs in order', next: ['a', 'b', 'c'] }],
// --- variables -------------------------------------------------------------------------------
GetVariable: [
{ name: 'reads a variable', params: { variable: 'speed' }, outputs: { value: 100 } },
{ name: 'an unknown variable reads as null', params: { variable: 'nope' }, outputs: { value: null } },
@@ -69,6 +68,7 @@ const CASES: Record<string, Case[]> = {
],
// --- references and properties ----------------------------------------------------------------
Self: [{ name: 'outputs the behavior object', outputs: { object: fakeContext().self } }],
Owner: [
{ name: 'outputs the object the behavior is parented to', outputs: { object: fakeContext().owner } },
@@ -154,6 +154,7 @@ const CASES: Record<string, Case[]> = {
],
// --- literals and math -------------------------------------------------------------------------
Number: [
{ name: 'outputs its setting', params: { value: 7.5 }, outputs: { value: 7.5 } },
{ name: 'unset is 0', outputs: { value: 0 } },
@@ -210,8 +211,7 @@ const CASES: Record<string, Case[]> = {
{ name: 'modulo zero is 0, not NaN', inputs: { a: 125, b: 0 }, outputs: { result: 0 } },
],
Random: [
// The spread is checked in "Random stays inside [min, max)" below; an empty range is the
// one case with a single right answer.
// The spread is checked in "Random stays inside [min, max)" below.
{ name: 'an empty range always yields min', inputs: { min: 3, max: 3 }, outputs: { result: 3 } },
],
Time: [
@@ -223,6 +223,7 @@ const CASES: Record<string, Case[]> = {
],
// --- text and comparison -----------------------------------------------------------------------
ToText: [
{ name: 'formats with decimals', inputs: { value: 12.345, decimals: 1 }, outputs: { text: '12.3' } },
{ name: 'text passes through unformatted', inputs: { value: 'x', decimals: 2 }, outputs: { text: 'x' } },
@@ -267,6 +268,7 @@ const CASES: Record<string, Case[]> = {
],
// --- vectors and input --------------------------------------------------------------------------
Length: [
{ name: '3-4-5 triangle', inputs: { x: 3, y: 4 }, outputs: { result: 5 } },
{ name: 'the zero vector has length 0', inputs: { x: 0, y: 0 }, outputs: { result: 0 } },
@@ -390,6 +392,7 @@ const CASES: Record<string, Case[]> = {
],
// --- actions --------------------------------------------------------------------------------------
Move: [
{
name: 'moves by (dx, dy) × scale × dt',
@@ -479,8 +482,8 @@ function eqNamesakes(): Record<string, Value> {
}
/**
* Nodes without a `run`: the interpreter seeds their outputs when the BehaviorSystem fires them,
* so they are only observable through a running world. The value says which test drives it.
* Nodes without a `run`: only observable through a running world, since the BehaviorSystem
* seeds their outputs. The value names the test that drives each one.
*/
const EVENT_NODES: Record<string, string> = {
OnStart: 'graph.test.ts',
@@ -513,8 +516,7 @@ describe('node catalog', () => {
const keys = [...def.inputs, ...def.outputs].map((p) => p.key);
expect(def.label, `${def.type} has a label`).not.toBe('');
expect(def.description, `${def.type} has a description`).not.toBe('');
// Inputs and outputs are addressed by key within their own side; a key may repeat across
// sides (Normalize reads x/y and writes x/y), never within one.
// Keys are unique per side, but may repeat across sides (Normalize reads and writes x/y).
expect(new Set(def.inputs.map((p) => p.key)).size, `${def.type} input keys unique`).toBe(
def.inputs.length,
);
@@ -545,7 +547,6 @@ for (const [type, cases] of Object.entries(CASES)) {
});
}
// Cases whose point is the mutation they cause – stated here rather than squeezed into the table.
describe('action nodes write through to the object they are given', () => {
it('Move applies dx/dy × scale × dt', () => {
const target = at('m', 0, 0);