Pick a brick up and bring what it was holding - #8
Merged
Merged
Conversation
Taking a brick out of the middle of a build left everything standing on it hanging in the air. Every placement was independent, so the one thing a person knows about a build, that the roof is on the wall, was the one thing the build did not know. LDraw carries no connectivity data, so the same trick the snapping uses works here: a part rests on another when the height that other part would hold it at is the height it is actually at. Only vertical contact counts, which is also what a real brick does, so two bricks side by side share an edge and nothing else and pulling one out leaves the other where it was. From that one relation come the two ways to pick something up. A plain click brings the part and whatever it alone was holding, because taking it out is what would bring that down anyway; a part with another leg still under it stays. Shift-click brings the whole piece of the build the part belongs to, reaching down as well as up, for when the thing you want to move is the turret rather than the brick you clicked on. Carrying is now a list of parts with offsets from the one under the pointer, merged into a single column profile so resting, snapping and the "will not fit" check cost what one part costs however many are in hand. Offsets turn as integers, so a gate turned four times is the gate it was, and putting a group down writes ordinary independent placements: a subassembly is a way of moving parts, not something the build knows about. A group turns about the upright only. A pose here is a yaw and a tip, which is sixteen of the twenty-four ways a part can sit square to the grid, and that set is not closed under tipping a group; the HUD drops the T key when more than one part is in hand and shows how many came along instead. Anything in hand has already left the placements, so a save taken while somebody is holding something, and one is taken the moment a tab goes to the background, had that hole in it. One brick short of a build is an annoyance and a subassembly short of one is a loss, so the save now includes what is being carried at the pose it would land at. FakeRenderer never walked the scene graph, so raycast tests were reading stale world matrices and passing by luck. It now updates them the way the real renderer does, which meant pointing two poured-brick tests at where the brick actually landed rather than at the origin.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
fallow put fold at cognitive 18, over the threshold, and it earned it: four nested loops and three guards in one function, where two of the loops walk the member being folded in and two walk the grid it is being folded into. Those are separate jobs, so they are now separate functions and the span a column covers has a name. No behaviour changes.
thebuilder
marked this pull request as ready for review
August 28, 2026 08:34
This branch was successfully deployed
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.
Taking a brick out of the middle of a free build left everything standing on it hanging in the air. Every placement was independent, so the one thing a person knows about a build, that the roof is on the wall, was the one thing the build did not know.
What a click does now
How connections are worked out
LDraw carries no connectivity data, so
subassembly.tsreuses the same trick the snapping uses: A rests on B when the height B would hold A at is the height A is actually at. Only vertical contact counts, which is also what a real brick does, so two bricks side by side share an edge and nothing else and pulling one out leaves the other where it was.loadBearingwalks upward from the clicked part, taking only parts that lose all their support.connectedTowalks both directions.Carrying a group
Carriednow holds a list of parts with offsets from the one under the pointer. The group is merged into a single column profile (mergeProfilesinheightField.ts), so resting, snapping and the "will not fit" check cost what one part costs however many are in hand, rather than every member against everything still built.Offsets turn as integers, so a gate turned four times is the gate it was. Putting a group down writes ordinary independent placements: a subassembly is a way of moving parts, not something the finished build knows about.
Known limitation, deliberately
A group turns about the upright only, no tip. A pose here is a yaw and a tip, sixteen of the twenty-four ways a part can sit square to the grid, and that set is not closed under tipping a group, so members would land in poses the save format cannot express. The HUD drops the
Tkey when more than one part is in hand, and shows+N attachedinstead.Two things that came along
placements, so a save while somebody is holding something, and one is taken the moment a tab goes to the background, had that hole in it. One brick short of a build is an annoyance; a subassembly short of one is a loss. The save now includes what is being carried at the pose it would land at.FakeRenderernever walked the scene graph, so raycast tests were reading stale world matrices and passing by luck. It now updates them the way the real renderer does, which meant pointing two poured-brick tests at where the brick actually landed rather than at the origin.Verification
541 tests pass,
tsc --noEmitandultracite checkare clean.Also driven in a real browser against the actual LDraw parts, not just the test fixtures: a four-brick tower (plain click on the bottom lifts all four; shift-click on the top lifts all four) and a gate of two 1x1 legs under a 2x4 deck (plain click on a leg leaves the deck; shift-click on a leg lifts all three;
Rturns the gate as a unit and it lands back on exact grid coordinates).