diff --git a/.gitignore b/.gitignore index a7f1abe..bd3dc16 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ # Object files +tsbuild +jsbuild public/js # Editor backups diff --git a/etc/depPreamble.text b/etc/depPreamble.text new file mode 100644 index 0000000..4358d5f --- /dev/null +++ b/etc/depPreamble.text @@ -0,0 +1,5 @@ +// This source file was replicated from the netless GitHub repository +// https://github.com/netless-io/netless-app +// compliant with the MIT License, under which it was released. +// The authors of archematics wish to express their thanks to the +// netless team for creating and releasing this code. diff --git a/etc/deps/geogebra/api.ts b/etc/deps/geogebra/api.ts new file mode 100644 index 0000000..859b5c7 --- /dev/null +++ b/etc/deps/geogebra/api.ts @@ -0,0 +1,390 @@ +// This source file was replicated from the netless GitHub repository +// https://github.com/netless-io/netless-app +// compliant with the MIT License, under which it was released. +// The authors of archematics wish to express their thanks to the +// netless team for creating and releasing this code. +/** + * @link https://wiki.geogebra.org/en/Reference:GeoGebra_Apps_API + */ +export interface AppletObject { + remove(): void; + getXML(objName?: string): string; + getAlgorithmXML(objName: string): string; + getPerspectiveXML(): string; + getBase64: { + (callback?: (base64string: string) => void): string; + (includeThumbnail?: boolean, callback?: (base64string: string) => void): string; + }; + setBase64(base64string: string, callback: () => void): void; + openFile(filename: string, callback: () => void): void; + login(token: string, ui: boolean): void; + logout(): void; + setXML(xml: string): void; + evalXML(xmlString: string): void; + setDisplayStyle(objName: string, style: string): void; + evalCommand(cmdString: string): boolean; + evalCommandGetLabels(cmdString: string): string; + asyncEvalCommand(cmdString: string): Promise; + asyncEvalCommandGetLabels(cmdString: string): Promise; + evalCommandCAS(cmdString: string): string; + evalGeoGebraCAS(cmdString: string): string; + setFixed(objName: string, flag: boolean, selection?: boolean): void; + isFixed(objName: string): boolean; + isSelectionAllowed(objName: string): boolean; + setOnTheFlyPointCreationActive(flag: boolean): void; + setUndoPoint(): void; + setSaved(): void; + isSaved(): boolean; + startSaveCallback(title: string, visibility: string, callbackAction: string): void; + initCAS(): void; + setErrorDialogsActive(flag: boolean): void; + setCoordSystem( + xmin: number, + xmax: number, + ymin: number, + ymax: number, + zmin?: number, + zmax?: number, + yVertical?: boolean + ): void; + reset(): void; + refreshViews(): void; + setVisible(objName: string, visible: boolean): void; + getVisible(objName: string, view?: number): boolean; + setLayer(objName: string, layer: number): void; + getLayer(objName: string): number; + setLayerVisible(layer: number, visible: boolean): void; + setTrace(objName: string, flag: boolean): void; + isTracing(objName: string): boolean; + setLabelVisible(objName: string, visible: boolean): void; + setLabelStyle(objName: string, style: number): void; + getLabelStyle(objName: string): number; + getLabelVisible(objName: string): boolean; + setColor(objName: string, red: number, green: number, blue: number): void; + setCorner(objName: string, x: number, y: number, index?: number): void; + setLineStyle(objName: string, style: number): void; + setLineThickness(objName: string, thickness: number): void; + setPointStyle(objName: string, style: number): void; + setPointSize(objName: string, style: number): void; + setFilling(objName: string, filling: number): void; + getColor(objName: string): string; + getPenColor(): string; + getPenSize(): number; + setPenSize(size: number): void; + setPenColor(red: number, green: number, blue: number): void; + getFilling(objName: string): number; + getImageFileName(objName: string): string; + getLineStyle(objName: string): number; + getLineThickness(objName: string): number; + getPointStyle(objName: string): number; + getPointSize(objName: string): number; + deleteObject(objName: string): void; + setAnimating(objName: string, animate: boolean): void; + setAnimationSpeed(objName: string, speed: number): void; + startAnimation(): void; + stopAnimation(): void; + setAuxiliary(objName: string, auxiliary: boolean): void; + hideCursorWhenDragging(hideCursorWhenDragging: boolean): void; + isAnimationRunning(): boolean; + getFrameRate(): number; + renameObject(oldName: string, newName: string, force?: boolean): boolean; + exists(objName: string): boolean; + isDefined(objName: string): boolean; + getValueString(objName: string, localized?: boolean): string; + getListValue(objName: string, index: number): number; + getDefinitionString(objName: string, localized?: boolean): string; + getLaTeXString(objName: string): string; + getLaTeXBase64(objName: string, value: boolean): string; + getCommandString(objName: string, localized?: boolean): string; + getCaption(objName: string, subst?: boolean): string; + setCaption(objName: string, caption: string): void; + getXcoord(objName: string): number; + getYcoord(objName: string): number; + getZcoord(objName: string): number; + setCoords(objName: string, x: number, y: number, z: number): void; + getValue(objName: string): number; + getVersion(): string; + getScreenshotBase64(callback: (data: string) => void, scale?: number): void; + getThumbnailBase64(): string; + setValue(objName: string, x: number): void; + setTextValue(objName: string, x: string): void; + setListValue(objName: string, x: number | boolean, y: number | boolean): void; + setRepaintingActive(flag: boolean): void; + setAxesVisible: { + (x: boolean, y: boolean): void; + (view: number, x: boolean, y: boolean, z: boolean): void; + }; + setAxisUnits(view: number, x: string, y: string, z: string): void; + setAxisLabels(view: number, x: string, y: string, z: string): void; + setAxisSteps(view: number, x: string, y: string, z: string): void; + getAxisUnits(view: number): string[]; + getAxisLabels(view: number): string[]; + setPointCapture(view: number, capture?: number): void; + getGridVisible(view?: number): boolean; + setGridVisible: { + (visible: boolean): void; + (view: number, visible?: boolean): void; + }; + getAllObjectNames(objectType?: string): string[]; + getObjectNumber(): number; + getObjectName(i: number): string; + getObjectType(objName: string): string; + setMode(mode: number): void; + getMode(): number; + getToolName(i: number): string; + openMaterial(material: string): void; + undo(): void; + redo(): void; + newConstruction(): void; + resetAfterSaveLoginCallbacks(): void; + debug(str: string): void; + setWidth(width: number): void; + setHeight(height: number): void; + setSize(width: number, height: number): void; + enableRightClick(enable: boolean): void; + enableLabelDrags(enable: boolean): void; + enableShiftDragZoom(enable: boolean): void; + showToolBar(show: boolean): void; + setCustomToolBar(toolbarDef: string): void; + showMenuBar(show: boolean): void; + showAlgebraInput(show: boolean): void; + showResetIcon(show: boolean): void; + getViewProperties(view: number): string; + setFont(label: string, size: number, bold: boolean, italic: boolean, serif: boolean): void; + insertImage(url: string, corner1: string, corner2: string, corner4: string): string; + addImage(fileName: string, urlOrSvgContent: string): void; + recalculateEnvironments(): void; + isIndependent(label: string): boolean; + isMoveable(label: string): boolean; + setPerspective(code: string): void; + enableCAS(enable: boolean): void; + enable3D(enable: boolean): void; + getFileJSON(thumbnail?: boolean): { archive: { fileName: string; fileContent: string }[] }; + setFileJSON(zip: { archive: { fileName: string; fileContent: string }[] }): void; + setLanguage(lang: string): void; + showTooltip(tooltip: boolean): void; + addMultiuserSelection( + clientId: string, + name: string, + color: string, + label: string, + newGeo: boolean + ): void; + removeMultiuserSelections(clientId: string): void; + getExerciseFraction(): number; + isExercise(): boolean; + setExternalPath(path: string): void; + checkSaved(path: () => void): void; + getCASObjectNumber(): number; + exportPGF(callback: (data: string) => void): void; + exportSVG: { + (filename: string): void; + (callback: (svg: string) => void): void; + }; + exportPDF: { + (scale: number, filename: string, sliderLabel: string): void; + (scale: number, callback: (pdf: string) => void, sliderLabel: string): void; + }; + exportPSTricks(callback: (data: string) => void): void; + exportAsymptote(callback: (data: string) => void): void; + setRounding(digits: string): void; + getRounding(): string; + copyTextToClipboard(text: string): void; + evalLaTeX(text: string, mode: number): void; + evalMathML(text: string): boolean; + getScreenReaderOutput(text: string): string; + getEditorState(): string; + setEditorState(state: string, label: string): void; + getGraphicsOptions(viewId: number): GraphicsOptions; + setGraphicsOptions(viewId: number, options: string | RecursivePartial): void; + translate(arg1: string, callback: (data: string) => void): string; + exportConstruction(flags: string[]): string; + updateConstruction(): void; + getConstructionSteps(breakpoints?: boolean): number; + setConstructionStep(n: number, breakpoints?: boolean): void; + previousConstructionStep(): void; + nextConstructionStep(): void; + getEmbeddedCalculators(includeGraspableMath?: boolean): Record; + getFrame(): HTMLElement; + enableFpsMeasurement(): void; + disableFpsMeasurement(): void; + testDraw(): void; + startDrawRecording(): void; + endDrawRecordingAndLogResults(): void; + registerAddListener(JSFunctionName: string | ((objName: string) => void)): void; + unregisterAddListener(JSFunctionName: string | ((objName: string) => void)): void; + registerStoreUndoListener(JSFunctionName: string | (() => void)): void; + unregisterStoreUndoListener(JSFunctionName: string | (() => void)): void; + registerRemoveListener(JSFunctionName: string | ((objName: string) => void)): void; + unregisterRemoveListener(JSFunctionName: string | ((objName: string) => void)): void; + registerClearListener(JSFunctionName: string | (() => void)): void; + unregisterClearListener(JSFunctionName: string | (() => void)): void; + registerRenameListener( + JSFunctionName: string | ((oldName: string, newName: string) => void) + ): void; + unregisterRenameListener( + JSFunctionName: string | ((oldName: string, newName: string) => void) + ): void; + registerUpdateListener(JSFunctionName: string | ((objName: string) => void)): void; + unregisterUpdateListener(JSFunctionName: string | ((objName: string) => void)): void; + registerClientListener(JSFunctionName: string | ((event: ClientEvent) => void)): void; + unregisterClientListener(JSFunctionName: string | ((event: ClientEvent) => void)): void; + registerObjectUpdateListener( + objName: string, + JSFunctionName: string | ((objName: string) => void) + ): void; + unregisterObjectUpdateListener(objName: string): void; + registerObjectClickListener(objName: string, JSFunctionName: string | (() => void)): void; + unregisterObjectClickListener(objName: string): void; + registerClickListener(JSFunctionName: string | ((objName: string) => void)): void; + unregisterClickListener(JSFunctionName: string | ((objName: string) => void)): void; + handleSlideAction(eventType: string, pageIdx: string, appState?: string): void; + selectSlide(pageIdx: string): void; + updateOrdering(labels: string): void; + previewRefresh(): void; + groupObjects(objects: string[]): void; + ungroupObjects(objects: string[]): void; + getObjectsOfItsGroup(object: string): string[]; + addToGroup(item: string, objectsInGroup: string[]): void; + setEmbedContent(label: string, base64: string): void; + addGeoToTV(label: string): void; + removeGeoFromTV(label: string): void; + setValuesOfTV(values: string): void; + showPointsTV(column: string, show: string): void; + hasUnlabeledPredecessors(label: string): boolean; + lockTextElement(label: string): void; + unlockTextElement(label: string): void; +} + +export type AxisConfiguration = { + label: string | null; + unitLabel: string | null; + positiveAxis: boolean; + showNumbers: boolean; + tickStyle: number; + visible: boolean; +}; + +export type AxesConfiguration = { + x: AxisConfiguration; + y: AxisConfiguration; + z: AxisConfiguration; +}; + +export type GraphicsOptions = { + axesColor: string; + bgColor: string; + gridColor: string; + axes: AxesConfiguration; + grid: boolean; + gridDistance: { x: number | null; y: number | null }; + gridType: number; + pointCapturing: number; + rightAngleStyle: number; + rulerType: number; +}; + +type RecursivePartial = { + [P in keyof T]?: RecursivePartial; +}; + +/** + * @link https://wiki.geogebra.org/en/Reference:GeoGebra_Apps_API#Client_Events + */ +export type ClientEvent = + // when new macro is added, `argument`: macro name + | { type: "addMacro"; argument: string } + // polygon construction started + | { type: "addPolygon" } + // polygon construction finished, `target`: polygon label + | { type: "addPolygonComplete"; target: string } + // Graphing / Geometry apps: algebra tab selected in sidebar + | { type: "algebraPanelSelected" } + // multiple objects deleted + | { type: "deleteGeos" } + // one or all objects removed from selection, `target`: object name (for single object) or null (deselect all) + | { type: "deselect"; target: string | null } + // mouse drag ended + | { type: "dragEnd" } + // dropdown list closed, `target`: dropdown list name, `index` index of selected item (0 based) */ + | { type: "dropdownClosed"; target: string; index: number } + // dropdown list item focused using mouse or keyboard, `target`: dropdown list name, `index` index of focused item (0 based) */ + | { type: "dropdownItemFocused"; target: string; index: number } + // dropdown list opened, `target`: dropdown list name + | { type: "dropdownOpened"; target: string } + // key typed in editor (Algebra view of any app or standalone Evaluator app), + | { type: "editorKeyTyped" } + // user moves focus to the editor (Algebra view of any app or standalone Evaluator app), `target:` object label if editing existing object + | { type: "editorStart"; target?: string } + // user (Algebra view of any app or standalone Evaluator app), `target`: object label if editing existing object + | { type: "editorStop"; target?: string } + // export started, `argument`: JSON encoded array including export format + | { type: "export"; argument: string } + // user pressed the mouse button, `x`: mouse x-coordinate, `y`: mouse y-coordinate + | { type: "mouseDown"; x: number; y: number } + // multiple objects move ended, `argument`: object labels + | { type: "movedGeos"; argument: string[] } + // multiple objects are being moved, `argument`: object labels + | { type: "movingGeos"; argument: string[] } + // dialog is opened (currently just for export dialog), `argument`: dialog ID + | { type: "openDialog"; argument: string } + // main menu or one of its submenus were open, `argument`: submenu ID + | { type: "openMenu"; argument: string } + // pasting multiple objects started, `argument`: pasted objects as XML + | { type: "pasteElms"; argument: string } + // pasting multiple objects ended, + | { type: "pasteElmsComplete" } + // perspective changed (e.g. a view was opened or closed), + | { type: "perspectiveChange" } + // redo button pressed, + | { type: "redo" } + // relation tool used, `argument`: HTML description of the object relation + | { type: "relationTool"; argument: string } + // custom tool removed, `argument`: custom tool name + | { type: "removeMacro"; argument: string } + // object renaming complete (in case of chain renames), + | { type: "renameComplete" } + // custom tool was renamed, `argument`: array [old name, new name] + | { type: "renameMacro"; argument: [oldName: string, newName: string] } + // object added to selection, `target`: object label + | { type: "select"; target: string } + // app mode changed (e.g. a tool was selected), `argument`: mode number (see toolbar reference for details) + | { type: "setMode"; argument: string } + // navigation bar visibility changed, `argument`: "true" or "false" + | { type: "showNavigationBar"; argument: string } + // style bar visibility changed, `argument`: "true" or "false" + | { type: "showStyleBar"; argument: string } + // side panel (where algebra view is in Graphing Calculator) closed, + | { type: "sidePanelClosed" } + // side panel (where algebra view is in Graphing Calculator) opened, + | { type: "sidePanelOpened" } + // table of values panel selected, + | { type: "tablePanelSelected" } + // tools panel selected, + | { type: "toolsPanelSelected" } + // undo pressed, + | { type: "undo" } + // object style changed, `target`: object label + | { type: "updateStyle"; target: string } + // graphics view dimensions changed by zooming or panning, `xZero`: horizontal pixel position of point (0,0), `yZero`: vertical pixel position of point (0,0), `xscale`: ratio pixels / horizontal units, `yscale`: ratio pixels / vertical units, `viewNo`: graphics view number (1 or 2) + | { + type: "viewChanged2D"; + xZero: number; + yZero: number; + scale: number; + yscale: number; + viewNo: 1 | 2; + } + // 3D view dimensions changed by zooming or panning, similar to 2D, e.g. `xZero: 0,yZero: 0,scale: 50,yscale: 50,viewNo: 512,zZero: -1.5,zscale: 50,xAngle: -40,zAngle: 24` + | { + type: "viewChanged3D"; + xZero: number; + yZero: number; + zZero: number; + scale: number; + yscale: number; + zscale: number; + xAngle: number; + zAngle: number; + viewNo: 1 | 2; + }; diff --git a/etc/deps/geogebra/entry.ts b/etc/deps/geogebra/entry.ts new file mode 100644 index 0000000..00a91c5 --- /dev/null +++ b/etc/deps/geogebra/entry.ts @@ -0,0 +1,76 @@ +// This source file was replicated from the netless GitHub repository +// https://github.com/netless-io/netless-app +// compliant with the MIT License, under which it was released. +// The authors of archematics wish to express their thanks to the +// netless team for creating and releasing this code. +import type { AppletObject } from "./api"; +import type { AppletParameters } from "./params"; + +export type AppletType = "preferJava" | "preferHTML5" | "java" | "html5" | "auto" | "screenshot"; + +export type Views = Record< + "is3D" | "AV" | "SV" | "CV" | "EV2" | "CP" | "PC" | "DA" | "FI" | "PV" | "macro", + boolean +>; + +export type GGBAppletParameters = AppletParameters & { + material_id?: string; + appletOnLoad?: (api: AppletObject) => void; +}; + +export declare class GGBApplet { + constructor( + version?: number | string, + parameters?: GGBAppletParameters, + html5NoWebSimple?: boolean + ); + constructor(parameters?: GGBAppletParameters, html5NoWebSimple?: boolean); + + /** + * Overrides the codebase for HTML5. + * @param codebase Can be an URL or a local file path. + * @param offline Set to true, if the codebase is a local URL and no web URL + */ + setHTML5Codebase(codebase: string, offline?: boolean): void; + + /** @deprecated not supported */ + setJavaCodebase(): void; + /** @deprecated not supported */ + setJavaCodebaseVersion(): void; + /** @deprecated not supported */ + isCompiledInstalled(): void; + /** @deprecated not supported */ + setPreCompiledScriptPath(): void; + /** @deprecated not supported */ + setPreCompiledResourcePath(): void; + + /** + * Overrides the codebase version for HTML5. + * If another codebase than the default codebase should be used, this method has to be called before setHTML5Codebase. + * @param version The version of the codebase that should be used for HTML5 applets. + */ + setHTML5CodebaseVersion(version: number | string, offline?: boolean): void; + + getHTML5CodebaseVersion(): string; + getParameters(): GGBAppletParameters | undefined; + setFontsCSSURL(url: string): void; + + inject(containerID: string | HTMLElement, type?: AppletType, noPreview?: boolean): void; + inject(containerID: string | HTMLElement, noPreview?: boolean): void; + + getViews(): Views | null; + + isJavaInstalled(): false; + isHTML5Installed(): true; + + getLoadedAppletType(): AppletType | null; + setPreviewImage(previewFilePath: string, loadingFilePath: string, playFilePath: string): void; + removeExistingApplet(appletParent: string, showScreenshot?: boolean): void; + + refreshHitPoints(): boolean; + startAnimation(): boolean; + stopAnimation(): boolean; + + getAppletObject(): AppletObject | undefined; + resize(): void; +} diff --git a/etc/deps/geogebra/params.ts b/etc/deps/geogebra/params.ts new file mode 100644 index 0000000..b631798 --- /dev/null +++ b/etc/deps/geogebra/params.ts @@ -0,0 +1,160 @@ +// This source file was replicated from the netless GitHub repository +// https://github.com/netless-io/netless-app +// compliant with the MIT License, under which it was released. +// The authors of archematics wish to express their thanks to the +// netless team for creating and releasing this code. +/** + * @link https://wiki.geogebra.org/en/Reference:GeoGebra_App_Parameters + */ +export interface AppletParameters { + /** @default "ggbApplet" */ + id?: string; + /** @default "" */ + filename?: string; + /** @default "" */ + json?: string; + /** @default true */ + enableLabelDrags?: boolean; + /** @default true */ + enableUndoRedo?: boolean; + /** @default true */ + enableRightClick?: boolean; + /** @default false */ + enableCAS?: boolean; + /** @default false */ + enable3D?: boolean; + /** @default false */ + lockExam?: boolean; + /** @default "" */ + rounding?: `${number}${"" | "s" | "r"}`; + /** @default "" */ + ggbBase64?: string; + /** @default false */ + showMenuBar?: boolean; + /** @default false */ + showToolBar?: boolean; + /** @default true */ + showToolBarHelp?: boolean; + /** @link https://wiki.geogebra.org/en/Reference:Toolbar @default "" */ + customToolBar?: string; + /** @default false */ + showAlgebraInput?: boolean; + /** @default "algebra" */ + algebraInputPosition?: "algebra" | "top" | "bottom"; + /** @default false */ + showResetIcon?: boolean; + /** @default true */ + showAnimationButton?: boolean; + /** @default 3 */ + capturingThreshold?: number; + /** @link https://www.wikiwand.com/en/List_of_ISO_639-1_codes @default "" */ + language?: string; + /** @default "" */ + country?: string; + /** @default false */ + useBrowserForJS?: boolean; + /** @default true */ + enableShiftDragZoom?: boolean; + /** @default 0 */ + width?: number; + /** @default 0 */ + height?: number; + /** @default false */ + fittoscreen?: boolean; + /** @default "" */ + borderColor?: string; + /** @default false */ + showLogging?: boolean; + /** @default true */ + allowSymbolTable?: boolean; + /** @default false */ + allowStyleBar?: boolean; + /** @default false */ + app?: boolean; + /** @default false */ + screenshotGenerator?: boolean; + /** @default "" */ + laf?: string; + /** @default false */ + preventFocus?: boolean; + /** @link https://wiki.geogebra.org/en/SetPerspective_Command @default "" */ + perspective?: string; + /** @default "classic" */ + appName?: "graphing" | "geometry" | "3d" | "classic" | "suite" | "evaluator" | "scientific"; + /** @default 1.0 */ + scale?: number; + /** @default false */ + buttonShadows?: boolean; + /** @default 0.2 */ + buttonRounding?: number; + /** @default "#000000" */ + buttonBorderColor?: string; + /** @default false */ + prerelease?: boolean; + /** @default "" */ + tubeid?: string; + /** @default false */ + showTutorialLink?: boolean; + /** @default true */ + enableFileFeatures?: boolean; + /** @default true */ + errorDialogsActive?: boolean; + /** @default false */ + showAppsPicker?: boolean; + /** @default false */ + showZoomButtons?: boolean; + /** @default false */ + showFullscreenButton?: boolean; + /** @default false */ + showSuggestionButtons?: boolean; + /** @default false */ + showStartTooltip?: boolean; + /** @default 0 */ + marginTop?: number; + /** @default -1 */ + randomSeed?: number; + /** @default "" */ + fontscssurl?: string; + /** @default "" */ + scaleContainerClass?: string; + /** @default false */ + allowUpscale?: boolean; + /** @default false */ + playButton?: boolean; + /** @default false */ + autoHeight?: boolean; + /** @default false */ + disableAutoScale?: boolean; + /** @default true */ + randomize?: boolean; + /** @default "" */ + loginURL?: string; + /** @default "" */ + logoutURL?: string; + /** @default "" */ + backendURL?: string; + /** @default "" */ + fullscreenContainer?: string; + /** @default "" */ + shareLinkPrefix?: string; + /** @default "" */ + vendor?: string; + /** @default 0 */ + fontSize?: number; + /** @default undefined */ + keyboardType?: "scientific" | "normal" | "notes"; + /** @default false */ + textMode?: boolean; + /** @default "white" */ + editorBackgroundColor?: string; + /** @default "black" */ + editorForegroundColor?: string; + /** @default false */ + showSlides?: boolean; + /** @default false */ + useLocalizedDigits?: boolean; + /** @default true */ + useLocalizedPointNames?: boolean; + /** @default "undef" */ + detachKeyboard?: string; +} diff --git a/etc/deps/geogebraAmbient.d.ts b/etc/deps/geogebraAmbient.d.ts new file mode 100644 index 0000000..3b3c893 --- /dev/null +++ b/etc/deps/geogebraAmbient.d.ts @@ -0,0 +1,7 @@ +// Hack to move GGBApplet into the global namespace +// (since we are getting it from a script) +import {GGBApplet as moduleGGBApplet} from './geogebra/entry.ts' +declare global { + class GGBApplet extends moduleGGBApplet { + } +} diff --git a/etc/deps/x_ite.d.ts b/etc/deps/x_ite.d.ts new file mode 100644 index 0000000..7b1600e --- /dev/null +++ b/etc/deps/x_ite.d.ts @@ -0,0 +1,2035 @@ +declare module 'https://create3000.github.io/code/x_ite/latest/x_ite.mjs' { + const x3d: X3D; + export default x3d; + export interface X3D { + (callback?: () => void, fallback?: (error: Error) => void): Promise; + createBrowser(): HTMLElement; + getBrowser(via?: string | HTMLElement): X3DBrowser; + noConflict(): X3D; + X3DConstants: X3DConstant; + SFBool(arg: unknown): boolean; + // NB. in all of the following `typeof Class` is an expression that + // extracts the type of the constructor for Class. + SFColor: typeof SFColor; + SFColorRGBA: typeof SFColorRGBA; + // Doubles and floats not different in JavaScript: + SFDouble: typeof SFDouble; + SFFloat: typeof SFDouble; + + SFImage: typeof SFImage; + SFInt32: typeof SFInt32; + + // Doubles and floats same: + SFMatrix3d: typeof SFMatrix3; + SFMatrix3f: typeof SFMatrix3; + SFMatrix4d: typeof SFMatrix4; + SFMatrix4f: typeof SFMatrix4; + + // SFNode: typeof SFNode; // no working constructors, just one that throws + SFRotation: typeof SFRotation; + SFString: typeof SFString; + SFTime: typeof SFTime; + + // Doubles and floats same: + SFVec2d: typeof SFVec2; + SFVec2f: typeof SFVec2; + SFVec3d: typeof SFVec3; + SFVec3f: typeof SFVec3; + SFVec4d: typeof SFVec4; + SFVec4f: typeof SFVec4; + + // All the array types: + MFBool: typeof X3DArrayField; + MFColor: typeof X3DArrayField; + MFColorRGBA: typeof X3DArrayField; + MFDouble: typeof X3DArrayField; // or should it be SFDouble? + MFFloat: typeof X3DArrayField; // ditto? + MFImage: typeof X3DArrayField; + MFMatrix3d: typeof X3DArrayField; + MFMatrix3f: typeof X3DArrayField; + MFMatrix4d: typeof X3DArrayField; + MFMatrix4f: typeof X3DArrayField; + MFInt32: typeof X3DArrayField; // or SFInt32? + MFNode: typeof X3DArrayField; + MFRotation: typeof X3DArrayField; + MFString: typeof X3DArrayField; // or SFSTring? + MFTime: typeof X3DArrayField; + MFVec2d: typeof X3DArrayField; + MFVec2f: typeof X3DArrayField; + MFVec3d: typeof X3DArrayField; + MFVec3f: typeof X3DArrayField; + MFVec4d: typeof X3DArrayField; + MFVec4f: typeof X3DArrayField; + } + + type JSONValue = + | string + | number + | boolean + | null + | JSONValue[] + | {[key: string]: JSONValue} + + interface JSONObject { + [k: string]: JSONValue + } + + type BrowserProperty = 'ABSTRACT_NODES' + | 'CONCRETE_NODES' + | 'EXTERNAL_INTERACTIONS' + | 'PROTOTYPE_CREATE' + | 'DOM_IMPORT' + | 'XML_ENCODING' + | 'CLASSIC_VRML_ENCODING' + | 'BINARY_ENCOIDING'; + + type QualityLevels = 'LOW' | 'MEDIUM' | 'HIGH'; + type BrowserOption = { + Antialiased: boolean, + Dashboard: boolean, + Rubberband: boolean, + EnableInlineViewpoints: boolean, + MotionBlur: boolean, + PrimitiveQuality: QualityLevels, + QualityWhenMoving: QualityLevels | 'SAME', + Shading: 'POINT' | 'WIREFRAME' | 'FLAT' + | 'GOURAUD' | 'PHONG', + SplashScreen: boolean, + TextureQuality: QualityLevels, + AutoUpdate: boolean, + Cache: boolean, + ContentScale: number, + ContextMenu: boolean, + Debug: boolean, + Gravity: number, + LogarithmicDepthBuffer: boolean, + Multisampling: number, + Notifications: boolean, + OrderIndependentTransparency: boolean, + StraightenHorizon: boolean, + Timings: boolean + } + export type RenderingProperty = { + Shading: BrowserOption['Shading'], + MaxTextureSize: number, + TextureUnits: number, + MaxLights: number, + Antialiased: boolean, + ColorDepth: number, + TextureMemory: number, + ContentScale: number, + MaxSamples: number, + Multisampling: number, + LogarithmicDepthBuffer: boolean + } + + type BrowserCallback = ( + event: number) => void; // event is a Browser Event Constant + + export interface X3DBrowser { + name: string; + version: string; + providerURL: string; + currentSpeed: number; + currentFrameRate: number; + description: string; + readonly supportedComponents: ComponentInfoArray; + readonly supportedProfiles: ProfileInfoArray; + baseURL: string; + currentScene: X3DScene; + + replaceWorld(scene: X3DScene): Promise; + createX3DFromString(x3dSyntax: string): Promise; + createX3DFromURL(url: X3DArrayField): Promise; + createX3DFromURL(url: X3DArrayField, + node: SFNode, fieldName: string): void; + loadURL(url: X3DArrayField, + parameter?: X3DArrayField): Promise; + importDocument(dom: HTMLElement | string): Promise; + importJS(json: string | JSONObject): Promise; + getBrowserProperty(prop: BrowserProperty): boolean; + getBrowserOption(op: T): BrowserOption[T]; + setBrowserOption( + op: T, value: BrowserOption[T]): void; + getRenderingProperty( + prop: T): RenderingProperty[T]; + addBrowserCallback(key: unknown, cb?: BrowserCallback): void; + addBrowserCallback( + key: unknown, event: number, // A Browser Event Constant + cb?: BrowserCallback): void; + removeBrowserCallback(key: unknown, event?: number): void; + viewAll(layer?: SFNode, transitionTime?: number): void; + nextViewpoint(layer?: SFNode): void; + previousViewpoint(layer?: SFNode): void; + firstViewpoint(layer?: SFNode): void; + lastViewpoint(layer?: SFNode): void; + changeViewpoint(name: string): void; + changeViewpoint(layer: SFNode, name: string): void; + print(thing: unknown): void; + printLn(thing: unknown): void; + // VRML methods + getName(): string; + getVersion(): string; + getCurrentSpeed(): number; + getCurrentFrameRate(): number; + getWorldURL(): string; + replaceWorld(nodes: X3DArrayField): string; + createVrmlFromString(vrmlSyntax: string): X3DArrayField; + createVrmlFromURL(url: X3DArrayField, + node: SFNode, fieldName: string): void; + addRoute(sourceNode: SFNode, sourceField: string, + destinationNode: SFNode, destinationField: string): void; + deleteRoute(sourceNode: SFNode, sourceField: string, + destinationNode: SFNode, destinationField: string): void; + loadURL(url: X3DArrayField, + parameter?: X3DArrayField): void; + setDescription(description: string): void; + } + + type MinimalArray = {[index: number]: T, length: number} + + type ComponentInfoArray = MinimalArray; + interface ComponentInfo { + readonly name: string; + readonly level?: number; + readonly title: string; + readonly providerURL: string; + } + + type ProfileInfoArray = MinimalArray; + interface ProfileInfo extends ComponentInfo { + readonly components: ComponentInfoArray + } + + export interface X3DScene { + readonly specificationVersion: string; + readonly encoding: 'ASCII' | 'VRML' | 'XML' | 'BINARY' + | 'SCRIPTED' | 'BIFS' | 'NONE'; + readonly profile: ProfileInfo; + readonly components: ComponentInfoArray; + readonly units: UnitInfoArray; + readonly worldURL: string; + readonly baseURL: string; + rootNodes: X3DArrayField; + readonly protos: ProtoDeclarationArray; + readonly externprotos: ExternProtoDeclarationArray; + readonly routes: RouteArray; + + // ExecutionContext methods. I didn't split these out because I + // didn't see a place in the interface where it mattered, but + // perhaps there should be a base class with just these... + createNode( + spec: T): SpecializeNodeType[T]; + createProto(protoName: string): SFNode; + getNamedNode(name: string): SFNode; + updateNamedNode(name: string, node: SFNode): void; + removeNamedNode(name: string): void; + getImportedNode(importedName: string): SFNode; + updateImportedNode( + inlineNode: SFNode, exportedName: string, importedName: string): void; + removeImportedNode(importedName: string): void; + addRoute(sourceNode: SFNode, sourceField: string, + destinationNode: SFNode, destinationField: string): X3DRoute; + deleteRoute(route: X3DRoute): void; + + // X3DScene methods: + getMetaData(name: string): string[]; + setMetaData(name: string, value: string | string[]): void; + addMetaData(name: string, value: string): void; + removeMetaData(name: string): void; + addRootNode(node: SFNode): void; + removeRootNode(node: SFNode): void; + getExportedNode(exportedName: string): SFNode; + updateExportedNode(exportedName: string, node: SFNode): void; + removeExportedNode(exportedName: string): void; + toVRMLString(options?: VRMLOptions): string; + toXMLString(options?: VRMLOptions): string; + toJSONString(options?: VRMLOptions): string; + } + + type UnitInfoArray = MinimalArray; + interface UnitInfo { + readonly category: string; + readonly name: string; + readonly conversionFactor: number; + } + + type ProtoDeclarationArray = MinimalArray; + export interface X3DProtoDeclaration { + readonly name: string; + readonly fields: FieldDefinitionArray; + isExternProto: false; + newInstance(): SFNode; + toVRMLString(options?: VRMLOptions): string; + toXMLString(options?: VRMLOptions): string; + toJSONString(options?: VRMLOptions): string; + } + + type ExternProtoDeclarationArray = MinimalArray; + export interface X3DExternProtoDeclaration { + readonly name: string; + readonly fields: FieldDefinitionArray; + readonly urls: X3DArrayField; + isExternProto: false; + readonly loadState: number; // A Load State Constant from X3DConstant + newInstance(): SFNode; + loadNow(): Promise; + toVRMLString(options?: VRMLOptions): string; + toXMLString(options?: VRMLOptions): string; + toJSONString(options?: VRMLOptions): string; + } + + type RouteArray = MinimalArray; + export interface X3DRoute { + sourceNode: SFNode; + sourceField: string; + destinationNode: SFNode; + destinationField: string; + } + + type FieldCallback = (value: unknown) => void + + class X3DField { + equals(other: X3DField): boolean; + assign(other: X3DField): void; + setValue(value: unknown): void; + getValue(): unknown; + getType(): number; // one of the Field Type Constants from X3DConstant + getAccessType(): number; // one of the Access Type Constants + isInitializable(): boolean; + isInput(): boolean; + isOutput(): boolean; + isReadable(): boolean; + isWritable(): boolean; + getUnit(): string; + hasReferences(): boolean; + isReference(accessType: number): boolean; + addReferencesCallback(key: unknown, callback: FieldCallback): void; + removeReferencesCallback(key: unknown): void; + getReferencesCallbacks(): Map; + addFieldInterest(other: X3DField): void; + removeFieldInterest(other: X3DField): void; + getFieldInterest(): Set + addFieldCallback(key: unknown, callback: FieldCallback): void; + removeFieldCallback(key: unknown): void; + getFieldCallbacks(): Map; + addInputRoute(route: unknown): void; // what's the proper type for route? + removeInputRoute(route: unknown): void; + getInputRoutes(): Set; + addOutputRoute(route: unknown): void; // ditto + removeOutputRoute(route: unknown): void; + getOutputRoutes(): Set; + addRouteCallback(key: unknown, callback: FieldCallback): void; + removeRouteCallback(key: unknown): void; + getRouteCallbacks(): Map; + dispose(): void; + } + + export class SFColor extends X3DField { + constructor(r?: number, g?: number, b?: number); + r: number; + g: number; + b: number; + copy(): SFColor; + isDefaultValue(): boolean; + set(r: number, g: number, b: number): SFColor; + getHSV(result: number[]): number[]; + setHSV(h: number, s: number, v: number): void; + lerp(destination: SFColor, t: number): SFColor; + static typeName: 'SFColor'; + } + + export class SFColorRGBA extends X3DField { + constructor(r?: number, g?: number, b?: number, a?: number); + r: number; + g: number; + b: number; + a: number; + copy(): SFColorRGBA; + isDefaultValue(): boolean; + set(r: number, g: number, b: number): SFColorRGBA; + getHSVA(result: number[]): number[]; + setHSVA(h: number, s: number, v: number): void; + lerp(destination: SFColor, t: number): SFColorRGBA; + static typeName: 'SFColor'; + } + + export class SFDouble extends X3DField { + constructor(arg?: unknown); + copy(): SFDouble; + isDefaultValue(): boolean; + set(arg: unknown): void; + valueOf(): number; + } + + export class SFImage extends X3DField { + constructor(width?: number, height?: number, + num_components?: number, array?: number[]); + x: number; + y: number; + width: number; + height: number; + comp: number; + array: number[]; + copy(): SFImage; + isDefaultValue(): boolean; + set(other: SFImage): void; + } + + export class SFInt32 extends X3DField { + constructor(val?: number); + copy(): SFInt32; + set(val?: number): void; + valueOf(): number; + } + + export class SFMatrix3 extends X3DField { + constructor(); + constructor(r1: SFVec3, r2: SFVec3, r3: SFVec3); + constructor(a: number, b: number, c: number, + d: number, e: number, f: number, + g: number, h: number, i: number); + copy(): SFMatrix3; + isDefaultValue(): boolean; + set(other: SFMatrix3): void; + setTransform(translation: SFVec2, rotation: number, scaleFactor: SFVec2, + scaleOrientation: number, center: SFVec2): void; + getTransform(translation: SFVec2, rotation: SFDouble, scaleFactor: SFVec2, + scaleOrientation: SFDouble, center: SFVec2): void; + determinant(): number; + inverse(): SFMatrix3; + transpose(): SFMatrix3; + multLeft(A: SFMatrix3): SFMatrix3; + multRight(B: SFMatrix3): SFMatrix3; + multVecMatrix(row: SFVec2): SFVec2; + multVecMatrix(row: SFVec3): SFVec3; + multMatrixVec(col: SFVec2): SFVec2; + multMatrixVec(col: SFVec3): SFVec3; + multDirMatrix(row: SFVec2): SFVec2; + multMatrixDir(col: SFVec2): SFVec2; + } + + export class SFMatrix4 extends X3DField { + constructor(); + constructor(r1: SFVec4, r2: SFVec4, r3: SFVec4, r4: SFVec4); + constructor(a: number, b: number, c: number, d: number, + e: number, f: number, g: number, h: number, + i: number, j: number, k: number, l: number, + m: number, n: number, o: number, p: number); + copy(): SFMatrix4; + isDefaultValue(): boolean; + set(other: SFMatrix4): void; + setTransform(translation: SFVec3, rotation: SFRotation, + scaleFactor: SFVec3, scaleOrientation: SFRotation, + center: SFVec3): void; + getTransform(translation: SFVec3, rotation: SFRotation, + scaleFactor: SFVec3, scaleOrientation: SFRotation, + center: SFVec3): void; + determinant(): number; + inverse(): SFMatrix4; + transpose(): SFMatrix4; + multLeft(A: SFMatrix4): SFMatrix4; + multRight(B: SFMatrix4): SFMatrix4; + multVecMatrix(row: SFVec4): SFVec4; + multVecMatrix(row: SFVec3): SFVec3; + multMatrixVec(col: SFVec4): SFVec4; + multMatrixVec(col: SFVec3): SFVec3; + multDirMatrix(row: SFVec3): SFVec3; + multMatrixDir(col: SFVec3): SFVec3; + } + + export interface SFNode extends X3DField { + // constructor(vrmlSyntax: string); // throws error, anyway + + // Each subclass of SFNode for the different node types + // has various properties, that will be defined for + // each one below. But as far as I can see, they all have metadata + // properties: + metadata: SFNode; + + copy(instance?: unknown): SFNode; // not sure what argument does... + isDefaultValue(): boolean; + set(other: SFNode): void; + dispose(): void; + // stupid WET TypeScript won't just overload the base class method: + addFieldCallback(key: unknown, callback: FieldCallback): void; + addFieldCallback(name: string, key: unknown, + callback: (value: unknown) => void): void; + getFieldDefinitions(): FieldDefinitionArray; + getField(name: string): X3DField; + getNodeName(): string; + getNodeDisplayName(): string; + getNodeType(): number[]; // Array of Node Type constants from X3DConstant + getNodeTypeName(): string; + getNodeUserData(key: unknown): unknown; + removeFieldCallback(key: unknown): void; + removeFieldCallback(name: string, key: unknown): void; + removeNodeUserData(key: unknown): void; + setNodeUserData(key: unknown, data: unknown): unknown; + toVRMLString(options?: VRMLOptions): string; + toXMLString(options?: VRMLOptions): string; + toJSONString(options?: VRMLOptions): string; + valueOf(): unknown; // what is proper type? May depend on what kind... + } + + interface SFNodeAcousticProperties extends SFNode { + description: string; + enabled: boolean; + absorption: number; + refraction: number; + diffuse: number; + specular: number; + } + + interface SFNodeAnalyser extends SFNode { + description: string; + enabled: boolean; + gain: number; + fftSize: number; + minDecibels: number; + maxDecibels: number; + smoothingTimeConstant: number; + tailTime: SFTime; + } + + interface Positioner extends SFNode { + visible: boolean; + bboxDisplay: boolean; + bboxSize: SFVec3; + bboxCenter: SFVec3; + } + + interface GroupingFields { + addChildren: X3DArrayField; + removeChildren: X3DArrayField; + children: X3DArrayField; + } + + interface X3DGroupingNode extends Positioner, GroupingFields { } + + interface URLFields { + description: string; + load: boolean; + url: X3DArrayField; + autoRefresh: SFTime; + autoRefreshTimeLimit: SFTime; + } + + interface SFNodeAnchor extends X3DGroupingNode { + parameter: X3DArrayField; + } + + interface SFNodeAppearance extends SFNode { + acousticProperties: SFNodeAcousticProperties; + alphaMode: 'AUTO' | 'OPAQUE' | 'MASK' | 'BLEND'; + alphaCutoff: number; + pointProperties: SFNodePointProperties; + lineProperties: SFNodeLineProperties; + fillProperties: SFNodeFillProperties; + material: SFNodeMaterial; + backMaterial: SFNodeMaterial; + texture: SFNode; + textureTransform: SFNodeTextureTransform; + shaders: X3DArrayField; + blendMode: SFNodeBlendMode; + } + + interface X3DTimeDependentNode extends SFNode { + startTime: SFTime; + resumeTime: SFTime; + pauseTime: SFTime; + stopTime: SFTime; + isPaused: boolean; + isActive: boolean; + elapsedTime: SFTime; + } + + interface SFNodeAudioClip extends X3DTimeDependentNode, URLFields { + enabled: boolean; + gain: number; + pitch: number; + loop: boolean; + duration_changed: SFTime; + } + + interface ChannelFields extends SFNode { + description: string; + enabled: boolean; + gain: number; + channelCount: number; + channelCountMode: 'MAX' | 'CLAMPED-MAX' | 'EXPLICIT'; + channelInterpretation: 'SPEAKERS' | 'DISCRETE'; + } + + interface X3DSoundDestinationNode extends ChannelFields { + mediaDeviceId: string; + isActive: boolean; + children: X3DArrayField; + } + + interface SFNodeAudioDestination extends X3DSoundDestinationNode { + maxChannelCount: number; + } + + interface X3DBindableNode extends SFNode { + set_bind: boolean; + isBound: boolean; + bindTime: SFTime; + } + + interface X3DBackgroundNode extends X3DBindableNode { + skyAngle: X3DArrayField; + skyColor: X3DArrayField; + groundAngle: X3DArrayField; + groundColor: X3DArrayField; + transparency: number; + } + + interface SFNodeBackground extends X3DBackgroundNode { + frontUrl: X3DArrayField; + backUrl: X3DArrayField; + leftUrl: X3DArrayField; + rightUrl: X3DArrayField; + topUrl: X3DArrayField; + bottomUrl: X3DArrayField; + } + + interface SFNodeBillboard extends X3DGroupingNode { + axisOfRotation: SFVec3; + } + + interface SFNodeBiquadFilter extends X3DTimeDependentNode, ChannelFields { + frequency: number; + detune: number; + type: 'LOWPASS' | 'HIGHPASS' | 'BANDPASS' + | 'LOWSHELF' | 'HIGHSHELF' | 'PEAKING' | 'NOTCH' | 'ALLPASS'; + qualityFactor: number; + tailTime: SFTime; + children: X3DArrayField; + } + + type BlendFactor = 'ZERO' | 'ONE' + | 'SRC_COLOR' | 'ONE_MINUS_SRC_COLOR' + | 'DST_COLOR' | 'ONE_MINUS_DST_COLOR' + | 'SRC_ALPHA' | 'ONE_MINUS_SRC_ALPHA' + | 'DST_ALPHA' | 'ONE_MINUS_DST_ALPHA' + | 'CONSTANT_COLOR' | 'ONE_MINUS_CONSTANT_COLOR' + | 'CONSTANT_ALPHA' | 'ONE_MINUS_CONSTANT_ALPHA' + + type BlendEquation = 'FUNC_ADD' | 'FUNC_SUBTRACT' | 'FUNC_REVERSE_SUBTRACT' + + interface SFNodeBlendMode extends SFNode { + blendColor: SFColorRGBA; + sourceColorFactor: BlendFactor; + sourceAlphaFactor: BlendFactor; + destinationColorFactor: BlendFactor; + destinationAlphaFactor: BlendFactor; + colorEquation: BlendEquation; + alphaEquation: BlendEquation; + } + + interface SFNodeBox extends SFNode { + size: SFVec3; + solid: boolean; + } + + interface SFNodeBufferAudioSource + extends X3DTimeDependentNode, ChannelFields, URLFields { + detune: number; + buffer: X3DArrayField; + bufferDuration: SFTime; + bufferLength: number; + numberOfChannels: number; + sampleRate: number; + playbackRate: number; + loopStart: SFTime; + loopEnd: SFTime; + loop: boolean; + } + + interface SFNodeChannelMerger extends ChannelFields { + children: X3DArrayField; + } + + interface SFNodeChannelSelector extends ChannelFields { + channelSelection: number; + children: X3DArrayField; + } + + interface SFNodeChannelSplitter extends ChannelFields { + children: X3DArrayField; + outputs: X3DArrayField; + } + + interface SFNodeClipPlane extends SFNode { + enabled: boolean; + plane: SFVec4; + } + + interface SFNodeCollision extends X3DGroupingNode { + enabled: boolean; + isActive: boolean; + collideTime: SFTime; + proxy: SFNode; + } + + interface SFNodeColor extends SFNode { + color: X3DArrayField; + } + + interface SFNodeColorRGBA extends SFNode { + color: X3DArrayField; + } + + interface X3DChaserNode extends SFNode { + set_value: T; + set_destination: T; + initialValue: T; + initialDestination: T; + duration: SFTime; + isActive: boolean; + value_changed: T; + } + + interface X3DDamperNode extends SFNode { + set_value: T; + set_destination: T; + initialValue: T; + initialDestination: T; + order: number; + tau: SFTime; + tolerance: number; + isActive: boolean; + value_changed: T; + } + + interface X3DInterpolatorNode extends SFNode { + set_fraction: number; + key: X3DArrayField; + keyValue: X3DArrayField; + value_changed: V; + } + + interface X3DShaderNode extends SFNode { + activate: boolean; + isSelected: boolean; + isValid: boolean; + language: string; + } + + interface SFNodeComposedShader extends X3DShaderNode { + parts: X3DArrayField; + } + + interface SFNodeCone extends SFNode { + side: boolean; + bottom: boolean; + height: number; + bottomRadius: number; + solid: boolean; + } + + interface SFNodeConvolver extends X3DTimeDependentNode, ChannelFields { + buffer: X3DArrayField; + normalize: boolean; + tailTime: SFTime; + children: X3DArrayField; + } + + interface SFNodeCoordinate extends SFNode { + point: X3DArrayField; + } + + interface SFNodeCylinder extends SFNode { + top: boolean; + side: boolean; + bottom: boolean; + height: number; + radius: number; + solid: boolean; + } + + interface X3DPointingDeviceSensorNode extends SFNode { + description: string; + enabled: boolean; + isOver: boolean; + isActive: boolean; + } + + interface X3DDragSensorNode extends X3DPointingDeviceSensorNode { + offset: number; + autoOffset: boolean; + trackPoint_changed: SFVec3; + } + + interface SFNodeCylinderSensor extends X3DDragSensorNode { + axisRotation: SFRotation, + diskAngle: number; + minAngle: number; + maxAngle: number; + rotation_changed: SFRotation; + } + + interface SFNodeDelay extends X3DTimeDependentNode, ChannelFields { + delayTime: SFTime; + maxDelayTime: SFTime; + tailTime: SFTime; + children: X3DArrayField; + } + + interface X3DLightNode extends SFNode { + global: boolean; + on: boolean; + color: SFColor; + intensity: number; + ambientIntensity: number; + shadows: boolean; + shadowColor: SFColor; + shadowIntensity: number; + shadowBias: number; + shadowMapSize: number; + } + + interface SFNodeDirectionalLight extends X3DLightNode { + direction: SFVec3; + } + + interface SFNodeDynamicsCompressor + extends X3DTimeDependentNode, ChannelFields { + attack: number; + knee: number; + ratio: number; + reduction: number; + release: SFTime; + threshold: number; + tailTime: SFTime; + children: X3DArrayField; + } + + interface SFNodeEaseInEaseOut extends SFNode { + set_fraction: number; + key: X3DArrayField; + easeInEaseOut: X3DArrayField; + modifiedFraction_changed: number; + } + + interface GeometrySubnodes { + attrib: X3DArrayField; + fogCoord: SFNodeFogCoordinate; + color: SFNodeColor | SFNodeColorRGBA; + normal: SFNodeNormal; + } + + interface SFNodeElevationGrid extends SFNode, GeometrySubnodes { + set_height: X3DArrayField; + xDimension: number; + zDimension: number; + xSpacing: number; + zSpacing: number; + solid: boolean; + ccw: boolean; + creaseAngle: number; + colorPerVertex: boolean; + normalPerVertex: boolean; + texCoord: SFNode; + height: X3DArrayField; + } + + interface SFNodeEnvironmentLight extends X3DLightNode { + rotation: SFRotation; + diffuseCoefficients: X3DArrayField; + diffuse: SFNode; + diffuseTexture: SFNode; + specularTexture: SFNode; + } + + interface SFNodeExtrusion extends SFNode { + set_crossSection: X3DArrayField; + set_orientation: X3DArrayField; + set_scale: X3DArrayField; + set_spine: X3DArrayField; + beginCap: boolean; + endCap: boolean; + solid: boolean; + ccw: boolean; + convex: boolean; + creaseAngle: number; + crossSection: X3DArrayField; + orientation: X3DArrayField; + scale: X3DArrayField; + spine: X3DArrayField; + } + + interface SFNodeFillProperties extends SFNode { + filled: boolean; + hatched: boolean; + hatchStyle: number; + hatchColor: SFColor; + } + + interface SFNodeFloatVertexAttribute extends SFNode { + name: string; + numComponents: number; + value: X3DArrayField; + } + + interface FogCommon extends SFNode { + fogType: 'LINEAR' | 'EXPONENTIAL'; + color: SFColor; + visibilityRange: number; + } + + interface SFNodeFog extends X3DBindableNode, FogCommon { } + + interface SFNodeFogCoordinate extends SFNode { + depth: X3DArrayField; + } + + interface SFNodeFontStyle extends SFNode { + language: string; + family: X3DArrayField; + style: 'PLAIN' | 'BOLD' | 'ITALIC' | 'BOLDITALIC' | ''; + size: number; + spacing: number; + horizontal: boolean; + leftToRight: boolean; + topToBottom: boolean; + justify: X3DArrayField<'BEGIN' | 'END' | 'FIRST' | 'MIDDLE' | ''>; + } + + interface SFNodeGain extends X3DTimeDependentNode, ChannelFields { + tailTime: SFTime; + children: X3DArrayField; + } + + interface Texture2DFields { + repeatS: boolean; + repeatT: boolean; + textureProperties: SFNodeTextureProperties; + } + + interface SFNodeImageTexture extends SFNode, URLFields, Texture2DFields { } + + interface IndexedColorCoord { + set_colorIndex: X3DArrayField; + set_coordIndex: X3DArrayField; + colorIndex: X3DArrayField; + coordIndex: X3DArrayField; + color: SFNodeColor | SFNodeColorRGBA; + coord: SFNodeCoordinate; + } + + interface SFNodeIndexedFaceSet extends SFNodeIndexedLineSet { + set_texCoordIndex: X3DArrayField; + set_normalIndex: X3DArrayField; + solid: boolean; + ccw: boolean; + convex: boolean; + creaseAngle: number; + normalPerVertex: boolean; + texCoordIndex: X3DArrayField; + normalIndex: X3DArrayField; + texCoord: SFNode; + } + + interface SFNodeIndexedLineSet + extends SFNode, GeometrySubnodes, IndexedColorCoord { + colorPerVertex: boolean; + } + + interface SFNodeTriangleSet extends SFNode, GeometrySubnodes { + solid: boolean; + ccw: boolean; + colorPerVertex: boolean; + normalPerVertex: boolean; + texCoord: SFNode; + coord: SFNodeCoordinate; + } + + interface IndexedTriangles extends SFNodeTriangleSet { + set_index: X3DArrayField; + index: X3DArrayField; + } + + interface SFNodeInline extends Positioner, URLFields { + global: boolean; + } + + interface SFNodeLOD extends X3DGroupingNode { + forceTransitions: boolean; + center: SFVec3; + range: X3DArrayField; + level_changed: number; + } + + interface SFNodeLayer extends SFNode, GroupingFields { + pickable: boolean; + objectType: X3DArrayField; + visible: boolean; + viewport: SFNodeViewport; + } + + interface SFNodeLayerSet extends SFNode { + activeLayer: number; + order: X3DArrayField; + layers: X3DArrayField; + } + + interface SFNodeLineProperties extends SFNode { + applied: boolean; + linetype: number; + linewidthScaleFactor: number; + } + + interface SFNodeLineSet extends SFNode, GeometrySubnodes { + vertexCount: X3DArrayField; + coord: SFNodeCoordinate; + } + + interface SFNodeListenerPointSource extends X3DTimeDependentNode { + description: string; + enabled: boolean; + orientation: SFRotation; + gain: number; + dopplerEnabled: boolean; + interauralDistance: number; + trackCurrentView: boolean; + } + + interface SFNodeLoadSensor extends SFNode { + enabled: boolean; + timeOut: SFTime; + isActive: boolean; + isLoaded: boolean; + progress: number; + loadTime: SFTime; + children: X3DArrayField; + } + + interface SFNodeLocalFog extends FogCommon { + enabled: boolean; + } + + interface SFNodeUnlitMaterial extends SFNode { + emissiveColor: SFColor; + emissiveTextureMapping: string; + emissiveTexture: SFNode; + normalScale: number; + normalTextureMapping: string; + normalTexture: SFNode; + transparency: number; + } + + interface MaterialCommon extends SFNodeUnlitMaterial { + occlusionStrength: number; + occlusionTextureMapping: string; + occlusionTexture: SFNode; + } + + interface SFNodeMaterial extends MaterialCommon { + ambientIntensity: number; + ambientTextureMapping: string; + ambientTexture: SFNode; + diffuseColor: SFColor; + diffuseTextureMapping: string; + diffuseTexture: SFNode; + specularColor: SFColor; + specularTextureMapping: string; + specularTexture: SFNode; + shininess: number; + shininessTextureMapping: string; + shininessTexture: SFNode; + } + + interface SFNodeMatrix3VertexAttribute extends SFNode { + name: string; + value: X3DArrayField; + } + + interface SFNodeMatrix4VertexAttribute extends SFNode { + name: string; + value: X3DArrayField; + } + + interface X3DMetadataNode extends SFNode { + name: string; + reference: string; + } + + interface MetadataInstance extends X3DMetadataNode { + value: X3DArrayField; + } + + interface SFNodeMicrophoneSource extends X3DTimeDependentNode { + description: string; + enabled: boolean; + gain: number; + mediaDeviceId: string; + } + + interface SFNodeMovieTexture extends SFNodeAudioClip, Texture2DFields { + speed: number; + } + + interface SFNodeMultiTexture extends SFNode { + description: string; + color: SFColor; + alpha: number; + mode: X3DArrayField; + source: X3DArrayField; + function: X3DArrayField; + texture: X3DArrayField; + } + + interface SFNodeMultiTextureCoordinate extends SFNode { + texCoord: X3DArrayField; + } + + interface SFNodeMultiTextureTransform extends SFNode { + textureTransform: X3DArrayField; + } + + interface SFNodeNavigationInfo extends X3DBindableNode { + type: X3DArrayField< + 'EXAMINE' | 'WALK' | 'FLY' | 'PLANE' | 'PLANE_create3000.github.io' + | 'PLANE_create3000.de' | 'LOOKAT' | 'EXPLORE' | 'ANY' | 'NONE'>; + avatarSize: X3DArrayField; + speed: number; + headlight: boolean; + visibilityLimit: number; + transitionType: X3DArrayField<'TELEPORT' | 'LINEAR' | 'ANIMATE'>; + transitionTime: SFTime; + transitionComplete: boolean; + } + + interface SFNodeNormal extends SFNode { + vector: X3DArrayField; + } + + interface X3DViewpointNode extends X3DBindableNode { + description: string; + position: SFVec3; + orientation: SFRotation; + centerOfRotation: SFVec3; + fieldOfView: number; + nearDistance: number; + farDistance: number; + viewAll: boolean; + jump: boolean; + retainUserOffsets: boolean; + navigationInfo: SFNodeNavigationInfo; + } + + interface SFNodeOscillatorSource extends X3DTimeDependentNode { + description: string; + enabled: boolean; + gain: number; + frequency: number; + detune: number; + periodicWave: SFNodePeriodicWave; + } + + interface SFNodePackagedShader extends X3DShaderNode, URLFields { } + + interface SFNodePeriodicWave extends SFNode { + description: string; + enabled: boolean; + type: 'SINE' | 'SQUARE' | 'SAWTOOTH' | 'TRIANGLE' | 'CUSTOM' + optionsReal: X3DArrayField; + optionsImag: X3DArrayField; + } + + interface SFNodePhysicalMaterial extends MaterialCommon { + baseColor: SFColor; + baseTextureMapping: String; + baseTexture: SFNode; + metallic: number; + roughness: number; + metallicRoughnessTextureMapping: string; + metallicRoughnessTexture: SFNode; + } + + interface SFNodePixelTexture extends SFNode, Texture2DFields { + description: string; + image: SFImage; + } + + interface SFNodePlaneSensor extends X3DDragSensorNode { + axisRotation: SFRotation; + minPosition: SFVec2; + maxPosition: SFVec2; + translation_changed: SFVec3; + } + + interface SFNodePointLight extends X3DLightNode { + attenuation: SFVec3; + location: SFVec3; + radius: number; + } + + interface SFNodePointProperties extends SFNode { + pointSizeScaleFactor: number; + pointSizeMinValue: number; + pointSizeMaxValue: number; + attenuation: SFVec3; + } + + interface SFNodePointSet extends SFNode, GeometrySubnodes { + coord: SFNodeCoordinate; + } + + interface SFNodeProgramShader extends X3DShaderNode { + programs: X3DArrayField + } + + interface X3DEnvironmentalSensorNode extends SFNode { + enabled: boolean; + size: SFVec3; + center: SFVec3; + enterTime: SFTime; + exitTime: SFTime; + isActive: boolean; + } + + interface SFNodeProximitySensor extends X3DEnvironmentalSensorNode { + position_changed: SFVec3; + orientation_changed: SFRotation; + centerOfRotation_changed: SFVec3; + } + + interface SFNodeScript extends SFNode, URLFields { + directOutput: boolean; + mustEvaluate: boolean; + } + + interface SFNodeShaderPart extends SFNode, URLFields { + type: 'VERTEX' | 'FRAGMENT'; + } + + type SFNodeShaderProgram = SFNodeShaderPart; // Why are there two node types? + + interface SFNodeShape extends Positioner { + castShadow: boolean; + appearance: SFNodeAppearance; + geometry: SFNode; + } + + interface SoundCommon extends SFNode { + description: string; + enabled: boolean; + spatialize: boolean; + location: SFVec3; + direction: SFVec3; + intensity: number; + priority: number; + children: X3DArrayField; + } + + interface SFNodeSound extends SFNode { + minBack: number; + minFront: number; + maxBack: number; + maxFront: number; + source: SFNode; + } + + interface SFNodeSpatialSound extends SFNode { + coneInnerAngle: number; + coneOuterAngle: number; + coneOuterGain: number; + distanceModel: 'LINEAR' | 'INVERSE' | 'EXPONENTIAL'; + dopplerEnabled: boolean; + enableHRTF: boolean; + gain: number; + maxDistance: number; + referenceDistance: number; + rolloffFactor: number; + } + + interface SFNodeSphere extends SFNode { + radius: number; + solid: boolean; + } + + interface SFNodeSphereSensor extends X3DPointingDeviceSensorNode { + rotation_changed: SFRotation; + } + + interface SplineInterpolator extends X3DInterpolatorNode { + closed: boolean; + keyVelocity: X3DArrayField; + normalizeVelocity: boolean; + } + + interface SFNodeSpotLight extends SFNodePointLight { + direction: SFVec3; + beamWidth: number; + cutOffAngle: number; + } + + interface SFNodeSquadOrientationInterpolator + extends X3DInterpolatorNode { + closed: boolean; + } + + interface SFNodeStaticGroup extends Positioner { + children: X3DArrayField; + } + + interface SFNodeStreamAudioDestination extends X3DSoundDestinationNode { + streamIdentifier: X3DArrayField; + } + + interface SFNodeStreamAudioSource extends X3DTimeDependentNode { + description: string; + enabled: boolean; + gain: number; + streamIdentifier: X3DArrayField; + } + + interface SFNodeSwitch extends X3DGroupingNode { + whichChoice: number; + } + + interface SFNodeText extends SFNode { + string: X3DArrayField; + length: X3DArrayField; + maxExtent: number; + solid: boolean; + origin: SFVec3; + textBounds: SFVec2; + lineBounds: X3DArrayField; + fontStyle: SFNodeFontStyle; + } + + interface SFNodeTextureBackground extends X3DBackgroundNode { + frontTexture: SFNode; + backTexture: SFNode; + leftTexture: SFNode; + rightTexture: SFNode; + topTexture: SFNode; + bottomTexture: SFNode; + } + + interface SFNodeTextureCoordinate extends SFNode { + mapping: string; + point: X3DArrayField; + } + + interface SFNodeTextureCoordinateGenerator extends SFNode { + mapping: string; + mode: 'SPHERE' | 'SPHERE-LOCAL' | 'SPHERE-REFLECT' | 'SPHERE-REFLECT-LOCAL' + | 'COORD' | 'COORD-EYE' | 'NOISE' | 'NOISE-EYE' | 'CAMERASPACENORMAL' + | 'CAMERASPACEPOSITION' | 'CAMERASPACEREFLECTIONVECTOR' ; + parameter: X3DArrayField; + } + + interface SFNodeTextureProperties extends SFNode { + borderColor: SFColorRGBA; + borderWidth: number; + anisotropicDegree: number; + generateMipMaps: boolean; + minificationFilter: string; + magnificationFilter: string; + boundaryModeS: string; + boundaryModeT: string; + boundaryModeR: string; + textureCompression: string; + texturePriority: number; + } + + interface SFNodeTextureTransform extends SFNode { + mapping: string; + translation: SFVec2; + rotation: number; + scale: SFVec2; + center: SFVec2; + } + + interface SFNodeTimeSensor extends X3DTimeDependentNode { + description: string; + enabled: boolean; + cycleInterval: SFTime; + loop: boolean; + cycleTime: SFTime; + fraction_changed: number; + time: SFTime; + } + + interface SFNodeTouchSensor extends X3DPointingDeviceSensorNode { + hitTexCoord_changed: SFVec2; + hitNormal_changed: SFVec3; + hitPoint_changed: SFVec3; + touchTime: SFTime; + } + + interface SFNodeTransform extends X3DGroupingNode { + translation: SFVec3; + rotation: SFRotation; + scale: SFVec3; + scaleOrientation: SFRotation; + center: SFVec3; + } + + interface SFNodeTransformSensor extends X3DEnvironmentalSensorNode { + position_changed: SFVec3; + orientation_changed: SFRotation; + targetObject: SFNode; + } + + interface SFNodeTriangleFanSet extends SFNodeTriangleSet { + fanCount: X3DArrayField; + } + + interface SFNodeTriangleStripSet extends SFNodeTriangleSet { + stripCount: X3DArrayField; + } + + interface SFNodeTwoSidedMaterial extends SFNode { + ambientIntensity: number; + backAmbientIntensity: number; + backDiffuseColor: SFColor; + backEmissiveColor: SFColor; + backShininess: number; + backSpecularColor: SFColor; + backTransparency: number; + diffuseColor: SFColor; + emissiveColor: SFColor; + shininess: number; + separateBackColor: boolean; + specularColor: SFColor; + transparency: number; + } + + interface SFNodeViewpointGroup extends SFNode { + description: string; + displayed: boolean; + retainUserOffsets: boolean; + size: SFVec3; + center: SFVec3; + children: X3DArrayField; + } + + interface SFNodeViewport extends X3DGroupingNode { + clipBoundary: X3DArrayField; + } + + interface SFNodeWaveShaper extends X3DTimeDependentNode, ChannelFields { + curve: X3DArrayField; + oversample: 'NONE' | '2x' | '4x'; + tailTime: SFTime; + children: X3DArrayField; + } + + interface SFNodeWorldInfo extends SFNode { + title: string; + info: X3DArrayField; + } + + export type SpecializeNodeType = { + AcousticProperties: SFNodeAcousticProperties, + Analyser: SFNodeAnalyser, + Anchor: SFNodeAnchor, + Appearance: SFNodeAppearance, + AudioClip: SFNodeAudioClip, + AudioDestination: SFNodeAudioDestination, + Background: SFNodeBackground, + Billboard: SFNodeBillboard, + BiquadFilter: SFNodeBiquadFilter, + BlendMode: SFNodeBlendMode, + Box: SFNodeBox, + BufferAudioSource: SFNodeBufferAudioSource, + ChannelMerger: SFNodeChannelMerger, + ChannelSelector: SFNodeChannelSelector, + ChannelSplitter: SFNodeChannelSplitter, + ClipPlane: SFNodeClipPlane, + Collision: SFNodeCollision, + Color: SFNodeColor, + ColorRGBA: SFNodeColorRGBA, + ColorChaser: X3DChaserNode, + ColorDamper: X3DDamperNode, + ColorInterpolator: X3DInterpolatorNode, + ComposedShader: SFNodeComposedShader, + Cone: SFNodeCone, + Convolver: SFNodeConvolver, + Coordinate: SFNodeCoordinate, + CoordinateChaser: X3DChaserNode>, + CoordinateDamper: X3DDamperNode>, + CoordinateInterpolator: X3DInterpolatorNode>, + CoordinateInterpolator2D: + X3DInterpolatorNode>, + Cylinder: SFNodeCylinder, + CylinderSensor: SFNodeCylinderSensor, + Delay: SFNodeDelay, + DirectionalLight: SFNodeDirectionalLight, + DynamicsCompressor: SFNodeDynamicsCompressor, + EaseInEaseOut: SFNodeEaseInEaseOut, + ElevationGrid: SFNodeElevationGrid, + EnvironmentLight: SFNodeEnvironmentLight, + Extrusion: SFNodeExtrusion, + FillProperties: SFNodeFillProperties, + FloatVertexAttribute: SFNodeFloatVertexAttribute, + Fog: SFNodeFog, + FogCoordinate: SFNodeFogCoordinate, + FontStyle: SFNodeFontStyle, + Gain: SFNodeGain, + Group: X3DGroupingNode, + ImageTexture: SFNodeImageTexture, + IndexedFaceSet: SFNodeIndexedFaceSet, + IndexedLineSet: SFNodeIndexedLineSet,​ + IndexedTriangleFanSet: IndexedTriangles, + IndexedTriangleSet: IndexedTriangles, + IndexedTriangleStripSet: IndexedTriangles, + Inline: SFNodeInline, + LOD: SFNodeLOD, + Layer: SFNodeLayer,​ + LayerSet: SFNodeLayerSet, + LineProperties: SFNodeLineProperties, + LineSet: SFNodeLineSet, + ListenerPointSource: SFNodeListenerPointSource, + LoadSensor: SFNodeLoadSensor, + LocalFog: SFNodeLocalFog, + Material: SFNodeMaterial, + Matrix3VertexAttribute: SFNodeMatrix3VertexAttribute, + Matrix4VertexAttribute: SFNodeMatrix4VertexAttribute, + MetadataBoolean: MetadataInstance, + MetadataDouble: MetadataInstance, + MetadataFloat: MetadataInstance, + MetadataInteger: MetadataInstance, + MetadataSet: MetadataInstance, + MetadataString: MetadataInstance, + MicrophoneSource: SFNodeMicrophoneSource, + MovieTexture: SFNodeMovieTexture, + MultiTexture: SFNodeMultiTexture, + MultiTextureCoordinate: SFNodeMultiTextureCoordinate, + MultiTextureTransform: SFNodeMultiTextureTransform, + NavigationInfo: SFNodeNavigationInfo, + Normal: SFNodeNormal, + NormalInterpolator: X3DInterpolatorNode>, + OrientationChaser: X3DChaserNode, + OrientationDamper: X3DDamperNode, + OrientationInterpolator: X3DInterpolatorNode, + OrthoViewpoint: X3DViewpointNode, + OscillatorSource: SFNodeOscillatorSource, + PackagedShader: SFNodePackagedShader, + PeriodicWave: SFNodePeriodicWave, + PhysicalMaterial: SFNodePhysicalMaterial, + PixelTexture: SFNodePixelTexture, + PlaneSensor: SFNodePlaneSensor, + PointLight: SFNodePointLight, + PointProperties: SFNodePointProperties, + PointSet: SFNodePointSet, + PositionChaser: X3DChaserNode, + PositionChaser2D: X3DChaserNode, + PositionDamper: X3DDamperNode, + PositionDamper2D: X3DDamperNode, + PositionInterpolator: X3DInterpolatorNode, + PositionInterpolator2D: X3DInterpolatorNode, + ProgramShader: SFNodeProgramShader, + ProximitySensor: SFNodeProximitySensor, + ScalarChaser: X3DChaserNode, + ScalarDamper: X3DDamperNode, + ScalarInterpolator: X3DInterpolatorNode, + Script: SFNodeScript, + ShaderPart: SFNodeShaderPart, + ShaderProgram: SFNodeShaderProgram, + Shape: SFNodeShape, + Sound: SFNodeSound, + SpatialSound: SFNodeSpatialSound, + Sphere: SFNodeSphere, + SphereSensor: SFNodeSphereSensor, + SplinePositionInterpolator: SplineInterpolator, + SplinePositionInterpolator2D: SplineInterpolator, + SplineScalarInterpolator: SplineInterpolator, + SpotLight: SFNodePointLight, + SquadOrientationInterpolator: SFNodeSquadOrientationInterpolator, + StaticGroup: SFNodeStaticGroup, + StreamAudioDestination: SFNodeStreamAudioDestination, + StreamAudioSource: SFNodeStreamAudioSource, + Switch: SFNodeSwitch, + TexCoordChaser2D: X3DChaserNode>, + TexCoordDamper2D: X3DDamperNode>, + Text: SFNodeText, + TextureBackground: SFNodeTextureBackground, + TextureCoordinate: SFNodeTextureCoordinate, + TextureCoordinateGenerator: SFNodeTextureCoordinateGenerator, + TextureProperties: SFNodeTextureProperties, + TextureTransform: SFNodeTextureTransform, + TimeSensor: SFNodeTimeSensor, + TouchSensor: SFNodeTouchSensor, + Transform: SFNodeTransform, + TransformSensor: SFNodeTransformSensor, + TriangleFanSet: SFNodeTriangleFanSet, + TriangleSet: SFNodeTriangleSet, + TriangleStripSet: SFNodeTriangleStripSet, + TwoSidedMaterial: SFNodeTwoSidedMaterial, + UnlitMaterial: SFNodeUnlitMaterial, + Viewpoint: X3DViewpointNode, + ViewpointGroup: SFNodeViewpointGroup, + Viewport: SFNodeViewport, + VisibilitySensor: X3DEnvironmentalSensorNode, + WaveShaper: SFNodeWaveShaper, + WorldInfo: SFNodeWorldInfo, + [name: string]: SFNode // catchall + } + + type FieldDefinitionArray = Map; + export type X3DFieldDefinition = { + accessType: number, // that's a guess + dataType: string, + name: string, + value: unknown // I don't think we can do better without parsing the + // possible values for dataType... + } + type VRMLOptions = { + style?: string, + indent?: string, + precision?: number, + doublePrecision?: number, + html?: boolean, + closingTags?: boolean + } + + export class SFRotation extends X3DField { + constructor(); + constructor(x: number, y: number, z: number, angle: number); + constructor(axis: SFVec3, angle: number); + constructor(from: SFVec3, to: SFVec3); + constructor(matrix: SFMatrix3); + x: number; + y: number; + z: number; + angle: number; + + copy(): SFRotation; + isDefaultValue(): boolean; + set(other: SFRotation): void; + + getAxis(): SFVec3; + getMatrix(): SFMatrix3; + inverse(): SFRotation; + multiply(other: SFRotation): SFRotation; + multVec(subject: SFVec3): SFVec3; + setAxis(axis: SFVec3): void; + setMatrix(matrix: SFMatrix3): void; + slerp(destination: SFRotation, t: number): SFRotation; + } + + export class SFString extends X3DField { + constructor(arg?: unknown); + copy(): SFString; + isDefaultValue(): boolean; + set(arg: unknown): void; + valueOf(): string; + length: number; + } + + export class SFTime extends X3DField { + constructor(arg?: unknown); + copy(): SFTime; + isDefaultValue(): boolean; + set(arg: unknown): void; + valueOf(): number; // I think that's the right type... + } + + export class SFVec2 extends X3DField { + constructor(x?: number, y?: number); + x: number; + y: number; + + copy(): SFVec2; + isDefaultValue(): boolean; + set(other: SFVec2): void; + + abs(): SFVec2; + add(other: SFVec2): SFVec2; + distance(other: SFVec2): number; + divide(denominator: number): SFVec2; + divVec(other: SFVec2): SFVec2; + dot(other: SFVec2): number; + inverse(): SFVec2; + length(): number; + lerp(destination: SFVec2, t: number): SFVec2; + min(other: SFVec2): SFVec2; + max(other: SFVec2): SFVec2; + multiply(factor: number): SFVec2; + multVec(other: SFVec2): SFVec2; + negate(): SFVec2; + normalize(): SFVec2; + subtract(other: SFVec2): SFVec2; + } + + export class SFVec3 extends X3DField { + constructor(x?: number, y?: number, z?: number); + x: number; + y: number; + z: number; + + copy(): SFVec3; + isDefaultValue(): boolean; + set(other: SFVec3): void; + + abs(): SFVec3; + add(other: SFVec3): SFVec3; + cross(other: SFVec3): SFVec3; + distance(other: SFVec3): number; + divide(denominator: number): SFVec3; + divVec(other: SFVec3): SFVec3; + dot(other: SFVec3): number; + inverse(): SFVec3; + length(): number; + lerp(destination: SFVec3, t: number): SFVec3; + min(other: SFVec3): SFVec3; + max(other: SFVec3): SFVec3; + multiply(factor: number): SFVec3; + multVec(other: SFVec3): SFVec3; + negate(): SFVec3; + normalize(): SFVec3; + subtract(other: SFVec3): SFVec3; + } + + export class SFVec4 extends X3DField { + constructor(x?: number, y?: number, z?: number, w?: number); + x: number; + y: number; + z: number; + w: number; + + copy(): SFVec4; + isDefaultValue(): boolean; + set(other: SFVec4): void; + + abs(): SFVec4; + add(other: SFVec4): SFVec4; + distance(other: SFVec4): number; + divide(denominator: number): SFVec4; + divVec(other: SFVec4): SFVec4; + dot(other: SFVec4): number; + inverse(): SFVec4; + length(): number; + lerp(destination: SFVec4, t: number): SFVec4; + min(other: SFVec4): SFVec4; + max(other: SFVec4): SFVec4; + multiply(factor: number): SFVec4; + multVec(other: SFVec4): SFVec4; + negate(): SFVec4; + normalize(): SFVec4; + subtract(other: SFVec4): SFVec4; + } + + type ArrayTest = (elt: T, ix: boolean, arr: X3DArrayField) => boolean + type ArrayAction = (elt: T, ix: boolean, arr: X3DArrayField) => void + type ArrayReducer = + (acc: U, elt: T, ix: number, arr: X3DArrayField) => U + export class X3DArrayField extends X3DField { + constructor(...elts: T[]); + [index: number]: T; + length: number; + at(index: number): T; + entries(): IterableIterator<[number, T]>; + every(predicate: ArrayTest): boolean; + fill(val: T, start?: number, end?: number): X3DArrayField; + filter(predicate: ArrayTest): X3DArrayField; + find(test: ArrayTest): T | undefined; + findIndex(test: ArrayTest): number; + findLast(test: ArrayTest): T | undefined; + findLastIndex(test: ArrayTest): number; + forEach(action: ArrayAction): void; + includes(needle: T): boolean; + indexOf(needle: T): number; + join(separator?: string): string; + keys(): number[]; + lastIndexOf(needle: T): number; + map(f: (elt: T, ix: number, arr: X3DArrayField) => U): U[]; + pop(): T; + push(...elts: T[]): number; + reduce(f: ArrayReducer, initial?: U): U; + reduceRight(f: ArrayReducer, initial?: U): U; + reverse(): X3DArrayField; + shift(): T; + slice(start?: number, end?: number): X3DArrayField; + some(predicate: ArrayTest): boolean; + sort(comparator?: (a: T, b: T) => number): X3DArrayField; + splice(start: number, deleteCount: number, + ...rest: T[]) : X3DArrayField; + toReversed(): X3DArrayField; + toSorted(comparator?: (a: T, b: T) => number): X3DArrayField; + toSpliced(start: number, deleteCount: number, + ...rest: T[]) : X3DArrayField; + unshift(...elts: T[]): number; + values(): IterableIterator; + with(index: number, value: T): X3DArrayField; + } + + // would be better to make these enums... + export interface X3DConstant { + // Browser Event Constants + CONNECTION_ERROR: 0; + BROWSER_EVENT: 1; + INITIALIZED_EVENT: 2; + SHUTDOWN_EVENT: 3; + INITIALIZED_ERROR: 4; + // Load State Constants​ + NOT_STARTED_STATE: 0; + IN_PROGRESS_STATE: 1; + COMPLETE_STATE: 2; + FAILED_STATE: 3; + // Access Type Constants + initializeOnly: 1; + ​inputOnly: 2; + outputOnly: 4​; + inputOutput: 7; + // Field Type Constants​ + SFBool: 0; + ​SFColor: 1;​ + SFColorRGBA: 2;​ + SFDouble: 3;​ + SFFloat: 4;​ + SFImage: 5;​ + SFInt32: 6;​ + SFMatrix3d: 7;​ + SFMatrix3f: 8; + ​SFMatrix4d: 9;​ + SFMatrix4f: 10;​ + SFNode: 11;​ + SFRotation: 12;​ + SFString: 13; + ​SFTime: 14;​ + SFVec2d: 15;​ + SFVec2f: 16;​ + SFVec3d: 17;​ + SFVec3f: 18;​ + SFVec4d: 19;​ + SFVec4f: 20; + MFBool: 22;​ + MFColor: 23;​ + MFColorRGBA: 24;​ + MFDouble: 25;​ + MFFloat: 26;​ + MFImage: 27;​ + MFInt32: 28;​ + MFMatrix3d: 29;​ + MFMatrix3f: 30;​ + MFMatrix4d: 31;​ + MFMatrix4f: 32;​ + MFNode: 33;​ + MFRotation: 34;​ + MFString: 35;​ + MFTime: 36;​ + MFVec2d: 37;​ + MFVec2f: 38;​ + MFVec3d: 39;​ + MFVec3f: 40;​ + MFVec4d: 41;​ + MFVec4f: 42; + // Concrete Node Types + AcousticProperties: 140;​ + Analyser: 155;​ + Anchor: 96;​ + Appearance: 141;​ + AudioClip: 156;​ + AudioDestination: 157;​ + Background: 21;​ + Billboard: 88;​ + BiquadFilter: 158;​ + Box: 49;​ + BufferAudioSource: 159;​ + ChannelMerger: 160;​ + ChannelSelector: 161;​ + ChannelSplitter: 162;​ + ClipPlane: 108;​ + Collision: 89;​ + Color: 109;​ + ColorChaser: 32;​ + ColorDamper: 33;​ + ColorInterpolator: 64;​ + ColorRGBA: 110;​ + ComposedShader: 129;​ + Cone: 50;​ + Convolver: 163;​ + Coordinate: 111;​ + CoordinateChaser: 34;​ + CoordinateDamper: 35;​ + CoordinateInterpolator: 65;​ + CoordinateInterpolator2D: 66;​ + Cylinder: 51;​ + CylinderSensor: 101;​ + Delay: 164;​ + DirectionalLight: 83;​ + DynamicsCompressor: 165;​ + EaseInEaseOut: 67;​ + ElevationGrid: 52;​ + EnvironmentLight: 84;​ + Extrusion: 53;​ + FillProperties: 142;​ + FloatVertexAttribute: 130;​ + Fog: 22;​ + FogCoordinate: 23;​ + FontStyle: 203;​ + Gain: 166;​ + Group: 56;​ + ImageTexture: 181;​ + IndexedFaceSet: 54;​ + IndexedLineSet: 112;​ + IndexedTriangleFanSet: 113;​ + IndexedTriangleSet: 114;​ + IndexedTriangleStripSet: 115; + Inline: 97;​ + LOD: 90;​ + Layer: 78;​ + LayerSet: 79;​ + LineProperties: 143;​ + LineSet: 116;​ + ListenerPointSource: 167;​ + LoadSensor: 98;​ + LocalFog: 24;​ + Material: 144;​ + Matrix3VertexAttribute: 131;​ + Matrix4VertexAttribute: 132;​ + MetadataBoolean: 7;​ + MetadataDouble: 8;​ + MetadataFloat: 9;​ + MetadataInteger: 10;​ + MetadataSet: 11;​ + MetadataString: 12;​ + MicrophoneSource: 168;​ + MovieTexture: 182;​ + MultiTexture: 183;​ + MultiTextureCoordinate: 184;​ + MultiTextureTransform: 185;​ + NavigationInfo: 91;​ + Normal: 117;​ + NormalInterpolator: 68;​ + OrientationChaser: 36;​ + OrientationDamper: 37;​ + OrientationInterpolator: 69;​ + OrthoViewpoint: 92;​ + OscillatorSource: 169;​ + PackagedShader: 133;​ + PeriodicWave: 170;​ + PhysicalMaterial: 145;​ + PixelTexture: 186;​ + PlaneSensor: 102;​ + PointLight: 85;​ + PointProperties: 146;​ + PointSet: 118;​ + PositionChaser: 38;​ + PositionChaser2D: 39;​ + PositionDamper: 40;​ + PositionDamper2D: 41;​ + PositionInterpolator: 70;​ + PositionInterpolator2D: 71;​ + ProgramShader: 134;​ + ProximitySensor: 28;​ + ScalarChaser: 42;​ + ScalarDamper: 43;​ + ScalarInterpolator: 72;​ + Script: 201;​ + ShaderPart: 135;​ + ShaderProgram: 136;​ + Shape: 147;​ + Sound: 171;​ + SpatialSound: 172;​ + Sphere: 55;​ + SphereSensor: 103;​ + SplinePositionInterpolator: 73;​ + SplinePositionInterpolator2D: 74;​ + SplineScalarInterpolator: 75;​ + SpotLight: 86;​ + SquadOrientationInterpolator: 76;​ + StaticGroup: 57;​ + StreamAudioDestination: 173;​ + StreamAudioSource: 174;​ + Switch: 58;​ + TexCoordChaser2D: 44;​ + TexCoordDamper2D: 45;​ + Text: 204;​ + TextureBackground: 25;​ + TextureCoordinate: 187;​ + TextureCoordinateGenerator: 188;​ + TextureProperties: 189;​ + TextureTransform: 190;​ + TimeSensor: 198;​ + TouchSensor: 104;​ + Transform: 59;​ + TransformSensor: 29;​ + TriangleFanSet: 119;​ + TriangleSet: 120;​ + TriangleStripSet: 121;​ + TwoSidedMaterial: 148;​ + UnlitMaterial: 149;​ + Viewpoint: 93;​ + ViewpointGroup: 94;​ + Viewport: 80;​ + VisibilitySensor: 30;​ + VrmlMatrix: 21;​ + WaveShaper: 175;​ + WorldInfo: 13; + // Abstract Node Types​ + X3DAppearanceChildNode: 150;​ + X3DAppearanceNode: 151;​ + X3DBackgroundNode: 26;​ + X3DBaseNode: 0;​ + X3DBindableNode: 14;​ + X3DBoundedObject: 60;​ + X3DBrowser: 200;​ + X3DChaserNode: 46;​ + X3DChildNode: 15;​ + X3DColorNode: 122;​ + X3DComposedGeometryNode: 123;​ + X3DCoordinateNode: 124;​ + X3DDamperNode: 47;​ + X3DDragSensorNode: 105;​ + X3DEnvironmentalSensorNode: 31;​ + X3DExecutionContext: 5;​ + X3DExternProtoDeclaration: 4;​ + X3DFogObject: 27;​ + X3DFollowerNode: 48;​ + X3DFontStyleNode: 205;​ + X3DGeometricPropertyNode: 125;​ + X3DGeometryNode: 126;​ + X3DGroupingNode: 61;​ + X3DInfoNode: 16;​ + X3DInterpolatorNode: 77;​ + X3DLayerNode: 81;​ + X3DLightNode: 87;​ + X3DLineGeometryNode: 127;​ + X3DMaterialNode: 152;​ + X3DMetadataObject: 17;​ + X3DNetworkSensorNode: 99;​ + X3DNode: 18;​ + X3DNormalNode: 128;​ + X3DOneSidedMaterialNode: 153;​ + X3DPointingDeviceSensorNode: 106;​ + X3DProgrammableShaderObject: 137;​ + X3DProtoDeclaration: 2;​ + X3DProtoDeclarationNode: 1;​ + X3DPrototypeInstance: 19;​ + X3DScene: 6;​ + X3DScriptNode: 202;​ + X3DSensorNode: 20;​ + X3DShaderNode: 138;​ + X3DShapeNode: 154;​ + X3DSingleTextureCoordinateNode: 191;​ + X3DSingleTextureNode: 192;​ + X3DSingleTextureTransformNode: 193;​ + X3DSoundChannelNode: 176;​ + X3DSoundDestinationNode: 177;​ + X3DSoundNode: 178;​ + X3DSoundProcessingNode: 179;​ + X3DSoundSourceNode: 180;​ + X3DTexture2DNode: 194;​ + X3DTextureCoordinateNode: 195;​ + X3DTextureNode: 196;​ + X3DTextureTransformNode: 197;​ + X3DTimeDependentNode: 199;​ + X3DTouchSensorNode: 107;​ + X3DTransformMatrix3DNode: 62;​ + X3DTransformNode: 63;​ + X3DUrlObject: 100;​ + X3DVertexAttributeNode: 139;​ + X3DViewpointNode: 95;​ + X3DViewportNode: 82;​ + X3DWorld: 3; + } +} diff --git a/package.json5 b/package.json5 index a9c2175..630af6b 100644 --- a/package.json5 +++ b/package.json5 @@ -4,12 +4,21 @@ description: 'Uncovering lost digital mathematical treasures', scripts: { test: 'echo "Error: no test specified" && exit 1', - build_js: 'civet --js -c src/*.civet -o public/js/.js', - build_deps: 'cp -rLT node_modules/vrml1to97 public/js/deps', + // Obtain additional source code needed: + prebuild: 'bash tools/fetchDeps.bash', + // Use civet to create .ts files from the source... + build_ts1: 'mkdir -p tsbuild && civet -c -o tsbuild/.ts src/*.civet', + // ... but also grab other existing files: + build_ts2: 'cp -r etc/deps tsbuild', + build_ts3: 'bash tools/copyDeps.bash tsbuild/deps', + // Use the Typescript compiler to create the final .js files: + build_js: 'tsc && mkdir -p public/js && cp -r jsbuild/* public/js', + build_deps: 'bash tools/copyDeps.bash public/js/deps', build: 'pnpm --sequential /build_/', start: 'node public/js', go: 'pnpm --sequential "/build|start/"', serve: 'pnpm build && http-server', + clean: 'rm -rf tsbuild jsbuild public/js', }, packageManager: 'pnpm', keywords: [ @@ -25,7 +34,9 @@ }, devDependencies: { '@danielx/civet': '^0.6.31', + '@types/jquery': '^3.5.18', 'http-server': '^14.1.1', + typescript: '^5.2.2', }, dependencies: { vrml1to97: '^0.1.3', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4bed961..b5e9b8a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,9 +13,15 @@ devDependencies: '@danielx/civet': specifier: ^0.6.31 version: 0.6.31(typescript@5.2.2) + '@types/jquery': + specifier: ^3.5.18 + version: 3.5.18 http-server: specifier: ^14.1.1 version: 14.1.1 + typescript: + specifier: ^5.2.2 + version: 5.2.2 packages: @@ -57,6 +63,16 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true + /@types/jquery@3.5.18: + resolution: {integrity: sha512-sNm7O6LECFhHmF+3KYo6QIl2fIbjlPYa0PDgDQwfOaEJzwpK20Eub9Ke7VKkGsSJ2K0HUR50S266qYzRX4GlSw==} + dependencies: + '@types/sizzle': 2.3.3 + dev: true + + /@types/sizzle@2.3.3: + resolution: {integrity: sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==} + dev: true + /@typescript/vfs@1.5.0: resolution: {integrity: sha512-AJS307bPgbsZZ9ggCT3wwpg3VbTKMFNHfaY/uF0ahSkYYrPF2dSSKDNIDIQAHm9qJqbLvCsSJH7yN4Vs/CsMMg==} dependencies: diff --git a/public/hartPoly.html b/public/hartPoly.html index bfea16a..509ea58 100644 --- a/public/hartPoly.html +++ b/public/hartPoly.html @@ -7,7 +7,7 @@

Here is a - Hart polyhedron + Hart polyhedron .

diff --git a/src/adapptlet.civet b/src/adapptlet.civet index 354f06a..2bc1f99 100644 --- a/src/adapptlet.civet +++ b/src/adapptlet.civet @@ -1,11 +1,19 @@ import https://code.jquery.com/jquery-3.7.1.js +import type {AppletObject} from ./deps/geogebra/api.ts -joyceApplets := [] +type AppletDescription + html: string + children: HTMLCollection + id: string + width: number + height: number + +joyceApplets: AppletDescription[] := [] $('applet[code="Geometry"]').before (i, html) -> id := `joyceApplet${i}` joyceApplets.push { html, this.children, id, - width: parseInt(this.getAttribute 'width'), - height: parseInt(this.getAttribute 'height') } + width: parseInt(this.getAttribute('width') ?? '200'), + height: parseInt(this.getAttribute('height') ?? '200') } `
` jQuery.getScript 'https://www.geogebra.org/apps/deployggb.js', => @@ -14,20 +22,25 @@ jQuery.getScript 'https://www.geogebra.org/apps/deployggb.js', => appName: 'classic', jApp.width, jApp.height, - appletOnLoad: (api) => + appletOnLoad: (api: AppletObject) => for child of jApp.children dispatchJcommand api, child api.setCoordSystem(-10, 10 + jApp.width, -10, 10 + jApp.height) - } + } as const geoApp := new GGBApplet params geoApp.inject jApp.id -type Cmdr - command: string - callbacks: ((api) => boolean)[] +type GeogebraCallback = (api: AppletObject) => void +type Commander + command: string + callbacks: GeogebraCallback[] -function dispatchJcommand(api, param) +type ClassHandler = ( + name: string, m: string, data: string, colors: string[]) => Commander + +function dispatchJcommand(api: AppletObject, param: Element): void val := param.getAttribute 'value' + unless val return switch param.getAttribute 'name' 'background' api.setGraphicsOptions 1, bgColor: `#${val}` @@ -48,39 +61,39 @@ function dispatchJcommand(api, param) else console.log `Unkown param ${param}` -function jToG(jCom: string): Cmdr +function jToG(jCom: string): Commander [name, klass, method, data, ...colors] := jCom.split(';') if klass in classHandler return classHandler[klass] name, method, data, colors console.log `Unknown entity class ${klass}` - return '' + command: '', callbacks: [] -classHandler := - point: (name: string, m: string, data: string, colors: string[]): Cmdr => +classHandler: Record := + point: (name, method, data, colors) => command .= '' - callbacks .= [] - switch m + callbacks: GeogebraCallback[] .= [] + switch method /free|fixed/ command += `${name} = (${data})` - if m is 'fixed' - callbacks.push (api) => api.setFixed(name, true) + if method is 'fixed' + callbacks.push (api: AppletObject) => api.setFixed(name, true) 'perpendicular' [center, direction] := data.split(',') command += `${name} = Rotate(${direction}, 3*pi/2, ${center})` return {command, callbacks} - line: (name: string, m: string, data: string, colors: string[]): Cmdr => + line: (name, method, data, colors) => command .= '' - callbacks .= [] - switch m + callbacks: GeogebraCallback[] .= [] + switch method 'connect' command += `${name} = Segment(${data})` return {command, callbacks} - circle: (name: string, m: string, data: string, colors: string[]): Cmdr => + circle: (name, method, data, colors) => command .= '' - callbacks .= [] - switch m + callbacks: GeogebraCallback[] .= [] + switch method 'radius' [center, point] := data.split(',') command += `${name} = Circle(${center}, ${point})` diff --git a/src/giveAwrl.civet b/src/giveAwrl.civet index 3345bf0..8597353 100644 --- a/src/giveAwrl.civet +++ b/src/giveAwrl.civet @@ -4,17 +4,20 @@ X3D from https://create3000.github.io/code/x_ite/latest/x_ite.mjs certainlyHandled := '.x3d .gltf .glb .obj .stl .ply'.split ' ' canvas := X3D.createBrowser() +browser := X3D.getBrowser canvas +browser.setBrowserOption 'StraightenHorizon', false site := $('a[href^="http"]') -url := site.attr 'href' +url := site.attr('href') ?? '' + if certainlyHandled.some((ext) => url.includes ext) - canvas.setAttribute 'src', site.attr 'href' + canvas.setAttribute 'src', url else if url.includes '.wrl' // Need to obtain the text and check what level it is response := await fetch url text .= await response.text() if /#\s*VRML\s*V?1./i.test(text) text = convert(text) - browser := X3D.getBrowser canvas scene := await browser.createX3DFromString text browser.replaceWorld(scene) + site.after(canvas) diff --git a/tools/copyDeps.bash b/tools/copyDeps.bash new file mode 100644 index 0000000..66c2e44 --- /dev/null +++ b/tools/copyDeps.bash @@ -0,0 +1,3 @@ +# Takes one parameter, the destination directory +mkdir -p $1 +cp -rL node_modules/vrml1to97/{deps,vrml1to97,streamToString.js} $1 diff --git a/tools/fetchDeps.bash b/tools/fetchDeps.bash new file mode 100644 index 0000000..8f60c46 --- /dev/null +++ b/tools/fetchDeps.bash @@ -0,0 +1,10 @@ +mkdir -p etc/deps/geogebra + +cp etc/depPreamble.text etc/deps/geogebra/api.ts +curl 'https://raw.githubusercontent.com/netless-io/netless-app/master/packages/app-geogebra/src/types/api.ts' >> etc/deps/geogebra/api.ts + +cp etc/depPreamble.text etc/deps/geogebra/entry.ts +curl 'https://raw.githubusercontent.com/netless-io/netless-app/master/packages/app-geogebra/src/types/entry.ts' >> etc/deps/geogebra/entry.ts + +cp etc/depPreamble.text etc/deps/geogebra/params.ts +curl 'https://raw.githubusercontent.com/netless-io/netless-app/master/packages/app-geogebra/src/types/params.ts' >> etc/deps/geogebra/params.ts diff --git a/tsconfig.json b/tsconfig.json index f5e6879..a227703 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,11 +1,14 @@ { "compilerOptions": { "strict": true, - "lib": ["esnext"], + "target": "esnext", "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "esModuleInterop": true + "module": "esnext", + "esModuleInterop": true, + "rootDir": "tsbuild", + "outDir": "jsbuild", }, + "include": [ "tsbuild/**/*" ], "ts-node": { "transpileOnly": true, "compilerOptions": { @@ -13,4 +16,4 @@ } } } -} +