Repository navigation
Split the face designer into steps, and fix what the phone showed - #388
Merged
drehtuer merged 8 commits intoOct 5, 2026
Merged
Conversation
Rolling a die from the face designer showed the set's number through every clear part of every drawn face. Every face was printed and the atlas was laid over the printing by its alpha (decision 59), so a drawing that did not cover its face edge to edge let the label through. A face is now printed or drawn, never both. The decoded atlas already knew which cells were empty (the validator's AtlasCellsEmpty warning); its complement is worked out once per upload for every catalogue face count (AtlasCoverage), the renderer asks the stage about it before adding a die (Stage.drawnCells) and leaves those cells out of the number field (DieNumbers.fieldOf, PrintedDice keyed by die and drawn faces). Undrawn faces keep their numbers, so a die drawn on one face is still readable; a number wanted on a drawn face is stamped into the drawing. Decision 96 records the change; dice-sets.md, physics-and-rendering.md and face-designer.md say the new rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Solid tab left every stroke of the pen out, on the grounds that a line of one width over a tilted face is not the line on the die. On the phone that was a die drawn with the pen turning with blank faces. A stroke is now handed to the stage as the shapes its ink covers (StrokeOutline): a disc at every dot, for the canvas's round caps and joins, and a band half a nib either side of every segment, all wound one way. Those project exactly like any other ring and are filled as their union under the non-zero rule, so the line is foreshortened as its face is rather than drawn at one width. The eraser is drawn in the face's paper, as on the canvas. Dots closer than a quarter of the nib are dropped first to keep a spinning die cheap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The owner reported that the designer's option for loading an image had no effect. There is no such option: the switch was the guide toggle, drawn with the prototype's #ic-image glyph (a framed landscape), which reads as "add a picture". And it really did appear to do nothing in a dark theme, because the guide was drawn in the page's ink at a third of its strength — pale grey on the white paper the canvas always uses. The guide is now drawn in black or white, whichever reads on the paper (PaperInk), and the switch says "Guide", as the prototype's checkbox does. The unused #ic-image glyph goes from DesignerIcons. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With rounded edges a face no longer fills its side, so a die coloured by bucket-filling every face kept the set's bone colour at its edges and corners. The owner asked for a configurable base colour. The die's finish now carries its body colour and the colour its undrawn faces are printed in. The body is chosen beside the material from the pen's twelve colours and the shared ColourPicker past them; the number colour follows it, near-black on a light body and white on a dark one (PaperInk), because its only job is to be read. Both go into the package as the existing per-die color and number_color keys, and into the draft as two optional integers: a finish written before them read as the bone die it described. The canvas, the eraser, the face strip and the turning die are all drawn on the body colour, so the canvas is the die. Decision 97. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The owner found that the four Edges steps only made sense for the d4 and asked for a slider. The steps did not fail in the solver — every shape but the d4 gets the full radius at every value — but the designer drew the sharp polyhedron whatever was chosen, and how much rounding shows depends on the solid: a corner stands in by r(|m|-1) and an edge band is r*tan(theta/2) wide, so across the whole range a d20 moves half a millimetre where a d4 moves two. Edges is now a slider over the set file's range, 1.5-12 % in half per cents (EdgeRounding), said under it as the share and as the millimetres the solver gives this die. The turning die is drawn rounded by that radius (RoundedSolid): flat parts, edge bands, corner patches and an outline round the rounded corners, so moving the slider is visible before a throw. The bounds stay decision 94's: the phone runs that would test them could not be made in this change, and physics-and-rendering.md lists them. Decision 98. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The owner asked for the design process in steps instead of everything on one screen: geometry, then material and base colour, then the faces. One screen was the base-die chooser, the canvas, six rows of tools, the material and the edges all scrolling past each other. The designer is now Shape (the dice, with the die turning above them), Material (the turning die, the material menu, body colour and edges slider) and Faces (the drawing, its Face/Solid tabs and the face strip). A segmented step bar under the title says where the player is and goes anywhere; Back and Next walk the steps, Next being the filled button until the last step, where Roll it and Save to set are. It stays one screen and one presenter: the steps are views of one draft, which is written down as a step is left. The menu opens on Shape; quick mode and the way back from a test throw know the die and open on Faces (DesignerStep.openingFor). The phone prototype shows the same steps, design/README.md maps them, and face-designer.md's Flow says it. Decision 99. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Function and branch coverage must not sink in a change. The new pieces left gaps: the bends and pieces of the stage built with their defaults, the artwork a stage reads coverage from, the body colour picker's two answers, undo and redo on the last step, and the skip branches Compose generates for small composables handed the whole designer state. The artwork and the question "which faces does it draw on" move into plain Kotlin (DieArtwork, generic in the texture) so a JVM test asks them; Stage.drawnCells has no default, so every stage answers it on purpose. The small composables that take the whole state are non-restartable, as OptionBox is: a state that changes on every stroke is one they could never skip on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The edge-rounding slider's range is still the set file's, unmeasured; the harness and FairnessTest runs that would narrow it are now the first box of step 4.6, and the owner's judgements on the three steps follow it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Base automatically changed from
fix/shader-plate-checks
to
feature/designer-material-and-roundness
October 5, 2026 07:28
drehtuer
merged commit Oct 5, 2026
5cd650f
into
feature/designer-material-and-roundness
9 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Answers the owner's face-designer feedback from the Pixel 10a: three bugs fixed, a body colour, an edge-rounding slider, and the designer split into three steps.
Based on #387 (
fix/shader-plate-checks), stacked as.claude/CLAUDE.mdasks.Bugs, each with a regression test
AtlasImage.drawnCells,AtlasCoverage). The renderer leaves those cells out of the printed numbers (Stage.drawnCells,DieNumbers.fieldOf(drawn),PrintedDicekeyed by die and drawn faces). Undrawn faces keep their numbers.docs/dice-sets.mdis updated.StrokeOutline), projected onto the turning die, and the eraser paints the body colour.PaperInk), and the switch now says Guide, as in the prototype.docs/face-designer.md.New
ColourPicker.color/number_colorkeys, so the format and the validator are unchanged.RoundedSolid).docs/TODO.md4.6.design/dInfinityPhone.dc.htmlshows the steps, the colour row and the slider.design/README.md, the README feature line,docs/face-designer.md,docs/architecture.mddecisions 96–99,docs/physics-and-rendering.md("How round a die may be"),docs/STATUS.mdanddocs/TODO.md.Tests and coverage
StrokeOutlineTest,RoundedSolidTest,PaperInkTest,DesignerGuideTestandDesignerStepsTest.AtlasTextureTest.theStageSaysWhichFacesTheUploadedAtlasDrawsOn. It compiles but has not been run yet.Locally in the devcontainer:
./gradlew build test coverageReport lint detekt ktlintCheckis green.Not done: needs the phone
FairnessTestruns at 1.5 %, 3 % and 12 % on d4, d6 and d20 were not made; the commands are indocs/TODO.md4.6. The permission settings blocked the agent's attempt.🤖 Generated with Claude Code