Implement Phase 10a - Prop Scaling

- Added specifications for Phase 10a, introducing permanent size changes to `.prop` documents and reversible uniform instance scaling in Sandbox EDIT mode.
- Updated `PropCanvas`, `PropAnchorData`, `PropEditor`, `StageGizmos`, `SandboxStage`, and `StageSelection` classes to support new scaling features.
- Implemented document transactions for scaling, including normalization to a 96 px maximum dimension.
- Introduced a new **Transform Whole Prop** tool in the Prop Editor for moving, rotating, and resizing props.
- Created unit tests for the new scaling functionality, validating shape scaling, anchor transformations, and whole-prop interactions.
- Ensured compatibility with existing prop formats and maintained the integrity of the document structure during scaling operations.
This commit is contained in:
2026-09-22 22:23:31 -04:00
parent 97f3730413
commit 0a7f97cec7
18 changed files with 1782 additions and 78 deletions
+111 -27
View File
@@ -13,14 +13,14 @@
"role": "grip",
"rotation_deg": 0.0,
"x": 0.0,
"y": -42.5,
"y": -82.066291809082,
"z_index_offset": 1
}
},
"material_preset": "wood",
"metadata": {
"created_at": "2026-09-21T16:00:00",
"modified_at": "2026-09-21T16:00:00"
"created_at": "2026-09-22T00:22:32",
"modified_at": "2026-09-22T00:22:32"
},
"prop_name": "Brown Briefcase",
"shapes": [
@@ -30,18 +30,51 @@
"outline_color": "#26150CFF",
"outline_width": 2.0,
"points": [
{ "x": -25.0, "y": -30.0 },
{ "x": -25.0, "y": -55.0 },
{ "x": 25.0, "y": -55.0 },
{ "x": 25.0, "y": -30.0 },
{ "x": 18.0, "y": -30.0 },
{ "x": 18.0, "y": -47.0 },
{ "x": -18.0, "y": -47.0 },
{ "x": -18.0, "y": -30.0 }
{
"x": -48.2742919921875,
"y": -57.9291458129883
},
{
"x": -48.2742919921875,
"y": -106.20344543457
},
{
"x": 48.2742919921875,
"y": -106.20344543457
},
{
"x": 48.2742919921875,
"y": -57.9291458129883
},
{
"x": 34.7574882507324,
"y": -57.9291458129883
},
{
"x": 34.7574882507324,
"y": -90.7556686401367
},
{
"x": -34.7574882507324,
"y": -90.7556686401367
},
{
"x": -34.7574882507324,
"y": -57.9291458129883
}
],
"reshaped": true,
"shape_type": "polygon",
"vertex_flags": [0, 0, 0, 0, 0, 0, 0, 0]
"vertex_flags": [
0,
0,
0,
0,
0,
0,
0,
0
]
},
{
"closed": true,
@@ -49,14 +82,31 @@
"outline_color": "#3B200AFF",
"outline_width": 3.0,
"points": [
{ "x": -70.0, "y": -30.0 },
{ "x": 70.0, "y": -30.0 },
{ "x": 70.0, "y": 40.0 },
{ "x": -70.0, "y": 40.0 }
{
"x": -135.168014526367,
"y": -57.9291458129883
},
{
"x": 135.168014526367,
"y": -57.9291458129883
},
{
"x": 135.168014526367,
"y": 77.2388610839844
},
{
"x": -135.168014526367,
"y": 77.2388610839844
}
],
"reshaped": false,
"shape_type": "polygon",
"vertex_flags": [0, 0, 0, 0]
"vertex_flags": [
0,
0,
0,
0
]
},
{
"closed": true,
@@ -64,14 +114,31 @@
"outline_color": "#8B7500FF",
"outline_width": 1.5,
"points": [
{ "x": -45.0, "y": -32.0 },
{ "x": -30.0, "y": -32.0 },
{ "x": -30.0, "y": -22.0 },
{ "x": -45.0, "y": -22.0 }
{
"x": -86.8937225341797,
"y": -61.791088104248
},
{
"x": -57.9291458129883,
"y": -61.791088104248
},
{
"x": -57.9291458129883,
"y": -42.481372833252
},
{
"x": -86.8937225341797,
"y": -42.481372833252
}
],
"reshaped": false,
"shape_type": "polygon",
"vertex_flags": [0, 0, 0, 0]
"vertex_flags": [
0,
0,
0,
0
]
},
{
"closed": true,
@@ -79,14 +146,31 @@
"outline_color": "#8B7500FF",
"outline_width": 1.5,
"points": [
{ "x": 30.0, "y": -32.0 },
{ "x": 45.0, "y": -32.0 },
{ "x": 45.0, "y": -22.0 },
{ "x": 30.0, "y": -22.0 }
{
"x": 57.9291458129883,
"y": -61.791088104248
},
{
"x": 86.8937225341797,
"y": -61.791088104248
},
{
"x": 86.8937225341797,
"y": -42.481372833252
},
{
"x": 57.9291458129883,
"y": -42.481372833252
}
],
"reshaped": false,
"shape_type": "polygon",
"vertex_flags": [0, 0, 0, 0]
"vertex_flags": [
0,
0,
0,
0
]
}
],
"version": "1.0"