import { LineSegments, ColorRepresentation, Vector3Like } from 'three/webgpu'; import { DIVEComponent } from '../../engine/component/Component.ts'; /** * Whatever a caller identifies one of its lines by. * * Opaque here: this component never inspects a key, it only compares them. A * caller drawing lines to scene objects passes the objects; one drawing an * arbitrary set passes numbers or symbols. */ export type DIVELineKey = unknown; /** * Draws a set of independent line segments. * * A pure drawing primitive: it knows about points, nothing else. It does not * watch the scene, does not care what the lines mean, and never decides when * they should change — a caller places lines and removes them. What keeps the * lines in sync with something else is that caller's job. * * All lines share **one** `LineSegments`, so the whole set costs a single draw * call no matter how many there are. Each line owns a fixed slot of two vertices * in a shared buffer, so adding, moving or hiding one rewrites only that slot and * uploads only that range. * * ### Lines are addressed by the caller's own identity for them * * There is no line handle to keep. `setLineFor(key, …)` places the line for a * key, adding it if there is none yet, so a caller never holds a second piece of * bookkeeping beside the thing the line belongs to — which is where handles and * their objects used to drift apart. It also means placing and moving are one * call, so the two cannot be confused. * * Coordinates are in the component's own space, which is its owner's space. * Passing world-space points would have them transformed a second time by the * owner's matrix. * * @module */ export declare class MultiLineComponent extends DIVEComponent { readonly isMultiLineComponent: true; private _lines; private _geometry; private _material; private _positions; private _distances; /** * Every line, by the key it was placed under. * * The single piece of bookkeeping: which keys exist, where each line is * drawn, which buffer slot it owns and whether it is visible. Those were four * separate containers keyed by a handle, which had to be kept in step with * each other and with whatever the caller kept on its own side. */ private _byKey; /** Slots freed by removed lines, reused before the buffer grows. */ private _freeSlots; private _capacity; /** One past the highest slot ever used, i.e. what has to be drawn. */ private _highWater; constructor(); /** The single object all lines are drawn by. */ get lines(): LineSegments; /** How many lines currently exist, hidden ones included. */ get lineCount(): number; /** * Places the line for a key, adding it if there is none yet. * * @param key - Whatever the caller identifies this line by. * @param start - Where the line begins. * @param end - Where the line ends. */ setLineFor(key: DIVELineKey, start: Vector3Like, end: Vector3Like): void; /** * Removes the line for a key and frees its slot for reuse. Does nothing if * there is no such line. * * @param key - Whatever the caller identifies this line by. */ removeLineFor(key: DIVELineKey): void; /** Whether a line is currently drawn for this key. */ hasLineFor(key: DIVELineKey): boolean; /** * Shows or hides a single line. * * A hidden line keeps its slot and is collapsed to zero length, so toggling * it back costs one range upload and never reshuffles the buffer. * * @param key - Whatever the caller identifies this line by. * @param visible - Whether it should be drawn. */ setLineVisibleFor(key: DIVELineKey, visible: boolean): void; /** * Shows or hides the whole set, including lines added later. * * @param visible - Whether the lines should be drawn. */ setVisible(visible: boolean): void; /** * @param color - The line colour. */ setColor(color: ColorRepresentation): void; /** * Sets the dash pattern. * * @param dashSize - Length of a drawn stretch. * @param gapSize - Length of a gap. */ setDashPattern(dashSize: number, gapSize: number): void; /** * Removes every line. * * Deliberately not called `clear`: that is `Object3D.clear()`, which removes * children, and overriding it with a different meaning would be a trap. */ clearLines(): void; /** * Takes on how the lines look, never which lines there are. * * A key is whatever the caller identifies a line by, usually one of its own * objects -- copying the set would leave the clone drawing lines to the * source's members. Placing lines is the caller's job here as everywhere. * * @param source - The component to copy from. */ copy(source: this): this; dispose(): void; private _createAttribute; /** Writes a line's endpoints into its slot, or collapses it when hidden. */ private _writeLine; private _collapseSlot; /** Uploads just this slot's range instead of the whole buffer. */ private _markSlotDirty; private _grow; }