From 779c850f4d1fa8ad7a46812f88c5f8478022a7be Mon Sep 17 00:00:00 2001 From: MelekTaus Date: Tue, 15 Sep 2026 10:21:25 +0200 Subject: [PATCH] The name of a thing beats its description, so search says so (#43) Architecture: the popup section now describes the ranked search, the two groups in the `+` menu and the tenth-of-the-canvas budget, including why the top margin is only a budget and not a floor. Behaviors, Concepts: what the palette and the `+` menu order looks like. Development: the two new debug hooks that make an order testable at all. --- Architecture.md | 28 ++++++++++++++++++++++------ Behaviors.md | 5 +++++ Concepts.md | 5 ++++- Development.md | 17 ++++++++++++----- 4 files changed, 43 insertions(+), 12 deletions(-) diff --git a/Architecture.md b/Architecture.md index 58f4b9a..d5c6c14 100644 --- a/Architecture.md +++ b/Architecture.md @@ -13,11 +13,27 @@ on the `click` it synthesises and leaves `detail` at 0 on `pointerdown`, so every press handler that trusted `e.detail` never saw a second click. Presses are counted per key rather than per widget, because a list rebuilds its rows when the first click changes the selection. - Menus read as lists: entries are left-aligned and scroll once they pass 320 px instead of - running off the screen. A menu that grows with the project — the parent picker lists every + Menus read as lists: entries are left-aligned and scroll once they are taller than there is room + for, instead of running off the screen. **The room is the canvas**, not a constant (#43): + `Popup.roomFor()` takes the window height, less a tenth of it at each end, less the chrome around + the scrolling part — and it *measures* that chrome (a search box, a header, a row of buttons) + rather than repeating it as a number, so no popup can forget one. A fixed cap would waste a tall + screen or overflow a short one, and a constant gap that frames a popup on a laptop is a hairline + on a large screen. It is what holds the whole `+` menu of fifteen asset types on screen, and what + lets the image, font and sound pickers show six rows of what the server has instead of two. + A popup that does not fit below its anchor is still *moved* up rather than squeezed, and + `clampPopupY()` enforces the tenth while moving it — otherwise the gap ends up entirely above it + and the popup sits flush on the bottom edge, which is exactly what it used to do. + Upwards that tenth is a budget the height cap spends, not a distance to keep: a menu hanging off + a button near the top of the screen belongs under its button, so nothing pushes it down to reach + the margin. Below is the rule, above is what is left over. + A menu that grows with the project — the parent picker lists every object of the scene — is opened with `{ searchable: true }`, which puts a filter box above - the entries (Enter takes the first match). A field that opens a menu is a `Dropdown`: value - flush left, chevron drawn flush right rather than written into the label. + the entries; that search ranks by `ui/search.ts` and Enter takes the best match, the same rule + the node palette uses. Entries can be grouped with `{ separator: true }` — a line, dropped when + a search flattens the list or when it would open, close or double up the menu. A field that + opens a menu is a `Dropdown`: value flush left, chevron drawn flush right rather than written + into the label. Every label that can be wider than its control is cut with an ellipsis (`truncate` in `Label.ts`, shared by `Label`, `ListRow` and `Button`). A `Button` keeps the full text and measures from it — only what is drawn is shortened — and a subclass that puts something else @@ -74,9 +90,9 @@ src/editor/inspector/ Inspector panel, host (what a section builds into), field (where a value lives — shared with the List tab), one section per selection kind (asset/object/node/frame), variableRows (one row shape for every variable), portSection, aspectAction, objectQueries/vectorRows/parentRow -src/editor/panels/ AssetPanel, HierarchyPanel, Toolbar +src/editor/panels/ AssetPanel, assetMenu (the two groups of the + menu), HierarchyPanel, Toolbar src/editor/graph/ GraphEditor (header + picker), GraphCanvas, EdgeLayer (curves and fold marks), graphMenus, - NodeView, NodePalette + paletteEntries, folding (hidden links, collapsed nodes), Breadcrumb + trail (the path into nested behaviors), beads (the run's pulses) + NodeView, NodePalette + paletteEntries (which also ranks a search), folding (hidden links, collapsed nodes), Breadcrumb + trail (the path into nested behaviors), beads (the run's pulses) src/editor/container/ ContainerEditor (header + picker), ContainerCanvas (a SceneViewport on a template) src/editor/texture/ TextureEditor (header + picker), TextureCanvas (picture + frames), SliceDialog, sheetView (the grid maths), ImagePicker + imageGrid (the "+ → Texture" dialog), checker (the transparency board) diff --git a/Behaviors.md b/Behaviors.md index c9776af..8bdc257 100644 --- a/Behaviors.md +++ b/Behaviors.md @@ -210,6 +210,11 @@ shown on the node and editable in the inspector. `vy` variable and moves the owner by `(axis.x · speed, vy)` with *Collide with solids* on; `blocked y` while falling means standing, so `vy` goes back to 0 and `onGround` becomes true; `On key down (Space)` sets `vy = -jumpSpeed` when `onGround`. +- **The palette answers by how well it matches**, not alphabetically: an exact hit on a node's name + or type first, then a name that begins with what was typed, then one that contains it, then the + type, and only last a node whose *description* mentions it. Category and alphabet order what is + equally good. That is what `Enter` takes, so typing `variable` adds the node called that and not + `Run behavior`, whose description happens to mention variables (#43). - **Editing**: right-click the canvas for the searchable palette, drag port → port to connect (types are checked; a data input holds one link and is replaced), drag nodes, right-click a node or port to delete/disconnect, `Delete` removes the selection, wheel zooms. Everything is diff --git a/Concepts.md b/Concepts.md index e7cd9a6..6de6dc2 100644 --- a/Concepts.md +++ b/Concepts.md @@ -36,7 +36,10 @@ no movement): everything that happens is defined by behavior graphs. **Toolbar and panels.** The toolbar holds the **Project** menu (new project, switch project, *Delete this project…*), the project name (type to rename), the **Scene** picker for the active scene, Undo/Redo, Play/Pause, and on the right the notice line, the save status and the frame -rate. The **Assets** panel's `+` creates an asset and opens its tab. A click on a row only +rate. The **Assets** panel's `+` creates an asset and opens its tab; its menu lists the types in +two alphabetical groups, first what can be placed into a scene, then what only lives in the library +(#43) — the line between them answers the question that follows right after "which type?". +A click on a row only selects (the inspector shows it, no tab moves); a **double-click** opens the tab the asset lives in — Scene, Behavior, State machine, Shader, Particles, Texture, Animation or Container — and on a scene also makes it the active one. `Enter` does the same once the list has keyboard focus (`Tab`). diff --git a/Development.md b/Development.md index b4a4491..86120fd 100644 --- a/Development.md +++ b/Development.md @@ -74,11 +74,18 @@ not by clicking its name: since the tenth tab the row hides some of them at the and the helper goes through the `»` menu when it has to. Clicking the label directly took the whole suite down the day the Particles tab was added. -The same holds for the **`+` menu**: it has one entry per asset type and scrolls past 320 px, so the -last of them sit under the mask, where `locate` still finds an entry but a click on it lands on -nothing. A step picks a type with `pickAssetType(t, 'Font')` from the same file, which scrolls it in -first. The fourteenth type (Variables) pushed `Font` under that edge and took the font step down, -because only the particles step had carried the workaround of its own. Sound is the fifteenth. +The same holds for the **`+` menu**: it has one entry per asset type, and an entry below the mask +edge is still found by `locate` while a click on it lands on nothing. The fourteenth type +(Variables) pushed `Font` under that edge and took the font step down, because only the particles +step had carried a workaround of its own; sound is the fifteenth. Since #43 a menu may grow to the +height of the canvas, so on the test window all fifteen stand on screen at once — the step still +picks a type with `pickAssetType(t, 'Font')` from the same file, which keeps the scroll as insurance +for a shorter window. The menu's own order is checked in the assets step through `__gm.menuRows()`: +two alphabetical groups, placeable types then library ones, one separator between them. Order is +the whole answer there, and no colour check can see an order. + +The node palette has the same property, and `__gm.graph.paletteRows()` is its witness: the rows all +look alike, only their sequence says whether the search ranked them (#43). **What no colour check can see: whether anything was drawn at all.** `__gm.pixelAt` re-renders the stage on demand, so it answers correctly on a screen that has been frozen for a minute — which is