@@ -2,125 +2,38 @@ import React, { useEffect, useRef } from 'react';
22import { environment } from '#store/environment' ;
33import { observer } from 'mobx-react' ;
44import { exportSprite } from '#formats/image' ;
5- import { rotateImageData , getRotateDiagonal } from '#util/rotsprite' ;
6- import { Input , Slider , Item , Button , Modal } from '#ui' ;
5+ import { rotsprite , threeShears } from '#util/rotsprite' ;
6+ import { Input , Slider , Item , Button , Modal , Select } from '#ui' ;
77import { mappingState } from './state' ;
88
99import { importState } from '../import/state' ;
1010
11- function rotateCurrentSprite ( canvas , angle ) {
11+ function rotateCurrentSprite ( canvas , angle , algorithm ) {
1212 const spriteCanv = exportSprite ( environment . currentSprite ) ;
13- const spriteCtx = spriteCanv . getContext ( '2d' ) ;
14- // const { width, height } = spriteCanv;
15- // const imageData = spriteCtx.getImageData(0, 0, width, height);
16- // const rotatedData = rotateImageData(imageData, angle, width, height);
1713
18- // const ctx = canvas.getContext('2d');
19- // canvas.width = rotatedData.width;
20- // canvas.height = rotatedData.height;
21- // ctx.putImageData(rotatedData, 0, 0);
22-
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- }
41-
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- ) ;
50- const width = diagonal ;
51- const height = diagonal ;
52-
53- const copy = spriteCtx . getImageData (
54- 0 ,
55- 0 ,
56- spriteCanv . width ,
57- spriteCanv . height ,
58- ) ;
59-
60- spriteCanv . width = diagonal ;
61- spriteCanv . height = diagonal ;
62-
63- spriteCtx . putImageData ( flipped ? flipImageData ( copy ) : copy , xMargin , yMargin ) ;
64-
65- const ctx = canvas . getContext ( '2d' ) ;
66- canvas . width = width ;
67- canvas . height = height ;
68-
69-
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);
14+ if ( algorithm === 'rotsprite' ) {
15+ rotsprite ( spriteCanv , canvas , angle ) ;
16+ } else {
17+ threeShears ( spriteCanv , canvas , angle ) ;
8018 }
8119
82- // rotate
83-
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 ) ;
88-
89- for ( let y = 0 ; y < height ; ++ y ) {
90- const shear = Math . round ( ( y - height / 2 ) * alpha ) ;
91- ctx . drawImage ( spriteCanv , 0 , y , width , 1 , shear , y , width , 1 ) ;
92- }
93- spriteCtx . clearRect ( 0 , 0 , width , height ) ;
94- spriteCtx . drawImage ( canvas , 0 , 0 ) ;
95- ctx . clearRect ( 0 , 0 , width , height ) ;
96- for ( let x = 0 ; x < width ; ++ x ) {
97- const shear = Math . round ( ( x - width / 2 ) * beta ) ;
98- ctx . drawImage ( spriteCanv , x , 0 , 1 , height , x , shear , 1 , height ) ;
99- }
100- spriteCtx . clearRect ( 0 , 0 , width , height ) ;
101- spriteCtx . drawImage ( canvas , 0 , 0 ) ;
102- ctx . clearRect ( 0 , 0 , width , height ) ;
103- for ( let y = 0 ; y < height ; ++ y ) {
104- const shear = Math . round ( ( y - height / 2 ) * alpha ) ;
105- ctx . drawImage ( spriteCanv , 0 , y , width , 1 , shear , y , width , 1 ) ;
106- }
10720}
10821
10922export const Rotate = observer ( ( ) => {
11023 const canvasRef = useRef ( ) ;
11124
112- const { active, angle } = mappingState . rotate ;
25+ const { active, angle, algorithm } = mappingState . rotate ;
11326
11427 useEffect ( ( ) => {
11528 if ( ! canvasRef . current ) {
11629 requestAnimationFrame ( ( ) => {
11730 canvasRef . current &&
118- rotateCurrentSprite ( canvasRef . current , angle ) ;
31+ rotateCurrentSprite ( canvasRef . current , angle , algorithm ) ;
11932 } ) ;
12033 return ;
12134 }
122- rotateCurrentSprite ( canvasRef . current , angle ) ;
123- } , [ environment . currentSprite , angle , active ] ) ;
35+ rotateCurrentSprite ( canvasRef . current , angle , algorithm ) ;
36+ } , [ environment . currentSprite , angle , active , algorithm ] ) ;
12437
12538 const assertInput = ( num ) => {
12639 const value = Math . max ( 0 , Math . min ( 360 , num ) ) ;
@@ -142,7 +55,14 @@ export const Rotate = observer(() => {
14255 opacity : active ? 1 : 0 ,
14356 } }
14457 >
58+ < div className = "row" >
14559 < Item > Rotate Sprite</ Item >
60+ < Select
61+ options = { mappingState . rotateAlgOptions }
62+ store = { mappingState . rotate }
63+ accessor = "algorithm"
64+ />
65+ </ div >
14666 < canvas ref = { canvasRef } />
14767 < div className = "angles" >
14868 < div className = "numbers" >
@@ -177,7 +97,7 @@ export const Rotate = observer(() => {
17797 </ div >
17898 < div className = "actions" >
17999 < Button color = "magenta" onClick = { mappingState . toggleRotate } >
180- close
100+ Close
181101 </ Button >
182102 < Button color = "red" onClick = { reImport } >
183103 Import
0 commit comments