import React, { useContext } from "react"; import { SvgVocabulary } from "../svg-vocabulary"; import { createSvgSymbolContext, SvgSymbolContent, SvgSymbolContext, SvgSymbolData, } from "../svg-symbol"; import { AttachmentPointType, PointWithNormal } from "../specs"; import { subtractPoints } from "../point"; const SYMBOL_MAP = new Map( SvgVocabulary.map((symbol) => [symbol.name, symbol]) ); function getSymbol(name: string): SvgSymbolData { const symbol = SYMBOL_MAP.get(name); if (!symbol) { throw new Error(`Unable to find the symbol "${name}"!`); } return symbol; } function getAttachmentPoint( s: SvgSymbolData, type: AttachmentPointType, idx: number = 0 ): PointWithNormal { const { specs } = s; if (!specs) { throw new Error(`Symbol ${s.name} has no specs!`); } const points = specs[type]; if (!(points && points.length > idx)) { throw new Error( `Symbol ${s.name} must have at least ${ idx + 1 } ${type} attachment point(s)!` ); } return points[idx]; } type AttachmentChildren = JSX.Element | JSX.Element[]; type CreatureContextType = SvgSymbolContext & { attachmentScale: number; parent: SvgSymbolData | null; }; const CreatureContext = React.createContext({ ...createSvgSymbolContext(), attachmentScale: 0.25, parent: null, }); type CreatureSymbolProps = { data: SvgSymbolData; children?: AttachmentChildren; attachTo?: AttachmentPointType; attachIndex?: number; }; const CreatureSymbol: React.FC = (props) => { const ctx = useContext(CreatureContext); const { data, attachTo, attachIndex } = props; const ourSymbol = ( <> {props.children && ( {props.children} )} ); if (!attachTo) { return ourSymbol; } const parent = ctx.parent; if (!parent) { throw new Error( `Cannot attach ${props.data.name} because it has no parent!` ); } const parentAp = getAttachmentPoint(parent, attachTo, attachIndex); const ourAp = getAttachmentPoint(data, "tail"); const dist = subtractPoints(parentAp.point, ourAp.point); return ( {ourSymbol} ); }; function createCreatureSymbol( name: string ): React.FC> { const data = getSymbol(name); return (props) => ; } const Eye = createCreatureSymbol("eye"); const Hand = createCreatureSymbol("hand"); const Cup = createCreatureSymbol("cup"); export const CreaturePage: React.FC<{}> = () => { return ( <>

Creature!

); };