Skip to content

Commit 6459bca

Browse files
committed
v0.2.0
1 parent f2c8384 commit 6459bca

File tree

6 files changed

+141
-67
lines changed

6 files changed

+141
-67
lines changed

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "react-hex-engine",
33
"description": "Hexagon Map Editor and Game Engine",
4-
"version": "0.1.0",
4+
"version": "0.2.0-rc.10",
55
"main": "lib/index.js",
66
"author": "IcculusC",
77
"repository": "IcculusC/react-hex-engine",
@@ -46,7 +46,8 @@
4646
"react-test-renderer": "^16.5.2"
4747
},
4848
"dependencies": {
49-
"classnames": "^2.2.5"
49+
"classnames": "^2.2.5",
50+
"memoize-one": "^4.0.2"
5051
},
5152
"files": [
5253
"lib/**/*"

src/Hexagon/Hexagon.js

Lines changed: 96 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ import PropTypes from "prop-types";
33
import classNames from "classnames";
44
import Hex from "../models/Hex";
55
import HexUtils from "../HexUtils";
6+
import Point from "../models/Point";
67
import { withExpandedLayout } from "../Context";
78

89
class Hexagon extends Component {
910
static propTypes = {
1011
children: PropTypes.node,
11-
className: PropTypes.string,
12+
classes: PropTypes.objectOf(PropTypes.any),
1213
data: PropTypes.object,
1314
highlighted: PropTypes.bool,
1415
layout: PropTypes.objectOf(PropTypes.any).isRequired,
@@ -24,7 +25,8 @@ class Hexagon extends Component {
2425
q: PropTypes.number.isRequired,
2526
r: PropTypes.number.isRequired,
2627
s: PropTypes.number.isRequired,
27-
selected: PropTypes.bool
28+
selected: PropTypes.bool,
29+
showCoordinates: PropTypes.bool
2830
};
2931

3032
static defaultProps = {
@@ -35,50 +37,60 @@ class Hexagon extends Component {
3537
highlighted: "",
3638
hovered: "",
3739
polygon: "",
40+
q: "",
41+
r: "",
42+
s: "",
3843
selected: ""
39-
}
44+
},
45+
showCoordinates: false
4046
};
4147

42-
static getDerivedStateFromProps(nextProps, prevState) {
43-
const { layout, q, r, s } = nextProps;
44-
const hex = new Hex(q, r, s);
45-
const pixel = HexUtils.hexToPixel(hex, layout);
46-
47-
if (
48-
(!prevState.hex && !prevState.pixel) ||
49-
!(
50-
HexUtils.equals(prevState.hex, hex) ||
51-
(prevState.pixel.x === pixel.x && prevState.pixel.y === pixel.y)
52-
)
53-
) {
54-
return { hex, pixel };
55-
}
56-
return null;
48+
static getCoordinateTextOffset(
49+
corner,
50+
{ orientation, size },
51+
offset = new Point(0, 0),
52+
scale = new Point(0.75, 0.75)
53+
) {
54+
const angle = (2.0 * Math.PI * (corner + 0.5)) / 6;
55+
return new Point(
56+
size.x * scale.x * Math.cos(angle),
57+
size.y * scale.y * Math.sin(angle)
58+
);
5759
}
5860

5961
state = {
6062
hex: {},
61-
hovered: false,
62-
pixel: {}
63+
hovered: false
6364
};
6465

66+
constructor(props) {
67+
super(props);
68+
const hex = new Hex(props.q, props.r, props.s);
69+
const pixel = HexUtils.hexToPixel(hex, props.layout);
70+
this.state = {
71+
...this.state,
72+
hex,
73+
pixel
74+
};
75+
}
76+
6577
onClick(e) {
6678
if (this.props.onClick) {
67-
this.props.onClick(e, this);
79+
this.props.onClick(e, this.state.hex);
6880
}
6981
}
7082

7183
onDragEnd(e) {
7284
if (this.props.onDragEnd) {
7385
e.preventDefault();
7486
const success = e.dataTransfer.dropEffect !== "none";
75-
this.props.onDragEnd(e, this, success);
87+
this.props.onDragEnd(e, this.state.hex, success);
7688
}
7789
}
7890

7991
onDragOver(e) {
8092
if (this.props.onDragOver) {
81-
this.props.onDragOver(e, this);
93+
this.props.onDragOver(e, this.state.hex);
8294
}
8395
}
8496

@@ -87,45 +99,69 @@ class Hexagon extends Component {
8799
const targetProps = {
88100
...this.state,
89101
data: this.props.data,
90-
fill: this.props.fill,
91-
className: this.props.className
102+
classes: this.props.classes
92103
};
93104
e.dataTransfer.setData("hexagon", JSON.stringify(targetProps));
94-
this.props.onDragStart(e, this);
105+
this.props.onDragStart(e, this.state.hex);
95106
}
96107
}
97108

98109
onDrop(e) {
99110
if (this.props.onDrop) {
100111
e.preventDefault();
101112
const target = JSON.parse(e.dataTransfer.getData("hexagon"));
102-
this.props.onDrop(e, this, target);
113+
this.props.onDrop(e, this.state.hex, target);
103114
}
104115
}
105116

106117
onMouseEnter(e) {
107118
this.setState({ hovered: true });
108119
if (this.props.onMouseEnter) {
109-
this.props.onMouseEnter(e, this);
120+
this.props.onMouseEnter(e, this.state.hex);
110121
}
111122
}
112123

113124
onMouseLeave(e) {
114125
this.setState({ hovered: false });
115126
if (this.props.onMouseLeave) {
116-
this.props.onMouseLeave(e, this);
127+
this.props.onMouseLeave(e, this.state.hex);
117128
}
118129
}
119130

120131
onMouseOver(e) {
121132
if (this.props.onMouseOver) {
122-
this.props.onMouseOver(e, this);
133+
this.props.onMouseOver(e, this.state.hex);
123134
}
124135
}
125136

126137
render() {
127-
const { classes, highlighted, points, selected } = this.props;
128-
const { hovered, pixel } = this.state;
138+
const {
139+
classes,
140+
highlighted,
141+
layout,
142+
points,
143+
q,
144+
r,
145+
s,
146+
selected,
147+
showCoordinates
148+
} = this.props;
149+
const { hex, hovered, pixel } = this.state;
150+
let qPixel, rPixel, sPixel;
151+
if (showCoordinates) {
152+
qPixel = Hexagon.getCoordinateTextOffset(3, layout, {
153+
x: 0,
154+
y: 1
155+
});
156+
rPixel = Hexagon.getCoordinateTextOffset(1, layout, {
157+
x: -1,
158+
y: -1
159+
});
160+
sPixel = Hexagon.getCoordinateTextOffset(5, layout, {
161+
x: -2,
162+
y: 1
163+
});
164+
}
129165
return (
130166
<g
131167
className={classNames("hexagon-group", classes.group)}
@@ -149,6 +185,34 @@ class Hexagon extends Component {
149185
>
150186
<polygon className={classes.polygon} points={points} />
151187
{this.props.children}
188+
{showCoordinates && (
189+
<React.Fragment>
190+
<text
191+
{...qPixel}
192+
className={classes.q}
193+
fontSize={2}
194+
textAnchor="middle"
195+
>
196+
{q}
197+
</text>
198+
<text
199+
{...rPixel}
200+
className={classes.r}
201+
fontSize={2}
202+
textAnchor="middle"
203+
>
204+
{r}
205+
</text>
206+
<text
207+
{...sPixel}
208+
className={classes.s}
209+
fontSize={2}
210+
textAnchor="middle"
211+
>
212+
{s}
213+
</text>
214+
</React.Fragment>
215+
)}
152216
</g>
153217
</g>
154218
);

src/Layout.js

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { Component } from "react";
22
import PropTypes from "prop-types";
33
import classNames from "classnames";
4+
import memoize from "memoize-one";
45
import Hexagon from "./Hexagon/Hexagon";
56
import HexUtils from "./HexUtils";
67
import Orientation from "./models/Orientation";
@@ -46,21 +47,22 @@ export class Layout extends Component {
4647
return corners;
4748
}
4849

49-
static filterChildren(children, layout, viewBox) {
50+
filterChildren = memoize((children, layout, viewBox) => {
51+
const childrenArray = React.Children.toArray(children);
5052
const { height, width, x, y } = viewBox;
5153
const cornerCoords = Layout.calculateCoordinates(
5254
layout.orientation,
5355
layout.size
5456
);
55-
return children.filter(child => {
57+
return childrenArray.filter(child => {
5658
if (!child.props) {
5759
return true;
5860
}
5961
if (
6062
child.type === Hexagon ||
61-
(typeof child.props.q !== "number" &&
62-
typeof child.props.r !== "number" &&
63-
typeof child.props.s !== "number")
63+
(child.props.q !== undefined &&
64+
child.props.r !== undefined &&
65+
child.props.s !== undefined)
6466
) {
6567
const point = HexUtils.hexToPixel(child.props, layout);
6668
const corners = cornerCoords.map(
@@ -76,37 +78,24 @@ export class Layout extends Component {
7678
}
7779
return true;
7880
});
79-
}
80-
81-
static getDerivedStateFromProps(nextProps, prevState) {
82-
const children = React.Children.toArray(nextProps.children);
83-
if (
84-
prevState.viewBox !== nextProps.viewBox ||
85-
prevState.childCount !== children.length
86-
) {
87-
const { flat, viewBox, ...rest } = nextProps;
88-
const orientation = flat ? Orientation.Flat : Orientation.Pointy;
89-
const layout = { orientation, ...rest };
90-
91-
return {
92-
childCount: children.length,
93-
inBounds: Layout.filterChildren(children, layout, viewBox),
94-
viewBox
95-
};
96-
}
97-
return null;
98-
}
99-
100-
state = { childCount: 0, inBounds: [], viewBox: {} };
81+
});
10182

10283
render() {
103-
const { flat, classes, className, size, viewBox, ...rest } = this.props;
104-
const { inBounds } = this.state;
84+
const {
85+
flat,
86+
children,
87+
classes,
88+
className,
89+
size,
90+
viewBox,
91+
...rest
92+
} = this.props;
10593
const orientation = flat ? Orientation.Flat : Orientation.Pointy;
10694
const points = Layout.calculateCoordinates(orientation, size)
10795
.map(point => point.toString())
10896
.join(" ");
10997
const layout = { orientation, size, ...rest };
98+
const inBounds = this.filterChildren(children, layout, viewBox);
11099
return (
111100
<LayoutProvider value={{ layout, points }}>
112101
<g className={classNames(className, classes.layout)}>{inBounds}</g>

test/src/__snapshots__/Layout.test.js.snap

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,11 +194,19 @@ exports[`Layout should only render hexagons in bounds again 1`] = `
194194
exports[`Layout should render correctly with custom props 1`] = `
195195
<g
196196
className="test2"
197-
/>
197+
>
198+
<div>
199+
child
200+
</div>
201+
</g>
198202
`;
199203

200204
exports[`Layout should render correctly with default props 1`] = `
201205
<g
202206
className="test1"
203-
/>
207+
>
208+
<div>
209+
child
210+
</div>
211+
</g>
204212
`;

test/src/__snapshots__/Path.test.js.snap

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,19 @@
33
exports[`Path should render correctly 1`] = `
44
<g
55
className="test1"
6-
/>
6+
>
7+
<path
8+
d="M 17.147302994931888,9.9 L 0,0 "
9+
/>
10+
</g>
711
`;
812

913
exports[`Path should render correctly without an end hex 1`] = `
1014
<g
1115
className="test2"
12-
/>
16+
>
17+
<path
18+
d=""
19+
/>
20+
</g>
1321
`;

yarn.lock

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3269,6 +3269,10 @@ mem@^1.1.0:
32693269
dependencies:
32703270
mimic-fn "^1.0.0"
32713271

3272+
memoize-one@^4.0.2:
3273+
version "4.0.2"
3274+
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-4.0.2.tgz#3fb8db695aa14ab9c0f1644e1585a8806adc1aee"
3275+
32723276
merge-stream@^1.0.1:
32733277
version "1.0.1"
32743278
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1"

0 commit comments

Comments
 (0)