🐛 Restore main orientation when resetting a component copy

Reset used the copy's geometry override to rotate the main before copying
its values, then cleared the override. The copy and its children kept the
old rotation until the next sync. Reset now uses the main's orientation.

The regression failed at 45 degrees before the fix and now passes, with
exact undo restoration. Shared scenarios and golden masters pass:
55 tests, 1866 assertions. No existing golden digest changed.

Sync benchmark ratios against the 1e baseline (lower quantile):
main 10/100/1000 copies 0.54/0.58/0.58; three levels 0.51; chain 0.62;
library 0.51; many shapes 0.47; variant switch 0.61. No regression flags.

AI-assisted-by: GPT-6
This commit is contained in:
alonso.torres 2026-10-23 08:43:19 +02:00
parent 7c5fde720c
commit f5be9d2dbb
2 changed files with 31 additions and 1 deletions

View File

@ -299,7 +299,10 @@
as it follows its near main."
[changes {:keys [container main-container root-inst root-main reset?]}
shape-inst shape-main]
(let [omit-touched? (not reset?)]
(let [omit-touched? (not reset?)
;; Reset takes the main's orientation too. Its old geometry override
;; must not turn the main into the copy's frame before overwriting it.
root-inst (cond-> root-inst reset? (dissoc :touched))]
(cond-> (update-attrs changes shape-inst shape-main root-inst root-main container omit-touched?)
;; the children refer to the children of `shape-main`, in the
;; container of the walk's main shapes

View File

@ -7,14 +7,18 @@
(ns common-tests.logic.comp-reset-test
(:require
[app.common.files.changes-builder :as pcb]
[app.common.geom.shapes :as gsh]
[app.common.logic.libraries :as cll]
[app.common.logic.shapes :as cls]
[app.common.test-helpers.components :as thc]
[app.common.test-helpers.composable.comp.nodes :as n]
[app.common.test-helpers.compositions :as tho]
[app.common.test-helpers.files :as thf]
[app.common.test-helpers.ids-map :as thi]
[app.common.test-helpers.normalize :as thn]
[app.common.test-helpers.shapes :as ths]
[app.common.types.container :as ctn]
[app.common.types.modifiers :as ctm]
[clojure.test :as t]))
(t/use-fixtures :each thi/test-fixture)
@ -572,3 +576,26 @@
(t/is (= #{:fill-group} (:touched (ths/get-shape-by-id file nested))))
(t/is (= #{:fill-group} (:touched (ths/get-shape-by-id file' nested))))))
(t/deftest reset-restores-the-main-rotation-and-undo-restores-the-override
(let [file (-> (thf/sample-file :file1)
(tho/add-simple-component-with-copy
:component1 :main-root :main-child :copy-root
:main-root-params {:width 100 :height 100}
:main-child-params {:width 40 :height 30}
:copy-root-params {:children-labels [:copy-child]}))
page (thf/current-page file)
root (ths/get-shape file :copy-root)
rotated (thf/apply-changes
file (n/transform-changes page root
(ctm/rotation-modifiers root (gsh/shape->center root) 45)))
page (thf/current-page rotated)
changes (cll/generate-reset-component
(pcb/empty-changes) rotated {(:id rotated) rotated}
(ctn/make-container page :page) (thi/id :copy-root))
reset (thf/apply-changes rotated changes)
undone (thf/apply-changes reset {:redo-changes (:undo-changes changes)})]
(t/is (= 0 (:rotation (ths/get-shape reset :copy-root))))
(t/is (= 0 (:rotation (ths/get-shape reset :copy-child))))
(t/is (nil? (:touched (ths/get-shape reset :copy-root))))
(t/is (= (thn/normalize-file rotated) (thn/normalize-file undone)))))