Skip to content

Commit 5085fcd

Browse files
committed
rotation +180 supported for 3 shears
1 parent b2c0677 commit 5085fcd

File tree

2 files changed

+65
-17
lines changed

2 files changed

+65
-17
lines changed

app/components/mappings/rotate.js

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,47 +20,88 @@ function rotateCurrentSprite(canvas, angle) {
2020
// canvas.height = rotatedData.height;
2121
// ctx.putImageData(rotatedData, 0, 0);
2222

23+
function flipImageData(imageData) {
24+
const { width, height, data } = imageData;
25+
const rotatedImageData = new ImageData(width, height);
26+
const rotatedData = rotatedImageData.data;
27+
28+
for (let y = 0; y < height; y++) {
29+
for (let x = 0; x < width; x++) {
30+
const srcIndex = (y * width + x) * 4;
31+
const dstIndex = ((height - y - 1) * width + (width - x - 1)) * 4;
32+
rotatedData[dstIndex + 0] = data[srcIndex + 0];
33+
rotatedData[dstIndex + 1] = data[srcIndex + 1];
34+
rotatedData[dstIndex + 2] = data[srcIndex + 2];
35+
rotatedData[dstIndex + 3] = data[srcIndex + 3];
36+
}
37+
}
38+
39+
return rotatedImageData;
40+
}
2341

24-
// add padding
25-
const { diagonal, xMargin, yMargin } = getRotateDiagonal(spriteCanv.width, spriteCanv.height);
42+
const flipped = angle > 90 && angle < 270;
43+
// TODO: fix flip clipping
44+
// TODO: fix padding clipping
45+
46+
let { diagonal, xMargin, yMargin } = getRotateDiagonal(
47+
spriteCanv.width,
48+
spriteCanv.height,
49+
);
2650
const width = diagonal;
2751
const height = diagonal;
2852

29-
const copy = spriteCtx.getImageData(0, 0, spriteCanv.width, spriteCanv.height);
53+
const copy = spriteCtx.getImageData(
54+
0,
55+
0,
56+
spriteCanv.width,
57+
spriteCanv.height,
58+
);
3059

3160
spriteCanv.width = diagonal;
3261
spriteCanv.height = diagonal;
3362

34-
spriteCtx.putImageData(copy, xMargin, yMargin);
63+
spriteCtx.putImageData(flipped ? flipImageData(copy) : copy, xMargin, yMargin);
3564

3665
const ctx = canvas.getContext('2d');
3766
canvas.width = width;
3867
canvas.height = height;
3968

40-
// rotate
4169

42-
const theta = angle * Math.PI / 180;
43-
const alpha = -Math.tan(theta/2);
44-
const beta = Math.sin(theta);
70+
if (flipped) {
71+
// // flip spriteCanv using ctx as a buffer
72+
// ctx.save();
73+
// ctx.translate(width / 2, height / 2);
74+
// ctx.rotate(Math.PI);
75+
// ctx.drawImage(spriteCanv, -width / 2, -width / 2);
76+
// ctx.restore();
77+
// spriteCtx.clearRect(0, 0, width, height);
78+
// spriteCtx.drawImage(canvas, 0, 0, width, height);
79+
// ctx.clearRect(0, 0, width, height);
80+
}
4581

82+
// rotate
4683

84+
const clampedAngle = flipped ? angle - 180 : angle;
85+
const theta = (clampedAngle * Math.PI) / 180;
86+
const alpha = -Math.tan(theta / 2);
87+
const beta = Math.sin(theta);
4788

4889
for (let y = 0; y < height; ++y) {
49-
const shear = Math.round((y - height/2) * alpha);
90+
const shear = Math.round((y - height / 2) * alpha);
5091
ctx.drawImage(spriteCanv, 0, y, width, 1, shear, y, width, 1);
5192
}
5293
spriteCtx.clearRect(0, 0, width, height);
5394
spriteCtx.drawImage(canvas, 0, 0);
5495
ctx.clearRect(0, 0, width, height);
5596
for (let x = 0; x < width; ++x) {
56-
const shear = Math.round((x - width/2) * beta);
97+
const shear = Math.round((x - width / 2) * beta);
5798
ctx.drawImage(spriteCanv, x, 0, 1, height, x, shear, 1, height);
5899
}
59100
spriteCtx.clearRect(0, 0, width, height);
60101
spriteCtx.drawImage(canvas, 0, 0);
61102
ctx.clearRect(0, 0, width, height);
62103
for (let y = 0; y < height; ++y) {
63-
const shear = Math.round((y - height/2) * alpha);
104+
const shear = Math.round((y - height / 2) * alpha);
64105
ctx.drawImage(spriteCanv, 0, y, width, 1, shear, y, width, 1);
65106
}
66107
}
@@ -138,7 +179,9 @@ export const Rotate = observer(() => {
138179
<Button color="magenta" onClick={mappingState.toggleRotate}>
139180
close
140181
</Button>
141-
<Button color="red" onClick={reImport}>Import</Button>
182+
<Button color="red" onClick={reImport}>
183+
Import
184+
</Button>
142185
</div>
143186
</Modal>
144187
);

app/util/rotsprite.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// 3 shears
2+
3+
// common
4+
15
export function getRotateDiagonal(width, height) {
26
const diagonal =
37
1 + (0 | (2 * Math.sqrt(width ** 2 / 4 + height ** 2 / 4)));
@@ -8,6 +12,12 @@ export function getRotateDiagonal(width, height) {
812
return { diagonal: xMargin * 2 + width, xMargin, yMargin };
913
}
1014

15+
// rotsprite
16+
//
17+
// original algorithm Xenowhirl
18+
// stole code from ChaseMor/pxt-arcade-rotsprite
19+
// some generated with chatGPT
20+
1121
export function rotateImageData(imageData, angle, width, height) {
1222
const { diagonal, xMargin, yMargin } = getRotateDiagonal(width, height);
1323

@@ -46,11 +56,6 @@ export function rotateImageData(imageData, angle, width, height) {
4656
return new ImageData(pixelData, diagonal, diagonal);
4757
}
4858

49-
// rotsprite
50-
// original algorithm Xenowhirl
51-
// stole code from ChaseMor/pxt-arcade-rotsprite
52-
// some generated with chatGPT
53-
5459
function rotSprite(image, angle) {
5560
image = scale2xImage(image);
5661
image = scale2xImage(image);

0 commit comments

Comments
 (0)