@3driseai/3drise-viewer 0.1.16 → 0.1.18

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.
Files changed (145) hide show
  1. package/README.md +4 -3
  2. package/dist/components/ChladniGrid.d.ts +15 -0
  3. package/dist/components/ChladniGrid.d.ts.map +1 -0
  4. package/dist/components/ChladniGrid.js +62 -0
  5. package/dist/components/CustomPrimitive.d.ts +2 -0
  6. package/dist/components/CustomPrimitive.d.ts.map +1 -1
  7. package/dist/components/CustomPrimitive.js +2 -2
  8. package/dist/components/EffectsGenerator.d.ts.map +1 -1
  9. package/dist/components/EffectsGenerator.js +26 -2
  10. package/dist/components/FlowNetGrid.d.ts +15 -0
  11. package/dist/components/FlowNetGrid.d.ts.map +1 -0
  12. package/dist/components/FlowNetGrid.js +61 -0
  13. package/dist/components/Galaxy.d.ts.map +1 -1
  14. package/dist/components/Galaxy.js +2 -0
  15. package/dist/components/GirihGrid.d.ts +15 -0
  16. package/dist/components/GirihGrid.d.ts.map +1 -0
  17. package/dist/components/GirihGrid.js +62 -0
  18. package/dist/components/GravWaveGrid.d.ts +15 -0
  19. package/dist/components/GravWaveGrid.d.ts.map +1 -0
  20. package/dist/components/GravWaveGrid.js +62 -0
  21. package/dist/components/GridsGenerator.d.ts +2 -2
  22. package/dist/components/GridsGenerator.d.ts.map +1 -1
  23. package/dist/components/GridsGenerator.js +21 -0
  24. package/dist/components/HyperbolicGrid.d.ts +15 -0
  25. package/dist/components/HyperbolicGrid.d.ts.map +1 -0
  26. package/dist/components/HyperbolicGrid.js +61 -0
  27. package/dist/components/LayoutInstances.d.ts +13 -0
  28. package/dist/components/LayoutInstances.d.ts.map +1 -0
  29. package/dist/components/LayoutInstances.js +39 -0
  30. package/dist/components/ModelPrimitive.d.ts +2 -0
  31. package/dist/components/ModelPrimitive.d.ts.map +1 -1
  32. package/dist/components/ModelPrimitive.js +3 -3
  33. package/dist/components/ObjectNode.d.ts.map +1 -1
  34. package/dist/components/ObjectNode.js +44 -9
  35. package/dist/components/ParticlesGenerator.d.ts +10 -0
  36. package/dist/components/ParticlesGenerator.d.ts.map +1 -0
  37. package/dist/components/ParticlesGenerator.js +23 -0
  38. package/dist/components/ReactionDiffusionGrid.d.ts +15 -0
  39. package/dist/components/ReactionDiffusionGrid.d.ts.map +1 -0
  40. package/dist/components/ReactionDiffusionGrid.js +376 -0
  41. package/dist/components/WallpaperGrid.d.ts +15 -0
  42. package/dist/components/WallpaperGrid.d.ts.map +1 -0
  43. package/dist/components/WallpaperGrid.js +555 -0
  44. package/dist/components/cursor/CursorController.d.ts.map +1 -1
  45. package/dist/components/effects/BlackHoleEffect.d.ts +3 -3
  46. package/dist/components/effects/BlackHoleEffect.d.ts.map +1 -1
  47. package/dist/components/effects/BlackHoleEffect.js +293 -163
  48. package/dist/components/effects/DandelionSeedsEffect.d.ts +13 -0
  49. package/dist/components/effects/DandelionSeedsEffect.d.ts.map +1 -0
  50. package/dist/components/effects/DandelionSeedsEffect.js +510 -0
  51. package/dist/components/effects/FallingLeavesEffect.d.ts +13 -0
  52. package/dist/components/effects/FallingLeavesEffect.d.ts.map +1 -0
  53. package/dist/components/effects/FallingLeavesEffect.js +446 -0
  54. package/dist/components/effects/FieldLinesEffect.d.ts +11 -0
  55. package/dist/components/effects/FieldLinesEffect.d.ts.map +1 -0
  56. package/dist/components/effects/FieldLinesEffect.js +260 -0
  57. package/dist/components/effects/FireflySwarmEffect.d.ts +13 -0
  58. package/dist/components/effects/FireflySwarmEffect.d.ts.map +1 -0
  59. package/dist/components/effects/FireflySwarmEffect.js +408 -0
  60. package/dist/components/effects/GalaxyEffect.d.ts +13 -0
  61. package/dist/components/effects/GalaxyEffect.d.ts.map +1 -0
  62. package/dist/components/effects/GalaxyEffect.js +374 -0
  63. package/dist/components/effects/HarmonicShellEffect.d.ts +11 -0
  64. package/dist/components/effects/HarmonicShellEffect.d.ts.map +1 -0
  65. package/dist/components/effects/HarmonicShellEffect.js +209 -0
  66. package/dist/components/effects/IceCrystalsEffect.d.ts +3 -3
  67. package/dist/components/effects/IceCrystalsEffect.d.ts.map +1 -1
  68. package/dist/components/effects/IceCrystalsEffect.js +286 -166
  69. package/dist/components/effects/IceHaloEffect.d.ts +13 -0
  70. package/dist/components/effects/IceHaloEffect.d.ts.map +1 -0
  71. package/dist/components/effects/IceHaloEffect.js +306 -0
  72. package/dist/components/effects/LichtenbergEffect.d.ts +13 -0
  73. package/dist/components/effects/LichtenbergEffect.d.ts.map +1 -0
  74. package/dist/components/effects/LichtenbergEffect.js +517 -0
  75. package/dist/components/effects/MoleculesEffect.d.ts +3 -3
  76. package/dist/components/effects/MoleculesEffect.d.ts.map +1 -1
  77. package/dist/components/effects/MoleculesEffect.js +322 -164
  78. package/dist/components/effects/MurmurationEffect.d.ts +13 -0
  79. package/dist/components/effects/MurmurationEffect.d.ts.map +1 -0
  80. package/dist/components/effects/MurmurationEffect.js +539 -0
  81. package/dist/components/effects/PlanetaryRingsEffect.d.ts +13 -0
  82. package/dist/components/effects/PlanetaryRingsEffect.d.ts.map +1 -0
  83. package/dist/components/effects/PlanetaryRingsEffect.js +458 -0
  84. package/dist/components/effects/PortalEffect.d.ts +3 -3
  85. package/dist/components/effects/PortalEffect.d.ts.map +1 -1
  86. package/dist/components/effects/PortalEffect.js +240 -163
  87. package/dist/components/effects/ShockwaveEffect.d.ts +5 -3
  88. package/dist/components/effects/ShockwaveEffect.d.ts.map +1 -1
  89. package/dist/components/effects/ShockwaveEffect.js +538 -142
  90. package/dist/components/effects/SmokePlumeEffect.d.ts +3 -3
  91. package/dist/components/effects/SmokePlumeEffect.d.ts.map +1 -1
  92. package/dist/components/effects/SmokePlumeEffect.js +180 -116
  93. package/dist/components/effects/SmokeRingEffect.d.ts +3 -3
  94. package/dist/components/effects/SmokeRingEffect.d.ts.map +1 -1
  95. package/dist/components/effects/SmokeRingEffect.js +260 -135
  96. package/dist/components/effects/StrangeAttractorEffect.d.ts +11 -0
  97. package/dist/components/effects/StrangeAttractorEffect.d.ts.map +1 -0
  98. package/dist/components/effects/StrangeAttractorEffect.js +229 -0
  99. package/dist/components/effects/VolumetricFogEffect.d.ts +5 -3
  100. package/dist/components/effects/VolumetricFogEffect.d.ts.map +1 -1
  101. package/dist/components/effects/VolumetricFogEffect.js +211 -93
  102. package/dist/components/effects/WaterCausticsEffect.d.ts +13 -0
  103. package/dist/components/effects/WaterCausticsEffect.d.ts.map +1 -0
  104. package/dist/components/effects/WaterCausticsEffect.js +308 -0
  105. package/dist/components/effects/index.d.ts +9 -0
  106. package/dist/components/effects/index.d.ts.map +1 -1
  107. package/dist/components/effects/index.js +9 -0
  108. package/dist/components/index.d.ts +19 -0
  109. package/dist/components/index.d.ts.map +1 -1
  110. package/dist/components/index.js +10 -0
  111. package/dist/components/particles/BioluminescentWakeParticles.d.ts +12 -0
  112. package/dist/components/particles/BioluminescentWakeParticles.d.ts.map +1 -0
  113. package/dist/components/particles/BioluminescentWakeParticles.js +1123 -0
  114. package/dist/components/particles/BrownianDustParticles.d.ts +12 -0
  115. package/dist/components/particles/BrownianDustParticles.d.ts.map +1 -0
  116. package/dist/components/particles/BrownianDustParticles.js +757 -0
  117. package/dist/components/particles/ElectronOrbitalsParticles.d.ts +12 -0
  118. package/dist/components/particles/ElectronOrbitalsParticles.d.ts.map +1 -0
  119. package/dist/components/particles/ElectronOrbitalsParticles.js +944 -0
  120. package/dist/components/particles/GrinderSparksParticles.d.ts +12 -0
  121. package/dist/components/particles/GrinderSparksParticles.d.ts.map +1 -0
  122. package/dist/components/particles/GrinderSparksParticles.js +744 -0
  123. package/dist/components/particles/TidalStreamParticles.d.ts +12 -0
  124. package/dist/components/particles/TidalStreamParticles.d.ts.map +1 -0
  125. package/dist/components/particles/TidalStreamParticles.js +788 -0
  126. package/dist/components/particles/index.d.ts +11 -0
  127. package/dist/components/particles/index.d.ts.map +1 -0
  128. package/dist/components/particles/index.js +6 -0
  129. package/dist/constants.d.ts +1 -1
  130. package/dist/constants.d.ts.map +1 -1
  131. package/dist/constants.js +1 -1
  132. package/dist/hooks/useModelObject.d.ts +6 -1
  133. package/dist/hooks/useModelObject.d.ts.map +1 -1
  134. package/dist/hooks/useModelObject.js +19 -6
  135. package/dist/types/gridConfigs.d.ts +98 -0
  136. package/dist/types/gridConfigs.d.ts.map +1 -1
  137. package/dist/types/index.d.ts +1 -1
  138. package/dist/types/index.d.ts.map +1 -1
  139. package/dist/utils/particleTrails.d.ts +70 -0
  140. package/dist/utils/particleTrails.d.ts.map +1 -0
  141. package/dist/utils/particleTrails.js +369 -0
  142. package/dist/utils/pointerField.d.ts +28 -0
  143. package/dist/utils/pointerField.d.ts.map +1 -0
  144. package/dist/utils/pointerField.js +103 -0
  145. package/package.json +2 -2
@@ -0,0 +1,61 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMemo, useRef } from 'react';
3
+ import * as THREE from 'three';
4
+ import { useObjectReady } from '../hooks/useObjectReady.js';
5
+ import { useGridSurface } from '../hooks/useGridSurface.js';
6
+ import { HyperbolicGridMaterial } from '@3driseai/3drise-core';
7
+ // Side-effect import registers <hyperbolicGridMaterial> via extend().
8
+ void HyperbolicGridMaterial;
9
+ /** HyperbolicGridConfig defaults. Must match the catalog entry in grid-defaults.json exactly. */
10
+ export const defaultHyperbolicGridConfig = {
11
+ cellSize: 22,
12
+ size: 50,
13
+ flat: true,
14
+ segments: undefined,
15
+ lineMode: 1,
16
+ cellMode: 2,
17
+ lineWidth: 1.4,
18
+ sectionSize: 3,
19
+ sectionWidth: 1,
20
+ animSpeed: 1,
21
+ animScale: 1.2,
22
+ animIntensity: 0.7,
23
+ fadeDistance: undefined,
24
+ fadeStrength: 0.2,
25
+ displace: 0,
26
+ sides: 7,
27
+ valence: 3,
28
+ drift: 0.5,
29
+ lineColor: '#c9a4ff',
30
+ sectionColor: '#ffd9f2',
31
+ cellColor: '#2a1446',
32
+ glowColor: '#b07cff',
33
+ bgColor: '#07030c',
34
+ bgOpacity: 0,
35
+ followMouse: false,
36
+ reveal: 1,
37
+ revealDuration: 0,
38
+ };
39
+ /**
40
+ * An Escher-style {p,q} tiling of the Poincare disk. A slow Mobius translation glides the tiling through itself, and the tiles shrink without end toward the rim.
41
+ */
42
+ export function HyperbolicGrid({ config = defaultHyperbolicGridConfig, groupProps, onObjectReady, onObjectDispose }) {
43
+ const matRef = useRef(null);
44
+ const rootRef = useRef(null);
45
+ const meshRef = useRef(null);
46
+ useObjectReady(rootRef, config, onObjectReady, onObjectDispose);
47
+ const { cellSize, size, segments, flat, lineMode, cellMode, lineWidth, sectionSize, sectionWidth, animSpeed, animScale, animIntensity, fadeDistance, fadeStrength, displace, sides, valence, drift, lineColor, sectionColor, cellColor, glowColor, bgColor, bgOpacity, followMouse, reveal, revealDuration, } = config;
48
+ // the ripple is fine-grained relative to the disk
49
+ const segs = segments ?? (displace > 0 ? Math.min(512, Math.max(96, Math.ceil(size / Math.max(cellSize, 1e-4)) * 64)) : 1);
50
+ const fade = fadeDistance ?? size * 0.5;
51
+ const colors = useMemo(() => ({
52
+ line: new THREE.Color(lineColor),
53
+ section: new THREE.Color(sectionColor),
54
+ cell: new THREE.Color(cellColor),
55
+ glow: new THREE.Color(glowColor),
56
+ bg: new THREE.Color(bgColor),
57
+ }), [lineColor, sectionColor, cellColor, glowColor, bgColor]);
58
+ useGridSurface(matRef, meshRef, { followMouse, reveal, revealDuration });
59
+ return (_jsx("group", { ref: rootRef, ...groupProps, children: _jsxs("mesh", { ref: meshRef, rotation: flat ? [-Math.PI / 2, 0, 0] : [0, 0, 0], children: [_jsx("planeGeometry", { args: [size, size, segs, segs] }), _jsx("hyperbolicGridMaterial", { ref: matRef, transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, side: THREE.DoubleSide, u_cellSize: cellSize, u_lineWidth: lineWidth, u_sectionSize: sectionSize, u_sectionWidth: sectionWidth, u_lineMode: lineMode, u_cellMode: cellMode, u_animSpeed: animSpeed, u_animScale: animScale, u_animIntensity: animIntensity, u_fadeDistance: fade, u_fadeStrength: fadeStrength, u_displace: displace, u_sides: sides, u_valence: valence, u_drift: drift, u_lineColor: colors.line, u_sectionColor: colors.section, u_cellColor: colors.cell, u_glowColor: colors.glow, u_bgColor: colors.bg, u_bgOpacity: bgOpacity }, HyperbolicGridMaterial.key)] }) }));
60
+ }
61
+ export default HyperbolicGrid;
@@ -0,0 +1,13 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { Object3D } from 'three';
3
+ import type { ThreeEvent } from '@react-three/fiber';
4
+ import type { CreatedObjectSettings, ObjectLayoutSettings } from '@3driseai/3drise-core';
5
+ export interface LayoutInstancesProps {
6
+ createdObject: CreatedObjectSettings;
7
+ layout: ObjectLayoutSettings;
8
+ render: (slot: number) => ReactNode;
9
+ handleObjectClick?: (createdObject: CreatedObjectSettings, ref: Object3D, event: ThreeEvent<MouseEvent>) => void;
10
+ }
11
+ declare const LayoutInstances: import("react").MemoExoticComponent<({ createdObject, layout, render, handleObjectClick }: LayoutInstancesProps) => import("react").JSX.Element>;
12
+ export default LayoutInstances;
13
+ //# sourceMappingURL=LayoutInstances.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LayoutInstances.d.ts","sourceRoot":"","sources":["../../src/components/LayoutInstances.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAS,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,qBAAqB,EAAc,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAErG,MAAM,WAAW,oBAAoB;IACjC,aAAa,EAAE,qBAAqB,CAAC;IACrC,MAAM,EAAE,oBAAoB,CAAC;IAC7B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS,CAAC;IACpC,iBAAiB,CAAC,EAAE,CAAC,aAAa,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;CACpH;AAmCD,QAAA,MAAM,eAAe,6FAA+D,oBAAoB,iCAmBtG,CAAC;AAGH,eAAe,eAAe,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // =============================================================================
3
+ // LayoutInstances — repeat one scene object across a gallery layout
4
+ // =============================================================================
5
+ //
6
+ // ObjectNode hands this the object's own renderer; each slot is a plain group at the
7
+ // transform LayoutCreator computed for it, and the renderer output goes inside.
8
+ //
9
+ // Rules (see the project doc claude/object-layout-plan.md):
10
+ // - Only slot 0 reports readiness. The render callback receives the slot index and
11
+ // ObjectNode passes no ready callbacks for the others, so one object still reports
12
+ // once and ObjectsRenderer's aggregate count stays right.
13
+ // - Slot groups never set userData.id, so findById(id) keeps returning the
14
+ // CreatedObject group that owns the transform.
15
+ // - Clicks are per slot: zoom / glow / vanish target the copy that was clicked, the
16
+ // same way gallery frames behave.
17
+ // - Motion stays on the CreatedObject group, so the whole layout animates as one.
18
+ import { memo, useMemo, useRef } from 'react';
19
+ import { generateLayoutSlots } from '@3driseai/3drise-core';
20
+ const LayoutSlotGroup = ({ slot, index, createdObject, handleObjectClick, children }) => {
21
+ const ref = useRef(null);
22
+ const onClick = handleObjectClick
23
+ ? (e) => {
24
+ if (!ref.current)
25
+ return;
26
+ e.stopPropagation();
27
+ handleObjectClick(createdObject, ref.current, e);
28
+ }
29
+ : undefined;
30
+ return (_jsx("group", { ref: ref, name: `layout-slot-${index}`, position: slot.position, rotation: slot.rotation ?? [0, 0, 0], scale: slot.scale ?? [1, 1, 1], userData: { layoutSlot: index }, onClick: onClick, children: children }));
31
+ };
32
+ const LayoutInstances = memo(({ createdObject, layout, render, handleObjectClick }) => {
33
+ // ObjectNode normalises the block on every render, so key on its contents.
34
+ const layoutKey = JSON.stringify(layout);
35
+ const slots = useMemo(() => generateLayoutSlots(layout.count, layout), [layoutKey]);
36
+ return (_jsx(_Fragment, { children: slots.map((slot, index) => (_jsx(LayoutSlotGroup, { slot: slot, index: index, createdObject: createdObject, handleObjectClick: handleObjectClick, children: render(index) }, index))) }));
37
+ });
38
+ LayoutInstances.displayName = 'LayoutInstances';
39
+ export default LayoutInstances;
@@ -4,6 +4,8 @@ import type { CreatedObjectSettings } from '@3driseai/3drise-core';
4
4
  import type { ObjectReadyProps } from '../types/objectReady';
5
5
  interface ModelPrimitiveProps extends ObjectReadyProps {
6
6
  createdObject: CreatedObjectSettings;
7
+ /** Layout slot. Slot 0 is the object itself; the rest are unregistered clones. */
8
+ slot?: number;
7
9
  children?: ReactNode;
8
10
  }
9
11
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ModelPrimitive.d.ts","sourceRoot":"","sources":["../../src/components/ModelPrimitive.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoC,MAAM,OAAO,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAGnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,UAAU,mBAAoB,SAAQ,gBAAgB;IAClD,aAAa,EAAE,qBAAqB,CAAC;IACrC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,QAAA,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA8BhD,CAAC;AAIH,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"ModelPrimitive.d.ts","sourceRoot":"","sources":["../../src/components/ModelPrimitive.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoC,MAAM,OAAO,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAGnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,UAAU,mBAAoB,SAAQ,gBAAgB;IAClD,aAAa,EAAE,qBAAqB,CAAC;IACrC,kFAAkF;IAClF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,SAAS,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,QAAA,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA8BhD,CAAC;AAIH,eAAe,cAAc,CAAC"}
@@ -29,9 +29,9 @@ import { useObjectReadyReporter } from '../hooks/useObjectReady.js';
29
29
  * master and every other instance of the same URL; letting R3F free them on unmount breaks
30
30
  * all of them.
31
31
  */
32
- const ModelPrimitive = memo(({ createdObject, onObjectReady, onObjectDispose, children }) => {
32
+ const ModelPrimitive = memo(({ createdObject, slot = 0, onObjectReady, onObjectDispose, children }) => {
33
33
  const attachedRef = useRef(null);
34
- const object = useModelObject(createdObject);
34
+ const object = useModelObject(createdObject, slot);
35
35
  const { report, reportDisposed } = useObjectReadyReporter(createdObject, onObjectReady, onObjectDispose);
36
36
  const setObjectRef = useCallback((instance) => {
37
37
  if (instance) {
@@ -46,7 +46,7 @@ const ModelPrimitive = memo(({ createdObject, onObjectReady, onObjectDispose, ch
46
46
  }, [report, reportDisposed]);
47
47
  if (!object)
48
48
  return null;
49
- return (_jsx("primitive", { ref: setObjectRef, name: createdObject.name, object: object, dispose: null, children: children }, createdObject.id));
49
+ return (_jsx("primitive", { ref: setObjectRef, name: createdObject.name, object: object, dispose: null, children: children }, `${createdObject.id}:${slot}`));
50
50
  });
51
51
  ModelPrimitive.displayName = 'ModelPrimitive';
52
52
  export default ModelPrimitive;
@@ -1 +1 @@
1
- {"version":3,"file":"ObjectNode.d.ts","sourceRoot":"","sources":["../../src/components/ObjectNode.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAe,qBAAqB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAChG,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,KAAK,eAAe,GAAG,gBAAgB,GAAG;IACtC,IAAI,EAAE,cAAc,CAAC;IACrB,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;CAC7G,CAAC;AAgBF,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAqHzC,CAAC;AACF,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"ObjectNode.d.ts","sourceRoot":"","sources":["../../src/components/ObjectNode.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAe,qBAAqB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAChG,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAiBrD,KAAK,eAAe,GAAG,gBAAgB,GAAG;IACtC,IAAI,EAAE,cAAc,CAAC;IACrB,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;CAC7G,CAAC;AAkBF,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAqIzC,CAAC;AACF,eAAe,UAAU,CAAC"}
@@ -7,6 +7,7 @@ import Text2D from './Text2D.js';
7
7
  import PathRenderer from './PathRenderer.js';
8
8
  import GalleryLayout from './GalleryLayout.js';
9
9
  import EffectsGenerator from './EffectsGenerator.js';
10
+ import ParticlesGenerator from './ParticlesGenerator.js';
10
11
  import ParticlesR3f from "./ParticlesR3f.js";
11
12
  import Lines from "./Lines.js";
12
13
  import LightObject from "./LightObject.js";
@@ -15,7 +16,23 @@ import Galaxy from "./Galaxy.js";
15
16
  import GridGenerator from "./GridsGenerator.js";
16
17
  import OceanBuilder from "./OceanBuilder.js";
17
18
  import LandscapeObject from "./LandscapeObject.js";
19
+ import LayoutInstances from "./LayoutInstances.js";
18
20
  import { SELF_MANAGED_MATERIAL } from "../constants.js";
21
+ import { LAYOUT_CAPABLE_TYPES, getObjectLayoutSupport, normalizeObjectLayout, isGenerativeParticlesConfig } from "@3driseai/3drise-core";
22
+ // Slots after the first render with no ready callbacks: one object reports once.
23
+ const NO_READY = {};
24
+ // A point light's shadow is six extra renders; only slot 0 keeps it. Cached per settings
25
+ // object so the copies do not re-run their shadow effect on every render.
26
+ const noShadowCache = new WeakMap();
27
+ const withoutShadow = (obj) => {
28
+ let copy = noShadowCache.get(obj);
29
+ if (!copy) {
30
+ const config = (obj.config ?? {});
31
+ copy = { ...obj, config: { ...config, shadow: { ...config.shadow, enabled: false } } };
32
+ noShadowCache.set(obj, copy);
33
+ }
34
+ return copy;
35
+ };
19
36
  // const EffectsLayer: React.FC<{ effects: CreatedObjectSettings['effects'] }> = ({ effects }) =>
20
37
  // effects?.length ? (
21
38
  // <>
@@ -26,7 +43,9 @@ import { SELF_MANAGED_MATERIAL } from "../constants.js";
26
43
  // ) : null;
27
44
  const GroupWithChildren = ({ createdObject, children, onObjectReady, onObjectDispose, handleObjectClick, renderObject }) => {
28
45
  const isGroup = createdObject.type === 'group';
29
- const selfManagedMaterial = SELF_MANAGED_MATERIAL.has(createdObject.type);
46
+ // Generative particle objects own their shaders, like effects do.
47
+ const selfManagedMaterial = SELF_MANAGED_MATERIAL.has(createdObject.type)
48
+ || (createdObject.type === 'particles' && isGenerativeParticlesConfig(createdObject.config));
30
49
  return (_jsxs(CreatedObject, { createdObject: createdObject, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose, handleObjectClick: handleObjectClick, shouldApply3driseMaterial: !isGroup && !selfManagedMaterial, children: [!isGroup && renderObject(createdObject, handleObjectClick), children.map(childNode => (_jsx(ObjectNode, { node: childNode, handleObjectClick: handleObjectClick, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }, childNode.objectId)))] }, createdObject.id));
31
50
  };
32
51
  const ObjectNode = ({ node, onObjectReady, onObjectDispose, handleObjectClick }) => {
@@ -40,7 +59,9 @@ const ObjectNode = ({ node, onObjectReady, onObjectDispose, handleObjectClick })
40
59
  // Specialized renderers for each object type
41
60
  const renderers = useMemo(() => ({
42
61
  group: () => null,
43
- mesh: (obj, onObjectReady) => (_jsx(CustomPrimitive, { createdObject: obj, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose, handleObjectClick: handleObjectClick }, obj.id)),
62
+ // mesh / model / effect / light take a layout slot as the third argument
63
+ // (see LayoutInstances); slot 0 is also the no-layout case.
64
+ mesh: (obj, _onObjectReady, slot = 0) => (_jsx(CustomPrimitive, { createdObject: obj, ...(slot === 0 ? { onObjectReady, onObjectDispose } : NO_READY), handleObjectClick: handleObjectClick }, obj.id)),
44
65
  // water: (obj: CreatedObjectSettings, cameraSettings: CameraState, onObjectReady?: (object: CreatedObjectSettings, ref: Object3D) => void) => (
45
66
  // <Ocean
46
67
  // settings={obj}
@@ -56,7 +77,7 @@ const ObjectNode = ({ node, onObjectReady, onObjectDispose, handleObjectClick })
56
77
  // settings={obj}
57
78
  // />
58
79
  // ),
59
- model: (obj, onObjectReady) => (_jsx(CustomPrimitive, { createdObject: obj, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose, handleObjectClick: handleObjectClick }, obj.id)),
80
+ model: (obj, _onObjectReady, slot = 0) => (_jsx(CustomPrimitive, { createdObject: obj, slot: slot, ...(slot === 0 ? { onObjectReady, onObjectDispose } : NO_READY), handleObjectClick: handleObjectClick }, obj.id)),
60
81
  // custom_primitive: (obj: CreatedObjectSettings, cameraSettings: CameraState, onObjectReady?: (object: CreatedObjectSettings, ref: Object3D) => void) => (
61
82
  // <CustomPrimitive
62
83
  // key={obj.id}
@@ -72,6 +93,10 @@ const ObjectNode = ({ node, onObjectReady, onObjectDispose, handleObjectClick })
72
93
  : _jsx(Text2D, { textSettings: obj, ...relabel(obj) }) }));
73
94
  },
74
95
  particles: (obj, onObjectReady) => {
96
+ // Generative particle objects (config.type) render through ParticlesGenerator;
97
+ // the legacy shape particles keep their own path.
98
+ if (isGenerativeParticlesConfig(obj.config))
99
+ return (_jsx(ParticlesGenerator, { settings: { config: obj.config }, ...relabel(obj) }, obj.id));
75
100
  const particlesSettings = obj;
76
101
  return (_jsxs(_Fragment, { children: [particlesSettings.config?.particles && (_jsx(ParticlesR3f, { particlesSettings: particlesSettings, duration: 1, transitionSettings: particlesSettings.meshSettings, ...relabel(obj) })), particlesSettings.config?.paths && (_jsx(Lines, { createdObject: particlesSettings, ...relabel(obj) }))] }));
77
102
  },
@@ -87,11 +112,11 @@ const ObjectNode = ({ node, onObjectReady, onObjectDispose, handleObjectClick })
87
112
  // LandscapeConnector instead; this one is a diorama, a floating island or
88
113
  // a game tile, and gets its transform from the CreatedObject wrapper.
89
114
  landscape: (obj, onObjectReady) => (_jsx(LandscapeObject, { settings: obj, ...relabel(obj) }, obj.id)),
90
- effect: (obj) => (_jsx(EffectsGenerator, { settings: {
115
+ effect: (obj, _onObjectReady, slot = 0) => (_jsx(EffectsGenerator, { settings: {
91
116
  config: obj.config,
92
- }, ...relabel(obj) }, obj.id)),
117
+ }, ...(slot === 0 ? relabel(obj) : NO_READY) }, obj.id)),
93
118
  gallery: (obj, onObjectReady) => (_jsx(GalleryLayout, { createdObject: obj, handleObjectClick: handleObjectClick, ...relabel(obj) })),
94
- light: (obj, onObjectReady) => (_jsx(LightObject, { createdObject: obj, ...relabel(obj) })),
119
+ light: (obj, _onObjectReady, slot = 0) => (_jsx(LightObject, { createdObject: slot === 0 ? obj : withoutShadow(obj), ...(slot === 0 ? relabel(obj) : NO_READY) })),
95
120
  environment: (obj, onObjectReady) => (_jsx(EnvironmentObject, { createdObject: obj, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose })),
96
121
  space: (obj, onObjectReady) => (_jsx(Galaxy, { createdObject: obj, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose })),
97
122
  // rain: (obj: CreatedObjectSettings, cameraSettings: CameraState, onObjectReady?: (object: CreatedObjectSettings, ref: Object3D) => void) => (
@@ -115,10 +140,20 @@ const ObjectNode = ({ node, onObjectReady, onObjectDispose, handleObjectClick })
115
140
  // />
116
141
  // ),
117
142
  }), [handleObjectClick, onObjectReady, onObjectDispose, relabel]);
118
- const renderObject = useCallback((obj, handleObjectClick) => {
143
+ const renderObject = useCallback((obj, _handleObjectClick) => {
119
144
  const renderer = renderers[obj.type];
120
- return renderer?.(obj, onObjectReady) ?? null;
121
- }, [onObjectReady, renderers]);
145
+ if (!renderer)
146
+ return null;
147
+ // meshSettings.layout: repeat the renderer output across a gallery layout.
148
+ // Absent on every object saved before layouts existed, which renders as before.
149
+ const layout = LAYOUT_CAPABLE_TYPES.has(obj.type) ? normalizeObjectLayout(obj.meshSettings?.layout) : null;
150
+ const support = layout?.enabled ? getObjectLayoutSupport(obj) : null;
151
+ if (layout && support?.allowed) {
152
+ const capped = layout.count > support.maxCount ? { ...layout, count: support.maxCount } : layout;
153
+ return (_jsx(LayoutInstances, { createdObject: obj, layout: capped, handleObjectClick: handleObjectClick, render: (slot) => renderer(obj, onObjectReady, slot) }));
154
+ }
155
+ return renderer(obj, onObjectReady) ?? null;
156
+ }, [onObjectReady, renderers, handleObjectClick]);
122
157
  if (!createdObject) {
123
158
  return null;
124
159
  }
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import type { GenerativeParticlesSettings } from '@3driseai/3drise-core';
3
+ import type { ObjectReadyProps } from '../types/objectReady';
4
+ export interface ParticlesGeneratorProps extends ObjectReadyProps {
5
+ settings: GenerativeParticlesSettings;
6
+ }
7
+ /** Standalone generative particle objects (type 'particles'), switched on config.type. */
8
+ declare const ParticlesGenerator: React.FC<ParticlesGeneratorProps>;
9
+ export default ParticlesGenerator;
10
+ //# sourceMappingURL=ParticlesGenerator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ParticlesGenerator.d.ts","sourceRoot":"","sources":["../../src/components/ParticlesGenerator.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAO7D,MAAM,WAAW,uBAAwB,SAAQ,gBAAgB;IAC7D,QAAQ,EAAE,2BAA2B,CAAC;CACzC;AAED,0FAA0F;AAC1F,QAAA,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAazD,CAAC;AACF,eAAe,kBAAkB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import TidalStreamParticles from './particles/TidalStreamParticles.js';
3
+ import BrownianDustParticles from './particles/BrownianDustParticles.js';
4
+ import BioluminescentWakeParticles from './particles/BioluminescentWakeParticles.js';
5
+ import ElectronOrbitalsParticles from './particles/ElectronOrbitalsParticles.js';
6
+ import GrinderSparksParticles from './particles/GrinderSparksParticles.js';
7
+ /** Standalone generative particle objects (type 'particles'), switched on config.type. */
8
+ const ParticlesGenerator = ({ settings, onObjectReady, onObjectDispose }) => {
9
+ const { config, animations } = settings;
10
+ if (!config?.enabled)
11
+ return null;
12
+ const size = config.size ?? 1;
13
+ const ready = { onObjectReady, onObjectDispose };
14
+ switch (config.type) {
15
+ case 'tidalStream': return _jsx(TidalStreamParticles, { size: size, config: config, animations: animations, ...ready });
16
+ case 'brownianDust': return _jsx(BrownianDustParticles, { size: size, config: config, animations: animations, ...ready });
17
+ case 'bioluminescentWake': return _jsx(BioluminescentWakeParticles, { size: size, config: config, animations: animations, ...ready });
18
+ case 'electronOrbitals': return _jsx(ElectronOrbitalsParticles, { size: size, config: config, animations: animations, ...ready });
19
+ case 'grinderSparks': return _jsx(GrinderSparksParticles, { size: size, config: config, animations: animations, ...ready });
20
+ default: return null;
21
+ }
22
+ };
23
+ export default ParticlesGenerator;
@@ -0,0 +1,15 @@
1
+ import type { ThreeElements } from '@react-three/fiber';
2
+ import type { ObjectReadyProps } from '../types/objectReady';
3
+ import type { ReactionDiffusionGridConfig } from '../types/gridConfigs';
4
+ export interface ReactionDiffusionGridProps extends ObjectReadyProps {
5
+ config?: ReactionDiffusionGridConfig;
6
+ groupProps?: ThreeElements['group'];
7
+ }
8
+ /** ReactionDiffusionGridConfig defaults. Must match the catalog entry in grid-defaults.json exactly. */
9
+ export declare const defaultReactionDiffusionGridConfig: ReactionDiffusionGridConfig;
10
+ /**
11
+ * A Gray-Scott reaction-diffusion field simulated on the GPU and sampled by the plane: coral, labyrinths and dividing spots grow, merge and keep evolving, wrapped seamlessly as a torus.
12
+ */
13
+ export declare function ReactionDiffusionGrid({ config, groupProps, onObjectReady, onObjectDispose }: ReactionDiffusionGridProps): import("react").JSX.Element;
14
+ export default ReactionDiffusionGrid;
15
+ //# sourceMappingURL=ReactionDiffusionGrid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReactionDiffusionGrid.d.ts","sourceRoot":"","sources":["../../src/components/ReactionDiffusionGrid.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAKxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAGxE,MAAM,WAAW,0BAA2B,SAAQ,gBAAgB;IAChE,MAAM,CAAC,EAAE,2BAA2B,CAAC;IACrC,UAAU,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;CACvC;AAKD,wGAAwG;AACxG,eAAO,MAAM,kCAAkC,EAAE,2BA6BhD,CAAC;AAuTF;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,MAA2C,EAAE,UAAU,EAAE,aAAa,EAAE,eAAe,EAAE,EAAE,0BAA0B,+BAgF5J;AAED,eAAe,qBAAqB,CAAC"}