@codefluss/threejs-shared 0.0.1-alpha.1
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/README.md +124 -0
- package/dist/context/instance-context.d.ts +39 -0
- package/dist/context/instance-context.d.ts.map +1 -0
- package/dist/core/ResourceManager.d.ts +85 -0
- package/dist/core/ResourceManager.d.ts.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +10 -0
- package/dist/index.mjs.map +1 -0
- package/dist/performance/PerformanceMonitor.d.ts +110 -0
- package/dist/performance/PerformanceMonitor.d.ts.map +1 -0
- package/dist/poi/POIManager.d.ts +29 -0
- package/dist/poi/POIManager.d.ts.map +1 -0
- package/dist/poi/POIMarker.d.ts +24 -0
- package/dist/poi/POIMarker.d.ts.map +1 -0
- package/dist/types/index.d.ts +55 -0
- package/dist/types/index.d.ts.map +1 -0
- package/package.json +60 -0
package/README.md
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# @codefluss/threejs-shared
|
|
2
|
+
|
|
3
|
+
Shared ThreeJS components and utilities for multi-instance canvas-based plugins.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ✅ **Instance Context** - Isolated store per plugin instance
|
|
8
|
+
- ✅ **Resource Manager** - Shared geometries/materials across instances
|
|
9
|
+
- ✅ **Performance Monitor** - Global FPS tracking with adaptive quality
|
|
10
|
+
- ✅ **POI System** - Points of Interest with 3D markers
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pnpm add @codefluss/threejs-shared
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
### Instance Context
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import { InstanceProvider, useInstanceState } from '@codefluss/threejs-shared';
|
|
24
|
+
import { createBackgroundStore } from './store';
|
|
25
|
+
|
|
26
|
+
function Background3D({ elementId, data }) {
|
|
27
|
+
return (
|
|
28
|
+
<InstanceProvider
|
|
29
|
+
instanceId={elementId}
|
|
30
|
+
createStore={createBackgroundStore}
|
|
31
|
+
>
|
|
32
|
+
<Scene data={data} />
|
|
33
|
+
</InstanceProvider>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function Scene({ data }) {
|
|
38
|
+
const isPlaying = useInstanceState(s => s.isPlaying);
|
|
39
|
+
// ...
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Resource Manager
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import { resourceManager } from '@codefluss/threejs-shared';
|
|
47
|
+
|
|
48
|
+
// Register instance
|
|
49
|
+
resourceManager.registerInstance('bg-1');
|
|
50
|
+
|
|
51
|
+
// Get shared geometry (created once, reused by all instances)
|
|
52
|
+
const starGeo = resourceManager.getSharedGeometry(
|
|
53
|
+
'star-sphere',
|
|
54
|
+
() => new THREE.SphereGeometry(0.05, 8, 8)
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
// Cleanup
|
|
58
|
+
resourceManager.unregisterInstance('bg-1');
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Performance Monitor
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import { globalPerfMonitor } from '@codefluss/threejs-shared';
|
|
65
|
+
import { useFrame } from '@react-three/fiber';
|
|
66
|
+
|
|
67
|
+
// Register canvas
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
globalPerfMonitor.registerCanvas(instanceId);
|
|
70
|
+
return () => globalPerfMonitor.unregisterCanvas(instanceId);
|
|
71
|
+
}, [instanceId]);
|
|
72
|
+
|
|
73
|
+
// Track FPS
|
|
74
|
+
useFrame((state, delta) => {
|
|
75
|
+
const fps = 1 / delta;
|
|
76
|
+
globalPerfMonitor.updateMetrics(instanceId, fps);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Listen for quality changes
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
const handler = (e: CustomEvent) => {
|
|
82
|
+
if (e.detail.instanceId === instanceId) {
|
|
83
|
+
setQuality(e.detail.quality);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
window.addEventListener('performance:quality-change', handler);
|
|
88
|
+
return () => window.removeEventListener('performance:quality-change', handler);
|
|
89
|
+
}, [instanceId]);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### POI System
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
import { createPOIManager, POIMarker } from '@codefluss/threejs-shared';
|
|
96
|
+
|
|
97
|
+
// Create POI store
|
|
98
|
+
const poiStore = createPOIManager('conf-1');
|
|
99
|
+
|
|
100
|
+
// Add POI
|
|
101
|
+
const id = poiStore.getState().addPOI({
|
|
102
|
+
position: [1, 0.5, 0],
|
|
103
|
+
label: 'Feature A',
|
|
104
|
+
description: 'Main product feature',
|
|
105
|
+
color: '#4CAF50'
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Render POI markers
|
|
109
|
+
function POIMarkers() {
|
|
110
|
+
const pois = poiStore(s => s.pois);
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<>
|
|
114
|
+
{pois.map(poi => (
|
|
115
|
+
<POIMarker key={poi.id} {...poi} />
|
|
116
|
+
))}
|
|
117
|
+
</>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## License
|
|
123
|
+
|
|
124
|
+
MIT
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { StoreApi } from 'zustand';
|
|
2
|
+
import { InstanceProviderProps } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Instance Provider - Creates isolated store per plugin instance
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```tsx
|
|
8
|
+
* <InstanceProvider
|
|
9
|
+
* instanceId={elementId}
|
|
10
|
+
* createStore={createBackgroundInstance}
|
|
11
|
+
* >
|
|
12
|
+
* <InteractiveBackground />
|
|
13
|
+
* </InstanceProvider>
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function InstanceProvider<T>({ instanceId, createStore, children }: InstanceProviderProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
/**
|
|
18
|
+
* Hook to access the instance store
|
|
19
|
+
*
|
|
20
|
+
* @throws Error if used outside InstanceProvider
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```tsx
|
|
24
|
+
* const instance = useInstance();
|
|
25
|
+
* const isPlaying = instance((state) => state.isPlaying);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function useInstance<T = any>(): StoreApi<T>;
|
|
29
|
+
/**
|
|
30
|
+
* Hook to select state from instance store
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* const isPlaying = useInstanceState(s => s.isPlaying);
|
|
35
|
+
* const camera = useInstanceState(s => s.camera);
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function useInstanceState<T, R>(selector: (state: T) => R): R;
|
|
39
|
+
//# sourceMappingURL=instance-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-context.d.ts","sourceRoot":"","sources":["../../src/context/instance-context.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAItD;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,EAClC,UAAU,EACV,WAAW,EACX,QAAQ,EACT,EAAE,qBAAqB,CAAC,CAAC,CAAC,2CAuB1B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,CAAC,GAAG,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAMlD;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,CAAC,EACnC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GACxB,CAAC,CAKH"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource Manager - Singleton for sharing geometries, materials, and textures
|
|
3
|
+
* across multiple ThreeJS instances
|
|
4
|
+
*
|
|
5
|
+
* Benefits:
|
|
6
|
+
* - Reduces memory usage by sharing resources
|
|
7
|
+
* - Automatic cleanup when last instance is removed
|
|
8
|
+
* - Debug tracking of active instances
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { resourceManager } from '@codefluss/threejs-shared';
|
|
13
|
+
*
|
|
14
|
+
* // Register instance
|
|
15
|
+
* resourceManager.registerInstance('bg-1');
|
|
16
|
+
*
|
|
17
|
+
* // Get shared geometry
|
|
18
|
+
* const starGeo = resourceManager.getSharedGeometry(
|
|
19
|
+
* 'star-sphere',
|
|
20
|
+
* () => new THREE.SphereGeometry(0.05, 8, 8)
|
|
21
|
+
* );
|
|
22
|
+
*
|
|
23
|
+
* // Cleanup
|
|
24
|
+
* resourceManager.unregisterInstance('bg-1');
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
declare class ResourceManager {
|
|
28
|
+
private static instance;
|
|
29
|
+
private geometries;
|
|
30
|
+
private materials;
|
|
31
|
+
private textures;
|
|
32
|
+
private activeInstances;
|
|
33
|
+
private constructor();
|
|
34
|
+
static getInstance(): ResourceManager;
|
|
35
|
+
/**
|
|
36
|
+
* Get or create shared geometry
|
|
37
|
+
* Multiple instances can use the same geometry
|
|
38
|
+
*/
|
|
39
|
+
getSharedGeometry(key: string, create: () => any): any;
|
|
40
|
+
/**
|
|
41
|
+
* Get or create shared material
|
|
42
|
+
* Multiple instances can use the same material
|
|
43
|
+
*/
|
|
44
|
+
getSharedMaterial(key: string, create: () => any): any;
|
|
45
|
+
/**
|
|
46
|
+
* Get or create shared texture
|
|
47
|
+
* Multiple instances can use the same texture
|
|
48
|
+
*/
|
|
49
|
+
getSharedTexture(key: string, create: () => any): any;
|
|
50
|
+
/**
|
|
51
|
+
* Register a new instance
|
|
52
|
+
* Tracks active instances for cleanup
|
|
53
|
+
*/
|
|
54
|
+
registerInstance(instanceId: string): void;
|
|
55
|
+
/**
|
|
56
|
+
* Unregister instance
|
|
57
|
+
* Triggers cleanup if last instance
|
|
58
|
+
*/
|
|
59
|
+
unregisterInstance(instanceId: string): void;
|
|
60
|
+
/**
|
|
61
|
+
* Get list of active instance IDs
|
|
62
|
+
*/
|
|
63
|
+
getActiveInstances(): string[];
|
|
64
|
+
/**
|
|
65
|
+
* Get resource statistics
|
|
66
|
+
*/
|
|
67
|
+
getStats(): {
|
|
68
|
+
geometries: number;
|
|
69
|
+
materials: number;
|
|
70
|
+
textures: number;
|
|
71
|
+
activeInstances: number;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Force cleanup all resources
|
|
75
|
+
* Called automatically when last instance is removed
|
|
76
|
+
*/
|
|
77
|
+
private cleanup;
|
|
78
|
+
/**
|
|
79
|
+
* Manual cleanup (for testing)
|
|
80
|
+
*/
|
|
81
|
+
forceCleanup(): void;
|
|
82
|
+
}
|
|
83
|
+
export declare const resourceManager: ResourceManager;
|
|
84
|
+
export {};
|
|
85
|
+
//# sourceMappingURL=ResourceManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResourceManager.d.ts","sourceRoot":"","sources":["../../src/core/ResourceManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,cAAM,eAAe;IACnB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAkB;IAEzC,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,eAAe,CAAqB;IAE5C,OAAO;IAIP,MAAM,CAAC,WAAW,IAAI,eAAe;IAOrC;;;OAGG;IACH,iBAAiB,CACf,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GAAG,GAChB,GAAG;IASN;;;OAGG;IACH,iBAAiB,CACf,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GAAG,GAChB,GAAG;IASN;;;OAGG;IACH,gBAAgB,CACd,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GAAG,GAChB,GAAG;IASN;;;OAGG;IACH,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAO1C;;;OAGG;IACH,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAY5C;;OAEG;IACH,kBAAkB,IAAI,MAAM,EAAE;IAI9B;;OAEG;IACH,QAAQ;;;;;;IASR;;;OAGG;IACH,OAAO,CAAC,OAAO;IA4Bf;;OAEG;IACH,YAAY,IAAI,IAAI;CAIrB;AAGD,eAAO,MAAM,eAAe,iBAAgC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @codefluss/threejs-shared
|
|
3
|
+
*
|
|
4
|
+
* Shared ThreeJS components and utilities for canvas-based plugins
|
|
5
|
+
*/
|
|
6
|
+
export { InstanceProvider, useInstance, useInstanceState } from './context/instance-context';
|
|
7
|
+
export { resourceManager } from './core/ResourceManager';
|
|
8
|
+
export { globalPerfMonitor } from './performance/PerformanceMonitor';
|
|
9
|
+
export { createPOIManager } from './poi/POIManager';
|
|
10
|
+
export { POIMarker } from './poi/POIMarker';
|
|
11
|
+
export type { QualityLevel, PerformanceMetrics, BaseThreeStore, POI, POIStore, SharedResource, PerformanceEvent, InstanceProviderProps } from './types';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAG7F,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAGrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,GAAG,EACH,QAAQ,EACR,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACtB,MAAM,SAAS,CAAC"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{createContext as s,useRef as n,useEffect as a,useContext as i,useState as r}from"react";import{createStore as o}from"zustand";import{Html as c}from"@react-three/drei";import{useSpring as l}from"@react-spring/three";const u=s(null);function g({instanceId:t,createStore:s,children:i}){const r=n(void 0);return r.current||(r.current=s(t)),a(()=>()=>{const e=r.current?.getState();"function"==typeof e?.dispose&&e.dispose()},[]),/* @__PURE__ */e(u.Provider,{value:r.current,children:i})}function h(){const e=i(u);if(!e)throw new Error("useInstance must be used within InstanceProvider");return e}function d(e){return h()(e)}class p{static instance;geometries=/* @__PURE__ */new Map;materials=/* @__PURE__ */new Map;textures=/* @__PURE__ */new Map;activeInstances=/* @__PURE__ */new Set;constructor(){}static getInstance(){return p.instance||(p.instance=new p),p.instance}getSharedGeometry(e,t){if(!this.geometries.has(e)){const s=t();this.geometries.set(e,s),console.log(`[ResourceManager] Created geometry: ${e}`)}return this.geometries.get(e)}getSharedMaterial(e,t){if(!this.materials.has(e)){const s=t();this.materials.set(e,s),console.log(`[ResourceManager] Created material: ${e}`)}return this.materials.get(e)}getSharedTexture(e,t){if(!this.textures.has(e)){const s=t();this.textures.set(e,s),console.log(`[ResourceManager] Created texture: ${e}`)}return this.textures.get(e)}registerInstance(e){this.activeInstances.add(e),console.log(`[ResourceManager] Registered instance: ${e} (${this.activeInstances.size} total)`)}unregisterInstance(e){this.activeInstances.delete(e),console.log(`[ResourceManager] Unregistered instance: ${e} (${this.activeInstances.size} remaining)`),0===this.activeInstances.size&&this.cleanup()}getActiveInstances(){return Array.from(this.activeInstances)}getStats(){return{geometries:this.geometries.size,materials:this.materials.size,textures:this.textures.size,activeInstances:this.activeInstances.size}}cleanup(){console.log("[ResourceManager] Cleaning up all resources"),this.geometries.forEach((e,t)=>{e.dispose(),console.log(`[ResourceManager] Disposed geometry: ${t}`)}),this.materials.forEach((e,t)=>{e.dispose(),console.log(`[ResourceManager] Disposed material: ${t}`)}),this.textures.forEach((e,t)=>{e.dispose(),console.log(`[ResourceManager] Disposed texture: ${t}`)}),this.geometries.clear(),this.materials.clear(),this.textures.clear(),console.log("[ResourceManager] Cleanup complete")}forceCleanup(){this.cleanup(),this.activeInstances.clear()}}const m=p.getInstance();class I{static instance;canvasInstances=/* @__PURE__ */new Map;globalFPS=60;updateInterval=null;CHECK_INTERVAL=1e3;LOW_FPS_THRESHOLD=30;HIGH_FPS_THRESHOLD=50;constructor(){}static getInstance(){return I.instance||(I.instance=new I),I.instance}registerCanvas(e){this.canvasInstances.set(e,{fps:60,quality:"high",particleCount:0}),console.log(`[PerformanceMonitor] Registered canvas: ${e} (${this.canvasInstances.size} total)`),1===this.canvasInstances.size&&this.startMonitoring()}unregisterCanvas(e){this.canvasInstances.delete(e),console.log(`[PerformanceMonitor] Unregistered canvas: ${e} (${this.canvasInstances.size} remaining)`),0===this.canvasInstances.size&&this.stopMonitoring()}updateMetrics(e,t){const s=this.canvasInstances.get(e);s&&(s.fps=t)}updateParticleCount(e,t){const s=this.canvasInstances.get(e);s&&(s.particleCount=t)}getGlobalMetrics(){return{globalFPS:this.globalFPS,instanceCount:this.canvasInstances.size,instances:Array.from(this.canvasInstances.entries()).map(([e,t])=>({id:e,...t}))}}startMonitoring(){console.log("[PerformanceMonitor] Starting monitoring"),this.updateInterval=setInterval(()=>{this.globalFPS=this.calculateAverageFPS(),this.globalFPS<this.LOW_FPS_THRESHOLD?this.adjustQualityAcrossAll("reduce"):this.globalFPS>this.HIGH_FPS_THRESHOLD&&this.canAnyIncrease()&&this.adjustQualityAcrossAll("increase")},this.CHECK_INTERVAL)}stopMonitoring(){console.log("[PerformanceMonitor] Stopping monitoring"),this.updateInterval&&(clearInterval(this.updateInterval),this.updateInterval=null)}calculateAverageFPS(){if(0===this.canvasInstances.size)return 60;const e=Array.from(this.canvasInstances.values()).map(e=>e.fps),t=e.reduce((e,t)=>e+t,0)/e.length;return Math.round(t)}canAnyIncrease(){return Array.from(this.canvasInstances.values()).some(e=>"high"!==e.quality)}adjustQualityAcrossAll(e){let t=0;this.canvasInstances.forEach((s,n)=>{let a=s.quality;"reduce"===e?"high"===s.quality?a="medium":"medium"===s.quality&&(a="low"):"low"===s.quality?a="medium":"medium"===s.quality&&(a="high"),a!==s.quality&&(s.quality=a,this.notifyInstance(n,a),t++)}),t>0&&console.log(`[PerformanceMonitor] Adjusted quality for ${t} instances (${e})`)}notifyInstance(e,t){"undefined"!=typeof window&&window.dispatchEvent(new CustomEvent("performance:quality-change",{detail:{instanceId:e,quality:t}}))}forceCleanup(){this.stopMonitoring(),this.canvasInstances.clear(),this.globalFPS=60}}const v=I.getInstance();function f(e){return o()((t,s)=>({instanceId:e,pois:[],activePOI:null,addPOI:s=>{const n=`poi-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,a={...s,id:n};return t(e=>({pois:[...e.pois,a]})),console.log(`[POIManager:${e}] Added POI: ${n}`),n},updatePOI:(s,n)=>{t(e=>({pois:e.pois.map(e=>e.id===s?{...e,...n}:e)})),console.log(`[POIManager:${e}] Updated POI: ${s}`)},removePOI:s=>{t(e=>({pois:e.pois.filter(e=>e.id!==s),activePOI:e.activePOI===s?null:e.activePOI})),console.log(`[POIManager:${e}] Removed POI: ${s}`)},setActivePOI:s=>{t({activePOI:s}),s&&console.log(`[POIManager:${e}] Set active POI: ${s}`)},getPOI:e=>s().pois.find(t=>t.id===e),clearAll:()=>{t({pois:[],activePOI:null}),console.log(`[POIManager:${e}] Cleared all POIs`)}}))}const P="mesh";function y({id:s,position:n,label:a,description:i,color:o="#4CAF50",onClick:u}){const[g,h]=r(!1),{scale:d}=l({scale:g?1.3:1,config:{tension:300,friction:20}});/* @__PURE__ */
|
|
2
|
+
return t("group",{position:n,children:[
|
|
3
|
+
/* @__PURE__ */t(P,{scale:d,onClick:()=>{u&&u(s)},onPointerOver:()=>h(!0),onPointerOut:()=>h(!1),children:[
|
|
4
|
+
/* @__PURE__ */e("sphereGeometry",{args:[.1,16,16]}),
|
|
5
|
+
/* @__PURE__ */e("meshStandardMaterial",{color:o,emissive:o,emissiveIntensity:g?.5:.2})]}),g&&/* @__PURE__ */t(P,{rotation:[Math.PI/2,0,0],children:[
|
|
6
|
+
/* @__PURE__ */e("ringGeometry",{args:[.12,.15,32]}),
|
|
7
|
+
/* @__PURE__ */e("meshBasicMaterial",{color:o,transparent:!0,opacity:.6})]}),
|
|
8
|
+
/* @__PURE__ */e(c,{position:[0,.3,0],center:!0,distanceFactor:10,style:{transition:"opacity 0.2s, transform 0.2s",opacity:g?1:.8,transform:g?"scale(1.05)":"scale(1)",pointerEvents:"none"},children:/* @__PURE__ */t("div",{style:{background:"rgba(0, 0, 0, 0.8)",color:"white",padding:"8px 12px",borderRadius:"4px",fontSize:"14px",whiteSpace:"nowrap",border:`2px solid ${o}`,boxShadow:"0 4px 12px rgba(0,0,0,0.3)"},children:[
|
|
9
|
+
/* @__PURE__ */e("div",{style:{fontWeight:"bold"},children:a}),g&&i&&/* @__PURE__ */e("div",{style:{fontSize:"12px",opacity:.8,marginTop:"4px",maxWidth:"200px",whiteSpace:"normal"},children:i})]})})]})}export{g as InstanceProvider,y as POIMarker,f as createPOIManager,v as globalPerfMonitor,m as resourceManager,h as useInstance,d as useInstanceState};
|
|
10
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/context/instance-context.tsx","../src/core/ResourceManager.ts","../src/performance/PerformanceMonitor.ts","../src/poi/POIManager.ts","../src/poi/POIMarker.tsx"],"sourcesContent":["\"use client\";\n\nimport { createContext, useContext, useRef, useEffect } from 'react';\nimport type { StoreApi } from 'zustand';\nimport type { InstanceProviderProps } from '../types';\n\nconst InstanceContext = createContext<StoreApi<any> | null>(null);\n\n/**\n * Instance Provider - Creates isolated store per plugin instance\n *\n * @example\n * ```tsx\n * <InstanceProvider\n * instanceId={elementId}\n * createStore={createBackgroundInstance}\n * >\n * <InteractiveBackground />\n * </InstanceProvider>\n * ```\n */\nexport function InstanceProvider<T>({\n instanceId,\n createStore,\n children\n}: InstanceProviderProps<T>) {\n const storeRef = useRef<StoreApi<T> | undefined>(undefined);\n\n // Create store only once\n if (!storeRef.current) {\n storeRef.current = createStore(instanceId);\n }\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n const state = storeRef.current?.getState() as any;\n if (typeof state?.dispose === 'function') {\n state.dispose();\n }\n };\n }, []);\n\n return (\n <InstanceContext.Provider value={storeRef.current}>\n {children}\n </InstanceContext.Provider>\n );\n}\n\n/**\n * Hook to access the instance store\n *\n * @throws Error if used outside InstanceProvider\n *\n * @example\n * ```tsx\n * const instance = useInstance();\n * const isPlaying = instance((state) => state.isPlaying);\n * ```\n */\nexport function useInstance<T = any>(): StoreApi<T> {\n const store = useContext(InstanceContext);\n if (!store) {\n throw new Error('useInstance must be used within InstanceProvider');\n }\n return store as StoreApi<T>;\n}\n\n/**\n * Hook to select state from instance store\n *\n * @example\n * ```tsx\n * const isPlaying = useInstanceState(s => s.isPlaying);\n * const camera = useInstanceState(s => s.camera);\n * ```\n */\nexport function useInstanceState<T, R>(\n selector: (state: T) => R\n): R {\n const store = useInstance<T>();\n\n // Use the store as a hook\n return (store as any)(selector);\n}\n","/**\n * Resource Manager - Singleton for sharing geometries, materials, and textures\n * across multiple ThreeJS instances\n *\n * Benefits:\n * - Reduces memory usage by sharing resources\n * - Automatic cleanup when last instance is removed\n * - Debug tracking of active instances\n *\n * @example\n * ```ts\n * import { resourceManager } from '@codefluss/threejs-shared';\n *\n * // Register instance\n * resourceManager.registerInstance('bg-1');\n *\n * // Get shared geometry\n * const starGeo = resourceManager.getSharedGeometry(\n * 'star-sphere',\n * () => new THREE.SphereGeometry(0.05, 8, 8)\n * );\n *\n * // Cleanup\n * resourceManager.unregisterInstance('bg-1');\n * ```\n */\nclass ResourceManager {\n private static instance: ResourceManager;\n\n private geometries = new Map<string, any>();\n private materials = new Map<string, any>();\n private textures = new Map<string, any>();\n private activeInstances = new Set<string>();\n\n private constructor() {\n // Singleton - private constructor\n }\n\n static getInstance(): ResourceManager {\n if (!ResourceManager.instance) {\n ResourceManager.instance = new ResourceManager();\n }\n return ResourceManager.instance;\n }\n\n /**\n * Get or create shared geometry\n * Multiple instances can use the same geometry\n */\n getSharedGeometry(\n key: string,\n create: () => any\n ): any {\n if (!this.geometries.has(key)) {\n const geometry = create();\n this.geometries.set(key, geometry);\n console.log(`[ResourceManager] Created geometry: ${key}`);\n }\n return this.geometries.get(key)!;\n }\n\n /**\n * Get or create shared material\n * Multiple instances can use the same material\n */\n getSharedMaterial(\n key: string,\n create: () => any\n ): any {\n if (!this.materials.has(key)) {\n const material = create();\n this.materials.set(key, material);\n console.log(`[ResourceManager] Created material: ${key}`);\n }\n return this.materials.get(key)!;\n }\n\n /**\n * Get or create shared texture\n * Multiple instances can use the same texture\n */\n getSharedTexture(\n key: string,\n create: () => any\n ): any {\n if (!this.textures.has(key)) {\n const texture = create();\n this.textures.set(key, texture);\n console.log(`[ResourceManager] Created texture: ${key}`);\n }\n return this.textures.get(key)!;\n }\n\n /**\n * Register a new instance\n * Tracks active instances for cleanup\n */\n registerInstance(instanceId: string): void {\n this.activeInstances.add(instanceId);\n console.log(\n `[ResourceManager] Registered instance: ${instanceId} (${this.activeInstances.size} total)`\n );\n }\n\n /**\n * Unregister instance\n * Triggers cleanup if last instance\n */\n unregisterInstance(instanceId: string): void {\n this.activeInstances.delete(instanceId);\n console.log(\n `[ResourceManager] Unregistered instance: ${instanceId} (${this.activeInstances.size} remaining)`\n );\n\n // Cleanup wenn keine Instanzen mehr\n if (this.activeInstances.size === 0) {\n this.cleanup();\n }\n }\n\n /**\n * Get list of active instance IDs\n */\n getActiveInstances(): string[] {\n return Array.from(this.activeInstances);\n }\n\n /**\n * Get resource statistics\n */\n getStats() {\n return {\n geometries: this.geometries.size,\n materials: this.materials.size,\n textures: this.textures.size,\n activeInstances: this.activeInstances.size\n };\n }\n\n /**\n * Force cleanup all resources\n * Called automatically when last instance is removed\n */\n private cleanup(): void {\n console.log('[ResourceManager] Cleaning up all resources');\n\n // Dispose geometries\n this.geometries.forEach((geo, key) => {\n geo.dispose();\n console.log(`[ResourceManager] Disposed geometry: ${key}`);\n });\n\n // Dispose materials\n this.materials.forEach((mat, key) => {\n mat.dispose();\n console.log(`[ResourceManager] Disposed material: ${key}`);\n });\n\n // Dispose textures\n this.textures.forEach((tex, key) => {\n tex.dispose();\n console.log(`[ResourceManager] Disposed texture: ${key}`);\n });\n\n this.geometries.clear();\n this.materials.clear();\n this.textures.clear();\n\n console.log('[ResourceManager] Cleanup complete');\n }\n\n /**\n * Manual cleanup (for testing)\n */\n forceCleanup(): void {\n this.cleanup();\n this.activeInstances.clear();\n }\n}\n\n// Export singleton instance\nexport const resourceManager = ResourceManager.getInstance();\n","import type { QualityLevel, PerformanceMetrics } from '../types';\n\n/**\n * Global Performance Monitor - Singleton for tracking FPS across all instances\n * and coordinating adaptive quality adjustments\n *\n * Features:\n * - Track FPS per instance\n * - Calculate global average FPS\n * - Automatic quality adjustment when performance drops\n * - Event-based quality change notifications\n *\n * @example\n * ```ts\n * import { globalPerfMonitor } from '@codefluss/threejs-shared';\n *\n * // Register canvas\n * globalPerfMonitor.registerCanvas('bg-1');\n *\n * // Update FPS in render loop\n * useFrame((state, delta) => {\n * const fps = 1 / delta;\n * globalPerfMonitor.updateMetrics('bg-1', fps);\n * });\n *\n * // Listen for quality changes\n * useEffect(() => {\n * const handler = (e: CustomEvent) => {\n * if (e.detail.instanceId === 'bg-1') {\n * setQuality(e.detail.quality);\n * }\n * };\n * window.addEventListener('performance:quality-change', handler);\n * return () => window.removeEventListener('performance:quality-change', handler);\n * }, []);\n * ```\n */\nclass GlobalPerformanceMonitor {\n private static instance: GlobalPerformanceMonitor;\n\n private canvasInstances = new Map<string, PerformanceMetrics>();\n private globalFPS = 60;\n private updateInterval: ReturnType<typeof setInterval> | null = null;\n private readonly CHECK_INTERVAL = 1000; // 1 second\n private readonly LOW_FPS_THRESHOLD = 30;\n private readonly HIGH_FPS_THRESHOLD = 50;\n\n private constructor() {\n // Singleton - private constructor\n }\n\n static getInstance(): GlobalPerformanceMonitor {\n if (!GlobalPerformanceMonitor.instance) {\n GlobalPerformanceMonitor.instance = new GlobalPerformanceMonitor();\n }\n return GlobalPerformanceMonitor.instance;\n }\n\n /**\n * Register a new canvas instance\n */\n registerCanvas(instanceId: string): void {\n this.canvasInstances.set(instanceId, {\n fps: 60,\n quality: 'high',\n particleCount: 0\n });\n\n console.log(\n `[PerformanceMonitor] Registered canvas: ${instanceId} (${this.canvasInstances.size} total)`\n );\n\n // Start monitoring if first instance\n if (this.canvasInstances.size === 1) {\n this.startMonitoring();\n }\n }\n\n /**\n * Unregister canvas instance\n */\n unregisterCanvas(instanceId: string): void {\n this.canvasInstances.delete(instanceId);\n\n console.log(\n `[PerformanceMonitor] Unregistered canvas: ${instanceId} (${this.canvasInstances.size} remaining)`\n );\n\n // Stop monitoring if no instances\n if (this.canvasInstances.size === 0) {\n this.stopMonitoring();\n }\n }\n\n /**\n * Update FPS for specific instance\n * Call this in your render loop (useFrame)\n */\n updateMetrics(instanceId: string, fps: number): void {\n const metrics = this.canvasInstances.get(instanceId);\n if (!metrics) return;\n\n metrics.fps = fps;\n }\n\n /**\n * Update particle count for specific instance\n */\n updateParticleCount(instanceId: string, count: number): void {\n const metrics = this.canvasInstances.get(instanceId);\n if (!metrics) return;\n\n metrics.particleCount = count;\n }\n\n /**\n * Get global performance metrics\n */\n getGlobalMetrics() {\n return {\n globalFPS: this.globalFPS,\n instanceCount: this.canvasInstances.size,\n instances: Array.from(this.canvasInstances.entries()).map(([id, metrics]) => ({\n id,\n ...metrics\n }))\n };\n }\n\n /**\n * Start monitoring performance\n */\n private startMonitoring(): void {\n console.log('[PerformanceMonitor] Starting monitoring');\n\n this.updateInterval = setInterval(() => {\n this.globalFPS = this.calculateAverageFPS();\n\n // Adaptive Quality basierend auf Global FPS\n if (this.globalFPS < this.LOW_FPS_THRESHOLD) {\n this.adjustQualityAcrossAll('reduce');\n } else if (this.globalFPS > this.HIGH_FPS_THRESHOLD && this.canAnyIncrease()) {\n this.adjustQualityAcrossAll('increase');\n }\n }, this.CHECK_INTERVAL);\n }\n\n /**\n * Stop monitoring\n */\n private stopMonitoring(): void {\n console.log('[PerformanceMonitor] Stopping monitoring');\n\n if (this.updateInterval) {\n clearInterval(this.updateInterval);\n this.updateInterval = null;\n }\n }\n\n /**\n * Calculate average FPS across all instances\n */\n private calculateAverageFPS(): number {\n if (this.canvasInstances.size === 0) return 60;\n\n const fpsList = Array.from(this.canvasInstances.values()).map(m => m.fps);\n const average = fpsList.reduce((a, b) => a + b, 0) / fpsList.length;\n\n return Math.round(average);\n }\n\n /**\n * Check if any instance can increase quality\n */\n private canAnyIncrease(): boolean {\n return Array.from(this.canvasInstances.values()).some(\n m => m.quality !== 'high'\n );\n }\n\n /**\n * Adjust quality across all instances\n */\n private adjustQualityAcrossAll(direction: 'reduce' | 'increase'): void {\n let changedCount = 0;\n\n this.canvasInstances.forEach((metrics, instanceId) => {\n let newQuality = metrics.quality;\n\n if (direction === 'reduce') {\n if (metrics.quality === 'high') {\n newQuality = 'medium';\n } else if (metrics.quality === 'medium') {\n newQuality = 'low';\n }\n } else {\n if (metrics.quality === 'low') {\n newQuality = 'medium';\n } else if (metrics.quality === 'medium') {\n newQuality = 'high';\n }\n }\n\n if (newQuality !== metrics.quality) {\n metrics.quality = newQuality;\n this.notifyInstance(instanceId, newQuality);\n changedCount++;\n }\n });\n\n if (changedCount > 0) {\n console.log(\n `[PerformanceMonitor] Adjusted quality for ${changedCount} instances (${direction})`\n );\n }\n }\n\n /**\n * Notify instance of quality change via CustomEvent\n */\n private notifyInstance(instanceId: string, quality: QualityLevel): void {\n if (typeof window === 'undefined') return;\n\n window.dispatchEvent(\n new CustomEvent('performance:quality-change', {\n detail: { instanceId, quality }\n })\n );\n }\n\n /**\n * Force cleanup (for testing)\n */\n forceCleanup(): void {\n this.stopMonitoring();\n this.canvasInstances.clear();\n this.globalFPS = 60;\n }\n}\n\n// Export singleton instance\nexport const globalPerfMonitor = GlobalPerformanceMonitor.getInstance();\n","import { createStore } from 'zustand';\nimport type { POI, POIStore } from '../types';\n\n/**\n * POI Manager Factory - Creates instance-based POI stores\n *\n * POI = Points of Interest (3D markers with labels)\n *\n * Features:\n * - Add/update/remove POI markers\n * - Track active POI\n * - Instance-based isolation\n *\n * @example\n * ```tsx\n * const poiStore = createPOIManager('conf-1');\n *\n * // Add POI\n * const id = poiStore.getState().addPOI({\n * position: [1, 0.5, 0],\n * label: 'Feature A',\n * description: 'Main product feature',\n * color: '#4CAF50'\n * });\n *\n * // Set active\n * poiStore.getState().setActivePOI(id);\n * ```\n */\nexport function createPOIManager(instanceId: string) {\n return createStore<POIStore>()((set, get) => ({\n instanceId,\n pois: [],\n activePOI: null,\n\n /**\n * Add new POI marker\n * @returns Generated POI ID\n */\n addPOI: (poi: Omit<POI, 'id'>) => {\n const id = `poi-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n const newPOI: POI = { ...poi, id };\n\n set(state => ({\n pois: [...state.pois, newPOI]\n }));\n\n console.log(`[POIManager:${instanceId}] Added POI: ${id}`);\n return id;\n },\n\n /**\n * Update existing POI\n */\n updatePOI: (id: string, updates: Partial<POI>) => {\n set(state => ({\n pois: state.pois.map(p =>\n p.id === id ? { ...p, ...updates } : p\n )\n }));\n\n console.log(`[POIManager:${instanceId}] Updated POI: ${id}`);\n },\n\n /**\n * Remove POI by ID\n */\n removePOI: (id: string) => {\n set(state => ({\n pois: state.pois.filter(p => p.id !== id),\n activePOI: state.activePOI === id ? null : state.activePOI\n }));\n\n console.log(`[POIManager:${instanceId}] Removed POI: ${id}`);\n },\n\n /**\n * Set active POI (highlighted)\n */\n setActivePOI: (id: string | null) => {\n set({ activePOI: id });\n\n if (id) {\n console.log(`[POIManager:${instanceId}] Set active POI: ${id}`);\n }\n },\n\n /**\n * Get POI by ID\n */\n getPOI: (id: string) => {\n return get().pois.find(p => p.id === id);\n },\n\n /**\n * Clear all POIs\n */\n clearAll: () => {\n set({ pois: [], activePOI: null });\n console.log(`[POIManager:${instanceId}] Cleared all POIs`);\n }\n }));\n}\n","\"use client\";\n\nimport { Html } from '@react-three/drei';\nimport { useSpring } from '@react-spring/three';\nimport { useState } from 'react';\nimport type { POI } from '../types';\n\nconst Group: any = 'group';\nconst Mesh: any = 'mesh';\nconst SphereGeometry: any = 'sphereGeometry';\nconst RingGeometry: any = 'ringGeometry';\nconst MeshStandardMaterial: any = 'meshStandardMaterial';\nconst MeshBasicMaterial: any = 'meshBasicMaterial';\n\n/**\n * POI Marker Component - 3D sphere with HTML label overlay\n *\n * Features:\n * - Animated hover effect\n * - Clickable interaction\n * - HTML label with description\n * - Custom color\n *\n * @example\n * ```tsx\n * <POIMarker\n * id=\"poi-1\"\n * position={[1, 0.5, 0]}\n * label=\"Feature A\"\n * description=\"Main product feature\"\n * color=\"#4CAF50\"\n * onClick={(id) => console.log('Clicked:', id)}\n * />\n * ```\n */\nexport function POIMarker({\n id,\n position,\n label,\n description,\n color = '#4CAF50',\n onClick\n}: POI) {\n const [hovered, setHovered] = useState(false);\n\n // Animated scale on hover\n const { scale } = useSpring({\n scale: hovered ? 1.3 : 1,\n config: { tension: 300, friction: 20 }\n });\n\n const handleClick = () => {\n if (onClick) {\n onClick(id);\n }\n };\n\n return (\n <Group position={position}>\n {/* 3D Marker Sphere */}\n <Mesh\n // @ts-ignore - animated scale is valid but types are incompatible\n scale={scale}\n onClick={handleClick}\n onPointerOver={() => setHovered(true)}\n onPointerOut={() => setHovered(false)}\n >\n <SphereGeometry args={[0.1, 16, 16]} />\n <MeshStandardMaterial\n color={color}\n emissive={color}\n emissiveIntensity={hovered ? 0.5 : 0.2}\n />\n </Mesh>\n\n {/* Pulsing ring effect */}\n {hovered && (\n <Mesh rotation={[Math.PI / 2, 0, 0]}>\n <RingGeometry args={[0.12, 0.15, 32]} />\n <MeshBasicMaterial color={color} transparent opacity={0.6} />\n </Mesh>\n )}\n\n {/* HTML Label Overlay */}\n <Html\n position={[0, 0.3, 0]}\n center\n distanceFactor={10}\n style={{\n transition: 'opacity 0.2s, transform 0.2s',\n opacity: hovered ? 1 : 0.8,\n transform: hovered ? 'scale(1.05)' : 'scale(1)',\n pointerEvents: 'none'\n }}\n >\n <div\n style={{\n background: 'rgba(0, 0, 0, 0.8)',\n color: 'white',\n padding: '8px 12px',\n borderRadius: '4px',\n fontSize: '14px',\n whiteSpace: 'nowrap',\n border: `2px solid ${color}`,\n boxShadow: '0 4px 12px rgba(0,0,0,0.3)'\n }}\n >\n <div style={{ fontWeight: 'bold' }}>{label}</div>\n {hovered && description && (\n <div\n style={{\n fontSize: '12px',\n opacity: 0.8,\n marginTop: '4px',\n maxWidth: '200px',\n whiteSpace: 'normal'\n }}\n >\n {description}\n </div>\n )}\n </div>\n </Html>\n </Group>\n );\n}\n"],"names":["InstanceContext","createContext","InstanceProvider","instanceId","createStore","children","storeRef","useRef","current","useEffect","state","getState","dispose","Provider","value","useInstance","store","useContext","Error","useInstanceState","selector","ResourceManager","static","geometries","Map","materials","textures","activeInstances","Set","constructor","getInstance","instance","getSharedGeometry","key","create","this","has","geometry","set","console","log","get","getSharedMaterial","material","getSharedTexture","texture","registerInstance","add","size","unregisterInstance","delete","cleanup","getActiveInstances","Array","from","getStats","forEach","geo","mat","tex","clear","forceCleanup","resourceManager","GlobalPerformanceMonitor","canvasInstances","globalFPS","updateInterval","CHECK_INTERVAL","LOW_FPS_THRESHOLD","HIGH_FPS_THRESHOLD","registerCanvas","fps","quality","particleCount","startMonitoring","unregisterCanvas","stopMonitoring","updateMetrics","metrics","updateParticleCount","count","getGlobalMetrics","instanceCount","instances","entries","map","id","setInterval","calculateAverageFPS","adjustQualityAcrossAll","canAnyIncrease","clearInterval","fpsList","values","m","average","reduce","a","b","length","Math","round","some","direction","changedCount","newQuality","notifyInstance","window","dispatchEvent","CustomEvent","detail","globalPerfMonitor","createPOIManager","pois","activePOI","addPOI","poi","Date","now","random","toString","substr","newPOI","updatePOI","updates","p","removePOI","filter","setActivePOI","getPOI","find","clearAll","Mesh","POIMarker","position","label","description","color","onClick","hovered","setHovered","useState","scale","useSpring","config","tension","friction","jsxs","onPointerOver","onPointerOut","jsx","args","emissive","emissiveIntensity","rotation","PI","transparent","opacity","Html","center","distanceFactor","style","transition","transform","pointerEvents","background","padding","borderRadius","fontSize","whiteSpace","border","boxShadow","fontWeight","marginTop","maxWidth"],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { QualityLevel } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Global Performance Monitor - Singleton for tracking FPS across all instances
|
|
4
|
+
* and coordinating adaptive quality adjustments
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - Track FPS per instance
|
|
8
|
+
* - Calculate global average FPS
|
|
9
|
+
* - Automatic quality adjustment when performance drops
|
|
10
|
+
* - Event-based quality change notifications
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { globalPerfMonitor } from '@codefluss/threejs-shared';
|
|
15
|
+
*
|
|
16
|
+
* // Register canvas
|
|
17
|
+
* globalPerfMonitor.registerCanvas('bg-1');
|
|
18
|
+
*
|
|
19
|
+
* // Update FPS in render loop
|
|
20
|
+
* useFrame((state, delta) => {
|
|
21
|
+
* const fps = 1 / delta;
|
|
22
|
+
* globalPerfMonitor.updateMetrics('bg-1', fps);
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* // Listen for quality changes
|
|
26
|
+
* useEffect(() => {
|
|
27
|
+
* const handler = (e: CustomEvent) => {
|
|
28
|
+
* if (e.detail.instanceId === 'bg-1') {
|
|
29
|
+
* setQuality(e.detail.quality);
|
|
30
|
+
* }
|
|
31
|
+
* };
|
|
32
|
+
* window.addEventListener('performance:quality-change', handler);
|
|
33
|
+
* return () => window.removeEventListener('performance:quality-change', handler);
|
|
34
|
+
* }, []);
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
declare class GlobalPerformanceMonitor {
|
|
38
|
+
private static instance;
|
|
39
|
+
private canvasInstances;
|
|
40
|
+
private globalFPS;
|
|
41
|
+
private updateInterval;
|
|
42
|
+
private readonly CHECK_INTERVAL;
|
|
43
|
+
private readonly LOW_FPS_THRESHOLD;
|
|
44
|
+
private readonly HIGH_FPS_THRESHOLD;
|
|
45
|
+
private constructor();
|
|
46
|
+
static getInstance(): GlobalPerformanceMonitor;
|
|
47
|
+
/**
|
|
48
|
+
* Register a new canvas instance
|
|
49
|
+
*/
|
|
50
|
+
registerCanvas(instanceId: string): void;
|
|
51
|
+
/**
|
|
52
|
+
* Unregister canvas instance
|
|
53
|
+
*/
|
|
54
|
+
unregisterCanvas(instanceId: string): void;
|
|
55
|
+
/**
|
|
56
|
+
* Update FPS for specific instance
|
|
57
|
+
* Call this in your render loop (useFrame)
|
|
58
|
+
*/
|
|
59
|
+
updateMetrics(instanceId: string, fps: number): void;
|
|
60
|
+
/**
|
|
61
|
+
* Update particle count for specific instance
|
|
62
|
+
*/
|
|
63
|
+
updateParticleCount(instanceId: string, count: number): void;
|
|
64
|
+
/**
|
|
65
|
+
* Get global performance metrics
|
|
66
|
+
*/
|
|
67
|
+
getGlobalMetrics(): {
|
|
68
|
+
globalFPS: number;
|
|
69
|
+
instanceCount: number;
|
|
70
|
+
instances: {
|
|
71
|
+
fps: number;
|
|
72
|
+
quality: QualityLevel;
|
|
73
|
+
particleCount: number;
|
|
74
|
+
drawCalls?: number;
|
|
75
|
+
triangles?: number;
|
|
76
|
+
id: string;
|
|
77
|
+
}[];
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Start monitoring performance
|
|
81
|
+
*/
|
|
82
|
+
private startMonitoring;
|
|
83
|
+
/**
|
|
84
|
+
* Stop monitoring
|
|
85
|
+
*/
|
|
86
|
+
private stopMonitoring;
|
|
87
|
+
/**
|
|
88
|
+
* Calculate average FPS across all instances
|
|
89
|
+
*/
|
|
90
|
+
private calculateAverageFPS;
|
|
91
|
+
/**
|
|
92
|
+
* Check if any instance can increase quality
|
|
93
|
+
*/
|
|
94
|
+
private canAnyIncrease;
|
|
95
|
+
/**
|
|
96
|
+
* Adjust quality across all instances
|
|
97
|
+
*/
|
|
98
|
+
private adjustQualityAcrossAll;
|
|
99
|
+
/**
|
|
100
|
+
* Notify instance of quality change via CustomEvent
|
|
101
|
+
*/
|
|
102
|
+
private notifyInstance;
|
|
103
|
+
/**
|
|
104
|
+
* Force cleanup (for testing)
|
|
105
|
+
*/
|
|
106
|
+
forceCleanup(): void;
|
|
107
|
+
}
|
|
108
|
+
export declare const globalPerfMonitor: GlobalPerformanceMonitor;
|
|
109
|
+
export {};
|
|
110
|
+
//# sourceMappingURL=PerformanceMonitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PerformanceMonitor.d.ts","sourceRoot":"","sources":["../../src/performance/PerformanceMonitor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAsB,MAAM,UAAU,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,cAAM,wBAAwB;IAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA2B;IAElD,OAAO,CAAC,eAAe,CAAyC;IAChE,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,cAAc,CAA+C;IACrE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAQ;IACvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAM;IACxC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAM;IAEzC,OAAO;IAIP,MAAM,CAAC,WAAW,IAAI,wBAAwB;IAO9C;;OAEG;IACH,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAiBxC;;OAEG;IACH,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAa1C;;;OAGG;IACH,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAOpD;;OAEG;IACH,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAO5D;;OAEG;IACH,gBAAgB;;;;;;;;;;;;IAWhB;;OAEG;IACH,OAAO,CAAC,eAAe;IAevB;;OAEG;IACH,OAAO,CAAC,cAAc;IAStB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAS3B;;OAEG;IACH,OAAO,CAAC,cAAc;IAMtB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAkC9B;;OAEG;IACH,OAAO,CAAC,cAAc;IAUtB;;OAEG;IACH,YAAY,IAAI,IAAI;CAKrB;AAGD,eAAO,MAAM,iBAAiB,0BAAyC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { POIStore } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* POI Manager Factory - Creates instance-based POI stores
|
|
4
|
+
*
|
|
5
|
+
* POI = Points of Interest (3D markers with labels)
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Add/update/remove POI markers
|
|
9
|
+
* - Track active POI
|
|
10
|
+
* - Instance-based isolation
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* const poiStore = createPOIManager('conf-1');
|
|
15
|
+
*
|
|
16
|
+
* // Add POI
|
|
17
|
+
* const id = poiStore.getState().addPOI({
|
|
18
|
+
* position: [1, 0.5, 0],
|
|
19
|
+
* label: 'Feature A',
|
|
20
|
+
* description: 'Main product feature',
|
|
21
|
+
* color: '#4CAF50'
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* // Set active
|
|
25
|
+
* poiStore.getState().setActivePOI(id);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function createPOIManager(instanceId: string): import('zustand').StoreApi<POIStore>;
|
|
29
|
+
//# sourceMappingURL=POIManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"POIManager.d.ts","sourceRoot":"","sources":["../../src/poi/POIManager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAO,QAAQ,EAAE,MAAM,UAAU,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,wCAyElD"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { POI } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* POI Marker Component - 3D sphere with HTML label overlay
|
|
4
|
+
*
|
|
5
|
+
* Features:
|
|
6
|
+
* - Animated hover effect
|
|
7
|
+
* - Clickable interaction
|
|
8
|
+
* - HTML label with description
|
|
9
|
+
* - Custom color
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* <POIMarker
|
|
14
|
+
* id="poi-1"
|
|
15
|
+
* position={[1, 0.5, 0]}
|
|
16
|
+
* label="Feature A"
|
|
17
|
+
* description="Main product feature"
|
|
18
|
+
* color="#4CAF50"
|
|
19
|
+
* onClick={(id) => console.log('Clicked:', id)}
|
|
20
|
+
* />
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function POIMarker({ id, position, label, description, color, onClick }: POI): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
//# sourceMappingURL=POIMarker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"POIMarker.d.ts","sourceRoot":"","sources":["../../src/poi/POIMarker.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AASpC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,SAAS,CAAC,EACxB,EAAE,EACF,QAAQ,EACR,KAAK,EACL,WAAW,EACX,KAAiB,EACjB,OAAO,EACR,EAAE,GAAG,2CAmFL"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { StoreApi } from 'zustand';
|
|
2
|
+
export type QualityLevel = 'high' | 'medium' | 'low';
|
|
3
|
+
export interface PerformanceMetrics {
|
|
4
|
+
fps: number;
|
|
5
|
+
quality: QualityLevel;
|
|
6
|
+
particleCount: number;
|
|
7
|
+
drawCalls?: number;
|
|
8
|
+
triangles?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface BaseThreeStore {
|
|
11
|
+
instanceId: string;
|
|
12
|
+
scene: any;
|
|
13
|
+
camera: any;
|
|
14
|
+
renderer: any;
|
|
15
|
+
isReady: boolean;
|
|
16
|
+
init: (canvasElement: HTMLCanvasElement) => void;
|
|
17
|
+
dispose: () => void;
|
|
18
|
+
}
|
|
19
|
+
export interface POI {
|
|
20
|
+
id: string;
|
|
21
|
+
position: [number, number, number];
|
|
22
|
+
label: string;
|
|
23
|
+
description?: string;
|
|
24
|
+
icon?: string;
|
|
25
|
+
color?: string;
|
|
26
|
+
metadata?: Record<string, unknown>;
|
|
27
|
+
onClick?: (id: string) => void;
|
|
28
|
+
}
|
|
29
|
+
export interface POIStore {
|
|
30
|
+
instanceId: string;
|
|
31
|
+
pois: POI[];
|
|
32
|
+
activePOI: string | null;
|
|
33
|
+
addPOI: (poi: Omit<POI, 'id'>) => string;
|
|
34
|
+
updatePOI: (id: string, updates: Partial<POI>) => void;
|
|
35
|
+
removePOI: (id: string) => void;
|
|
36
|
+
setActivePOI: (id: string | null) => void;
|
|
37
|
+
getPOI: (id: string) => POI | undefined;
|
|
38
|
+
clearAll: () => void;
|
|
39
|
+
}
|
|
40
|
+
export interface SharedResource {
|
|
41
|
+
key: string;
|
|
42
|
+
refCount: number;
|
|
43
|
+
resource: any;
|
|
44
|
+
}
|
|
45
|
+
export interface PerformanceEvent {
|
|
46
|
+
instanceId: string;
|
|
47
|
+
quality: QualityLevel;
|
|
48
|
+
fps?: number;
|
|
49
|
+
}
|
|
50
|
+
export interface InstanceProviderProps<T> {
|
|
51
|
+
instanceId: string;
|
|
52
|
+
createStore: (id: string) => StoreApi<T>;
|
|
53
|
+
children: React.ReactNode;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGxC,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAGrD,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,YAAY,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAGD,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,GAAG,CAAC;IACX,MAAM,EAAE,GAAG,CAAC;IACZ,QAAQ,EAAE,GAAG,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IAEjB,IAAI,EAAE,CAAC,aAAa,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACjD,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAGD,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAEzB,MAAM,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,MAAM,CAAC;IACzC,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IACvD,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC1C,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,GAAG,GAAG,SAAS,CAAC;IACxC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAGD,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,GAAG,CAAC;CACf;AAGD,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAGD,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC;IACzC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B"}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@codefluss/threejs-shared",
|
|
3
|
+
"version": "0.0.1-alpha.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Shared ThreeJS components and utilities for canvas-based plugins",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"codefluss",
|
|
8
|
+
"threejs",
|
|
9
|
+
"3d",
|
|
10
|
+
"canvas",
|
|
11
|
+
"shared"
|
|
12
|
+
],
|
|
13
|
+
"author": "Codefluss",
|
|
14
|
+
"main": "./dist/index.mjs",
|
|
15
|
+
"module": "./dist/index.mjs",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"import": "./dist/index.mjs"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist"
|
|
25
|
+
],
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@react-spring/three": "^10.0.3",
|
|
28
|
+
"@react-three/drei": "^10.7.7",
|
|
29
|
+
"@react-three/fiber": "^9.4.2",
|
|
30
|
+
"@react-three/rapier": "^2.2.0",
|
|
31
|
+
"react": "^19.2.3",
|
|
32
|
+
"react-dom": "^19.2.3",
|
|
33
|
+
"three": "^0.181.2",
|
|
34
|
+
"zustand": "^5.0.9"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/react": "19.2.4",
|
|
38
|
+
"@types/react-dom": "^19.2.3",
|
|
39
|
+
"@types/three": "^0.181.0",
|
|
40
|
+
"@vitejs/plugin-react": "^5.1.2",
|
|
41
|
+
"typescript": "^5.9.3",
|
|
42
|
+
"vite": "^7.2.7",
|
|
43
|
+
"vite-plugin-dts": "^4.5.4",
|
|
44
|
+
"@codefluss/vite-config-lib": "0.0.1-alpha.1"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"react": "^19.2.0",
|
|
48
|
+
"react-dom": "^19.2.0"
|
|
49
|
+
},
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"access": "public"
|
|
53
|
+
},
|
|
54
|
+
"scripts": {
|
|
55
|
+
"dev": "vite",
|
|
56
|
+
"build": "tsc && vite build",
|
|
57
|
+
"preview": "vite preview",
|
|
58
|
+
"type-check": "tsc --noEmit"
|
|
59
|
+
}
|
|
60
|
+
}
|