diff --git a/app/context/assets.js b/app/context/assets.js index a493e95..42b0e19 100644 --- a/app/context/assets.js +++ b/app/context/assets.js @@ -10,6 +10,9 @@ const loading = {}; export function useAsset(source) { const [assets, setAssets] = useContext(context); useEffect(() => { + if (!source) { + return undefined; + } if (!assets[source]) { if (!loading[source]) { (loading[source] = Assets.load(source)).then((asset) => { @@ -21,5 +24,5 @@ export function useAsset(source) { } } }, [assets, setAssets, source]); - return assets[source]; + return source ? assets[source] : undefined; } diff --git a/app/react-components/pixi/extensions.js b/app/react-components/pixi/extensions.js index c805f39..9976428 100644 --- a/app/react-components/pixi/extensions.js +++ b/app/react-components/pixi/extensions.js @@ -1,10 +1,12 @@ import {ExtensionType} from '@pixi/core'; import {Layer, Stage as LayerStage} from '@pixi/layers'; -let AmbientLight, diffuseGroup, normalGroup, lightGroup; -if ('undefined' !== typeof window) { - ({AmbientLight, diffuseGroup, normalGroup, lightGroup} = await import('@pixi/lights')); -} +import { + AmbientLight, + diffuseGroup, + normalGroup, + lightGroup, +} from './lights.js'; export const ApplicationStageLayers = { type: ExtensionType.Application, @@ -26,6 +28,7 @@ export const ApplicationStageLights = { stage.addChild(new Layer(diffuseGroup)); stage.addChild(new Layer(normalGroup)); stage.addChild(new Layer(lightGroup)); + // stage.addChild(new AmbientLight(0x2244ff, 0.1)); stage.addChild(new AmbientLight(0xffffff, 1)); }, }, diff --git a/app/react-components/pixi/light.jsx b/app/react-components/pixi/light.jsx index 9f3ea82..8089f82 100644 --- a/app/react-components/pixi/light.jsx +++ b/app/react-components/pixi/light.jsx @@ -9,6 +9,11 @@ const LightInternal = PixiComponent('Light', { create({x, y}) { const light = new PointLight(0xffffff, 1); light.position.set(x, y); + // light.shader.program.fragmentSrc = light.shader.program.fragmentSrc.replace( + // 'float D = length(lightVector)', + // 'float D = length(lightVector) / 2.0', + // ); + // light.falloff = [1, 10, 100] return light; }, applyProps(light, oldProps, {x, y}) { diff --git a/app/react-components/pixi/lights.js b/app/react-components/pixi/lights.js new file mode 100644 index 0000000..8cd5a2c --- /dev/null +++ b/app/react-components/pixi/lights.js @@ -0,0 +1,7 @@ +let AmbientLight, diffuseGroup, normalGroup, lightGroup; + +if ('undefined' !== typeof window) { + ({AmbientLight, diffuseGroup, normalGroup, lightGroup} = await import('@pixi/lights')); +} + +export {AmbientLight, diffuseGroup, normalGroup, lightGroup}; diff --git a/app/react-components/pixi/sprite.jsx b/app/react-components/pixi/sprite.jsx index 315b91d..5c9b863 100644 --- a/app/react-components/pixi/sprite.jsx +++ b/app/react-components/pixi/sprite.jsx @@ -1,27 +1,84 @@ import {Sprite as PixiSprite} from '@pixi/react'; +import {useEffect, useState} from 'react'; import {useAsset} from '@/context/assets.js'; -export default function Sprite({entity, ...rest}) { - const asset = useAsset(entity.Sprite.source); +import {diffuseGroup, normalGroup} from './lights.js'; + +function textureFromAsset(asset, animation, frame) { if (!asset) { - return false; + return undefined; } let texture; if (asset.data.animations) { - texture = asset.animations[entity.Sprite.animation][entity.Sprite.frame]; + texture = asset.animations[animation][frame]; } else { texture = asset.textures['']; } + return texture; +} + +export default function Sprite({entity, ...rest}) { + const [mounted, setMounted] = useState(); + const [normals, setNormals] = useState(); + const [normalsMounted, setNormalsMounted] = useState(); + const {anchor, animation, frame, scale, source} = entity.Sprite; + const asset = useAsset(source); + const normalsAsset = useAsset(normals); + useEffect(() => { + if (!asset) { + return; + } + const {normals} = asset.data.meta; + if (normals) { + const {pathname} = new URL( + source.split('/').slice(0, -1).concat(normals).join('/'), + 'http://example.org', + ); + setNormals(pathname); + } + }, [asset, source]); + const texture = textureFromAsset( + asset, + animation, + frame, + ); + const normalsTexture = textureFromAsset( + normalsAsset, + animation, + frame, + ); + if (mounted) { + mounted.parentGroup = diffuseGroup; + } + if (normalsMounted) { + normalsMounted.parentGroup = normalGroup; + } return ( - + <> + {texture && ( + + )} + {normalsTexture && ( + + )} + ); } \ No newline at end of file diff --git a/app/react-components/pixi/tile-layer.jsx b/app/react-components/pixi/tile-layer.jsx index 3cefda8..21b5e64 100644 --- a/app/react-components/pixi/tile-layer.jsx +++ b/app/react-components/pixi/tile-layer.jsx @@ -8,14 +8,10 @@ import {CompositeTilemap} from '@pixi/tilemap'; import {CHUNK_SIZE} from '@/constants.js'; import {useAsset} from '@/context/assets.js'; -let diffuseGroup, normalGroup; -if ('undefined' !== typeof window) { - ({diffuseGroup, normalGroup} = await import('@pixi/lights')); -} - +import {diffuseGroup, normalGroup} from './lights.js'; const TileLayerInternal = PixiComponent('TileLayer', { - create: ({group, stage, 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); @@ -85,7 +81,7 @@ const TileLayerInternal = PixiComponent('TileLayer', { }); export default function TileLayer(props) { - const {renderer, stage} = useApp(); + const {renderer} = useApp(); const {tileLayer} = props; const asset = useAsset(tileLayer.source); const normalsAsset = useAsset([tileLayer.source.slice(0, -'.json'.length), 'normals.json'].join('.')); @@ -99,14 +95,12 @@ export default function TileLayer(props) { asset={asset} group={diffuseGroup} renderer={renderer} - stage={stage} /> ); diff --git a/public/assets/shit-shack/shit-shack.normals.json b/public/assets/shit-shack/shit-shack.normals.json new file mode 100644 index 0000000..fda6633 --- /dev/null +++ b/public/assets/shit-shack/shit-shack.normals.json @@ -0,0 +1 @@ +{"frames":{"":{"frame":{"x":0,"y":0,"w":110,"h":102},"spriteSourceSize":{"x":0,"y":0,"w":110,"h":102},"sourceSize":{"w":110,"h":102}}},"meta":{"format":"RGBA8888","image":"./shit-shack.normals.png","scale":1,"size":{"w":110,"h":102}}} \ No newline at end of file diff --git a/public/assets/shit-shack/shit-shack.normals.png b/public/assets/shit-shack/shit-shack.normals.png new file mode 100644 index 0000000..9c680ae Binary files /dev/null and b/public/assets/shit-shack/shit-shack.normals.png differ