1
1
// 3 shears
2
2
3
-
4
3
export function threeShears ( spriteCanv , canvas , angle ) {
5
4
const spriteCtx = spriteCanv . getContext ( '2d' ) ;
6
5
7
6
const flipped = angle > 90 && angle < 270 ;
8
- // TODO: fix padding clipping
9
7
10
- let { diagonal , xMargin , yMargin } = getRotateDiagonal (
8
+ const diag = getRotateDiagonal (
11
9
spriteCanv . width ,
12
10
spriteCanv . height ,
13
11
) ;
12
+ const minXPad = 1 + ( 0 | ( spriteCanv . width / 2 ) ) ;
13
+ const overflow = diag . xMargin < minXPad ? minXPad - diag . xMargin : 0 ;
14
+ const diagonal = diag . diagonal + overflow * 2 ;
15
+ const xMargin = diag . xMargin + overflow ;
16
+ const yMargin = diag . yMargin + overflow ;
14
17
const width = diagonal ;
15
18
const height = diagonal ;
16
19
@@ -21,29 +24,29 @@ export function threeShears(spriteCanv, canvas, angle) {
21
24
spriteCanv . height ,
22
25
) ;
23
26
27
+
24
28
spriteCanv . width = diagonal ;
25
- spriteCanv . height = diagonal ;
29
+ spriteCanv . height = spriteCanv . width ;
26
30
27
31
if ( flipped ) {
28
- spriteCtx . putImageData ( flipImageData ( copy ) , xMargin + 1 , yMargin + 1 ) ;
32
+ spriteCtx . putImageData (
33
+ flipImageData ( copy ) ,
34
+ xMargin + 1 ,
35
+ yMargin + 1 ,
36
+ ) ;
29
37
} else {
30
38
spriteCtx . putImageData ( copy , xMargin , yMargin ) ;
31
-
32
39
}
33
40
34
41
const ctx = canvas . getContext ( '2d' ) ;
35
- canvas . width = width ;
36
- canvas . height = height ;
37
-
38
- // ctx.drawImage(spriteCanv,0,0);
39
- // return;
42
+ canvas . width = diagonal ;
43
+ canvas . height = diagonal ;
40
44
41
45
// rotate
42
46
43
47
const clampedAngle = flipped ? angle - 180 : angle ;
44
48
const theta = ( clampedAngle * Math . PI ) / 180 ;
45
49
const alpha = - Math . tan ( theta / 2 ) ;
46
- const beta = Math . sin ( theta ) ;
47
50
48
51
for ( let y = 0 ; y < height ; ++ y ) {
49
52
const shear = Math . round ( ( y - height / 2 ) * alpha ) ;
@@ -53,7 +56,7 @@ export function threeShears(spriteCanv, canvas, angle) {
53
56
spriteCtx . drawImage ( canvas , 0 , 0 ) ;
54
57
ctx . clearRect ( 0 , 0 , width , height ) ;
55
58
for ( let x = 0 ; x < width ; ++ x ) {
56
- const shear = Math . round ( ( x - width / 2 ) * beta ) ;
59
+ const shear = Math . round ( ( x - width / 2 ) * Math . sin ( theta ) ) ;
57
60
ctx . drawImage ( spriteCanv , x , 0 , 1 , height , x , shear , 1 , height ) ;
58
61
}
59
62
spriteCtx . clearRect ( 0 , 0 , width , height ) ;
@@ -63,6 +66,12 @@ export function threeShears(spriteCanv, canvas, angle) {
63
66
const shear = Math . round ( ( y - height / 2 ) * alpha ) ;
64
67
ctx . drawImage ( spriteCanv , 0 , y , width , 1 , shear , y , width , 1 ) ;
65
68
}
69
+
70
+ // crop overflow
71
+ const inner = ctx . getImageData ( overflow , overflow , diag . diagonal , diag . diagonal ) ;
72
+ canvas . width = diag . diagonal ;
73
+ canvas . height = diag . diagonal ;
74
+ ctx . putImageData ( inner , 0 , 0 ) ;
66
75
}
67
76
68
77
function flipImageData ( imageData ) {
@@ -84,7 +93,6 @@ function flipImageData(imageData) {
84
93
return rotatedImageData ;
85
94
}
86
95
87
-
88
96
// common
89
97
90
98
function getRotateDiagonal ( width , height ) {
@@ -103,7 +111,6 @@ function getRotateDiagonal(width, height) {
103
111
// stole code from ChaseMor/pxt-arcade-rotsprite
104
112
// some generated with chatGPT
105
113
106
-
107
114
export function rotsprite ( spriteCanv , canvas , angle ) {
108
115
const spriteCtx = spriteCanv . getContext ( '2d' ) ;
109
116
const { width, height } = spriteCanv ;
@@ -119,11 +126,7 @@ export function rotsprite(spriteCanv, canvas, angle) {
119
126
function rotateImageData ( imageData , angle , width , height ) {
120
127
const { diagonal, xMargin, yMargin } = getRotateDiagonal ( width , height ) ;
121
128
122
- const spriteData = addMarginToImageData (
123
- imageData ,
124
- xMargin ,
125
- yMargin ,
126
- ) ;
129
+ const spriteData = addMarginToImageData ( imageData , xMargin , yMargin ) ;
127
130
128
131
const data = new Uint32Array ( diagonal ** 2 ) ;
129
132
0 commit comments