import {RenderTexture} from '@pixi/core'; import {Container} from '@pixi/display'; import {PixiComponent, useApp} from '@pixi/react'; import {Sprite} from '@pixi/sprite'; import '@pixi/spritesheet'; // NECESSARY! import {CompositeTilemap} from '@pixi/tilemap'; import {CHUNK_SIZE} from '@/constants.js'; import {useAsset} from '@/context/assets.js'; import {diffuseGroup, normalGroup} from './lights.js'; const TileLayerInternal = PixiComponent('TileLayer', { create: ({group, tileLayer}) => { const container = new Container(); const cy = Math.ceil(tileLayer.area.y / CHUNK_SIZE); const cx = Math.ceil(tileLayer.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: tileLayer.tileSize.x * CHUNK_SIZE, height: tileLayer.tileSize.y * CHUNK_SIZE, }); const sprite = new Sprite(renderTexture); sprite.x = tileLayer.tileSize.x * CHUNK_SIZE * ix; sprite.y = tileLayer.tileSize.y * CHUNK_SIZE * iy; sprite.parentGroup = group; sprite.tilemap = tilemap; container.addChild(sprite); } } 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; } for (const i in tileLayer.$$chunks) { if (!oldTileLayer || oldTileLayer.$$chunks[i] !== tileLayer.$$chunks[i]) { const {texture, tilemap} = container.children[i]; 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, ...(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 ( <> ); }