Skip to content

Commit 2172711

Browse files
committed
add border
1 parent e7a80fe commit 2172711

File tree

8 files changed

+99
-41
lines changed

8 files changed

+99
-41
lines changed

app/components/mappings/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ export const Mappings = observer(class Mappings extends Component {
5858

5959
return (
6060
<div className="mappings" ref={this.onRef}>
61-
<Rotate />
6261
<div
6362
ref={this.mappingRef}
6463
className="mappingContainer"
@@ -134,6 +133,7 @@ export const Mappings = observer(class Mappings extends Component {
134133
/>
135134

136135
<RawEditor />
136+
<Rotate />
137137

138138
<Commands />
139139
</div>

app/components/mappings/rotate.js

Lines changed: 70 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,97 @@
1-
import React, { useState, useEffect, useRef } from 'react';
1+
import React, { useEffect, useRef } from 'react';
22
import { environment } from '#store/environment';
3+
import { observer } from 'mobx-react';
34
import { exportSprite } from '#formats/image';
45
import rotSprite, { Pixels } from '#util/rotsprite';
6+
import { Input, Slider, Item } from '#ui';
7+
import { mappingState } from './state';
58

6-
export function Rotate() {
7-
return null;
9+
export const Rotate = observer(() => {
810
const canvasRef = useRef();
9-
const [angle, setAngle] = useState(45);
1011

1112
useEffect(() => {
12-
const canvas = canvasRef.current;
13-
const ctx = canvas.getContext('2d');
14-
1513
const spriteCanv = exportSprite(environment.currentSprite);
1614
const spriteCtx = spriteCanv.getContext('2d');
1715

18-
const imageData = spriteCtx.getImageData(0, 0, canvas.width, canvas.height);
19-
const data = new Uint32Array(imageData.width * imageData.height);
16+
const { width, height } = spriteCanv;
17+
spriteCtx.scale(2, 2)
18+
19+
const imageData = spriteCtx.getImageData(0, 0, width, height);
20+
21+
const diagonal =
22+
1 + (0 | (2 * Math.sqrt(width ** 2 / 4 + height ** 2 / 4)));
23+
24+
const xMargin = (diagonal - width) / 2;
25+
const yMargin = (diagonal - height) / 2;
2026

21-
for (let i = 0; i < imageData.data.length; i += 4) {
22-
const r = imageData.data[i];
23-
const g = imageData.data[i + 1];
24-
const b = imageData.data[i + 2];
25-
data[i / 4] = (r << 16) + (g << 8) + b;
27+
spriteCanv.width = diagonal;
28+
spriteCanv.height = diagonal;
29+
spriteCtx.putImageData(imageData, xMargin, yMargin);
30+
31+
const spriteData = spriteCtx.getImageData(0, 0, diagonal, diagonal);
32+
33+
const data = new Uint32Array(diagonal ** 2);
34+
35+
for (let i = 0; i < spriteData.data.length; i += 4) {
36+
const r = spriteData.data[i];
37+
const g = spriteData.data[i + 1];
38+
const b = spriteData.data[i + 2];
39+
const a = spriteData.data[i + 3];
40+
data[i / 4] = (a << 24) + (r << 16) + (g << 8) + b;
2641
}
2742

2843
const rotated = rotSprite(
29-
new Pixels(imageData.width, imageData.height, data),
30-
angle
44+
new Pixels(diagonal, diagonal, data),
45+
(mappingState.rotateAngle * Math.PI) / 180,
3146
).pixels;
3247

3348
const pixelData = new Uint8ClampedArray(data.length * 4);
3449

3550
for (let i = 0; i < data.length; i++) {
3651
const value = rotated[i];
3752

38-
pixelData[i * 4] = (value >> 16) & 0xFF;
39-
pixelData[i * 4 + 1] = (value >> 8) & 0xFF;
40-
pixelData[i * 4 + 2] = value & 0xFF;
41-
pixelData[i * 4 + 3] = 255;
53+
pixelData[i * 4] = (value >> 16) & 0xff;
54+
pixelData[i * 4 + 1] = (value >> 8) & 0xff;
55+
pixelData[i * 4 + 2] = value & 0xff;
56+
pixelData[i * 4 + 3] = (value >> 24) & 0xff;
4257
}
4358

44-
const imageData2 = new ImageData(pixelData, canvas.width, canvas.height);
59+
const rotatedData = new ImageData(pixelData, diagonal, diagonal);
60+
61+
const canvas = canvasRef.current;
62+
const ctx = canvas.getContext('2d');
4563

46-
canvas.width = spriteCanv.width;
47-
canvas.height = spriteCanv.height;
48-
ctx.putImageData(imageData2, 0, 0);
49-
canvas.style.width = '200px';
64+
canvas.width = diagonal;
65+
canvas.height = diagonal;
66+
ctx.putImageData(rotatedData, 0, 0);
67+
canvas.style.width = '400px';
5068
canvas.style.imageRendering = 'pixelated';
69+
canvas.style.backgroundColor = 'red';
70+
}, [environment.currentSprite, mappingState.rotateAngle]);
5171

72+
const assertInput = (num) => {
73+
const value = Math.max(0, Math.min(360, num));
74+
if (Number.isNaN(value)) return 0;
75+
return value;
76+
};
5277

53-
}, [environment.currentSprite, angle]);
54-
return <>
55-
<canvas ref={canvasRef} />
56-
<input className="slider" type="range" min="0" step="0.01" max="6.5" value={angle} onChange={e => setAngle(e.target.value)} />
57-
</>
58-
}
78+
return (
79+
<div className="rotsprite">
80+
<Item>Rotate Sprite</Item>
81+
<canvas ref={canvasRef} />
82+
<Input
83+
store={mappingState}
84+
assert={assertInput}
85+
accessor="rotateAngle"
86+
isNumber
87+
/>
88+
<Slider
89+
min="0"
90+
step="1"
91+
max="360"
92+
store={mappingState}
93+
accessor="rotateAngle"
94+
/>
95+
</div>
96+
);
97+
});

app/components/mappings/state/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { observable, computed, action, autorun, toJS, makeObservable } from 'mobx';
1+
import { observable, computed, action, makeObservable } from 'mobx';
22
import { environment } from '#store/environment';
33
import clamp from 'lodash/clamp';
44
import { getCenter } from './bounds';
@@ -16,6 +16,7 @@ class MappingState {
1616
scale = 4;
1717
x = 300;
1818
y = 300;
19+
rotateAngle = 0;
1920

2021
resetPanAndZoom = () => {
2122
this.setZoom(4);
@@ -63,6 +64,7 @@ class MappingState {
6364
scale: observable,
6465
x: observable,
6566
y: observable,
67+
rotateAngle: observable,
6668
resetPanAndZoom: action,
6769
setWidth: action,
6870
setZoom: action,

app/components/ui/input/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ export const Input = observer(class Input extends Component {
2121
};
2222

2323
onKeyDown = (e) => {
24-
if (e.key == 'Escape') {
24+
if (e.key === 'Escape') {
2525
e.target.blur();
2626
}
2727
else if (this.props.isNumber) {
28-
if (e.key == 'ArrowUp') {
28+
if (e.key === 'ArrowUp') {
2929
this.mutateNum(1);
3030
e.preventDefault();
3131
}
32-
else if (e.key == 'ArrowDown') {
32+
else if (e.key === 'ArrowDown') {
3333
this.mutateNum(-1);
3434
e.preventDefault();
3535
}

app/components/ui/slider/index.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ import { observer } from 'mobx-react';
33

44
export const Slider = observer(class Slider extends Component {
55

6-
onChange = (e) => {
6+
onChange = ((e) => {
77
const { store, accessor } = this.props;
88
store[accessor] = parseInt(e.target.value);
99
this.node.blur();
10-
}
10+
});
1111

1212
render() {
1313
const { store, accessor, ...otherProps } = this.props;
14-
const value = store[accessor];
14+
const value = this.props.value ?? store[accessor];
1515

1616
return <div className="slider">
1717
<input
@@ -22,7 +22,7 @@ export const Slider = observer(class Slider extends Component {
2222
step="1"
2323
value={value}
2424
className="mousetrap"
25-
onChange={this.onChange}
25+
onChange={this.props.onChange || this.onChange}
2626
{...otherProps}/>
2727
</div>;
2828
}

app/util/rotsprite.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export class Pixels {
7777
// The width and height of the image in pixels
7878
width;
7979
height;
80-
// A Uint8Array representing the colors of the pixels in the image
80+
// A Uint32Array representing the colors of the pixels in the image
8181
pixels;
8282

8383
// Constructor to create a new Image object with the given dimensions

styles/components/rotsprite.scss

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
.rotsprite {
2+
.close {
3+
display: flex;
4+
justify-content: space-between;
5+
margin-bottom: 10px;
6+
}
7+
box-sizing: content-box;
8+
position: absolute;
9+
z-index: 2;
10+
background-color: $black;
11+
left: 15px;
12+
right: 15px;
13+
box-shadow: 2px 2px 4px $black;
14+
padding: 15px;
15+
margin-top: 100px;
16+
}

styles/main.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
@import './components/mappings.scss';
1111
@import './components/palettes.scss';
1212
@import './components/import.scss';
13+
@import './components/rotsprite.scss';
1314
@import './components/documentation.scss';
1415

1516
html {

0 commit comments

Comments
 (0)