refactor: room
This commit is contained in:
parent
2d5459399c
commit
8ce4e5de8c
|
@ -1,6 +1,7 @@
|
||||||
import Renderer from '@avocado/graphics/renderer';
|
import Renderer from '@avocado/graphics/renderer';
|
||||||
import {Vector} from '@avocado/math';
|
import {Vector} from '@avocado/math';
|
||||||
import {
|
import {
|
||||||
|
classnames,
|
||||||
forwardRef,
|
forwardRef,
|
||||||
memo,
|
memo,
|
||||||
PropTypes,
|
PropTypes,
|
||||||
|
@ -13,7 +14,7 @@ import {
|
||||||
import K from 'kefir';
|
import K from 'kefir';
|
||||||
import Slider from 'rc-slider';
|
import Slider from 'rc-slider';
|
||||||
|
|
||||||
import './index.css';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
const marks = {
|
const marks = {
|
||||||
1: '1x',
|
1: '1x',
|
||||||
|
@ -23,6 +24,7 @@ const marks = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const Stage = forwardRef(({
|
const Stage = forwardRef(({
|
||||||
|
className,
|
||||||
centered,
|
centered,
|
||||||
renderable,
|
renderable,
|
||||||
renderer,
|
renderer,
|
||||||
|
@ -114,9 +116,7 @@ const Stage = forwardRef(({
|
||||||
};
|
};
|
||||||
}, [renderable, renderer, ticker]);
|
}, [renderable, renderer, ticker]);
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={classnames(styles.stage, className)}>
|
||||||
className="stage"
|
|
||||||
>
|
|
||||||
{scalable && (
|
{scalable && (
|
||||||
<Slider
|
<Slider
|
||||||
min={1}
|
min={1}
|
||||||
|
@ -129,16 +129,14 @@ const Stage = forwardRef(({
|
||||||
value={scale}
|
value={scale}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div
|
<div className={styles.canvas} ref={hostRef} />
|
||||||
className="canvas-host"
|
|
||||||
ref={hostRef}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Stage.defaultProps = {
|
Stage.defaultProps = {
|
||||||
centered: true,
|
centered: true,
|
||||||
|
className: '',
|
||||||
renderer: new Renderer([0, 0]),
|
renderer: new Renderer([0, 0]),
|
||||||
scalable: true,
|
scalable: true,
|
||||||
};
|
};
|
||||||
|
@ -147,6 +145,7 @@ Stage.displayName = 'Stage';
|
||||||
|
|
||||||
Stage.propTypes = {
|
Stage.propTypes = {
|
||||||
centered: PropTypes.bool,
|
centered: PropTypes.bool,
|
||||||
|
className: PropTypes.string,
|
||||||
renderable: PropTypes.shape({
|
renderable: PropTypes.shape({
|
||||||
position: PropTypes.arrayOf(PropTypes.number),
|
position: PropTypes.arrayOf(PropTypes.number),
|
||||||
scale: PropTypes.arrayOf(PropTypes.number),
|
scale: PropTypes.arrayOf(PropTypes.number),
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stage > .canvas-host {
|
.stage > .canvas {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
/* border-top: 1px solid rgba(255, 255, 255, 0.1); */
|
/* border-top: 1px solid rgba(255, 255, 255, 0.1); */
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -20,15 +20,3 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stage > .rc-slider {
|
|
||||||
margin: 0.5em 0 1.25em;
|
|
||||||
width: calc(100% - 2em);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rc-slider-handle {
|
|
||||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
|
||||||
}
|
|
||||||
.rc-slider-track {
|
|
||||||
background-color: #d60000;
|
|
||||||
}
|
|
|
@ -36,6 +36,7 @@
|
||||||
"@avocado/math": "^3.0.0",
|
"@avocado/math": "^3.0.0",
|
||||||
"@avocado/resource": "^3.0.0",
|
"@avocado/resource": "^3.0.0",
|
||||||
"@avocado/s13n": "^3.0.0",
|
"@avocado/s13n": "^3.0.0",
|
||||||
|
"@avocado/timing": "^3.0.0",
|
||||||
"@avocado/traits": "^3.0.0",
|
"@avocado/traits": "^3.0.0",
|
||||||
"@flecks/core": "^1.4.1",
|
"@flecks/core": "^1.4.1",
|
||||||
"@flecks/react": "^1.4.1",
|
"@flecks/react": "^1.4.1",
|
||||||
|
|
2
packages/topdown/src/components/room/index.js
Normal file
2
packages/topdown/src/components/room/index.js
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export {default as RoomRenderable} from './renderable';
|
||||||
|
export {default as RoomUi} from './ui';
|
117
packages/topdown/src/components/room/renderable.jsx
Normal file
117
packages/topdown/src/components/room/renderable.jsx
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
import {
|
||||||
|
classnames,
|
||||||
|
PropTypes,
|
||||||
|
React,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useFlecks,
|
||||||
|
useState,
|
||||||
|
} from '@flecks/react';
|
||||||
|
|
||||||
|
import {Container, Renderer, Stage} from '@avocado/graphics';
|
||||||
|
import {Vector} from '@avocado/math';
|
||||||
|
import {createLoop, destroyLoop} from '@avocado/timing';
|
||||||
|
|
||||||
|
import styles from './renderable.module.scss';
|
||||||
|
|
||||||
|
const renderer = new Renderer();
|
||||||
|
|
||||||
|
const RoomRenderable = ({camera, className, room}) => {
|
||||||
|
const flecks = useFlecks();
|
||||||
|
const [container] = useState(new Container());
|
||||||
|
const [roomRenderable, setRoomRenderable] = useState();
|
||||||
|
const [viewSize, setViewSize] = useState(flecks.get('@avocado/topdown.viewSize'));
|
||||||
|
useEffect(() => {
|
||||||
|
[container.x, container.y] = Vector.scale(viewSize, 0.5);
|
||||||
|
}, [container, viewSize]);
|
||||||
|
useEffect(() => {
|
||||||
|
if (!room) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const roomRenderable = new (room.constructor.Renderable)(room, renderer);
|
||||||
|
setRoomRenderable(roomRenderable);
|
||||||
|
container.addChild(roomRenderable);
|
||||||
|
return () => {
|
||||||
|
container.removeChild(roomRenderable);
|
||||||
|
};
|
||||||
|
}, [container, room]);
|
||||||
|
useEffect(() => {
|
||||||
|
if (!roomRenderable || !camera) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const halfViewport = Vector.scale(viewSize, 0.5);
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
camera.realPosition = camera.position;
|
||||||
|
const onCameraRealOffsetChanged = () => {
|
||||||
|
roomRenderable.renderChunksForExtent(camera.rectangle);
|
||||||
|
container.pivot = Vector.sub(halfViewport, Vector.scale(camera.realOffset, -1));
|
||||||
|
};
|
||||||
|
const onCameraRotationChanged = () => {
|
||||||
|
container.rotation = camera.rotation;
|
||||||
|
};
|
||||||
|
const onCameraScaleChanged = () => {
|
||||||
|
[container.scaleX, container.scaleY] = [1, 1] || camera.scale;
|
||||||
|
};
|
||||||
|
const onCameraViewSizeChanged = () => {
|
||||||
|
setViewSize(camera.viewSize);
|
||||||
|
};
|
||||||
|
onCameraRealOffsetChanged();
|
||||||
|
onCameraRotationChanged();
|
||||||
|
onCameraScaleChanged();
|
||||||
|
onCameraViewSizeChanged();
|
||||||
|
camera.on('realOffsetChanged', onCameraRealOffsetChanged);
|
||||||
|
camera.on('rotationChanged', onCameraRotationChanged);
|
||||||
|
camera.on('scaleChanged', onCameraScaleChanged);
|
||||||
|
camera.on('viewSize', onCameraViewSizeChanged);
|
||||||
|
return () => {
|
||||||
|
camera.off('realOffsetChanged', onCameraRealOffsetChanged);
|
||||||
|
camera.off('rotationChanged', onCameraRotationChanged);
|
||||||
|
camera.off('scaleChanged', onCameraScaleChanged);
|
||||||
|
camera.off('viewSize', onCameraViewSizeChanged);
|
||||||
|
};
|
||||||
|
}, [container, roomRenderable, camera, viewSize]);
|
||||||
|
const ticker = useCallback(
|
||||||
|
(elapsed) => {
|
||||||
|
container.renderTick(elapsed);
|
||||||
|
},
|
||||||
|
[container],
|
||||||
|
);
|
||||||
|
useEffect(() => {
|
||||||
|
if (!room) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const handle = createLoop((elapsed) => {
|
||||||
|
room.tick(elapsed);
|
||||||
|
});
|
||||||
|
return () => {
|
||||||
|
destroyLoop(handle);
|
||||||
|
};
|
||||||
|
}, [container, room]);
|
||||||
|
return (
|
||||||
|
<Stage
|
||||||
|
centered={false}
|
||||||
|
className={classnames(styles.stage, className)}
|
||||||
|
scalable={false}
|
||||||
|
renderer={renderer}
|
||||||
|
renderable={container}
|
||||||
|
size={viewSize}
|
||||||
|
ticker={ticker}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
RoomRenderable.defaultProps = {
|
||||||
|
camera: null,
|
||||||
|
className: '',
|
||||||
|
room: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
RoomRenderable.propTypes = {
|
||||||
|
// eslint-disable-next-line react/forbid-prop-types
|
||||||
|
camera: PropTypes.any,
|
||||||
|
className: PropTypes.string,
|
||||||
|
// eslint-disable-next-line react/forbid-prop-types
|
||||||
|
room: PropTypes.any,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RoomRenderable;
|
|
@ -0,0 +1,7 @@
|
||||||
|
.stage {
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 0;
|
||||||
|
canvas {
|
||||||
|
image-rendering: pixelated;
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,10 +6,10 @@ import {
|
||||||
useRef,
|
useRef,
|
||||||
} from '@flecks/react';
|
} from '@flecks/react';
|
||||||
|
|
||||||
import styles from './room.module.scss';
|
import styles from './ui.module.scss';
|
||||||
|
|
||||||
// This is the DOM side of a rendered room. Dialog text, damage numbers, (DOM node entities)...
|
// This is the DOM side of a rendered room. Dialog text, damage numbers, (DOM node entities)...
|
||||||
function Room({
|
function RoomUi({
|
||||||
domScale,
|
domScale,
|
||||||
position,
|
position,
|
||||||
room,
|
room,
|
||||||
|
@ -52,11 +52,11 @@ function Room({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Room.defaultProps = {
|
RoomUi.defaultProps = {
|
||||||
room: undefined,
|
room: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
Room.propTypes = {
|
RoomUi.propTypes = {
|
||||||
// @todo Real prop type
|
// @todo Real prop type
|
||||||
domScale: PropTypes.arrayOf(PropTypes.number).isRequired,
|
domScale: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||||
position: PropTypes.arrayOf(PropTypes.number).isRequired,
|
position: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||||
|
@ -67,4 +67,4 @@ Room.propTypes = {
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Room;
|
export default RoomUi;
|
|
@ -1,6 +1,6 @@
|
||||||
import {Flecks, Hooks} from '@flecks/core';
|
import {Flecks, Hooks} from '@flecks/core';
|
||||||
|
|
||||||
export {default as Room} from './components/room';
|
export * from './components/room';
|
||||||
|
|
||||||
export {default as Camera} from './camera';
|
export {default as Camera} from './camera';
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user