@3driseai/3drise-viewer 0.1.30 → 0.1.32
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/dist/animationsV2/ClipPlayer.d.ts.map +1 -1
- package/dist/animationsV2/ClipPlayer.js +14 -12
- package/dist/animationsV2/ClipsRuntime.d.ts +9 -0
- package/dist/animationsV2/ClipsRuntime.d.ts.map +1 -1
- package/dist/animationsV2/ClipsRuntime.js +54 -7
- package/dist/animationsV2/appliers.d.ts.map +1 -1
- package/dist/animationsV2/appliers.js +21 -2
- package/dist/animationsV2/clipUtils.d.ts.map +1 -1
- package/dist/animationsV2/clipUtils.js +4 -0
- package/dist/animationsV2/sequenceUtils.js +4 -5
- package/dist/animationsV2/sunSystemLive.d.ts +12 -0
- package/dist/animationsV2/sunSystemLive.d.ts.map +1 -0
- package/dist/animationsV2/sunSystemLive.js +8 -0
- package/dist/api/sceneHandle.d.ts +3 -1
- package/dist/api/sceneHandle.d.ts.map +1 -1
- package/dist/api/sceneHandle.js +2 -2
- package/dist/components/AdaptiveResolution.d.ts +9 -0
- package/dist/components/AdaptiveResolution.d.ts.map +1 -0
- package/dist/components/AdaptiveResolution.js +61 -0
- package/dist/components/CameraController.d.ts.map +1 -1
- package/dist/components/CameraController.js +24 -7
- package/dist/components/MoonDisc.d.ts.map +1 -1
- package/dist/components/MoonDisc.js +2 -1
- package/dist/components/OceanBuilder.d.ts +4 -1
- package/dist/components/OceanBuilder.d.ts.map +1 -1
- package/dist/components/OceanBuilder.js +2 -1
- package/dist/components/ParticlesGenerator.d.ts.map +1 -1
- package/dist/components/ParticlesGenerator.js +2 -0
- package/dist/components/SceneBuilder.d.ts.map +1 -1
- package/dist/components/SceneBuilder.js +5 -2
- package/dist/components/Skybox.d.ts.map +1 -1
- package/dist/components/Skybox.js +2 -1
- package/dist/components/SunLight.d.ts.map +1 -1
- package/dist/components/SunLight.js +3 -2
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -0
- package/dist/components/lightBulb/LightBulb.d.ts.map +1 -1
- package/dist/components/lightBulb/LightBulb.js +7 -2
- package/dist/components/particles/FireworksParticles.d.ts +22 -0
- package/dist/components/particles/FireworksParticles.d.ts.map +1 -0
- package/dist/components/particles/FireworksParticles.js +1649 -0
- package/dist/components/particles/index.d.ts +2 -0
- package/dist/components/particles/index.d.ts.map +1 -1
- package/dist/components/particles/index.js +1 -0
- package/dist/components/terrain/TerrainSurface.d.ts.map +1 -1
- package/dist/components/terrain/TerrainSurface.js +26 -4
- package/dist/components/water/OceanSurface.d.ts.map +1 -1
- package/dist/components/water/OceanSurface.js +5 -1
- package/dist/components/water/types.d.ts +3 -1
- package/dist/components/water/types.d.ts.map +1 -1
- package/dist/hooks/useOceanMaterial.d.ts +6 -2
- package/dist/hooks/useOceanMaterial.d.ts.map +1 -1
- package/dist/hooks/useOceanMaterial.js +22 -2
- package/dist/hooks/useOrbitTargetFollow.d.ts +10 -0
- package/dist/hooks/useOrbitTargetFollow.d.ts.map +1 -0
- package/dist/hooks/useOrbitTargetFollow.js +194 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/shaders/glsl/terrainCore.glsl.d.ts +18 -3
- package/dist/shaders/glsl/terrainCore.glsl.d.ts.map +1 -1
- package/dist/shaders/glsl/terrainCore.glsl.js +42 -21
- package/dist/shaders/ocean/OceanSurfaceMaterial.d.ts +36 -11
- package/dist/shaders/ocean/OceanSurfaceMaterial.d.ts.map +1 -1
- package/dist/shaders/ocean/OceanSurfaceMaterial.js +96 -5
- package/dist/triggers/hosts/actions.d.ts.map +1 -1
- package/dist/triggers/hosts/actions.js +2 -0
- package/dist/triggers/hosts/timelineCues.js +1 -1
- package/dist/triggers/kinds/change.d.ts +4 -0
- package/dist/triggers/kinds/change.d.ts.map +1 -0
- package/dist/triggers/kinds/change.js +50 -0
- package/dist/triggers/kinds/index.d.ts +1 -0
- package/dist/triggers/kinds/index.d.ts.map +1 -1
- package/dist/triggers/kinds/index.js +1 -0
- package/dist/utils/CameraSingleton.d.ts +4 -0
- package/dist/utils/CameraSingleton.d.ts.map +1 -1
- package/dist/utils/CameraSingleton.js +4 -0
- package/dist/utils/deviceTier.d.ts +2 -0
- package/dist/utils/deviceTier.d.ts.map +1 -0
- package/dist/utils/deviceTier.js +16 -0
- package/dist/utils/environmentDrawOrder.d.ts +23 -0
- package/dist/utils/environmentDrawOrder.d.ts.map +1 -0
- package/dist/utils/environmentDrawOrder.js +22 -0
- package/dist/utils/terrainUniforms.d.ts +7 -0
- package/dist/utils/terrainUniforms.d.ts.map +1 -1
- package/dist/utils/terrainUniforms.js +15 -2
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClipPlayer.d.ts","sourceRoot":"","sources":["../../src/animationsV2/ClipPlayer.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAKjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEhE,MAAM,WAAW,eAAe;IAC5B,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,GAAG,CAAC;IACpC,wDAAwD;IACxD,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,cAAc,GAAG,SAAS,CAAC;IACvD,6FAA6F;IAC7F,QAAQ,CAAC,EAAE;QAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC;QAAC,KAAK,EAAE,aAAa,EAAE,CAAA;KAAE,CAAC;CACzE;AAcD,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,
|
|
1
|
+
{"version":3,"file":"ClipPlayer.d.ts","sourceRoot":"","sources":["../../src/animationsV2/ClipPlayer.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAKjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEhE,MAAM,WAAW,eAAe;IAC5B,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,GAAG,CAAC;IACpC,wDAAwD;IACxD,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,cAAc,GAAG,SAAS,CAAC;IACvD,6FAA6F;IAC7F,QAAQ,CAAC,EAAE;QAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC;QAAC,KAAK,EAAE,aAAa,EAAE,CAAA;KAAE,CAAC;CACzE;AAcD,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAyJzC,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -156,12 +156,14 @@ const ClipPlayer = ({ getSettings, getAction, autoplay }) => {
|
|
|
156
156
|
};
|
|
157
157
|
}, [gl]);
|
|
158
158
|
// --- zoom: OrbitControls must not zoom while the wheel drives a sequence -----------
|
|
159
|
-
|
|
159
|
+
// Held off every frame while one runs (the camera settings sync may write it back), and
|
|
160
|
+
// handed back afterwards with the authored setting (so the Controls zoom switch wins).
|
|
161
|
+
const zoomHeld = useRef(null);
|
|
162
|
+
const authoredZoom = () => settingsRef.current('camera')?.controls?.enableZoom !== false;
|
|
160
163
|
useEffect(() => () => {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
zoomRestore.current = null;
|
|
164
|
+
if (zoomHeld.current)
|
|
165
|
+
zoomHeld.current.enableZoom = authoredZoom();
|
|
166
|
+
zoomHeld.current = null;
|
|
165
167
|
}, []);
|
|
166
168
|
// --- camera: OrbitControls sit out while an animation drives the camera ------------
|
|
167
169
|
// Their update (damping residue, min / max distance and angle limits, auto-rotate)
|
|
@@ -187,15 +189,15 @@ const ClipPlayer = ({ getSettings, getAction, autoplay }) => {
|
|
|
187
189
|
cameraHeld.current = null;
|
|
188
190
|
}
|
|
189
191
|
const wheelActive = ClipsRuntime.getDrivenSequences().some(d => d.driver === 'mouseWheel');
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
192
|
+
if (wheelActive && controls) {
|
|
193
|
+
if (zoomHeld.current && zoomHeld.current !== controls)
|
|
194
|
+
zoomHeld.current.enableZoom = authoredZoom();
|
|
195
|
+
zoomHeld.current = controls;
|
|
193
196
|
controls.enableZoom = false;
|
|
194
197
|
}
|
|
195
|
-
else if (
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
zoomRestore.current = null;
|
|
198
|
+
else if (zoomHeld.current) {
|
|
199
|
+
zoomHeld.current.enableZoom = authoredZoom();
|
|
200
|
+
zoomHeld.current = null;
|
|
199
201
|
}
|
|
200
202
|
});
|
|
201
203
|
return null;
|
|
@@ -102,6 +102,12 @@ declare class ClipsRuntime {
|
|
|
102
102
|
pose(clip: AnimationClip, t: number): void;
|
|
103
103
|
/** The clip data changed (editor edit): keep time and play state, use the new tracks. */
|
|
104
104
|
updateClip(clip: AnimationClip): void;
|
|
105
|
+
/**
|
|
106
|
+
* A timeline's cue lanes changed under it (a Change cue's settings edited, a lane's
|
|
107
|
+
* command swapped): let go of every lane it holds; the next tick switches the lanes
|
|
108
|
+
* back on at the playhead with their new commands.
|
|
109
|
+
*/
|
|
110
|
+
resyncCues(host: 'sequence' | 'clip', timelineId: string): void;
|
|
105
111
|
getTime(clipId: string): number;
|
|
106
112
|
isPlaying(clipId: string): boolean;
|
|
107
113
|
isActive(clipId: string): boolean;
|
|
@@ -184,6 +190,9 @@ declare class ClipsRuntime {
|
|
|
184
190
|
*/
|
|
185
191
|
private advanceSequence;
|
|
186
192
|
private finishSequence;
|
|
193
|
+
/** Owners already reported for an element (one report per pair until reset). */
|
|
194
|
+
private clashed;
|
|
195
|
+
private noteLayerClash;
|
|
187
196
|
private emit;
|
|
188
197
|
private bump;
|
|
189
198
|
/** A state change: notifies both kinds of subscribers. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClipsRuntime.d.ts","sourceRoot":"","sources":["../../src/animationsV2/ClipsRuntime.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ClipsRuntime.d.ts","sourceRoot":"","sources":["../../src/animationsV2/ClipsRuntime.ts"],"names":[],"mappings":"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"}
|
|
@@ -39,7 +39,8 @@
|
|
|
39
39
|
// driven); a posed sequence (the editor's scrub) applies patches only. Stopping
|
|
40
40
|
// the sequence reverts its actions; a 'hold' finish keeps them.
|
|
41
41
|
//
|
|
42
|
-
import { SceneActions } from '@3driseai/3drise-core';
|
|
42
|
+
import { SceneActions, expandMaterialVariant } from '@3driseai/3drise-core';
|
|
43
|
+
import { logTrigger } from '../triggers/log.js';
|
|
43
44
|
import { getAtPath, sampleTrack } from './clipUtils.js';
|
|
44
45
|
import { applyValue, clearApplierCaches, isApplicable, isTargetMounted } from './appliers.js';
|
|
45
46
|
import { readNodeValue, restoreNodeTrack } from './nodeTracks.js';
|
|
@@ -53,8 +54,9 @@ const REWRITE_FRAMES = 30;
|
|
|
53
54
|
/** Deep patch from flat (path -> value) pairs. */
|
|
54
55
|
function patchOf(pairs) {
|
|
55
56
|
const out = {};
|
|
56
|
-
for (const [path, value] of pairs) {
|
|
57
|
-
|
|
57
|
+
for (const [path, value, node] of pairs) {
|
|
58
|
+
// A part's switch track sits under its node override (node keys may contain dots: no split).
|
|
59
|
+
const parts = node ? ['config', 'nodeOverrides', node, ...path.split('.')] : path.split('.');
|
|
58
60
|
let cur = out;
|
|
59
61
|
for (let i = 0; i < parts.length - 1; i++)
|
|
60
62
|
cur = (cur[parts[i]] ??= {});
|
|
@@ -185,6 +187,7 @@ class ClipsRuntime {
|
|
|
185
187
|
this.written.clear();
|
|
186
188
|
this.laid.clear();
|
|
187
189
|
this.rewrite.clear();
|
|
190
|
+
this.clashed.clear();
|
|
188
191
|
SceneActions.setLayer(TIMELINE_LAYER, null);
|
|
189
192
|
clearApplierCaches();
|
|
190
193
|
this.bumpState();
|
|
@@ -259,6 +262,19 @@ class ClipsRuntime {
|
|
|
259
262
|
this.written.clear(); // values may have changed under the same time
|
|
260
263
|
this.bumpState();
|
|
261
264
|
}
|
|
265
|
+
/**
|
|
266
|
+
* A timeline's cue lanes changed under it (a Change cue's settings edited, a lane's
|
|
267
|
+
* command swapped): let go of every lane it holds; the next tick switches the lanes
|
|
268
|
+
* back on at the playhead with their new commands.
|
|
269
|
+
*/
|
|
270
|
+
resyncCues(host, timelineId) {
|
|
271
|
+
const inst = host === 'clip' ? this.clips.get(timelineId) : this.sequences.get(timelineId);
|
|
272
|
+
if (!inst)
|
|
273
|
+
return;
|
|
274
|
+
this.releaseCues(inst.owned, host, timelineId);
|
|
275
|
+
inst.cueState.clear();
|
|
276
|
+
this.bump();
|
|
277
|
+
}
|
|
262
278
|
getTime(clipId) { return this.clips.get(clipId)?.time ?? 0; }
|
|
263
279
|
isPlaying(clipId) { return !!this.clips.get(clipId)?.playing; }
|
|
264
280
|
isActive(clipId) { return this.clips.has(clipId); }
|
|
@@ -534,12 +550,13 @@ class ClipsRuntime {
|
|
|
534
550
|
if (!p.discrete)
|
|
535
551
|
continue;
|
|
536
552
|
const list = discrete.get(p.state) ?? [];
|
|
537
|
-
list.push([p.path, p.value]);
|
|
553
|
+
list.push([p.path, p.value, p.node]);
|
|
538
554
|
discrete.set(p.state, list);
|
|
539
555
|
}
|
|
540
556
|
const layer = {};
|
|
557
|
+
// A material variant switch track stands for the variant's full settings (expanded here).
|
|
541
558
|
for (const [state, pairs] of discrete)
|
|
542
|
-
layer[state] = patchOf(pairs);
|
|
559
|
+
layer[state] = expandMaterialVariant(patchOf(pairs));
|
|
543
560
|
for (const state of new Set([...this.laid.keys(), ...discrete.keys()])) {
|
|
544
561
|
const json = layer[state] ? JSON.stringify(layer[state]) : '';
|
|
545
562
|
if ((this.laid.get(state) ?? '') === json)
|
|
@@ -549,6 +566,9 @@ class ClipsRuntime {
|
|
|
549
566
|
else
|
|
550
567
|
this.laid.delete(state);
|
|
551
568
|
this.rewrite.set(state, REWRITE_FRAMES);
|
|
569
|
+
// Switch tracks over an action / Change cue setting the same thing: reported, not resolved.
|
|
570
|
+
if (json)
|
|
571
|
+
this.noteLayerClash(state, layer[state]);
|
|
552
572
|
}
|
|
553
573
|
SceneActions.setLayer(TIMELINE_LAYER, layer);
|
|
554
574
|
const failed = [];
|
|
@@ -587,7 +607,10 @@ class ClipsRuntime {
|
|
|
587
607
|
missing.add(t.node ? `${t.state} › ${t.node}` : t.state);
|
|
588
608
|
}
|
|
589
609
|
}
|
|
590
|
-
const
|
|
610
|
+
const ENV = ['camera', 'sky', 'clouds', 'ocean', 'terrain'];
|
|
611
|
+
const idsOf = (c) => (c?.kind === 'effect' ? c.effect?.targets ?? []
|
|
612
|
+
: c?.kind === 'effectClip' ? c.use?.targets ?? []
|
|
613
|
+
: c?.kind === 'change' ? (c.targets ?? []).map((t) => t?.state).filter((s) => s && !ENV.includes(s)) : []);
|
|
591
614
|
for (const sc of inst.schedule.cues) {
|
|
592
615
|
const cmd = cueCommand(sc.cue);
|
|
593
616
|
for (const id of idsOf(cmd))
|
|
@@ -624,6 +647,15 @@ class ClipsRuntime {
|
|
|
624
647
|
if ((state.get(key) ?? false) === on) {
|
|
625
648
|
if (!wanted.has(key))
|
|
626
649
|
state.delete(key);
|
|
650
|
+
else if (on) {
|
|
651
|
+
// The lane's command changed under it (a Change cue edited, a lane re-targeted): re-apply it.
|
|
652
|
+
const cmd = commandOf.get(key);
|
|
653
|
+
const prev = owned.get(key);
|
|
654
|
+
if (cmd && prev && prev !== cmd && JSON.stringify(prev) !== JSON.stringify(cmd) && this.cueRunner) {
|
|
655
|
+
if (this.cueRunner(cmd, 'apply', { ...opts, getAction: this.ctx?.getAction }))
|
|
656
|
+
owned.set(key, cmd);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
627
659
|
continue;
|
|
628
660
|
}
|
|
629
661
|
if (wanted.has(key))
|
|
@@ -854,6 +886,21 @@ class ClipsRuntime {
|
|
|
854
886
|
if (inst.seq.endMode === 'restore')
|
|
855
887
|
this.stopSequence(inst.seq.id);
|
|
856
888
|
}
|
|
889
|
+
/** Owners already reported for an element (one report per pair until reset). */
|
|
890
|
+
clashed = new Set();
|
|
891
|
+
noteLayerClash(state, patch) {
|
|
892
|
+
for (const owner of SceneActions.overlaps(state, patch, `layer:${TIMELINE_LAYER}`)) {
|
|
893
|
+
const key = `${state}|${owner}`;
|
|
894
|
+
if (this.clashed.has(key))
|
|
895
|
+
continue;
|
|
896
|
+
this.clashed.add(key);
|
|
897
|
+
const who = owner.startsWith('layer:change:') ? `Change cue ${owner.slice(13)}` : owner.startsWith('layer:') ? owner.slice(6) : `action ${owner}`;
|
|
898
|
+
logTrigger({
|
|
899
|
+
type: 'clash', kind: 'animationClip', subject: state, source: { host: 'clip', id: 'switch-tracks' }, chain: [],
|
|
900
|
+
detail: `a switch track sets the same settings on ${state} as ${who} — the last one to change wins`,
|
|
901
|
+
});
|
|
902
|
+
}
|
|
903
|
+
}
|
|
857
904
|
emit(e) {
|
|
858
905
|
this.eventListeners.forEach(l => { try {
|
|
859
906
|
l(e);
|
|
@@ -882,7 +929,7 @@ function* sampleTracks(tracks, t) {
|
|
|
882
929
|
const value = sampleTrack(track, t);
|
|
883
930
|
if (value === undefined)
|
|
884
931
|
continue;
|
|
885
|
-
yield { state: track.state, node: track.node, path: track.path, value, discrete: track.discrete
|
|
932
|
+
yield { state: track.state, node: track.node, path: track.path, value, discrete: !!track.discrete };
|
|
886
933
|
}
|
|
887
934
|
}
|
|
888
935
|
const clipsRuntime = new ClipsRuntime();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appliers.d.ts","sourceRoot":"","sources":["../../src/animationsV2/appliers.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"appliers.d.ts","sourceRoot":"","sources":["../../src/animationsV2/appliers.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAiB/C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGxC,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACjC,qDAAqD;IACrD,QAAQ,EAAE,GAAG,CAAC;IACd,yFAAyF;IACzF,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,GAAG,CAAC;IACpC,0EAA0E;IAC1E,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,cAAc,GAAG,SAAS,CAAC;CACxD;AAWD,wBAAgB,kBAAkB,IAAI,IAAI,CAIzC;AAwMD,uFAAuF;AACvF,mFAAmF;AACnF,wBAAgB,UAAU,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAIlH;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAKxF;AAED,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjE"}
|
|
@@ -4,7 +4,8 @@ import { CLOUD_LIVE_KEY } from '../hooks/useCloudLive.js';
|
|
|
4
4
|
import { OCEAN_LIVE_KEY } from '../hooks/useOceanLive.js';
|
|
5
5
|
import { TERRAIN_LIVE_KEY } from '../hooks/useTerrainLive.js';
|
|
6
6
|
import { createSunPosition } from '../utils/utils3d.js';
|
|
7
|
-
import { sunAnglesFromDirection } from '@3driseai/3drise-core';
|
|
7
|
+
import { sunAnglesFromDirection, skySystemManager } from '@3driseai/3drise-core';
|
|
8
|
+
import { sunSystemLive, SUN_SYSTEM_LIVE_PATHS, TIME_PATHS } from './sunSystemLive.js';
|
|
8
9
|
import { publishRenderedSky, sceneOf } from '../utils/renderedSky.js';
|
|
9
10
|
import { applyNodeValue, clearNodeCaches, nodesFor } from './nodeTracks.js';
|
|
10
11
|
// --- live-target caches (cleared when the scene changes under us) -------------
|
|
@@ -202,8 +203,26 @@ const applyTerrain = (ctx, _state, path, value) => {
|
|
|
202
203
|
return false;
|
|
203
204
|
handle.config(path.slice('config.'.length), value);
|
|
204
205
|
};
|
|
206
|
+
/**
|
|
207
|
+
* Time: the Sky System clock and rig. `hour` seeks the clock (sun, moon, sky colours and
|
|
208
|
+
* the key light all follow it); the rest are live multipliers the Sky System reads per frame.
|
|
209
|
+
*/
|
|
210
|
+
const applyTime = (_ctx, _state, path, value) => {
|
|
211
|
+
if (typeof value !== 'number' || !Number.isFinite(value))
|
|
212
|
+
return false;
|
|
213
|
+
if (path === 'hour') {
|
|
214
|
+
skySystemManager.setTime(((value % 24) + 24) % 24);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
if (SUN_SYSTEM_LIVE_PATHS.includes(path)) {
|
|
218
|
+
sunSystemLive[path] = Math.max(0, value);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
return false;
|
|
222
|
+
};
|
|
205
223
|
const APPLIERS = [
|
|
206
224
|
{ match: (s) => s === 'camera', apply: applyCamera },
|
|
225
|
+
{ match: (s, p) => s === 'time' && TIME_PATHS.includes(p), apply: applyTime },
|
|
207
226
|
// Environment before the generic path families: the ocean's `config.*` is not an object's.
|
|
208
227
|
{ match: (s) => s === 'sky', apply: applySky },
|
|
209
228
|
{ match: (s) => s === 'clouds', apply: applyClouds },
|
|
@@ -226,7 +245,7 @@ export function applyValue(ctx, state, path, value, node) {
|
|
|
226
245
|
export function isTargetMounted(ctx, state, node) {
|
|
227
246
|
if (state === 'camera')
|
|
228
247
|
return !!ctx.camera;
|
|
229
|
-
if (state === 'sky' || state === 'clouds' || state === 'ocean' || state === 'terrain')
|
|
248
|
+
if (state === 'sky' || state === 'clouds' || state === 'ocean' || state === 'terrain' || state === 'time')
|
|
230
249
|
return true;
|
|
231
250
|
if (node)
|
|
232
251
|
return nodesFor(state, node).length > 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clipUtils.d.ts","sourceRoot":"","sources":["../../src/animationsV2/clipUtils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAOlF,eAAO,MAAM,GAAG,GAAI,QAAQ,MAAM,WAAqF,CAAC;AAExH,uFAAuF;AACvF,wBAAgB,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,GAAG,CAOrD;AAMD,eAAO,MAAM,cAAc,GAAI,GAAG,MAAM,EAAE,KAAK,MAAM,WAAwB,CAAC;AAC9E,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,EAAE,KAAK,MAAM,WAAgB,CAAC;AAC1E,eAAO,MAAM,WAAW,GAAI,GAAG,MAAM,EAAE,KAAK,MAAM,WAAgD,CAAC;AAEnG,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAKvD;AAaD,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAK1E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"clipUtils.d.ts","sourceRoot":"","sources":["../../src/animationsV2/clipUtils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAOlF,eAAO,MAAM,GAAG,GAAI,QAAQ,MAAM,WAAqF,CAAC;AAExH,uFAAuF;AACvF,wBAAgB,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,GAAG,CAOrD;AAMD,eAAO,MAAM,cAAc,GAAI,GAAG,MAAM,EAAE,KAAK,MAAM,WAAwB,CAAC;AAC9E,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,EAAE,KAAK,MAAM,WAAgB,CAAC;AAC1E,eAAO,MAAM,WAAW,GAAI,GAAG,MAAM,EAAE,KAAK,MAAM,WAAgD,CAAC;AAEnG,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAKvD;AAaD,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAK1E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAyBzE;AAMD,eAAO,MAAM,QAAQ,GAAI,MAAM,QAAQ,EAAE,eAAwC,CAAC;AAElF,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,CAOtF;AAED,0FAA0F;AAC1F,wBAAgB,QAAQ,CAAC,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,aAAa,CAc9G;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,aAAa,CAKrF;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,GAAG,aAAa,CAQtG;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,aAAa,CAQ9F;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,QAAQ,CAAA;CAAE,GAAG,SAAS,CAMvG;AAED,oEAAoE;AACpE,wBAAgB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,EAAE,CAIzD;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,aAAa,CAEhE;AAED,4CAA4C;AAC5C,wBAAgB,SAAS,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,aAAa,CAQvF"}
|
|
@@ -54,6 +54,10 @@ export function sampleTrack(track, t) {
|
|
|
54
54
|
const keys = track.keys;
|
|
55
55
|
if (keys.length === 0)
|
|
56
56
|
return undefined;
|
|
57
|
+
// A switch track switches AT its first key: before it the element keeps its authored value
|
|
58
|
+
// (an eased track holds its first value before it, so a move can start later than 0).
|
|
59
|
+
if (t < keys[0].t - 1e-9 && track.discrete)
|
|
60
|
+
return undefined;
|
|
57
61
|
if (t <= keys[0].t)
|
|
58
62
|
return keys[0].value;
|
|
59
63
|
const last = keys[keys.length - 1];
|
|
@@ -145,13 +145,12 @@ export function findCueConflicts(seq, clips, getAction) {
|
|
|
145
145
|
if (sc.cue.mode !== 'apply')
|
|
146
146
|
continue;
|
|
147
147
|
const cmd = cueCommand(sc.cue);
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if (!action?.targets?.length)
|
|
148
|
+
// an action's patches, or a Change cue's own
|
|
149
|
+
const targets = cmd?.kind === 'action' ? getAction(cmd.ref)?.targets : cmd?.kind === 'change' ? cmd.targets : undefined;
|
|
150
|
+
if (!targets?.length)
|
|
152
151
|
continue;
|
|
153
152
|
const entries = schedule.entries.filter(e => e.stepIndex === sc.stepIndex);
|
|
154
|
-
for (const target of
|
|
153
|
+
for (const target of targets) {
|
|
155
154
|
const paths = patchPaths(target.patch);
|
|
156
155
|
for (const e of entries) {
|
|
157
156
|
for (const track of e.clip.tracks) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface SunSystemLive {
|
|
2
|
+
moonSize?: number;
|
|
3
|
+
sunSize?: number;
|
|
4
|
+
intensity?: number;
|
|
5
|
+
moonIntensity?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare const sunSystemLive: SunSystemLive;
|
|
8
|
+
export declare const SUN_SYSTEM_LIVE_PATHS: readonly ["moonSize", "sunSize", "intensity", "moonIntensity"];
|
|
9
|
+
/** Every path the `time` target accepts. */
|
|
10
|
+
export declare const TIME_PATHS: readonly ["hour", "moonSize", "sunSize", "intensity", "moonIntensity"];
|
|
11
|
+
export declare function resetSunSystemLive(): void;
|
|
12
|
+
//# sourceMappingURL=sunSystemLive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sunSystemLive.d.ts","sourceRoot":"","sources":["../../src/animationsV2/sunSystemLive.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,aAAa;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,eAAO,MAAM,aAAa,EAAE,aAAkB,CAAC;AAE/C,eAAO,MAAM,qBAAqB,gEAAiE,CAAC;AACpG,4CAA4C;AAC5C,eAAO,MAAM,UAAU,wEAA8C,CAAC;AAEtE,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export const sunSystemLive = {};
|
|
2
|
+
export const SUN_SYSTEM_LIVE_PATHS = ['moonSize', 'sunSize', 'intensity', 'moonIntensity'];
|
|
3
|
+
/** Every path the `time` target accepts. */
|
|
4
|
+
export const TIME_PATHS = ['hour', ...SUN_SYSTEM_LIVE_PATHS];
|
|
5
|
+
export function resetSunSystemLive() {
|
|
6
|
+
for (const k of SUN_SYSTEM_LIVE_PATHS)
|
|
7
|
+
delete sunSystemLive[k];
|
|
8
|
+
}
|
|
@@ -62,10 +62,12 @@ export type SceneValue = number | boolean | string | number[];
|
|
|
62
62
|
/** Write live properties of the scene — what a slider or colour picker does. */
|
|
63
63
|
export interface SceneValues {
|
|
64
64
|
/**
|
|
65
|
-
* Write one property now. `target` is `sky` | `camera` | `clouds` | `ocean` | `terrain`, or an
|
|
65
|
+
* Write one property now. `target` is `sky` | `camera` | `clouds` | `ocean` | `terrain` | `time`, or an
|
|
66
66
|
* object ref (key, id or exact name), with `/NodeName` to address a part of a model. `path` is a
|
|
67
67
|
* settings path as clip tracks use it (`materialSettings.opacity`, `meshSettings.position.y`,
|
|
68
68
|
* `config.intensity`, `sky:elevation`; for a model node: `position`, `rotation.y`, `material.color`).
|
|
69
|
+
* `time` drives the Sky System: `hour` (the clock — sun, moon, sky, light), `moonSize`, `sunSize`,
|
|
70
|
+
* `intensity`, `moonIntensity` (`sky` is the analytic sky, not the Sky System).
|
|
69
71
|
* A `.x` / `.y` / `.z` suffix writes one component of a vector. Nothing is saved: this is the
|
|
70
72
|
* live scene, like an animation frame, and a page reload puts it back. False when the target or
|
|
71
73
|
* path is not writable (see `check`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sceneHandle.d.ts","sourceRoot":"","sources":["../../src/api/sceneHandle.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1E,OAAO,EAAc,KAAK,gBAAgB,EAAuB,MAAM,aAAa,CAAC;AAErF,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE9E,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,0FAA0F;IAC1F,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACpD,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC7B,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qDAAqD;AACrD,MAAM,WAAW,aAAa,CAAC,IAAI;IAC/B,IAAI,IAAI,IAAI,EAAE,CAAC;IACf,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC;IACvD,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7B,sEAAsE;IACtE,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3B,4CAA4C;IAC5C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7C,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACnC;AAED,0GAA0G;AAC1G,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;AAE9D,gFAAgF;AAChF,MAAM,WAAW,WAAW;IACxB
|
|
1
|
+
{"version":3,"file":"sceneHandle.d.ts","sourceRoot":"","sources":["../../src/api/sceneHandle.ts"],"names":[],"mappings":"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"}
|
package/dist/api/sceneHandle.js
CHANGED
|
@@ -182,7 +182,7 @@ export function createSceneHandle(getSource) {
|
|
|
182
182
|
},
|
|
183
183
|
};
|
|
184
184
|
// ----- values ----------------------------------------------------------------------
|
|
185
|
-
const ENVIRONMENT = ['camera', 'sky', 'clouds', 'ocean', 'terrain'];
|
|
185
|
+
const ENVIRONMENT = ['camera', 'sky', 'clouds', 'ocean', 'terrain', 'time'];
|
|
186
186
|
const COMPONENT = { x: 0, y: 1, z: 2 };
|
|
187
187
|
/** `engine/Door` -> { state: <object id>, node: 'Door' }; quiet when it is unknown (this runs on a poll). */
|
|
188
188
|
function target(ref) {
|
|
@@ -207,7 +207,7 @@ export function createSceneHandle(getSource) {
|
|
|
207
207
|
check(ref, path) {
|
|
208
208
|
const t = target(ref);
|
|
209
209
|
if (!t)
|
|
210
|
-
return `no target "${ref}". Use sky, camera, clouds, ocean, terrain or an object${ref.includes('/') ? ' (and sky/camera/… take no node)' : ''}.`;
|
|
210
|
+
return `no target "${ref}". Use sky, camera, clouds, ocean, terrain, time or an object${ref.includes('/') ? ' (and sky/camera/… take no node)' : ''}.`;
|
|
211
211
|
const c = t.node ? undefined : component(t.state, t.node, path);
|
|
212
212
|
if (!t.node && !ClipsRuntime.canSetLiveValue(t.state, c ? c.base : path))
|
|
213
213
|
return `"${path}" cannot be written live on ${ref}.`;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export declare const MOBILE_MAX_DPR = 1.5;
|
|
3
|
+
export interface AdaptiveResolutionProps {
|
|
4
|
+
/** The canvas's own dpr setting (number or [min, max]); its max is the ceiling. */
|
|
5
|
+
max?: number | [number, number];
|
|
6
|
+
}
|
|
7
|
+
declare const AdaptiveResolution: React.FC<AdaptiveResolutionProps>;
|
|
8
|
+
export default AdaptiveResolution;
|
|
9
|
+
//# sourceMappingURL=AdaptiveResolution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdaptiveResolution.d.ts","sourceRoot":"","sources":["../../src/components/AdaptiveResolution.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAC;AAyBpE,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC,MAAM,WAAW,uBAAuB;IACpC,mFAAmF;IACnF,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAID,QAAA,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAmCzD,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
+
import { useThree } from '@react-three/fiber';
|
|
4
|
+
import { PerformanceMonitor } from '@react-three/drei';
|
|
5
|
+
import { isMobileDevice } from '../utils/deviceTier.js';
|
|
6
|
+
/**
|
|
7
|
+
* Render resolution that follows the frame rate. Mount inside <Canvas>.
|
|
8
|
+
*
|
|
9
|
+
* The terrain (and most of what makes the environment expensive) costs per PIXEL:
|
|
10
|
+
* textures and noise octaves in the fragment shader. Pixel ratio is therefore the
|
|
11
|
+
* biggest single lever — 1.5 is 2.25x the pixels of 1, and a phone's 3 is 9x.
|
|
12
|
+
*
|
|
13
|
+
* - Ceiling: the canvas's configured dpr, capped at MOBILE_MAX_DPR on phones and
|
|
14
|
+
* tablets, where the device ratio is 2-3 and the GPU is a fraction of a desktop's.
|
|
15
|
+
* - Under load: drei's PerformanceMonitor averages the frame rate and steps the
|
|
16
|
+
* ratio down while it stays under ~50 fps, and back up when there is room.
|
|
17
|
+
* After a few flip-flops it freezes where it is, so a scene sitting on the edge
|
|
18
|
+
* does not oscillate between sharp and soft.
|
|
19
|
+
* - Floor: half the ceiling, never below 0.6 — softer, never mush.
|
|
20
|
+
* - Warm-up: the monitor starts WARMUP_MS after mount. Loading a scene compiles
|
|
21
|
+
* shaders and packs textures, and those stalls used to burn the flip-flop
|
|
22
|
+
* budget in the first seconds, freezing the ratio below the ceiling for the
|
|
23
|
+
* whole session (seen in the studio: stuck at 1.42 of 1.5 at a steady 60 fps).
|
|
24
|
+
*/
|
|
25
|
+
const WARMUP_MS = 4000;
|
|
26
|
+
export const MOBILE_MAX_DPR = 1.5;
|
|
27
|
+
const round2 = (v) => Math.round(v * 100) / 100;
|
|
28
|
+
const AdaptiveResolution = ({ max }) => {
|
|
29
|
+
const setDpr = useThree((s) => s.setDpr);
|
|
30
|
+
const ceiling = useMemo(() => {
|
|
31
|
+
const device = typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1;
|
|
32
|
+
const configured = Array.isArray(max) ? max[1] : (max ?? device);
|
|
33
|
+
return isMobileDevice() ? Math.min(configured, MOBILE_MAX_DPR) : configured;
|
|
34
|
+
}, [max]);
|
|
35
|
+
const floor = Math.max(0.6, ceiling * 0.5);
|
|
36
|
+
const frozen = useRef(false);
|
|
37
|
+
const [watching, setWatching] = useState(false);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
frozen.current = false;
|
|
40
|
+
setDpr(ceiling);
|
|
41
|
+
setWatching(false);
|
|
42
|
+
const t = setTimeout(() => setWatching(true), WARMUP_MS);
|
|
43
|
+
return () => clearTimeout(t);
|
|
44
|
+
}, [ceiling, setDpr]);
|
|
45
|
+
if (!watching)
|
|
46
|
+
return null;
|
|
47
|
+
return (_jsx(PerformanceMonitor
|
|
48
|
+
// 60 Hz: below 45 fps step down, above 55 step up. Not tighter: the
|
|
49
|
+
// studio's own main-thread work makes a GPU-idle frame rate wander
|
|
50
|
+
// between 55 and 60, and a 58 threshold pinned the ratio low for good.
|
|
51
|
+
, {
|
|
52
|
+
// 60 Hz: below 45 fps step down, above 55 step up. Not tighter: the
|
|
53
|
+
// studio's own main-thread work makes a GPU-idle frame rate wander
|
|
54
|
+
// between 55 and 60, and a 58 threshold pinned the ratio low for good.
|
|
55
|
+
bounds: (refresh) => (refresh > 100 ? [70, 100] : [45, 55]), flipflops: 3, onChange: ({ factor }) => {
|
|
56
|
+
if (frozen.current)
|
|
57
|
+
return;
|
|
58
|
+
setDpr(round2(floor + (ceiling - floor) * factor));
|
|
59
|
+
}, onFallback: () => { frozen.current = true; } }));
|
|
60
|
+
};
|
|
61
|
+
export default AdaptiveResolution;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CameraController.d.ts","sourceRoot":"","sources":["../../src/components/CameraController.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAQ7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"CameraController.d.ts","sourceRoot":"","sources":["../../src/components/CameraController.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAQ7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGzD,UAAU,qBAAsB,SAAQ,gBAAgB;IACpD,QAAQ,EAAE,WAAW,CAAC;IACtB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;IAC1C,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;CAC/C;AAGD,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA4H5D,CAAC;AACF,eAAe,gBAAgB,CAAC"}
|
|
@@ -7,6 +7,8 @@ import { cameraManager } from '../utils/CameraSingleton.js';
|
|
|
7
7
|
import { usePathAnimation } from '../hooks/usePathAnimation.js';
|
|
8
8
|
import { OrbitControls } from "@react-three/drei";
|
|
9
9
|
import { useRuntimeSettings } from '../hooks/useRuntimeSettings.js';
|
|
10
|
+
import { orbitAngleLimits } from "@3driseai/3drise-core";
|
|
11
|
+
import { useOrbitTargetFollow } from '../hooks/useOrbitTargetFollow.js';
|
|
10
12
|
export const CameraController = ({ enableAutoAnimation = true, animationDuration = 1, animationEase = "power2.out", settings, onObjectReady, onObjectDispose, onControlsReady, onControlsDispose, }) => {
|
|
11
13
|
// Authored camera + any applied action patch ('camera').
|
|
12
14
|
settings = useRuntimeSettings('camera', settings);
|
|
@@ -19,8 +21,11 @@ export const CameraController = ({ enableAutoAnimation = true, animationDuration
|
|
|
19
21
|
const controls = controlsRef.current;
|
|
20
22
|
if (!controls)
|
|
21
23
|
return;
|
|
24
|
+
cameraManager.setControls(controls);
|
|
22
25
|
onControlsReady && onControlsReady(controls);
|
|
23
26
|
return () => {
|
|
27
|
+
if (cameraManager.getControls() === controls)
|
|
28
|
+
cameraManager.setControls(null);
|
|
24
29
|
onControlsDispose && onControlsDispose(controls);
|
|
25
30
|
};
|
|
26
31
|
}, [controlsRef.current]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
@@ -59,15 +64,27 @@ export const CameraController = ({ enableAutoAnimation = true, animationDuration
|
|
|
59
64
|
}
|
|
60
65
|
}
|
|
61
66
|
}, [position, orientation]);
|
|
67
|
+
// The stored orbit point is applied only when it (or the object choice) changes: a
|
|
68
|
+
// followed object or a pan moves the live point, and an unrelated edit (a speed, a
|
|
69
|
+
// limit) must not snap it back.
|
|
70
|
+
const appliedTarget = useRef('');
|
|
62
71
|
// Sync controls config changes imperatively via ref (after initial mount)
|
|
63
72
|
useEffect(() => {
|
|
64
73
|
const orbitControls = controlsRef.current;
|
|
65
74
|
if (!orbitControls)
|
|
66
75
|
return;
|
|
67
76
|
orbitControls.enabled = controls.enabled;
|
|
68
|
-
|
|
69
|
-
|
|
77
|
+
// Orbiting an object: the follow hook owns the target, and panning is off
|
|
78
|
+
// (a pan would pull the orbit point off the object).
|
|
79
|
+
const lookingAtObject = !!controls.targetObject?.id;
|
|
80
|
+
const targetKey = `${controls.target?.join(',')}|${controls.targetObject?.id ?? ''}|${controls.targetObject?.node ?? ''}`;
|
|
81
|
+
if (!lookingAtObject && targetKey !== appliedTarget.current)
|
|
82
|
+
orbitControls.target.set(controls.target[0], controls.target[1], controls.target[2]);
|
|
83
|
+
appliedTarget.current = targetKey;
|
|
84
|
+
orbitControls.enablePan = lookingAtObject ? false : controls.enablePan;
|
|
70
85
|
orbitControls.enableRotate = controls.enableRotate;
|
|
86
|
+
// ClipPlayer holds zoom off while a wheel-driven sequence runs (it re-asserts every frame).
|
|
87
|
+
orbitControls.enableZoom = controls.enableZoom !== false;
|
|
71
88
|
orbitControls.autoRotate = controls.autoRotate;
|
|
72
89
|
orbitControls.autoRotateSpeed = controls.autoRotateSpeed;
|
|
73
90
|
orbitControls.zoomSpeed = controls.zoomSpeed;
|
|
@@ -75,11 +92,11 @@ export const CameraController = ({ enableAutoAnimation = true, animationDuration
|
|
|
75
92
|
orbitControls.rotateSpeed = controls.rotateSpeed;
|
|
76
93
|
orbitControls.minDistance = controls.minDistance;
|
|
77
94
|
orbitControls.maxDistance = controls.maxDistance;
|
|
78
|
-
|
|
79
|
-
orbitControls
|
|
80
|
-
orbitControls.minAzimuthAngle = controls.minAzimuthAngle ?? -Infinity;
|
|
81
|
-
orbitControls.maxAzimuthAngle = controls.maxAzimuthAngle ?? Infinity;
|
|
95
|
+
// Saved limits may be null (once ±Infinity): the full range then.
|
|
96
|
+
Object.assign(orbitControls, orbitAngleLimits(controls));
|
|
82
97
|
}, [controls]);
|
|
98
|
+
// Look at a scene object (orbit target) and / or travel with one (follow).
|
|
99
|
+
useOrbitTargetFollow(controlsRef, controls.targetObject, controls.followObject, () => isInAnimatedTransition.current || isAnimating() || isPathAnimating(), controls.enabled !== false, controls);
|
|
83
100
|
// Sync camera projection settings from state
|
|
84
101
|
useEffect(() => {
|
|
85
102
|
const cam = cameraRef.current;
|
|
@@ -117,6 +134,6 @@ export const CameraController = ({ enableAutoAnimation = true, animationDuration
|
|
|
117
134
|
const ic = initialControls.current;
|
|
118
135
|
return _jsx(OrbitControls, { ref: controlsRef, makeDefault: true, enabled: ic.enabled,
|
|
119
136
|
// target={new Vector3(...ic.target)}
|
|
120
|
-
enablePan: ic.enablePan, enableRotate: ic.enableRotate, autoRotate: ic.autoRotate, autoRotateSpeed: ic.autoRotateSpeed, zoomSpeed: ic.zoomSpeed, panSpeed: ic.panSpeed, rotateSpeed: ic.rotateSpeed, minDistance: ic.minDistance, maxDistance: ic.maxDistance,
|
|
137
|
+
enablePan: ic.targetObject?.id ? false : ic.enablePan, enableRotate: ic.enableRotate, enableZoom: ic.enableZoom !== false, autoRotate: ic.autoRotate, autoRotateSpeed: ic.autoRotateSpeed, zoomSpeed: ic.zoomSpeed, panSpeed: ic.panSpeed, rotateSpeed: ic.rotateSpeed, minDistance: ic.minDistance, maxDistance: ic.maxDistance, ...orbitAngleLimits(ic) });
|
|
121
138
|
};
|
|
122
139
|
export default CameraController;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MoonDisc.d.ts","sourceRoot":"","sources":["../../src/components/MoonDisc.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAG1D,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"MoonDisc.d.ts","sourceRoot":"","sources":["../../src/components/MoonDisc.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAG1D,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAKvE,MAAM,WAAW,aAAa;IAC1B,YAAY,EAAE,YAAY,CAAC;IAC3B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,8CAA8C;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AA+ED,QAAA,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAoDrC,CAAC;AAEF,eAAe,QAAQ,CAAC"}
|
|
@@ -4,6 +4,7 @@ import * as THREE from 'three';
|
|
|
4
4
|
import { useFrame } from '@react-three/fiber';
|
|
5
5
|
import { useCloudSun } from '../hooks/useCloudSun.js';
|
|
6
6
|
import { resolveMoon } from '../utils/skyMoon.js';
|
|
7
|
+
import { sunSystemLive } from '../animationsV2/sunSystemLive.js';
|
|
7
8
|
/**
|
|
8
9
|
* The moon in the sky, for either sky renderer.
|
|
9
10
|
*
|
|
@@ -114,7 +115,7 @@ const MoonDisc = ({ timeSettings, skySettings, size = 1 }) => {
|
|
|
114
115
|
const dist = far * 0.9;
|
|
115
116
|
mesh.position.copy(camera.position).addScaledVector(m.direction, dist);
|
|
116
117
|
mesh.quaternion.copy(camera.quaternion);
|
|
117
|
-
const radius = dist * Math.tan(THREE.MathUtils.degToRad(MOON_ANGULAR_DIAMETER_DEG * size) / 2);
|
|
118
|
+
const radius = dist * Math.tan(THREE.MathUtils.degToRad(MOON_ANGULAR_DIAMETER_DEG * (sunSystemLive.moonSize ?? size)) / 2);
|
|
118
119
|
mesh.scale.setScalar(radius * SPAN);
|
|
119
120
|
// Sun direction in the quad's frame, so the disc is lit from where the sun is.
|
|
120
121
|
scratch.q.copy(camera.quaternion).invert();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { SkySettings, TimeSettings } from '@3driseai/3drise-core';
|
|
2
|
+
import type { SkySettings, TerrainConfig, TimeSettings } from '@3driseai/3drise-core';
|
|
3
3
|
import type { ObjectReadyProps } from '../types/objectReady';
|
|
4
4
|
import type { OceanWaterSettings } from '@3driseai/3drise-core';
|
|
5
5
|
export interface OceanBuilderProps extends ObjectReadyProps {
|
|
@@ -11,6 +11,9 @@ export interface OceanBuilderProps extends ObjectReadyProps {
|
|
|
11
11
|
timeSettings?: TimeSettings;
|
|
12
12
|
/** Matches SkySystem's sunIntensity, so water brightens with the scene. */
|
|
13
13
|
sunIntensity?: number;
|
|
14
|
+
/** The environment terrain's config: the world ocean's shoreline and the
|
|
15
|
+
* terrain's shadow on the water. Omit (or disabled) for open water. */
|
|
16
|
+
terrain?: TerrainConfig | null;
|
|
14
17
|
}
|
|
15
18
|
/**
|
|
16
19
|
* Picks the water body for the scene.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OceanBuilder.d.ts","sourceRoot":"","sources":["../../src/components/OceanBuilder.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"OceanBuilder.d.ts","sourceRoot":"","sources":["../../src/components/OceanBuilder.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAOhE,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACvD;;uEAEmE;IACnE,QAAQ,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC;IAC9C,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;4EACwE;IACxE,OAAO,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAuC7C,CAAC;AAEF,eAAe,YAAY,CAAC"}
|