Skip to content
This repository has been archived by the owner on Sep 23, 2024. It is now read-only.

Commit

Permalink
started context API
Browse files Browse the repository at this point in the history
  • Loading branch information
AKST committed Sep 22, 2019
1 parent d5c1d4f commit e88e4e0
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 42 deletions.
1 change: 1 addition & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
- [x] Add correct rendering functionality to avoid throwing away child state.
- [ ] Add `useContext`, to replace program context.
- [ ] Add `useAnimationFrame`, this will be to handle updating state.
- [ ] Add a means to perform user input.
- [ ] Add mobx bindings.
69 changes: 69 additions & 0 deletions src/renderer/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,78 @@ export type AttributeLocation = { location: number, size: number };

export type UniformLocation = { location: WebGLUniformLocation, type: string };

export type Component<T> = (props: T, environment: Environment) => Element;

export type Element =
| PrimativeElementApi
| ComponentElementApi<any>;

export type Children = readonly Element[];

export interface ElementApi {
primativeIsEqual(other: Primative): boolean;
propsAreEqual<U extends Props>(_other: U): boolean;
}

export interface PrimativeElementApi extends ElementApi {
primative: Primative;
}

export interface ComponentElementApi<T extends Props> extends ElementApi {
props: T;
}

export type PrimativeKind =
| 'fragment'
| 'set-program'
| 'set-uniform'
| 'set-context'
| 'set-attribute-data';

export type PrimativePropMap = {
'fragment': {
children?: Children;
};
'set-program': {
program: WebGLProgram;
children?: Children;
};
'set-attribute-data': {
attribute: AttributeLocation;
buffer: BufferInfo;
drawKind: number;
children?: Children;
};
'set-context': {
key: number;
value: any;
children: Children;
};
'set-uniform': {
uniform: UniformLocation;
value: number[];
children?: Children;
};
};

type AbstractPrimative<T extends PrimativeKind> = { type: T, props: PrimativePropMap[T] };

export type Primative =
| AbstractPrimative<'fragment'>
| AbstractPrimative<'set-attribute-data'>
| AbstractPrimative<'set-program'>
| AbstractPrimative<'set-context'>
| AbstractPrimative<'set-uniform'>;

export type Context<T> = {
key: number,
Producer: Component<{ children: readonly Element[], value: T }>;
};

export interface Environment {
useBuffer(array: Float32Array, drawKind: number): any;
useAttribute(name: string, size: number): AttributeLocation;
useContext<T>(context: Context<T>): T;
useUniform(name: string, size: string): UniformLocation;
useState<T>(value: T): [T, (value: T) => void];
useMemo<T>(createValue: () => T, dependencies: Dependencies): T;
Expand Down
19 changes: 19 additions & 0 deletions src/renderer/context/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Context, Element } from '/src/renderer/base';
import { createElement } from '/src/renderer/element/element';

export function createContextFactory() {
let lastContextKey = 0;

return <T>(): Context<T> => {
const key = lastContextKey++;

return {
key,
Producer: ({ children, value }) => (
createElement('set-context', { key, value, children })
),
};
};
}

export { Context }
52 changes: 10 additions & 42 deletions src/renderer/element/element.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import {
AttributeLocation,
Component,
ComponentElementApi,
BufferInfo,
Environment,
Element,
UniformLocation,
Primative,
PrimativeKind,
PrimativePropMap,
PrimativeElementApi,
Props,
} from '/src/renderer/base';

Expand All @@ -23,19 +30,11 @@ function propsAreEqual(a: Props, b: Props): boolean {
return true;
}

export type Component<T> = (props: T, environment: Environment) => Element;

export type Element =
| PrimativeElement
| ComponentElement<any>;
export { Component, Element }

export type Children = readonly Element[];

export interface ElementApi {
primativeIsEqual(other: Primative): boolean;
propsAreEqual<U extends Props>(_other: U): boolean;
}

export function isComponentElement(element: Element): element is ComponentElement<any> {
return element instanceof ComponentElement;
}
Expand All @@ -44,7 +43,7 @@ export function isPrimativeElement(element: Element): element is PrimativeElemen
return element instanceof PrimativeElement;
}

export class PrimativeElement implements ElementApi {
export class PrimativeElement implements PrimativeElementApi {
constructor(
public primative: Primative,
) {
Expand All @@ -60,7 +59,7 @@ export class PrimativeElement implements ElementApi {
}
}

export class ComponentElement<T extends Props> implements ElementApi {
export class ComponentElement<T extends Props> implements ComponentElementApi<T> {
constructor(
public component: Component<T>,
public props: T,
Expand All @@ -76,37 +75,6 @@ export class ComponentElement<T extends Props> implements ElementApi {
}
}

type PrimativeKind = 'fragment' | 'set-program' | 'set-uniform' | 'set-attribute-data';

type PrimativePropMap = {
'fragment': {
children?: Children;
};
'set-program': {
program: WebGLProgram;
children?: Children;
};
'set-attribute-data': {
attribute: AttributeLocation;
buffer: BufferInfo;
drawKind: number;
children?: Children;
};
'set-uniform': {
uniform: UniformLocation;
value: number[];
children?: Children;
};
};

type AbstractPrimative<T extends PrimativeKind> = { type: T, props: PrimativePropMap[T] };

export type Primative =
| AbstractPrimative<'fragment'>
| AbstractPrimative<'set-attribute-data'>
| AbstractPrimative<'set-program'>
| AbstractPrimative<'set-uniform'>;

export function createElement<T, K extends PrimativeKind>(element: Component<T>, props: T): Element;
export function createElement<T, K extends PrimativeKind>(element: K, props: PrimativePropMap[K]): Element;
export function createElement<T, K extends PrimativeKind>(element: Component<T> | K, props: T | PrimativePropMap[K]): Element {
Expand Down

0 comments on commit e88e4e0

Please sign in to comment.