Skip to content

[UUM-149791] Fix First Vertex pivot offset when resizing shapes or shift-duplicating - #696

Open
lopezt-unity wants to merge 5 commits into
masterfrom
bugfix/uum-149791-fixing-shape-pivot
Open

[UUM-149791] Fix First Vertex pivot offset when resizing shapes or shift-duplicating#696
lopezt-unity wants to merge 5 commits into
masterfrom
bugfix/uum-149791-fixing-shape-pivot

Conversation

@lopezt-unity

@lopezt-unity lopezt-unity commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

Summary

[UUM-149791] Fixed the First Vertex pivot ending up offset from the shape after resizing an existing shape or shift-duplicating one with
the Shape tool.

Original bug:

  • Shift-duplicate offset: DrawShapeTool.previewPivotPosition normalized the drag-captured corner offset (m_LastNonDuplicateCenterToOrigin) and rescaled it by that same vector's own magnitude - a no-op that always reconstructed the offset using the size of whatever shape was last dragged out, ignoring the size of the shape actually being placed. Repro: draw a shape with Pivot = First Vertex, change its size (e.g. via Shape Settings), then shift-duplicate it - the new shape's pivot was offset using the previous shape's dimensions instead of its own.
  • Resize offset: ProBuilderShape.UpdateShape() had the same class of bug one level down - it rebuilt a resized shape around its stale center (valid only for the previous size) instead of its pivot corner, so resizing an already-placed First-Vertex-pivoted shape via Shape Settings left the mesh floating away from its pivot/gizmo.

Fix:

  • Both are now fixed with the same insight: for a First Vertex pivot, center = pivot + size/2 holds exactly, regardless of the sign of size - there's no independent "corner choice" to reconstruct. (An intermediate fix that re-derived a corner sign from the stale center was still wrong for shapes with a negative size axis, e.g. a Stairs shape dragged backwards - ProBuilderShape now instead records the pivot-to-center ratio, per axis, which is exactly 0 or 1 regardless of size's sign, once at rebuild time, and re-derives the center from that ratio and the current size on every resize.)
firstcorner-pivot-fixed

Test plan

Executed by @lopezt-unity :

  • Tests/Editor/Editor/DrawShapeToolPivotOffsetTests.cs - previewPivotPosition against both an all-positive and a negative-size-axis "last drawn shape", proving stale drag data can't leak into the duplicate's placement.
  • Tests/Editor/Editor/ProBuilderShapeResizePivotTests.cs - UpdateShape() resizing a First-Vertex-pivoted Stairs shape down, with both an all-positive and a negative-Z initial size, proving the shape stays anchored at its pivot after resize regardless of the original size's sign.
  • All cases run via Unity Test Runner (EditMode) and pass.
  • Manually reproduced and verified fixed in-editor: shift-duplicate after a Shape Settings resize, and resizing an existing First-Vertex-pivoted Stairs shape (including the negative-size-axis case from the screenshot).

…t Vertex pivot

previewPivotPosition normalized the drag-captured corner offset and then
rescaled it by its own original magnitude, which is a no-op and always
reconstructs the offset from the size of the shape that was last dragged
out rather than the size of the shape currently being placed. Resizing a
shape (e.g. via Shape Settings) before shift-duplicating it with Pivot =
First Vertex therefore placed the new shape's pivot using the previous
shape's dimensions instead of its own.

Now only the corner (sign per axis) is kept from the last drag, and the
offset magnitude is scaled from the current bounds size.

@u-pr u-pr Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Harness Review

Needs changes

The revised offset correctly uses the current dimensions for positive-size shapes, but it loses the established drag-direction information when those dimensions are signed.

Reviewed commit 4ca7439

🤖 Helpful? 👍/👎

Comment thread Editor/EditorCore/DrawShapeTool.cs Outdated
@codecov-github-com

codecov-github-com Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

@@            Coverage Diff             @@
##           master     #696      +/-   ##
==========================================
+ Coverage   38.43%   38.55%   +0.12%     
==========================================
  Files         279      279              
  Lines       39164    39195      +31     
==========================================
+ Hits        15052    15112      +60     
+ Misses      24112    24083      -29     
Flag Coverage Δ
probuilder_MacOS_6000.0 36.28% <100.00%> (+0.15%) ⬆️
probuilder_MacOS_6000.3 36.28% <100.00%> (+0.14%) ⬆️
probuilder_MacOS_6000.4 36.27% <100.00%> (+0.14%) ⬆️
probuilder_MacOS_6000.5 36.28% <100.00%> (+0.14%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
Editor/EditorCore/DrawShapeTool.cs 29.38% <100.00%> (+1.07%) ⬆️
Runtime/Shapes/ProBuilderShape.cs 78.76% <100.00%> (+1.23%) ⬆️

... and 6 files with indirect coverage changes

ℹ️ Need help interpreting these results?

…ift-duplicating

ProBuilderShape.UpdateShape() rebuilt a resized shape around its stale
center (valid only for the previous size) instead of the pivot corner,
so resizing a shape via Shape Settings left the mesh floating away from
its pivot. The first attempt at this re-derived the pivot corner from
the sign of the stale center, but that breaks for shapes with a negative
size axis (e.g. Stairs dragged backwards): center = pivot + size/2 holds
regardless of size's sign, so a corner "sign" derived independently of
size can end up flipped relative to it.

Fixed by recording, per axis, the ratio of the pivot-to-center offset to
the half-size (0 for Center, 1 for First Vertex - a value immune to
size's sign) once at rebuild time, and re-deriving the center from that
ratio and the current size on every resize.

DrawShapeTool.previewPivotPosition had the same class of bug: it
reconstructed the shift-duplicate placement offset from the sign of
the last-drawn shape's recorded corner vector and that shape's own
(possibly stale or differently-signed) size. Since a First Vertex pivot
is always exactly bounds.center - size/2, that reconstruction is
unnecessary - the fix uses the current preview bounds directly.
@lopezt-unity lopezt-unity changed the title [UUM-149791] Fix offset pivot gizmo when duplicating shapes with First Vertex pivot [UUM-149791] Fix First Vertex pivot offset when resizing shapes or shift-duplicating Aug 21, 2026
…acement

Covers the reviewer-reported scenario directly: a shape drawn toward
negative X (positive m_LastNonDuplicateCenterToOrigin.x, negative
current size.x). Already passes - previewPivotPosition stopped using
m_LastNonDuplicateCenterToOrigin entirely as of aa36ccd, in favor of
computing the offset straight from the current (signed) bounds size.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant