@naniteninja/trait-visual 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -1,162 +1,5 @@
1
- import * as i0 from '@angular/core';
2
- import { OnInit, AfterViewInit, OnDestroy, OnChanges, ElementRef, Renderer2, NgZone, SimpleChanges } from '@angular/core';
3
- import * as THREE from 'three';
4
- import { Vector3 } from 'three';
5
- import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
6
-
7
- interface IHumanAttributes {
8
- [key: string]: number;
9
- }
10
- interface INodeData {
11
- id: number;
12
- name: string;
13
- initialPosition: [number, number, number];
14
- isSun: boolean;
15
- color: string;
16
- attributes: IHumanAttributes;
17
- preferences: IHumanAttributes;
18
- }
19
- interface ISwapAnimation {
20
- start: Vector3;
21
- end: Vector3;
22
- startTime: number;
23
- duration: number;
24
- }
25
- interface IPlanetConfigs {
26
- attraction: number;
27
- repulsion: number;
28
- repulsionInitializationThreshold: number;
29
- }
30
- interface ISunConfigs {
31
- attraction: number;
32
- repulsion: number;
33
- repulsionInitializationThreshold: number;
34
- }
35
- interface ISimulationConfigs {
36
- sun: ISunConfigs;
37
- planet: IPlanetConfigs;
38
- maxVelocity: number;
39
- velocityDamping: number;
40
- minAttributeValue: number;
41
- minPreferenceValue: number;
42
- maxAttributeValue: number;
43
- maxPreferenceValue: number;
44
- }
45
-
46
- declare class Node extends THREE.Object3D {
47
- options: ISimulationConfigs;
48
- velocity: THREE.Vector3;
49
- isSun: boolean;
50
- attributes: number[];
51
- preferences: number[];
52
- preference: number;
53
- mesh: THREE.Mesh;
54
- swap: ISwapAnimation | null;
55
- static attributeWeights: number[];
56
- static preferenceWeights: number[];
57
- private static normalizeWeights;
58
- private sunBaseScale;
59
- private halo;
60
- private coreSprite;
61
- private haloSprite;
62
- private readonly baseSphereRadius;
63
- private clock;
64
- constructor(data: INodeData, options: ISimulationConfigs);
65
- updatePhysics(nodes: Node[], central: Node | null, deltaTime: number): void;
66
- setSun(state?: boolean, preference?: number): void;
67
- calculatePreferredCompatibility(sun: Node): number;
68
- calculateAttributeCompatibility(other: Node): number;
69
- update(nodes: Node[], cursorPosition?: THREE.Vector3, scene?: THREE.Scene, camera?: THREE.Camera): void;
70
- private createBillboardGlow;
71
- private calculateSunForce;
72
- private calculatePlanetAttraction;
73
- private calculatePlanetRepulsion;
74
- private applyForces;
75
- private handleSwapAnimation;
76
- }
77
-
78
- declare class Cluster extends THREE.Object3D {
79
- options: ISimulationConfigs;
80
- nodes: Node[];
81
- constructor(nodeData: INodeData[], options?: Partial<ISimulationConfigs>);
82
- setUp(nodeData: INodeData[]): void;
83
- update(cursorPosition?: THREE.Vector3, scene?: THREE.Scene, camera?: THREE.Camera): void;
84
- }
85
-
86
- declare class TraitVisualComponent implements OnInit, AfterViewInit, OnDestroy, OnChanges {
87
- private renderer2;
88
- private ngZone;
89
- canvasRef: ElementRef;
90
- nodeData: INodeData[];
91
- attributeWeights: number[];
92
- preferenceWeights: number[];
93
- attributeCount?: number;
94
- preferenceCount?: number;
95
- scene: THREE.Scene;
96
- camera: THREE.PerspectiveCamera;
97
- renderer: THREE.WebGLRenderer;
98
- controls: OrbitControls;
99
- raycaster: THREE.Raycaster;
100
- mouse: THREE.Vector2;
101
- cluster: Cluster;
102
- selectedNode: Node | null;
103
- draggingNode: Node | null;
104
- dragPlane: THREE.Plane;
105
- dragOffset: THREE.Vector3;
106
- newNodeCounter: number;
107
- isCameraLocked: boolean;
108
- private nodeAuras;
109
- private starFieldNear;
110
- private starFieldFar;
111
- private starTexture;
112
- private dustField;
113
- private readonly pointerPitchAxis;
114
- private readonly pointerYawAxis;
115
- private pointerPitchCurrent;
116
- private pointerPitchTarget;
117
- private pointerYawCurrent;
118
- private pointerYawTarget;
119
- private pointerYawAccumulated;
120
- private readonly pointerOffset;
121
- private readonly pointerPitchMax;
122
- private readonly pointerYawMax;
123
- private readonly pointerYawSpeed;
124
- private readonly pointerPitchDamping;
125
- private readonly pointerYawDamping;
126
- constructor(renderer2: Renderer2, ngZone: NgZone);
127
- ngOnInit(): void;
128
- ngOnChanges(changes: SimpleChanges): void;
129
- ngAfterViewInit(): void;
130
- ngOnDestroy(): void;
131
- currentCentral(): Node | null;
132
- nonSuns(): Node[];
133
- private syncNodeWeightGlobals;
134
- private initScene;
135
- private loadNodes;
136
- private onWindowResize;
137
- private onRightClick;
138
- private onMouseMove;
139
- private onDragStart;
140
- private onDragMove;
141
- private onDragEnd;
142
- private onCanvasLeave;
143
- private resetPointerPitch;
144
- private updateCameraOrbitFromPointer;
145
- private animate;
146
- private ensureNodeAuras;
147
- private createStarField;
148
- private getStarTexture;
149
- static ɵfac: i0.ɵɵFactoryDeclaration<TraitVisualComponent, never>;
150
- static ɵcmp: i0.ɵɵComponentDeclaration<TraitVisualComponent, "tv-trait-visual", never, { "nodeData": { "alias": "nodeData"; "required": false; }; "attributeWeights": { "alias": "attributeWeights"; "required": false; }; "preferenceWeights": { "alias": "preferenceWeights"; "required": false; }; "attributeCount": { "alias": "attributeCount"; "required": false; }; "preferenceCount": { "alias": "preferenceCount"; "required": false; }; }, {}, never, never, true, never>;
151
- }
152
-
153
- declare let dynamicCounts: {
154
- attributes: number;
155
- preferences: number;
156
- };
157
- declare function updateCounts(attrCount: number, prefCount: number): void;
158
- declare const nodeData: INodeData[];
159
- declare const attributeWeights: number[];
160
-
161
- export { TraitVisualComponent, attributeWeights, dynamicCounts, nodeData, updateCounts };
162
- export type { IHumanAttributes, INodeData, IPlanetConfigs, ISimulationConfigs, ISunConfigs, ISwapAnimation };
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ /// <amd-module name="@naniteninja/trait-visual" />
5
+ export * from './public-api';
@@ -0,0 +1,124 @@
1
+ import { Vector3 } from 'three';
2
+ /** userData attached to blackhole meshes (aura core radius, occluder mesh). */
3
+ export interface IBlackholeUserData {
4
+ id?: number;
5
+ _auraCoreRadius?: number;
6
+ _occluder?: unknown;
7
+ }
8
+ export interface IHumanAttributes {
9
+ [key: string]: number;
10
+ }
11
+ export interface INodeData {
12
+ id: number;
13
+ name: string;
14
+ initialPosition: [number, number, number];
15
+ isSupermassiveBlackhole: boolean;
16
+ /** Node sphere color: 6-digit hex (#RRGGBB) or 8-digit hex with alpha (#RRGGBBAA). Alpha 0 hides the sphere so particles show (like SMBH). */
17
+ color: string;
18
+ attributes: IHumanAttributes;
19
+ preferences: IHumanAttributes;
20
+ }
21
+ export interface ISwapAnimation {
22
+ start: Vector3;
23
+ end: Vector3;
24
+ startTime: number;
25
+ duration: number;
26
+ }
27
+ export interface IBlackholeConfigs {
28
+ attraction: number;
29
+ repulsion: number;
30
+ repulsionInitializationThreshold: number;
31
+ pairwiseRepulsionMain: number;
32
+ pairwiseRepulsionSecondary: number;
33
+ /** Multiplier for BH-BH repulsion (1 = normal; small changes give visible effect). Default 1. */
34
+ pairwiseRepulsionMultiplier?: number;
35
+ dissimilarityRepulsionExponent?: number;
36
+ }
37
+ export interface ISupermassiveBlackHoleConfigs {
38
+ attraction: number;
39
+ repulsion: number;
40
+ repulsionInitializationThreshold: number;
41
+ /** Min distance from central in SMBHW (supermassive black hole widths); high compat. Default 0.25. */
42
+ minDistanceWidths?: number;
43
+ /** Max distance from central in SMBHW; low compat; viewport radius 7 = diameter 14 SMBHW. Default 7. */
44
+ maxDistanceWidths?: number;
45
+ }
46
+ export interface ISimulationConfigs {
47
+ supermassiveBlackHole: ISupermassiveBlackHoleConfigs;
48
+ blackhole: IBlackholeConfigs;
49
+ maxVelocity: number;
50
+ velocityDamping: number;
51
+ minAttributeValue: number;
52
+ minPreferenceValue: number;
53
+ maxAttributeValue: number;
54
+ maxPreferenceValue: number;
55
+ /** Simulation speed multiplier (1 = real time). */
56
+ simulationSpeed?: number;
57
+ }
58
+ /** Preset entry for config sidenav (name + data to apply). */
59
+ export interface IPresetConfig {
60
+ name: string;
61
+ centralPreferences: number[];
62
+ nodeAttributes: number[][];
63
+ }
64
+ /** Optional appearance fields for host (e.g. test app background/galaxy colors). */
65
+ export interface IAppearanceConfig {
66
+ backgroundColor?: string;
67
+ primaryColor?: string;
68
+ secondaryColor?: string;
69
+ }
70
+ /** Full config state for the config sidenav: what it reads and what changes it emits. */
71
+ export interface ITraitVisualConfigState {
72
+ nodeData: INodeData[];
73
+ attributeWeights: number[];
74
+ preferenceWeights: number[];
75
+ simulation?: Partial<ISimulationConfigs>;
76
+ appearance?: IAppearanceConfig;
77
+ selectedPreset: string;
78
+ availablePresets: IPresetConfig[];
79
+ /** When true, right-click on a node shows the context menu. Default false. */
80
+ showContextMenu?: boolean;
81
+ /** Default zoom level: multiplier on initial camera distance (1 = normal, 1.25 = zoom out 25%). */
82
+ defaultZoomLevel?: number;
83
+ }
84
+ /** Discriminated union for config change events from the sidenav. */
85
+ export type ConfigChangePayload = {
86
+ type: 'weights';
87
+ attributeWeights?: number[];
88
+ preferenceWeights?: number[];
89
+ } | {
90
+ type: 'simulation';
91
+ simulation: Partial<ISimulationConfigs>;
92
+ } | {
93
+ type: 'nodeData';
94
+ nodeData: INodeData[];
95
+ } | {
96
+ type: 'preset';
97
+ selectedPreset: string;
98
+ } | {
99
+ type: 'appearance';
100
+ appearance: Partial<IAppearanceConfig>;
101
+ } | {
102
+ type: 'addNode';
103
+ } | {
104
+ type: 'removeNode';
105
+ nodeId: number;
106
+ } | {
107
+ type: 'setTraitCount';
108
+ count: number;
109
+ } | {
110
+ type: 'centralPreferenceChange';
111
+ index: number;
112
+ value: number;
113
+ } | {
114
+ type: 'nodeAttributeChange';
115
+ nodeId: number;
116
+ attrIndex: number;
117
+ value: number;
118
+ } | {
119
+ type: 'showContextMenu';
120
+ value: boolean;
121
+ } | {
122
+ type: 'defaultZoomLevel';
123
+ value: number;
124
+ };
@@ -0,0 +1,30 @@
1
+ import { EventEmitter } from '@angular/core';
2
+ import type { ITraitVisualConfigState, ConfigChangePayload, INodeData } from '../app.types';
3
+ import * as i0 from "@angular/core";
4
+ export declare class ConfigSidenavComponent {
5
+ config: ITraitVisualConfigState;
6
+ open: boolean;
7
+ configChange: EventEmitter<ConfigChangePayload>;
8
+ /** Active tab: 'docs' shows documentation, 'configs' shows configuration UI. */
9
+ activeTab: 'docs' | 'configs';
10
+ setActiveTab(tab: 'docs' | 'configs'): void;
11
+ get centralNode(): INodeData | null;
12
+ get nonSupermassiveBlackholeNodes(): INodeData[];
13
+ traitCount(): number;
14
+ centralPrefsArray(): number[];
15
+ nodeAttrsArray(node: INodeData): number[];
16
+ onPresetChange(value: string): void;
17
+ onWeightChange(index: number, value: number): void;
18
+ onPrefWeightChange(index: number, value: number): void;
19
+ onSimulationSpeedChange(value: number): void;
20
+ onBlackholeRepulsionChange(value: number): void;
21
+ onTraitCountChange(count: number): void;
22
+ onCentralPreferenceChange(index: number, value: number): void;
23
+ onNodeAttributeChange(nodeId: number, attrIndex: number, value: number): void;
24
+ onAddNode(): void;
25
+ onRemoveNode(nodeId: number): void;
26
+ onShowContextMenuChange(value: boolean): void;
27
+ onDefaultZoomLevelChange(value: number): void;
28
+ static ɵfac: i0.ɵɵFactoryDeclaration<ConfigSidenavComponent, never>;
29
+ static ɵcmp: i0.ɵɵComponentDeclaration<ConfigSidenavComponent, "tv-config-sidenav", never, { "config": { "alias": "config"; "required": false; }; "open": { "alias": "open"; "required": false; }; }, { "configChange": "configChange"; }, never, ["[config-appearance]", "[config-simulation-extra]"], true, never>;
30
+ }
@@ -0,0 +1,20 @@
1
+ import { INodeData } from '../app.types';
2
+ /** Minimal PCA model interface for 3D projection. */
3
+ export interface IPCAModel {
4
+ predict(data: number[][], opts: {
5
+ nComponents: number;
6
+ }): {
7
+ to2DArray(): number[][];
8
+ };
9
+ getLoadings(): {
10
+ to2DArray(): number[][];
11
+ };
12
+ }
13
+ export declare let dynamicCounts: {
14
+ attributes: number;
15
+ preferences: number;
16
+ };
17
+ export declare function updateCounts(attrCount: number, prefCount: number): void;
18
+ export declare function projectTo3D(vec: number[]): [number, number, number];
19
+ export declare const nodeData: INodeData[];
20
+ export declare const attributeWeights: number[];
@@ -0,0 +1,45 @@
1
+ import * as THREE from 'three';
2
+ import { ISimulationConfigs, INodeData, ISwapAnimation } from '../app.types';
3
+ export declare class Blackhole extends THREE.Object3D {
4
+ options: ISimulationConfigs;
5
+ velocity: THREE.Vector3;
6
+ isSupermassiveBlackhole: boolean;
7
+ attributes: number[];
8
+ preferences: number[];
9
+ preference: number;
10
+ mesh: THREE.Mesh;
11
+ swap: ISwapAnimation | null;
12
+ nodeMaterial: THREE.Material | null;
13
+ private fixedY;
14
+ static attributeWeights: number[];
15
+ static preferenceWeights: number[];
16
+ private static toNumberArray;
17
+ private static normalizeWeights;
18
+ private supermassiveBlackholeBaseScale;
19
+ private readonly baseSphereRadius;
20
+ private clock;
21
+ /** Used by Cluster for deltaTime. */
22
+ getClockDelta(): number;
23
+ makeCoreGlowMaterial: (color: THREE.Color, opacity?: number, power?: number, base?: number) => THREE.ShaderMaterial;
24
+ makeRimGlowMaterial: (color: THREE.Color, opacity?: number, c?: number, power?: number) => THREE.ShaderMaterial;
25
+ /** Reused force vectors per blackhole index (avoids N² allocations per frame). */
26
+ private _forces;
27
+ private readonly _scratchD;
28
+ private readonly _scratchDir;
29
+ private readonly _scratchF;
30
+ constructor(data: INodeData, options: ISimulationConfigs);
31
+ private enforceFixedY;
32
+ updatePhysics(blackholes: Blackhole[], central: Blackhole | null, deltaTime: number): void;
33
+ setSupermassiveBlackhole(state?: boolean, preference?: number): void;
34
+ /** Preferred compatibility via PCA: map preferences and attributes to 3D (each trait its own dimension, then PCA to 3D) and use distance. */
35
+ calculatePreferredCompatibility(supermassiveBlackhole: Blackhole): number;
36
+ private fallbackPreferredCompatibility;
37
+ calculateAttributeCompatibility(other: Blackhole): number;
38
+ update(blackholes: Blackhole[], cursorPosition?: THREE.Vector3, scene?: THREE.Scene, camera?: THREE.Camera): void;
39
+ private createBillboardGlow;
40
+ private calculateSupermassiveBlackHoleForce;
41
+ private calculateBlackholeAttraction;
42
+ private calculateBlackholeRepulsion;
43
+ private applyForces;
44
+ private handleSwapAnimation;
45
+ }
@@ -0,0 +1,11 @@
1
+ import * as THREE from 'three';
2
+ import { ISimulationConfigs, INodeData } from '../app.types';
3
+ import { Blackhole } from './Blackhole';
4
+ export declare class Cluster extends THREE.Object3D {
5
+ options: ISimulationConfigs;
6
+ blackholes: Blackhole[];
7
+ private _lastLogDist;
8
+ constructor(nodeData: INodeData[], options?: Partial<ISimulationConfigs>);
9
+ setUp(nodeData: INodeData[]): void;
10
+ update(cursorPosition?: THREE.Vector3, scene?: THREE.Scene, camera?: THREE.Camera): void;
11
+ }
@@ -0,0 +1,74 @@
1
+ import * as THREE from 'three';
2
+ import { IParticleFieldOptions } from '../types/particle-field.types';
3
+ export declare class BlackHoleParticleField {
4
+ private scene;
5
+ private particles;
6
+ private particleSystem;
7
+ private particleCount;
8
+ private coreRadius;
9
+ private readonly FIELD_RADIUS_FACTOR;
10
+ private readonly NEON_PURPLE;
11
+ private readonly PINK_RED;
12
+ private palette;
13
+ private useSurface;
14
+ private seedCounter;
15
+ private speedScale;
16
+ private readonly MIN_SPEED;
17
+ private readonly MAX_SPEED;
18
+ private get FRONT_MIN();
19
+ private readonly OMEGA_K;
20
+ private readonly OMEGA_MAX_RIM;
21
+ private readonly OMEGA_MAX_CAP;
22
+ private readonly OMEGA_SURFACE_K;
23
+ private readonly OMEGA_SURFACE_MAX;
24
+ private readonly OMEGA_SURFACE_BASE_MIN;
25
+ private readonly OMEGA_SURFACE_BASE_MAX;
26
+ private readonly SPEED_EPS;
27
+ private readonly SHIMMER_FRAC;
28
+ private debugBands;
29
+ private lastDebugLogMs;
30
+ private bandCounts;
31
+ private readonly MIN_LIFETIME;
32
+ private readonly MAX_LIFETIME;
33
+ private targetAnchor;
34
+ private anchor;
35
+ private readonly anchorLerp;
36
+ private lastRight;
37
+ private flowSpeedScale;
38
+ private prevTargetAnchor;
39
+ private readonly worldUp;
40
+ private particleSizeMax;
41
+ private particleSizeScale;
42
+ private surfaceRadiusMin;
43
+ private surfaceRadiusMax;
44
+ private rimMinShellFactor;
45
+ constructor(scene: THREE.Scene, opts?: IParticleFieldOptions);
46
+ /**
47
+ * Update particle field anchored at `anchorPosition`, advected by `flow`.
48
+ */
49
+ update(anchorPosition: THREE.Vector3, flow: THREE.Vector3, deltaTime: number, camera?: THREE.Camera): void;
50
+ /**
51
+ * Resize the field to a new `coreRadius` while preserving particle distribution.
52
+ * Scales all radius-like parameters so visuals stay consistent.
53
+ */
54
+ resizeCoreRadius(newRadius: number): void;
55
+ setDebugBands(enabled: boolean): void;
56
+ toggleDebugBands(): boolean;
57
+ setPalette(newPalette: 'supermassiveBlackhole' | 'blackhole'): void;
58
+ /** Set global particle size scale (affects shader uniform). */
59
+ setParticleSizeScale(value: number): void;
60
+ /** Set how far rim particles can go inside the node (0.7 = 30% inside, 1 = on surface). */
61
+ setRimMinShellFactor(value: number): void;
62
+ /** Set surface shell radius range (factors of coreRadius). */
63
+ setSurfaceRadiusMin(value: number): void;
64
+ setSurfaceRadiusMax(value: number): void;
65
+ dispose(): void;
66
+ private initializeParticleField;
67
+ private generateParticles;
68
+ /** Base size: mostly 0.8–1.8, ~12% chance of small 0.4–0.7, clamped by particleSizeMax. */
69
+ private nextParticleSize;
70
+ private createNewParticle;
71
+ private createParticleSystem;
72
+ private getLocalOrbitPos;
73
+ private getDebugColorForType;
74
+ }
@@ -0,0 +1,4 @@
1
+ import { Blackhole } from '../objects/Blackhole';
2
+ import { Cluster } from '../objects/Cluster';
3
+ export declare function addNode(cluster: Cluster, newNodeCounter: number): number;
4
+ export declare function removeNode(cluster: Cluster, selectedBlackhole: Blackhole | null, hiddenBlackholes: Blackhole[], contextMenuElement: HTMLElement): void;
@@ -0,0 +1,102 @@
1
+ import * as THREE from 'three';
2
+ import { DustMode, IDustOptions } from '../types/dust-field.types';
3
+ export type { DustMode, DustOptions, DustPaletteOptions, DustPaletteStop } from '../types/dust-field.types';
4
+ /**
5
+ * StellarDustField
6
+ *
7
+ * A true 3D, GPU‑animated particle disk that orbits a given center (the supermassive black hole).
8
+ * It uses two draw calls: a dense mid/far bed of tiny points and a sparse
9
+ * foreground bokeh cohort of large, soft discs. Motion is computed fully on
10
+ * the GPU (vertex shader) from per‑particle attributes; the CPU only updates
11
+ * a few uniforms per frame.
12
+ */
13
+ export declare class StellarDustField {
14
+ private scene;
15
+ private group;
16
+ private points;
17
+ private readonly MAX_ATTRACTORS;
18
+ private readonly MAX_PALETTE_STOPS;
19
+ private attractorWorldPos;
20
+ private attractorWorldRad;
21
+ private attractorLocalPos;
22
+ private attractorRadius;
23
+ private nearRadiusFactor;
24
+ private stickEpsRel;
25
+ private stickEpsMin;
26
+ private stickEpsMax;
27
+ private attractStrength;
28
+ private tangentialBias;
29
+ private debugDustTouch;
30
+ private lastDustLogMs;
31
+ private useAttract;
32
+ private debugLogPalette;
33
+ private debugLogBands;
34
+ private debugEdgeMix;
35
+ private debugDimLights;
36
+ private whitenScale;
37
+ private alphaScale;
38
+ private paletteStops;
39
+ private paletteHueBiasScale;
40
+ private paletteBackgroundLift;
41
+ private paletteCoreIntensity;
42
+ private paletteUniformColors;
43
+ private paletteUniformStops;
44
+ private paletteUniformIntensities;
45
+ private paletteUniformCount;
46
+ private diskFraction;
47
+ private diskBokehFraction;
48
+ private haloRadiusMultiplier;
49
+ private armCount;
50
+ private armPopulation;
51
+ private armSpread;
52
+ private armTwist;
53
+ private haloArmPopulation;
54
+ private haloArmSpread;
55
+ private haloArmTwist;
56
+ private dustMode;
57
+ private sphereJitter;
58
+ private static readonly DEFAULT_PALETTE;
59
+ private opts;
60
+ private time;
61
+ private viewportHeight;
62
+ constructor(scene: THREE.Scene, options?: IDustOptions);
63
+ setBrightnessScale(scale: number): void;
64
+ setWhitenScale(scale: number): void;
65
+ setBrightness(value01: number): void;
66
+ applyOptions(o: IDustOptions): void;
67
+ setMode(mode: DustMode): void;
68
+ setSphereParameters(params: {
69
+ jitter?: number;
70
+ }): void;
71
+ setDiskNormal(normal: THREE.Vector3): void;
72
+ setViewportHeight(h: number): void;
73
+ private buildPaletteFromLegacyColors;
74
+ private applyPalette;
75
+ private syncLegacyColorsFromPalette;
76
+ private updatePaletteUniformsOnMaterials;
77
+ private samplePaletteAt;
78
+ private colorToHexString;
79
+ logPaletteRamp(samples?: number): void;
80
+ private logDiskBandStats;
81
+ private refreshPaletteUniformData;
82
+ update(dt: number, center: THREE.Vector3): void;
83
+ dispose(): void;
84
+ /**
85
+ * Provide world-space node centers and radii; internally converted to
86
+ * dust-local coordinates and pushed to shader uniforms.
87
+ * @param usedCount If set, only the first usedCount entries of attractors are read (allows reusing a buffer).
88
+ */
89
+ setAttractorsWorld(attractors: {
90
+ position: THREE.Vector3;
91
+ radius: number;
92
+ }[], usedCount?: number): void;
93
+ setAttractEnabled(enabled: boolean): void;
94
+ private build;
95
+ private makeCohort;
96
+ private makeMaterial;
97
+ private valueNoise2D;
98
+ private samplePeriodicFbm;
99
+ private sampleAndLogContacts;
100
+ private hashFloat;
101
+ private syncAttractorUniforms;
102
+ }
@@ -0,0 +1,85 @@
1
+ import { ElementRef, EventEmitter, OnInit, AfterViewInit, OnDestroy, Renderer2, NgZone, OnChanges, SimpleChanges } from '@angular/core';
2
+ import * as THREE from 'three';
3
+ import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
4
+ import { INodeData, ISimulationConfigs } from './app.types';
5
+ import { Cluster } from './objects/Cluster';
6
+ import { Blackhole } from './objects/Blackhole';
7
+ import * as i0 from "@angular/core";
8
+ export declare class TraitVisualComponent implements OnInit, AfterViewInit, OnDestroy, OnChanges {
9
+ private renderer2;
10
+ private ngZone;
11
+ canvasRef: ElementRef;
12
+ nodeData: INodeData[];
13
+ attributeWeights: number[];
14
+ preferenceWeights: number[];
15
+ attributeCount?: number;
16
+ preferenceCount?: number;
17
+ simulationOptions?: Partial<ISimulationConfigs>;
18
+ /** When true, right-click on a node can show the context menu (when implemented). Default false. */
19
+ showContextMenu: boolean;
20
+ /** Default zoom level: multiplier on initial camera distance (1 = normal, > 1 = zoom out more). Default 1.25. */
21
+ defaultZoomLevel: number;
22
+ /** Emits when the user selects a blackhole (e.g. via right-click). Host app can use this for context menu or sidenav. */
23
+ blackholeSelected: EventEmitter<Blackhole | null>;
24
+ scene: THREE.Scene;
25
+ camera: THREE.PerspectiveCamera;
26
+ renderer: THREE.WebGLRenderer;
27
+ controls: OrbitControls;
28
+ raycaster: THREE.Raycaster;
29
+ mouse: THREE.Vector2;
30
+ cluster: Cluster;
31
+ selectedNode: Blackhole | null;
32
+ draggingNode: Blackhole | null;
33
+ dragPlane: THREE.Plane;
34
+ dragOffset: THREE.Vector3;
35
+ newNodeCounter: number;
36
+ isCameraLocked: boolean;
37
+ private nodeAuras;
38
+ private starFieldNear;
39
+ private starFieldFar;
40
+ private starTexture;
41
+ private dustField;
42
+ private readonly pointerPitchAxis;
43
+ private readonly pointerYawAxis;
44
+ private pointerPitchCurrent;
45
+ private pointerPitchTarget;
46
+ private pointerYawCurrent;
47
+ private pointerYawTarget;
48
+ private pointerYawAccumulated;
49
+ private readonly pointerOffset;
50
+ private readonly pointerPitchMax;
51
+ private readonly pointerYawMax;
52
+ private readonly pointerYawSpeed;
53
+ private readonly pointerPitchDamping;
54
+ private readonly pointerYawDamping;
55
+ /** Reused buffer for dust-field attractors (avoids per-frame allocations). */
56
+ private readonly _attractorsBuffer;
57
+ private readonly _centerFallback;
58
+ constructor(renderer2: Renderer2, ngZone: NgZone);
59
+ ngOnInit(): void;
60
+ ngOnChanges(changes: SimpleChanges): void;
61
+ /** Apply defaultZoomLevel to camera: same direction from target, scaled distance. */
62
+ private applyDefaultZoomLevel;
63
+ ngAfterViewInit(): void;
64
+ ngOnDestroy(): void;
65
+ currentSupermassiveBlackhole(): Blackhole | null;
66
+ nonSupermassiveBlackholes(): Blackhole[];
67
+ private syncNodeWeightGlobals;
68
+ private initScene;
69
+ private loadNodes;
70
+ private onWindowResize;
71
+ private onRightClick;
72
+ private onMouseMove;
73
+ private onDragStart;
74
+ private onDragMove;
75
+ private onDragEnd;
76
+ private onCanvasLeave;
77
+ private resetPointerPitch;
78
+ private updateCameraOrbitFromPointer;
79
+ private animate;
80
+ private ensureNodeAuras;
81
+ private createStarField;
82
+ private getStarTexture;
83
+ static ɵfac: i0.ɵɵFactoryDeclaration<TraitVisualComponent, never>;
84
+ static ɵcmp: i0.ɵɵComponentDeclaration<TraitVisualComponent, "tv-trait-visual", never, { "nodeData": { "alias": "nodeData"; "required": false; }; "attributeWeights": { "alias": "attributeWeights"; "required": false; }; "preferenceWeights": { "alias": "preferenceWeights"; "required": false; }; "attributeCount": { "alias": "attributeCount"; "required": false; }; "preferenceCount": { "alias": "preferenceCount"; "required": false; }; "simulationOptions": { "alias": "simulationOptions"; "required": false; }; "showContextMenu": { "alias": "showContextMenu"; "required": false; }; "defaultZoomLevel": { "alias": "defaultZoomLevel"; "required": false; }; }, { "blackholeSelected": "blackholeSelected"; }, never, never, true, never>;
85
+ }