150 lines
4.5 KiB
JavaScript
150 lines
4.5 KiB
JavaScript
import {RenderTexture} from '@pixi/core';
|
|
import {Container} from '@pixi/display';
|
|
import {Graphics} from '@pixi/graphics';
|
|
import {PixiComponent, useApp} from '@pixi/react';
|
|
import {Sprite} from '@pixi/sprite';
|
|
import '@pixi/spritesheet'; // NECESSARY!
|
|
import {CompositeTilemap} from '@pixi/tilemap';
|
|
|
|
import {useAsset} from '@/react/context/assets.js';
|
|
import {CHUNK_SIZE, RESOLUTION} from '@/util/constants.js';
|
|
|
|
import {deferredLighting} from './lights.js';
|
|
|
|
const TileLayerInternal = PixiComponent('TileLayer', {
|
|
create: () => {
|
|
const container = new Container();
|
|
return container;
|
|
},
|
|
applyProps: (container, {tileLayer: oldTileLayer}, props) => {
|
|
const {asset, group, renderer, tileLayer} = props;
|
|
const extless = tileLayer.source.slice('/assets/'.length, -'.json'.length);
|
|
const {textures} = asset;
|
|
if (tileLayer === oldTileLayer) {
|
|
return;
|
|
}
|
|
if (
|
|
!oldTileLayer
|
|
|| (
|
|
oldTileLayer.area.x !== tileLayer.area.x
|
|
|| oldTileLayer.area.y !== tileLayer.area.y
|
|
|| oldTileLayer.tileSize.x !== tileLayer.tileSize.x
|
|
|| oldTileLayer.tileSize.y !== tileLayer.tileSize.y
|
|
)
|
|
) {
|
|
container.removeChildren();
|
|
const {area, tileSize} = tileLayer;
|
|
const g = new Graphics();
|
|
g.beginFill(group === deferredLighting.diffuseGroup ? 0x000000 : 0x7777ff);
|
|
// outer frame
|
|
g.drawRect(
|
|
-RESOLUTION.x / 2,
|
|
-RESOLUTION.y / 2,
|
|
area.x * tileSize.x + RESOLUTION.x,
|
|
RESOLUTION.y / 2,
|
|
);
|
|
g.drawRect(
|
|
-RESOLUTION.x / 2,
|
|
-RESOLUTION.y / 2,
|
|
RESOLUTION.x / 2,
|
|
area.y * tileSize.y + RESOLUTION.y,
|
|
);
|
|
g.drawRect(
|
|
area.x * tileSize.x,
|
|
0,
|
|
RESOLUTION.x / 2,
|
|
area.y * tileSize.y,
|
|
);
|
|
g.drawRect(
|
|
0,
|
|
area.y * tileSize.y,
|
|
area.x * tileSize.x,
|
|
RESOLUTION.y / 2,
|
|
);
|
|
g.parentGroup = group;
|
|
container.addChild(g);
|
|
const cy = Math.ceil(area.y / CHUNK_SIZE);
|
|
const cx = Math.ceil(area.x / CHUNK_SIZE);
|
|
for (let iy = 0; iy < cy; ++iy) {
|
|
for (let ix = 0; ix < cx; ++ix) {
|
|
const tilemap = new CompositeTilemap();
|
|
const renderTexture = RenderTexture.create({
|
|
width: tileSize.x * CHUNK_SIZE,
|
|
height: tileSize.y * CHUNK_SIZE,
|
|
});
|
|
const sprite = new Sprite(renderTexture);
|
|
sprite.x = tileSize.x * CHUNK_SIZE * ix;
|
|
sprite.y = tileSize.y * CHUNK_SIZE * iy;
|
|
sprite.parentGroup = group;
|
|
sprite.tilemap = tilemap;
|
|
container.addChild(sprite);
|
|
}
|
|
}
|
|
}
|
|
for (const i in tileLayer.$$chunks) {
|
|
if (!oldTileLayer || oldTileLayer.$$chunks[i] !== tileLayer.$$chunks[i]) {
|
|
const {texture, tilemap} = container.children[parseInt(i) + 1];
|
|
tilemap.clear();
|
|
const ax = Math.ceil(tileLayer.area.x / CHUNK_SIZE);
|
|
const cy = Math.floor(i / ax);
|
|
const cx = i % ax;
|
|
for (let y = 0; y < CHUNK_SIZE; ++y) {
|
|
for (let x = 0; x < CHUNK_SIZE; ++x) {
|
|
const ty = (cy * CHUNK_SIZE) + y;
|
|
const tx = (cx * CHUNK_SIZE) + x;
|
|
if (
|
|
tx < 0
|
|
|| ty < 0
|
|
|| tx >= tileLayer.area.x
|
|
|| ty >= tileLayer.area.y
|
|
) {
|
|
continue;
|
|
}
|
|
const parts = [
|
|
extless,
|
|
...(deferredLighting.normalGroup === group ? ['normals'] : []),
|
|
tileLayer.data[ty * tileLayer.area.x + tx],
|
|
];
|
|
tilemap.tile(
|
|
textures[parts.join('/')],
|
|
tileLayer.tileSize.x * x,
|
|
tileLayer.tileSize.y * y,
|
|
{
|
|
tileWidth: 16,
|
|
tileHeight: 16,
|
|
},
|
|
);
|
|
}
|
|
}
|
|
renderer.render(tilemap, {renderTexture: texture});
|
|
}
|
|
}
|
|
},
|
|
});
|
|
|
|
export default function TileLayer(props) {
|
|
const {renderer} = useApp();
|
|
const {tileLayer} = props;
|
|
const asset = useAsset(tileLayer.source);
|
|
const normalsAsset = useAsset([tileLayer.source.slice(0, -'.json'.length), 'normals.json'].join('.'));
|
|
if (!asset || !normalsAsset) {
|
|
return false;
|
|
}
|
|
return (
|
|
<>
|
|
<TileLayerInternal
|
|
{...props}
|
|
asset={asset}
|
|
group={deferredLighting.diffuseGroup}
|
|
renderer={renderer}
|
|
/>
|
|
<TileLayerInternal
|
|
{...props}
|
|
asset={normalsAsset}
|
|
group={deferredLighting.normalGroup}
|
|
renderer={renderer}
|
|
/>
|
|
</>
|
|
);
|
|
}
|