From e265a853a72c2ce71346067ee9e31592b6d6855c Mon Sep 17 00:00:00 2001 From: Fadi Shawki Date: Tue, 16 Jan 2024 23:42:01 +0100 Subject: [PATCH] 2024/01/16 - Refactoring, some tests, after this is done need a much better interface setup --- src/@orbitmines/explorer/Ray.spec.ts | 107 ++++++---- src/@orbitmines/explorer/Ray.ts | 151 +++++++++----- .../explorer/debug/DebugCanvas.tsx | 12 +- src/@orbitmines/external/chyp/ChypCanvas.tsx | 192 ++++++++++++++++-- 4 files changed, 352 insertions(+), 110 deletions(-) diff --git a/src/@orbitmines/explorer/Ray.spec.ts b/src/@orbitmines/explorer/Ray.spec.ts index 99a41fa..4021ecd 100644 --- a/src/@orbitmines/explorer/Ray.spec.ts +++ b/src/@orbitmines/explorer/Ray.spec.ts @@ -20,6 +20,18 @@ describe("Ray", () => { expect(method(a)(b).terminal.self.any.js).toBe('B'); expect(method(a)(b).type).toBe(RayType.VERTEX); }); + test("[A, B, C].copy", () => { + const A = Ray.vertex().o({ js: 'A' }).as_reference().o({ js: 'A.#' }); + const B = Ray.vertex().o({ js: 'B' }).as_reference().o({ js: 'B.#' }); + const C = Ray.vertex().o({ js: 'C' }).as_reference().o({ js: 'C.#' }); + + A.continues_with(B).continues_with(C); + + expect(() => A.copy()).toThrow(); + // const copy = A.copy(); + // expect(A.has_previous()).toBe(false); + // expect(copy.has_previous()).toBe(false); + }); test("[A, B, C].next()", () => { const A = Ray.vertex().o({ js: 'A' }).as_reference().o({ js: 'A.#' }); const B = Ray.vertex().o({ js: 'B' }).as_reference().o({ js: 'B.#' }); @@ -404,22 +416,66 @@ describe("Ray", () => { // // // }); - // test(".as_vertex", () => { - // const initial = Ray.terminal().o({js: 'A'}).as_reference().o({js: 'A.#'}); - // const terminal= Ray.initial().o({js: 'B'}).as_reference().o({js: 'B.#'}); - // - // initial.self = terminal.as_arbitrary(); - // terminal.self = initial.as_arbitrary(); - // - // const as_vertex = initial.as_vertex(); - // expect(as_vertex.self.any.js).toBe('B'); - // }); - test(".#.equivalent(.#)", () => { + test(".as_vertex", () => { + let A = Ray.terminal().o({js: 'A'}).as_reference().o({js: 'A.#'}); + // const B= Ray.initial().o({js: 'B'}).as_reference().o({js: 'B.#'}); + + // initial.self = terminal.self.as_arbitrary(); + // terminal.self = initial.self.as_arbitrary(); + + A = A.as_vertex(); + + // expect(A.self.any.js).toBe('A'); + expect(A.self.self.any.js).toBe('A'); + // expect(A.self.self.self.any.js).toBe('A'); + expect(A.self.self.self.self.any.js).toBe('A'); + }); + test(".None.#.equivalent(.None.#)", () => { + const A = Ray.None().o({ js: 'A' }).as_reference(); // TODO Tagging the 'NONE' vertices here is incredibly inconsistent, but just to demonstrate the test. + const B = Ray.None().o({ js: 'B' }).as_reference(); + + expect(A.is_none()).toBe(true); + expect(A.self.any.js).toBe('A'); + expect(A.self.self.any.js).toBe('A'); + expect(A.self.self.self.any.js).toBe('A'); + + expect(B.is_none()).toBe(true); + expect(B.self.any.js).toBe('B'); + expect(B.self.self.any.js).toBe('B'); + expect(B.self.self.self.any.js).toBe('B'); + + const ret = A.equivalent(B); + + expect(A.is_none()).toBe(false); + expect(A.self.any.js).toBe('A'); + expect(A.self.self.any.js).toBe('B'); + expect(A.self.self.self.any.js).toBe('A'); + + expect(B.is_none()).toBe(false); + expect(B.self.any.js).toBe('B'); + expect(B.self.self.any.js).toBe('A'); + expect(B.self.self.self.any.js).toBe('B'); + }); + test(".None.#.equivalent(.vertex.#)", () => { + const A = Ray.None().as_reference(); + const B = Ray.vertex().o({ js: 'B' }).as_reference().o({ js: 'B.#' }); + + // const ret = A.equivalent(B); + + // expect() + }); + test(".vertex.#.equivalent(.vertex.#)", () => { const A = Ray.vertex().o({ js: 'A' }).as_reference().o({ js: 'A.#' }); const B = Ray.vertex().o({ js: 'B' }).as_reference().o({ js: 'B.#' }); + expect(A.any.js).toBe('A.#'); + expect(B.any.js).toBe('B.#'); + const ret = A.equivalent(B); + expect(A.self.any.js).toBe('A'); + expect(B.self.any.js).toBe('B'); + expect(A.self.self.any.js).toBe('B'); expect(B.self.self.any.js).toBe('A'); @@ -492,35 +548,6 @@ describe("Ray", () => { .any.js ).toBe('B'); }); - test(".vertex.#.equivalent(.vertex.#)", () => { - let A = Ray.vertex().o({js: 'A'}) - .as_reference().o({js: 'A.#'}); - let B = Ray.vertex().o({js: 'B'}) - .as_reference().o({js: 'B.#'}); - - expect(A.any.js).toBe('A.#'); - expect(B.any.js).toBe('B.#'); - - let ref = A.equivalent(B); - - expect(ref.self.initial).toBe(A); - expect(ref.self.terminal).toBe(B); - expect(ref.self.initial.any.js).toBe('A.#'); - expect(ref.self.terminal.any.js).toBe('B.#'); - - expect(A.self.any.js).toBe('A'); - expect(B.self.any.js).toBe('B'); - - expect(A.self.self).toBe(B.self); - expect(B.self.self).toBe(A.self); - expect(A.self.self.any.js).toBe('B'); - expect(B.self.self.any.js).toBe('A'); - - expect(B.self.self.self).toBe(B.self); - expect(B.self.self.self.self).toBe(A.self); - expect(B.self.self.self.any.js).toBe('B'); - expect(B.self.self.self.self.any.js).toBe('A'); - }); test(".vertex.#.continues_with(.vertex.#)", () => { let A = Ray.vertex().o({ js: 'A' }).as_reference(); let B = Ray.vertex().o({ js: 'B'}).as_reference(); diff --git a/src/@orbitmines/explorer/Ray.ts b/src/@orbitmines/explorer/Ray.ts index 431c540..948944c 100644 --- a/src/@orbitmines/explorer/Ray.ts +++ b/src/@orbitmines/explorer/Ray.ts @@ -139,6 +139,8 @@ export class Ray // Other possibly names: AbstractDirectionality, ..., ?? /** * Tries for "global coherence" - since we probably can't actually do that, practically this just means self-reference, were no change is assumed... + * + * @see https://orbitmines.com/papers/on-orbits-equivalence-and-inconsistencies#:~:text=And%20there%20we%20have%20it%2C%20an%20infinity%2C%20loop%2C%20...%2C%20orbit%20if%20we%20ignore%20the%20difference. */ static is_orbit = (a: Ray, b: Ray) => a === b; // is, ..., appears equal. protected self_reference = () => this; @@ -152,6 +154,20 @@ export class Ray // Other possibly names: AbstractDirectionality, ..., ?? */ get dereference() { return this.self.self.as_reference(); } + /** + * Places the current structure inside a new non-ignorant vertex. + */ + as_vertex = (): Ray => { + const vertex = Ray.vertex(this.self.as_arbitrary()); + const current = this.self.self; + + this.self.self = vertex.as_arbitrary(); + + // TODO: Disregards anything on this.self.self?? - or not with current?? + + return vertex.as_reference();//.continues_with(current.as_reference()); + } + /** [ ] */ static None = () => new Ray({ }).o({ }); /** [--?--] */ static vertex = (value: Arbitrary = Ray.None) => { // /** [?????] -> [ ???] */ as_initial = () => new Ray({ vertex: () => this.initial, terminal: this.as_arbitrary(), js: () => 'initial ref' }); @@ -177,17 +193,6 @@ export class Ray // Other possibly names: AbstractDirectionality, ..., ?? as_arbitrary = (): Arbitrary => () => this; - as_vertex = (): Ray => { - const vertex = Ray.vertex(this.self.as_arbitrary()); - const current = this.self.self; - - this.self.self = vertex.as_arbitrary(); - - // TODO: Disregards anything on this.self.self?? - or not with current?? - - return vertex.as_reference();//.continues_with(current.as_reference()); - } - /** * * @@ -305,31 +310,45 @@ export class Ray // Other possibly names: AbstractDirectionality, ..., ?? // @alias('merge, 'continues_with', 'compose') /** - * Compose as "Equivalence at Continuations" + * Compose as "Equivalence at Continuations": (can usually be done in parallel - not generally) + * - `A.compose(B)` = `(A.TERMINAL).equivalent(B.INITIAL)` + * - `A.compose(B).compose(C)` = `(A.TERMINAL).equivalent(B.INITIAL) & (B.TERMINAL).equivalent(C.INITIAL)` * - * `A.compose(B).compose(C)` = `A.` + * Another interesting connection: + * - `A.compose(B).compose(C)` = `(A.equivalent(B).equivalent(C)).dereference.(MISSING ALL FUNC).compose` * - * @see https://orbitmines.com/papers/on-orbits-equivalence-and-inconsistencies#:~:text=Constructing%20Continuations%20%2D%20Continuations%20as%20Equivalence + * @see "Continuations as Equivalence": https://orbitmines.com/papers/on-orbits-equivalence-and-inconsistencies#:~:text=Constructing%20Continuations%20%2D%20Continuations%20as%20Equivalence */ - // static compose = Ray.___func(ref => ref.step({ - // [RayType.VERTEX]: () => { throw new NotImplementedError(); }, - // CONTINUATION: (self): Ray => { - // throw new NotImplementedError(); - // } - // })); - // compose = Ray.compose.as_method(this); - - // static equivalent2 = Ray.___func(ref => { - // let { initial, terminal} = ref.self; - // - // return Ray.vertex(initial).compose(terminal); - // }); - // equivalent2 = Ray.compose(this); + static compose = Ray.___func(ref => { + + }); + compose = Ray.compose.as_method(this); + + /** + * Equivalence as "Composing Vertices" + * - `A.equivalent(B)` = `A.as_vertex().compose(B.as_vertex())` + * - `A.equivalent(B).equivalent(C)` = `A.as_vertex().compose(B.as_vertex()).compose(C.as_vertex())` + * + * @see https://orbitmines.com/papers/on-orbits-equivalence-and-inconsistencies#:~:text=On%20Equivalences%20%26%20Inconsistencies + */ + static equivalent2 = Ray.___func(ref => { + let { initial, terminal} = ref.self; + initial.as_vertex().compose(terminal.as_vertex()); + return ref; + }); + equivalent2 = Ray.equivalent2.as_method(this); + + + /** + * Equivalence in this context, is best understood as the drawing of the line between two things. And ensures that the line can be found on the `.vertex/.self` of those two things. (Albeit in an arbitrary place on it). + */ static equivalent= Ray.___func(ref => { let { initial, terminal } = ref.self; + // TODO: Can just move the terminal which holds the oointer to the boundary + // TODO: IS THIS EVEN HOW THIS SHOULD WORK?? - Now just takes the pointer and assumes that as its own @@ -344,6 +363,18 @@ export class Ray // Other possibly names: AbstractDirectionality, ..., ?? * initial.self.self / terminal.self.self - The direction which defines what it's connected to (could be ignorant) */ + if (initial.self.is_none() && terminal.self.is_none()) { + /** + * Basically turns an Orbit which repeats on every step, to one which repeats every 2 steps. + * Or in textual terms something like: `(A.self = A) | (B.self = B)` to `(A.self = B) | (B.self = A)`. + */ + + initial.self.self = terminal.self.as_arbitrary(); + terminal.self.self = initial.self.as_arbitrary(); + + return ref; + } + if (initial.self.is_none() || terminal.self.is_none()) { /** * Basically when [].self === [].self.self - See "{Ray.is_orbit}". @@ -610,7 +641,28 @@ export class Ray // Other possibly names: AbstractDirectionality, ..., ?? get count(): Ray { throw new NotImplementedError() } // TODO; Could return the ignorant reference to both instances, or just the result., .. - copy = (): Ray => { throw new NotImplementedError() } + + /** + * TODO: Need more control over the (non-/)lazyness of copy. + */ + copy = (): Ray => { + throw new NotImplementedError(); + + // const copy = new Ray({ + // initial: this.self._initial().as_reference().none_or(ref => ref.copy()).as_arbitrary(), + // vertex: this.self._vertex().as_reference().none_or(ref => ref.copy()).as_arbitrary(), + // }).o({ ___dirty_copy_buffer: {} }); + // // copy._initial = () => copy.any.___dirty_copy_buffer._initial ??= this.self._initial().as_reference().copy(); + // // copy._vertex = () => copy.any.___dirty_copy_buffer._vertex ??= this.self._vertex().as_reference().copy(); + // // copy._terminal = () => copy.any.___dirty_copy_buffer._terminal ??= this.self._terminal().as_reference().copy(); + // + // + // // TODO: Doesn't copy .any + // + // return copy.as_reference(); + } + + none_or = (arbitrary: Implementation): Ray => this.is_none() ? Ray.None() : arbitrary(this); // @alias('converse', 'opposite', 'swap') get reverse(): Ray { @@ -658,6 +710,8 @@ export class Ray // Other possibly names: AbstractDirectionality, ..., ?? } /** * Just uses length/size for permutation. TODO: More complex permutation implementation should follow at some point. (@see https://orbitmines.com/papers/on-orbits-equivalence-and-inconsistencies#:~:text=One%20of%20them%20could%20even%20be%20putting%20both%20our%20points%20on%20our%20selection for an example) + * + * @see "Combinatorics as Equivalence": https://orbitmines.com/papers/on-orbits-equivalence-and-inconsistencies#:~:text=Constructing%20Combinatorics%20%2D%20Combinatorics%20as%20Equivalence */ static permutation = (permutation: number | undefined, of: number): Ray => Ray.at( // In the case of a bit: 2nd value for '1' (but could be the reverse, if our interpreter does this) @@ -744,6 +798,10 @@ export class Ray // Other possibly names: AbstractDirectionality, ..., ?? } } + *traverse2(step: Implementation = Ray.directions.next): Generator { + + } + /** * JavaScript, possible compilations - TODO: Could have enumeratd possibilities, but just ignore that for now. */ @@ -848,7 +906,7 @@ export class Ray // Other possibly names: AbstractDirectionality, ..., ?? static POSITION_OF_DOOM = [0, 100, 0] // TODO: Abstract away as compilation - get render_options(): Required { + render_options = (Interface: Ray): Required => { return ({ position: this.self.any.position @@ -860,14 +918,17 @@ export class Ray // Other possibly names: AbstractDirectionality, ..., ?? this.self.any.scale ?? (this.is_none() ? 1.5 : 1.5), color: - this.self.any.color - ?? (this.is_none() ? 'red' : { - [RayType.VERTEX]: 'orange', - [RayType.TERMINAL]: '#FF5555', - [RayType.INITIAL]: '#5555FF', - [RayType.REFERENCE]: '#555555', - }[this.type] - ) + (Ray.is_orbit(Interface.any.selection.self, this.self) && Interface.any.cursor.tick) ? '#AAAAAA' // TODO: Should do lines as well, line render should prefer based on level of description.. (flat line only vertices, then render for the vertex?) + : ( + this.self.any.color + ?? (this.is_none() ? 'red' : { + [RayType.VERTEX]: 'orange', + [RayType.TERMINAL]: '#FF5555', + [RayType.INITIAL]: '#5555FF', + [RayType.REFERENCE]: '#555555', + }[this.type] + ) + ) }); } @@ -1091,22 +1152,13 @@ export class Ray // Other possibly names: AbstractDirectionality, ..., ?? } -// force = (): any => self.match({ -// Some: (a) => a, -// None: () => { throw new Error('Expected Some(value) to be present but found None.') } -// }); -// + // default = (fn: () => any): any => self.match({ // Some: (a) => a, // None: () => fn() // }) // -// none_or = (or: (obj: any) => any): Option => { -// return self.match({ -// Some: (some: any) => Option.Some(or(some)), -// None: () => Ray.None -// }) -// } + /** * @@ -1173,6 +1225,7 @@ export namespace JS { export const Generator = (generator: Generator): Ray => JS.Iterable(generator); + // TODO Could have parallel threads in general. // export const AsyncGenerator = (generator: AsyncGenerator): Ray => { // // [ |--] // return JS.Iterable(generator); diff --git a/src/@orbitmines/explorer/debug/DebugCanvas.tsx b/src/@orbitmines/explorer/debug/DebugCanvas.tsx index 7ba374b..a6f4838 100644 --- a/src/@orbitmines/explorer/debug/DebugCanvas.tsx +++ b/src/@orbitmines/explorer/debug/DebugCanvas.tsx @@ -13,10 +13,10 @@ import _ from "lodash"; // TODO: It's, rende rboth draw equivalence, then ignore the difference from either perspective or take some middle thing. - Line from both ends, also vertex? (or take the pos, take the x from one/other, y from the other/..) // TODO: Could be a function on Ray (any func really) -export const Render = ({ ray }: { ray: Ray }) => { - const initial: Required = ray.self.initial.as_reference().render_options; - const vertex: Required = ray.render_options; - const terminal: Required = ray.self.terminal.as_reference().render_options; +export const Render = ({ ray, Interface }: { ray: Ray, Interface: Ray }) => { + const initial: Required = ray.self.initial.as_reference().render_options(Interface); + const vertex: Required = ray.render_options(Interface); + const terminal: Required = ray.self.terminal.as_reference().render_options(Interface); switch (ray.type) { case RayType.REFERENCE: @@ -131,7 +131,7 @@ export const DebugInterface = ({ scale = 1.5 }: InterfaceOptions) => { console.log(`rays.length at pos=[${Interface.any.selection.render_options.position}]: ${Interface.any.rays.filter((ray: Ray) => _.isEqual( Interface.any.selection.render_options.position, - ray.render_options.position + ray.render_options(Interface).position ) ).length} / ${Interface.any.rays.length}`) console.log('ref', Interface.any.selection) @@ -166,7 +166,7 @@ export const DebugInterface = ({ scale = 1.5 }: InterfaceOptions) => { {/*{Interface.any.rays.map((ray: Ray) => )}*/} - {Interface.any.rays.map((ray: Ray) => )} + {Interface.any.rays.map((ray: Ray) => )} } diff --git a/src/@orbitmines/external/chyp/ChypCanvas.tsx b/src/@orbitmines/external/chyp/ChypCanvas.tsx index 0d4401b..3a40a91 100644 --- a/src/@orbitmines/external/chyp/ChypCanvas.tsx +++ b/src/@orbitmines/external/chyp/ChypCanvas.tsx @@ -1,4 +1,4 @@ -import React, {useRef, useState} from "react"; +import React, {useEffect, useRef, useState} from "react"; import IEventListener from "../../js/react/IEventListener"; import {VisualizationCanvas} from "../../explorer/Visualization"; import { @@ -144,15 +144,15 @@ const ___index = (ray: Ray): number => { } } -export const Render2 = ({ ray, show = { initial: true, terminal: true } }: { ray: Ray, index: number, show?: { initial: boolean, terminal: boolean } }) => { +export const Render2 = ({ ray, Interface, show = { initial: true, terminal: true } }: { ray: Ray, Interface: Ray, index: number, show?: { initial: boolean, terminal: boolean } }) => { const index = ___index(ray); let added = [15 * index, 60 * index, 0]; - const initial: Required = ray.self.initial.as_reference().render_options; + const initial: Required = ray.self.initial.as_reference().render_options(Interface); initial.position = add_(initial.position, added); - const vertex: Required = ray.render_options; + const vertex: Required = ray.render_options(Interface); vertex.position = add_(vertex.position, added); - const terminal: Required = ray.self.terminal.as_reference().render_options; + const terminal: Required = ray.self.terminal.as_reference().render_options(Interface); terminal.position = add_(terminal.position, added); switch (ray.type) { @@ -268,14 +268,14 @@ export const DebugInterface2 = ({scale = 1.5}: InterfaceOptions) => { combo: ["d", "arrowright"], global: true, label: "", onKeyDown: () => { const { selection, rays } = Interface.any; - const current = Interface.any.selection.render_options; + const current = Interface.any.selection.render_options(Interface); const next = Ray.vertex().o2({ initial: { position: add_(current.position, [(space_between * 2) - space_between, 0, 0]), scale, color: 'orange' }, vertex: { index: Interface.any.selection.self.any.index + 1, position: add_(current.position, [(space_between * 2), 0, 0]), scale, color: 'orange' }, terminal: { position: add_(current.position, [(space_between * 2) + space_between, 0, 0 ]), scale, color: 'orange' } }).as_reference().o({ - ...selection.as_reference().render_options, + ...selection.as_reference().render_options(Interface), position: add(selection.any.position ?? [0, 0, 0], [space_between * 2, 0, 0]) }); @@ -294,10 +294,10 @@ export const DebugInterface2 = ({scale = 1.5}: InterfaceOptions) => { Interface.any.selection = Interface.any.selection.pop(); Interface.any.selection.o({ - position: Interface.any.selection.render_options.position + position: Interface.any.selection.render_options(Interface).position }); // TODO, Same with this. Interface.any.selection.self.terminal.o({ - position: add(Interface.any.selection.render_options.position, [space_between, 0, 0]), scale, color: 'orange' + position: add(Interface.any.selection.render_options(Interface).position, [space_between, 0, 0]), scale, color: 'orange' }); // TODO: The continues_with function doesn't persist the options, as they are ignored on the equivalency. Probably need some better way to deal with this kind of thing. Interface.any.rays = Interface.any.selection.self.___dirty_all([]).map((ray: Ray) => { @@ -346,10 +346,10 @@ export const DebugInterface2 = ({scale = 1.5}: InterfaceOptions) => { combo: "/", global: true, label: "", onKeyDown: () => { console.log('---------') console.log(`Debugging: ${Interface.any.selection.self.label} (type=${Interface.any.selection.type})`) - console.log(`rays.length at pos=[${Interface.any.selection.render_options.position}]: ${Interface.any.rays.filter((ray: Ray) => + console.log(`rays.length at pos=[${Interface.any.selection.render_options(Interface).position}]: ${Interface.any.rays.filter((ray: Ray) => _.isEqual( Interface.any.selection.render_options.position, - ray.render_options.position + ray.render_options(Interface).position ) ).length} / ${Interface.any.rays.length}`) console.log('ref', Interface.any.selection) @@ -389,13 +389,13 @@ export const DebugInterface2 = ({scale = 1.5}: InterfaceOptions) => { {/*{Interface.any.rays.map((ray: Ray) => )}*/} - {Interface.any.rays.map((ray: Ray) => )} + {Interface.any.rays.map((ray: Ray) => )} - {Interface.any.rays.map((ray: Ray, index: number) => )} + {Interface.any.rays.map((ray: Ray, index: number) => )} @@ -403,7 +403,7 @@ export const DebugInterface2 = ({scale = 1.5}: InterfaceOptions) => { - {Interface.any.rays.map((ray: Ray, index: number) => )} + {Interface.any.rays.map((ray: Ray, index: number) => )} @@ -444,6 +444,168 @@ export const DebugInterface2 = ({scale = 1.5}: InterfaceOptions) => { } +export const DebugInterface3 = ({scale = 1.5}: InterfaceOptions) => { + const ref = useRef(); + const hotkeyConfig = useHotkeys(); + + const { + gl: renderer, + camera, + scene, + raycaster + } = useThree(); + + const space_between = 20 * scale; + + const [Interface] = useState(Ray.vertex().o({ + selection: Ray.vertex().o2({ + initial: { position: [-space_between, 0, 0], scale, color: 'orange' }, + vertex: { index: 0, position: [0, 0, 0], scale, color: 'orange' }, + terminal: { position: [space_between, 0, 0 ], scale, color: 'orange' }, + }).as_reference().o({ + position: [0, 0, 0], + scale, + rotation: [0, 0, Math.PI / 6 ], + color: '#555555' + }), + rays: [] as Ray[], + stats: false, + cursor: { + tick: false + }, + controls: Ray.vertex().o({ + hotkeys: [ + { + combo: ["d", "arrowright"], global: true, label: "", onKeyDown: () => { + const { selection, rays } = Interface.any; + + const current = Interface.any.selection.render_options(Interface); + + const next = Ray.vertex().o2({ + initial: { position: add_(current.position, [(space_between * 2) - space_between, 0, 0]), scale, color: 'orange' }, + vertex: { index: Interface.any.selection.self.any.index + 1, position: add_(current.position, [(space_between * 2), 0, 0]), scale, color: 'orange' }, + terminal: { position: add_(current.position, [(space_between * 2) + space_between, 0, 0 ]), scale, color: 'orange' } + }).as_reference().o({ + ...selection.as_reference().render_options(Interface), + position: add(selection.any.position ?? [0, 0, 0], [space_between * 2, 0, 0]) + }); + + Interface.any.selection = selection.continues_with(next); + Interface.any.rays = Interface.any.selection.self.___dirty_all([]).map((ray: Ray) => { + ray.any.traversed = true; + return ray.as_reference(); + }); + + } + }, + { + combo: ["a", "arrowleft"], global: true, label: "", onKeyDown: () => { + if (Interface.any.rays.length === 0) + return; + + Interface.any.selection = Interface.any.selection.pop(); + Interface.any.selection.o({ + position: Interface.any.selection.render_options(Interface).position + }); // TODO, Same with this. + Interface.any.selection.self.terminal.o({ + position: add(Interface.any.selection.render_options(Interface).position, [space_between, 0, 0]), scale, color: 'orange' + }); // TODO: The continues_with function doesn't persist the options, as they are ignored on the equivalency. Probably need some better way to deal with this kind of thing. + + Interface.any.rays = Interface.any.selection.self.___dirty_all([]).map((ray: Ray) => { + ray.any.traversed = true; + return ray.as_reference(); + }); + + if (Interface.any.length === 0) { + Interface.any.selection.any.position = [0, 0, 0] + return; + } + } + }, + { + combo: ["w", "arrowup"], global: true, label: "", onKeyDown: () => { + const { selection, rays } = Interface.any; + + Interface.any.rays = rays.flatMap((ray: Ray) => [ + ray, + // Ray.js("A").as_reference().o({ + // // ...ray.o, + // position: add(ray.any.position ?? [0, 0, 0], [0, i * 2, 0]) + // }), + // Ray.js("A").as_reference().o({ + // // ...ray.o, + // position: ray.any.position, + // rotation: [0, 0, Math.PI / 2] + // }), + // Ray.js("A").as_reference().o({ + // // ...ray.o, + // position: add(ray.any.position ?? [0, 0, 0], [0, i * 2, 0]), + // rotation: [0, 0, Math.PI / 2] + // }) + ]); + + // Chyp_naieve_pass.any.selection = Chyp_naieve_pass; + + // selection.o({...selection.o, position: add(selection.any.position ?? [0, 0, 0], [0, i * 2, 0])}) + + // selection.continues_with( + + // ); + } + }, + { + combo: "/", global: true, label: "", onKeyDown: () => { + console.log('---------') + console.log(`Debugging: ${Interface.any.selection.self.label} (type=${Interface.any.selection.type})`) + console.log(`rays.length at pos=[${Interface.any.selection.render_options(Interface).position}]: ${Interface.any.rays.filter((ray: Ray) => + _.isEqual( + Interface.any.selection.render_options(Interface).position, + ray.render_options(Interface).position + ) + ).length} / ${Interface.any.rays.length}`) + console.log('ref', Interface.any.selection) + console.log('ref.self', Interface.any.selection.self) + + const debug: DebugResult = {}; + Interface.any.selection.self.debug(debug); + console.log('ref.debug', debug); + Interface.any.rays.forEach((ray: Ray) => ray.debug(debug)); + console.log('rays.debug', debug); + } + }, + { + combo: "f3", global: true, label: "Show stats Panel", onKeyDown: (e) => { + e.preventDefault(); + Interface.any.stats = !Interface.any.stats; + } + }, + ] as HotkeyConfig[] + }) + })); + + // useEffect(() => { + // TODO: Eventually goes over maximum size of react-debug callstack when updates each frame like this. + hotkeyConfig.set(...Interface.any.controls.any.hotkeys); + // }, [Interface.any.controls.any.hotkeys]); + + useEffect(() => { + + setInterval(() => { + Interface.any.cursor.tick = !Interface.any.cursor.tick; + + // TODO THIS NEEDS TO BE EASIER + }, 500); // TODO; On react reload interval is not destroyed + }, []); + + return <> + {Interface.any.stats ? : <>} + + + + {Interface.any.rays.map((ray: Ray) => )} + +} + // const Interface = () => { // // TODO: Direct call to rerender on change, now there's lag // @@ -501,7 +663,7 @@ const ChypCanvas = ( - + }