Skip to content

Instantly share code, notes, and snippets.

@a-type
Last active January 9, 2021 23:22
Show Gist options
  • Save a-type/baf6a44d5fae1d39d3cb2ee8d22f91af to your computer and use it in GitHub Desktop.
Save a-type/baf6a44d5fae1d39d3cb2ee8d22f91af to your computer and use it in GitHub Desktop.
use-javelin
import { ComponentOf, ComponentType, query, Selector } from '@javelin/ecs';
import { useEffect, useRef, useState } from 'react';
import { useWorld } from './useWorld';
function compareIdLists(a: number[], b: number[]) {
return a.sort().join('') === b.sort().join('');
}
export function useEntities(...filters: Selector) {
const [entities, setEntities] = useState<number[]>([]);
const { registerSubsystem } = useWorld();
const [q] = useState(() => query(...filters));
const idListRef = useRef<number[]>([]);
const lastIdListRef = useRef<number[]>([]);
useEffect(() => {
// TODO: fix perf of this
return registerSubsystem((world) => {
for (const [e] of q(world)) {
idListRef.current.push(e);
}
// ugly but prevents unnecessary re-renders
if (!compareIdLists(lastIdListRef.current, idListRef.current)) {
setEntities(idListRef.current);
}
lastIdListRef.current = idListRef.current;
idListRef.current = [];
});
}, [registerSubsystem, idListRef, lastIdListRef, q]);
return entities;
}
export function useComponent<T extends ComponentType>(
entityId: number,
Type: T,
) {
const { world } = useWorld();
const [comp] = useState<ComponentOf<T>>(() =>
world.getComponent(entityId, Type),
);
return comp;
}
export function useObservedComponent<T extends ComponentType>(
entityId: number,
Type: T,
) {
const { world } = useWorld();
const comp = useComponent(entityId, Type);
const [, setVersion] = useState(0);
useEffect(() => {
let frame: number;
function loop() {
if (world.isComponentChanged(comp)) {
setVersion((c) => (c + 1) % Number.MAX_SAFE_INTEGER);
}
frame = requestAnimationFrame(loop);
}
loop();
return () => {
cancelAnimationFrame(frame);
};
}, [world, comp]);
return comp;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment