Skip to content

Preserve off-center body position after copying - #318

Merged
viblo merged 2 commits into
viblo:masterfrom
antonsoo:fix/restore-body-center-of-gravity
Oct 18, 2026
Merged

viblo merged 2 commits into
viblo:masterfrom
antonsoo:fix/restore-body-center-of-gravity

Conversation

@antonsoo

@antonsoo antonsoo commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

A copied body with a nonzero center of gravity initially reports the correct position, then jumps on its first position update:

body = pymunk.Body(2, 9)
body.center_of_gravity = (2, 3)
body.position = (10, 11)
restored = body.copy()
pymunk.Body.update_position(restored, 0.1)
print(restored.position)  # currently Vec2d(8.0, 8.0), despite zero velocity

Restore center_of_gravity before position, following the maintainer's suggested attribute ordering. Older saved states still carry the old ordering, so restoration also puts position last in a fresh attribute list. Position is assigned once, and the caller's saved state is unchanged.

Regression checks cover dynamic/kinematic bodies, deepcopy and pickle protocols 2 and 5, then perform a native position update. Two added subtests load the historical attribute order; the simple ordering-only variant fails those, and the final correction passes them. Current upstream now includes the independently merged segment-neighbor correction in #319. Full native tests and mypy pass on the rebased correction; the native Munk2D source and reused extension are unchanged.

A native continuation check uses Space.copy and pickle protocols 2, 4 and 5, three seeds, eight/32 bodies, offset/centered bodies, gravity and angular motion. All 48 corrected histories exactly match their uninterrupted source histories and independent center-of-mass equations. Another 36 cases load frozen archives written by unchanged current upstream: 18 displaced scenes and 86,400 wrong body-step observations become zero. All frozen input hashes and all original histories remain exact. Newly written pickles use the requested attribute order; their raw hashes consequently change. These are contact-free physics scenes; this does not address the documented collision-cache limitation.

@viblo

viblo commented Oct 14, 2026

Copy link
Copy Markdown
Owner

Thanks for finding the bug and the PR, great to have someone looking into the copy/pickle feature!

For the PR, I think instead of setting the position twice you could rearrange the order of the attributes in the _pickle_attrs_general so that cog is set before position. Then position would not need to be set twice.

@antonsoo
antonsoo force-pushed the fix/restore-body-center-of-gravity branch from bedb5b2 to 3664775 Compare October 15, 2026 00:07
@antonsoo

Copy link
Copy Markdown
Contributor Author

Thanks. Updated the attribute order and removed the second position assignment. Older pickles retain their saved attribute order, so restoration also puts position last without changing the caller's state; two regressions cover that case. All 48 current-copy scenes and 36 frozen-archive scenes match uninterrupted motion exactly. The branch is rebased onto the #319 merge.

@viblo
viblo merged commit b6e0ce1 into viblo:master Oct 18, 2026
7 checks passed
@viblo

viblo commented Oct 18, 2026

Copy link
Copy Markdown
Owner

Thanks!
(A minor note, I updated the code after merge to not fix unpickling of pickles made with old versions. To keep the code cleaner for this special edge case.)

@antonsoo

Copy link
Copy Markdown
Contributor Author

Understood. #321 removes the old-version state test and retains the current-format coverage. It is rebased onto the #320 merge.

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.

2 participants