@react-three/fiber 10.0.0-canary.c49d4cb → 10.0.0-canary.c5c1a94

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.
@@ -12,7 +12,7 @@ import { HDRLoader } from 'three/examples/jsm/loaders/HDRLoader.js';
12
12
  import { EXRLoader } from 'three/examples/jsm/loaders/EXRLoader.js';
13
13
  import { UltraHDRLoader } from 'three/examples/jsm/loaders/UltraHDRLoader.js';
14
14
  import { GainMapLoader } from '@monogrid/gainmap-js';
15
- import Tb, { unstable_scheduleCallback, unstable_IdlePriority } from 'scheduler';
15
+ import Tb, { unstable_getCurrentPriorityLevel, unstable_IdlePriority, unstable_LowPriority, unstable_NormalPriority, unstable_UserBlockingPriority, unstable_ImmediatePriority, unstable_scheduleCallback } from 'scheduler';
16
16
  import { createWithEqualityFn } from 'zustand/traditional';
17
17
  import { getScheduler } from '@pmndrs/scheduler';
18
18
  export { Scheduler, getScheduler } from '@pmndrs/scheduler';
@@ -444,7 +444,6 @@ function Environment(props) {
444
444
  var __defProp$1 = Object.defineProperty;
445
445
  var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
446
446
  var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
447
- const act = React["act"];
448
447
  const useIsomorphicLayoutEffect = /* @__PURE__ */ (() => typeof window !== "undefined" && (window.document?.createElement || window.navigator?.product === "ReactNative"))() ? React.useLayoutEffect : React.useEffect;
449
448
  function useMutableCallback(fn) {
450
449
  const ref = React.useRef(fn);
@@ -948,9 +947,9 @@ function diffProps(instance, newProps) {
948
947
  const { root, key } = resolve(instance.object, prop);
949
948
  if (root.constructor && root.constructor.length === 0) {
950
949
  const ctor = getMemoizedPrototype(root);
951
- if (!is.und(ctor)) changedProps[key] = ctor[key];
950
+ if (!is.und(ctor)) changedProps[prop] = ctor[key];
952
951
  } else {
953
- changedProps[key] = 0;
952
+ changedProps[prop] = 0;
954
953
  }
955
954
  }
956
955
  return changedProps;
@@ -13683,7 +13682,7 @@ function n0() {
13683
13682
  var t0 = n0();
13684
13683
  const r0 = Xb(t0);
13685
13684
 
13686
- const t = 1, o = 8, r = 32, e = 2;
13685
+ const t = 1, o = 8, r = 32, e = 2, i$1 = 268435456;
13687
13686
 
13688
13687
  function createReconciler(config) {
13689
13688
  const reconciler2 = r0(config);
@@ -13848,7 +13847,15 @@ function setFiberRef(fiber, publicInstance) {
13848
13847
  }
13849
13848
  }
13850
13849
  const reconstructed = [];
13851
- function swapInstances() {
13850
+ function flushReconstructedInstances() {
13851
+ if (reconstructed.length === 0) return;
13852
+ try {
13853
+ swapReconstructedInstances();
13854
+ } finally {
13855
+ reconstructed.length = 0;
13856
+ }
13857
+ }
13858
+ function swapReconstructedInstances() {
13852
13859
  for (const [instance] of reconstructed) {
13853
13860
  const parent = instance.parent;
13854
13861
  if (parent) {
@@ -13897,14 +13904,114 @@ function swapInstances() {
13897
13904
  invalidateInstance(instance);
13898
13905
  }
13899
13906
  }
13900
- reconstructed.length = 0;
13901
13907
  }
13902
13908
  const handleTextInstance = () => {
13903
13909
  };
13904
13910
  const NO_CONTEXT = {};
13905
13911
  let currentUpdatePriority = NoEventPriority;
13906
- const NoFlags = 0;
13907
- const Update = 4;
13912
+ function getEventPriority(type) {
13913
+ switch (type) {
13914
+ case "beforetoggle":
13915
+ case "cancel":
13916
+ case "click":
13917
+ case "close":
13918
+ case "contextmenu":
13919
+ case "copy":
13920
+ case "cut":
13921
+ case "auxclick":
13922
+ case "dblclick":
13923
+ case "dragend":
13924
+ case "dragstart":
13925
+ case "drop":
13926
+ case "focusin":
13927
+ case "focusout":
13928
+ case "input":
13929
+ case "invalid":
13930
+ case "keydown":
13931
+ case "keypress":
13932
+ case "keyup":
13933
+ case "mousedown":
13934
+ case "mouseup":
13935
+ case "paste":
13936
+ case "pause":
13937
+ case "play":
13938
+ case "pointercancel":
13939
+ case "pointerdown":
13940
+ case "pointerup":
13941
+ case "ratechange":
13942
+ case "reset":
13943
+ case "resize":
13944
+ case "seeked":
13945
+ case "submit":
13946
+ case "touchcancel":
13947
+ case "touchend":
13948
+ case "touchstart":
13949
+ case "volumechange":
13950
+ case "change":
13951
+ case "selectionchange":
13952
+ case "compositionstart":
13953
+ case "compositionend":
13954
+ case "compositionupdate":
13955
+ case "beforeinput":
13956
+ case "blur":
13957
+ case "fullscreenchange":
13958
+ case "focus":
13959
+ case "hashchange":
13960
+ case "popstate":
13961
+ case "select":
13962
+ case "selectstart":
13963
+ return e;
13964
+ case "drag":
13965
+ case "dragenter":
13966
+ case "dragexit":
13967
+ case "dragleave":
13968
+ case "dragover":
13969
+ case "mousemove":
13970
+ case "mouseout":
13971
+ case "mouseover":
13972
+ case "pointermove":
13973
+ case "pointerout":
13974
+ case "pointerover":
13975
+ case "scroll":
13976
+ case "touchmove":
13977
+ case "wheel":
13978
+ case "mouseenter":
13979
+ case "mouseleave":
13980
+ case "pointerenter":
13981
+ case "pointerleave":
13982
+ return o;
13983
+ case "message": {
13984
+ switch (unstable_getCurrentPriorityLevel()) {
13985
+ case unstable_ImmediatePriority:
13986
+ return e;
13987
+ case unstable_UserBlockingPriority:
13988
+ return o;
13989
+ case unstable_NormalPriority:
13990
+ case unstable_LowPriority:
13991
+ return r;
13992
+ case unstable_IdlePriority:
13993
+ return i$1;
13994
+ default:
13995
+ return r;
13996
+ }
13997
+ }
13998
+ default:
13999
+ return r;
14000
+ }
14001
+ }
14002
+ function scheduleMicrotask(callback) {
14003
+ if (typeof queueMicrotask === "function") {
14004
+ queueMicrotask(callback);
14005
+ } else if (typeof Promise !== "undefined") {
14006
+ Promise.resolve().then(callback).catch((error) => {
14007
+ setTimeout(() => {
14008
+ throw error;
14009
+ });
14010
+ });
14011
+ } else {
14012
+ setTimeout(callback);
14013
+ }
14014
+ }
13908
14015
  const reconciler = /* @__PURE__ */ createReconciler({
13909
14016
  isPrimaryRenderer: false,
13910
14017
  warnsIfNotActing: false,
@@ -13943,16 +14050,15 @@ const reconciler = /* @__PURE__ */ createReconciler({
13943
14050
  else if (newProps.args?.length !== oldProps.args?.length) reconstruct = true;
13944
14051
  else if (newProps.args?.some((value, index) => value !== oldProps.args?.[index])) reconstruct = true;
13945
14052
  if (reconstruct) {
13946
- reconstructed.push([instance, { ...newProps }, fiber]);
14053
+ reconstructed.push([instance, getInstanceProps(newProps), fiber]);
13947
14054
  } else {
13948
14055
  const changedProps = diffProps(instance, newProps);
13949
- if (Object.keys(changedProps).length) {
13950
- Object.assign(instance.props, changedProps);
13951
- applyProps(instance.object, changedProps);
13952
- }
14056
+ const attach2 = instance.props.attach;
14057
+ instance.props = getInstanceProps(newProps);
14058
+ if (attach2 !== void 0) instance.props.attach = attach2;
14059
+ else delete instance.props.attach;
14060
+ if (Object.keys(changedProps).length) applyProps(instance.object, changedProps);
13953
14061
  }
13954
- const isTailSibling = fiber.sibling === null || (fiber.flags & Update) === NoFlags;
13955
- if (isTailSibling) swapInstances();
13956
14062
  },
13957
14063
  finalizeInitialChildren: (instance) => {
13958
14064
  for (const prop in instance.props) {
@@ -13977,8 +14083,9 @@ const reconciler = /* @__PURE__ */ createReconciler({
13977
14083
  const target = container.getState().internal.container ?? container.getState().scene;
13978
14084
  return prepare(target, container, "", {});
13979
14085
  },
13980
- resetAfterCommit: () => {
13981
- },
14086
+ // Reconstructed instances are swapped once all mutations are committed,
14087
+ // before layout effects run so refs point to the new objects
14088
+ resetAfterCommit: flushReconstructedInstances,
13982
14089
  shouldSetTextContent: () => false,
13983
14090
  clearContainer: () => false,
13984
14091
  hideInstance,
@@ -13986,6 +14093,9 @@ const reconciler = /* @__PURE__ */ createReconciler({
13986
14093
  createTextInstance: handleTextInstance,
13987
14094
  hideTextInstance: handleTextInstance,
13988
14095
  unhideTextInstance: handleTextInstance,
14096
+ // Mirrors react-dom, which flushes discrete work in microtasks
14097
+ supportsMicrotasks: true,
14098
+ scheduleMicrotask,
13989
14099
  scheduleTimeout: typeof setTimeout === "function" ? setTimeout : void 0,
13990
14100
  cancelTimeout: typeof clearTimeout === "function" ? clearTimeout : void 0,
13991
14101
  noTimeout: -1,
@@ -14026,28 +14136,9 @@ const reconciler = /* @__PURE__ */ createReconciler({
14026
14136
  },
14027
14137
  resolveUpdatePriority() {
14028
14138
  if (currentUpdatePriority !== NoEventPriority) return currentUpdatePriority;
14029
- switch (typeof window !== "undefined" && window.event?.type) {
14030
- case "click":
14031
- case "contextmenu":
14032
- case "dblclick":
14033
- case "dragenter":
14034
- case "dragleave":
14035
- case "drop":
14036
- case "pointercancel":
14037
- case "pointerdown":
14038
- case "pointerup":
14039
- return e;
14040
- case "dragover":
14041
- case "pointermove":
14042
- case "pointerout":
14043
- case "pointerover":
14044
- case "pointerenter":
14045
- case "pointerleave":
14046
- case "wheel":
14047
- return o;
14048
- default:
14049
- return r;
14050
- }
14139
+ const eventType = typeof window !== "undefined" ? window.event?.type : void 0;
14140
+ if (eventType === void 0) return r;
14141
+ return getEventPriority(eventType);
14051
14142
  },
14052
14143
  resetFormInstance() {
14053
14144
  },
@@ -14796,14 +14887,133 @@ function parseRendererConfig(rendererProp) {
14796
14887
  return { primaryCanvas: void 0, scheduler: void 0, renderer: rendererProp };
14797
14888
  }
14798
14889
 
14890
+ const RESOURCE_KINDS = ["nodes", "uniforms", "buffers", "gpuStorage"];
14891
+ const ROOT_SCOPE = "";
14892
+ const registries = /* @__PURE__ */ new WeakMap();
14893
+ function getKindRegistry(store, kind) {
14894
+ let registry = registries.get(store);
14895
+ if (!registry) {
14896
+ registry = {
14897
+ nodes: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
14898
+ uniforms: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
14899
+ buffers: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
14900
+ gpuStorage: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() }
14901
+ };
14902
+ registries.set(store, registry);
14903
+ }
14904
+ return registry[kind];
14905
+ }
14906
+ function resolvePrimary$1(store) {
14907
+ return store.getState().primaryStore ?? store;
14908
+ }
14909
+ function isScopeValid(store, kind, scopeKey) {
14910
+ return getKindRegistry(store, kind).valid.has(scopeKey);
14911
+ }
14912
+ function peekStaged(store, kind, scopeKey) {
14913
+ return getKindRegistry(store, kind).staged.get(scopeKey);
14914
+ }
14915
+ function stageEntries(store, kind, scopeKey, entries) {
14916
+ const { staged } = getKindRegistry(store, kind);
14917
+ const current = staged.get(scopeKey);
14918
+ if (current) Object.assign(current, entries);
14919
+ else staged.set(scopeKey, { ...entries });
14920
+ }
14921
+ function readCommittedScope(map, scopeKey, isLeaf) {
14922
+ if (scopeKey === ROOT_SCOPE) {
14923
+ const leaves = {};
14924
+ for (const [key, value] of Object.entries(map)) if (isLeaf(value)) leaves[key] = value;
14925
+ return leaves;
14926
+ }
14927
+ const scopeData = map[scopeKey];
14928
+ if (scopeData && typeof scopeData === "object" && !isLeaf(scopeData)) return scopeData;
14929
+ return {};
14930
+ }
14931
+ function withStagedOverlay(store, kind, committed) {
14932
+ const { staged } = getKindRegistry(store, kind);
14933
+ if (staged.size === 0) return committed;
14934
+ const view = { ...committed };
14935
+ for (const [scopeKey, entries] of staged) {
14936
+ if (scopeKey === ROOT_SCOPE) Object.assign(view, entries);
14937
+ else view[scopeKey] = { ...view[scopeKey], ...entries };
14938
+ }
14939
+ return view;
14940
+ }
14941
+ function flushStagedScope(store, kind, scopeKey, isLeaf) {
14942
+ const registry = getKindRegistry(store, kind);
14943
+ const staged = registry.staged.get(scopeKey);
14944
+ if (!staged) return;
14945
+ registry.staged.delete(scopeKey);
14946
+ const replace = !registry.valid.has(scopeKey);
14947
+ store.setState((state) => {
14948
+ const map = state[kind];
14949
+ if (scopeKey === ROOT_SCOPE) {
14950
+ if (!replace) return { [kind]: { ...map, ...staged } };
14951
+ const next = {};
14952
+ for (const [key, value] of Object.entries(map)) if (!isLeaf(value)) next[key] = value;
14953
+ return { [kind]: { ...next, ...staged } };
14954
+ }
14955
+ const current = replace ? {} : map[scopeKey] ?? {};
14956
+ return { [kind]: { ...map, [scopeKey]: { ...current, ...staged } } };
14957
+ });
14958
+ registry.valid.add(scopeKey);
14959
+ }
14960
+ function invalidateResource(store, kind, scopeKey) {
14961
+ const registry = getKindRegistry(store, kind);
14962
+ if (scopeKey === void 0) {
14963
+ registry.valid.clear();
14964
+ registry.staged.clear();
14965
+ } else {
14966
+ registry.valid.delete(scopeKey);
14967
+ registry.staged.delete(scopeKey);
14968
+ }
14969
+ }
14970
+ function rebuildResource(store, kind, userScope) {
14971
+ const primary = resolvePrimary$1(store);
14972
+ invalidateResource(primary, kind, userScope === "root" ? ROOT_SCOPE : userScope);
14973
+ primary.setState((state) => ({ _hmrVersion: state._hmrVersion + 1 }));
14974
+ }
14975
+ function invalidateAllResources(store) {
14976
+ for (const kind of RESOURCE_KINDS) invalidateResource(store, kind);
14977
+ }
14978
+ function removeResourceEntries(store, kind, names, scope, isLeaf) {
14979
+ const staged = peekStaged(store, kind, scope ?? ROOT_SCOPE);
14980
+ if (staged) for (const name of names) delete staged[name];
14981
+ store.setState((state) => {
14982
+ const map = state[kind];
14983
+ if (scope) {
14984
+ const currentScope = { ...map[scope] };
14985
+ for (const name of names) delete currentScope[name];
14986
+ return { [kind]: { ...map, [scope]: currentScope } };
14987
+ }
14988
+ const next = { ...map };
14989
+ for (const name of names) if (isLeaf(next[name])) delete next[name];
14990
+ return { [kind]: next };
14991
+ });
14992
+ }
14993
+ function clearResourceEntries(store, kind, scope, isLeaf) {
14994
+ const registry = getKindRegistry(store, kind);
14995
+ if (scope && scope !== "root") registry.staged.delete(scope);
14996
+ else if (scope === "root") registry.staged.delete(ROOT_SCOPE);
14997
+ else registry.staged.clear();
14998
+ store.setState((state) => {
14999
+ const map = state[kind];
15000
+ if (scope && scope !== "root") {
15001
+ const { [scope]: _, ...rest } = map;
15002
+ return { [kind]: rest };
15003
+ }
15004
+ if (scope === "root") {
15005
+ const next = {};
15006
+ for (const [key, value] of Object.entries(map)) if (!isLeaf(value)) next[key] = value;
15007
+ return { [kind]: next };
15008
+ }
15009
+ return { [kind]: {} };
15010
+ });
15011
+ }
15012
+
14799
15013
  function clearHmrCaches(store) {
14800
- store.setState((state) => ({
14801
- nodes: {},
14802
- uniforms: {},
14803
- buffers: {},
14804
- gpuStorage: {},
14805
- _hmrVersion: state._hmrVersion + 1
14806
- }));
15014
+ const primary = store.getState().primaryStore ?? store;
15015
+ invalidateAllResources(primary);
15016
+ primary.setState((state) => ({ _hmrVersion: state._hmrVersion + 1 }));
14807
15017
  }
14808
15018
 
14809
15019
  function CanvasImpl({
@@ -15116,30 +15326,31 @@ let ScopedStore = _ScopedStore;
15116
15326
  function createScopedStore(data) {
15117
15327
  return new ScopedStore(data);
15118
15328
  }
15119
- function createLazyCreatorState(state) {
15329
+ function createLazyCreatorState(state, store) {
15120
15330
  let _uniforms = null;
15121
15331
  let _nodes = null;
15122
15332
  let _buffers = null;
15123
15333
  let _gpuStorage = null;
15334
+ const view = (kind) => store ? withStagedOverlay(store, kind, state[kind]) : state[kind];
15124
15335
  return Object.create(state, {
15125
15336
  uniforms: {
15126
15337
  get() {
15127
- return _uniforms ?? (_uniforms = createScopedStore(state.uniforms));
15338
+ return _uniforms ?? (_uniforms = createScopedStore(view("uniforms")));
15128
15339
  }
15129
15340
  },
15130
15341
  nodes: {
15131
15342
  get() {
15132
- return _nodes ?? (_nodes = createScopedStore(state.nodes));
15343
+ return _nodes ?? (_nodes = createScopedStore(view("nodes")));
15133
15344
  }
15134
15345
  },
15135
15346
  buffers: {
15136
15347
  get() {
15137
- return _buffers ?? (_buffers = createScopedStore(state.buffers));
15348
+ return _buffers ?? (_buffers = createScopedStore(view("buffers")));
15138
15349
  }
15139
15350
  },
15140
15351
  gpuStorage: {
15141
15352
  get() {
15142
- return _gpuStorage ?? (_gpuStorage = createScopedStore(state.gpuStorage));
15353
+ return _gpuStorage ?? (_gpuStorage = createScopedStore(view("gpuStorage")));
15143
15354
  }
15144
15355
  }
15145
15356
  });
@@ -15262,65 +15473,56 @@ function useCompareMemoize(value, deep) {
15262
15473
  return ref.current;
15263
15474
  }
15264
15475
 
15476
+ function useScopedResource(options) {
15477
+ const { store, kind, scope, isLeaf, create, prepare, reconcile, input } = options;
15478
+ const scopeKey = scope ?? ROOT_SCOPE;
15479
+ const version = store((s) => s._hmrVersion);
15480
+ const entries = useMemo(() => {
15481
+ const staged = peekStaged(store, kind, scopeKey);
15482
+ const reusable = isScopeValid(store, kind, scopeKey);
15483
+ const map = store.getState()[kind];
15484
+ const committed = reusable ? readCommittedScope(map, scopeKey, isLeaf) : void 0;
15485
+ const result = {};
15486
+ let fresh = null;
15487
+ for (const [name, candidate] of Object.entries(create())) {
15488
+ const existing = staged?.[name] ?? committed?.[name];
15489
+ if (existing !== void 0) {
15490
+ result[name] = existing;
15491
+ reconcile?.(existing, candidate);
15492
+ } else {
15493
+ const value = prepare ? prepare(name, candidate) : candidate;
15494
+ result[name] = value;
15495
+ (fresh ?? (fresh = {}))[name] = value;
15496
+ }
15497
+ }
15498
+ if (fresh) stageEntries(store, kind, scopeKey, fresh);
15499
+ return result;
15500
+ }, [store, kind, scopeKey, version, input]);
15501
+ useIsomorphicLayoutEffect(() => {
15502
+ flushStagedScope(store, kind, scopeKey, isLeaf);
15503
+ });
15504
+ return entries;
15505
+ }
15506
+
15265
15507
  const isUniformNode$1 = (value) => value !== null && typeof value === "object" && "value" in value && "uuid" in value;
15266
15508
  function useUniforms(creatorOrScope, scope) {
15267
15509
  const store = usePrimaryStore();
15268
15510
  const removeUniforms2 = useCallback(
15269
- (names, targetScope) => {
15270
- const nameArray = Array.isArray(names) ? names : [names];
15271
- store.setState((state) => {
15272
- if (targetScope) {
15273
- const currentScope = { ...state.uniforms[targetScope] };
15274
- for (const name of nameArray) delete currentScope[name];
15275
- return { uniforms: { ...state.uniforms, [targetScope]: currentScope } };
15276
- }
15277
- const uniforms2 = { ...state.uniforms };
15278
- for (const name of nameArray) if (isUniformNode$1(uniforms2[name])) delete uniforms2[name];
15279
- return { uniforms: uniforms2 };
15280
- });
15281
- },
15511
+ (names, targetScope) => removeResourceEntries(store, "uniforms", Array.isArray(names) ? names : [names], targetScope, isUniformNode$1),
15282
15512
  [store]
15283
15513
  );
15284
15514
  const clearUniforms = useCallback(
15285
- (targetScope) => {
15286
- store.setState((state) => {
15287
- if (targetScope && targetScope !== "root") {
15288
- const { [targetScope]: _, ...rest } = state.uniforms;
15289
- return { uniforms: rest };
15290
- }
15291
- if (targetScope === "root") {
15292
- const uniforms2 = {};
15293
- for (const [key, value] of Object.entries(state.uniforms)) {
15294
- if (!isUniformNode$1(value)) uniforms2[key] = value;
15295
- }
15296
- return { uniforms: uniforms2 };
15297
- }
15298
- return { uniforms: {} };
15299
- });
15300
- },
15515
+ (targetScope) => clearResourceEntries(store, "uniforms", targetScope, isUniformNode$1),
15301
15516
  [store]
15302
15517
  );
15303
15518
  const rebuildUniforms = useCallback(
15304
- (targetScope) => {
15305
- store.setState((state) => {
15306
- let newUniforms = {};
15307
- if (targetScope && targetScope !== "root") {
15308
- const { [targetScope]: _, ...rest } = state.uniforms;
15309
- newUniforms = rest;
15310
- } else if (targetScope === "root") {
15311
- for (const [key, value] of Object.entries(state.uniforms)) {
15312
- if (!isUniformNode$1(value)) newUniforms[key] = value;
15313
- }
15314
- }
15315
- return { uniforms: newUniforms, _hmrVersion: state._hmrVersion + 1 };
15316
- });
15317
- },
15519
+ (targetScope) => rebuildResource(store, "uniforms", targetScope),
15318
15520
  [store]
15319
15521
  );
15320
15522
  const inputForMemoization = useMemo(() => {
15321
15523
  let raw = creatorOrScope;
15322
15524
  if (is.fun(creatorOrScope)) {
15323
- const wrappedState = createLazyCreatorState(store.getState());
15525
+ const wrappedState = createLazyCreatorState(store.getState(), store);
15324
15526
  raw = creatorOrScope(wrappedState);
15325
15527
  }
15326
15528
  if (raw && typeof raw === "object" && !Array.isArray(raw)) {
@@ -15335,80 +15537,43 @@ function useUniforms(creatorOrScope, scope) {
15335
15537
  const memoizedInput = useCompareMemoize(inputForMemoization);
15336
15538
  const isReader = memoizedInput === void 0 || typeof memoizedInput === "string";
15337
15539
  const storeUniforms = usePrimaryThree((s) => s.uniforms);
15338
- const hmrVersion = usePrimaryThree((s) => s._hmrVersion);
15339
- const readerDep = isReader ? storeUniforms : null;
15340
- const creatorDep = isReader ? null : hmrVersion;
15341
- const uniforms = useMemo(() => {
15342
- if (memoizedInput === void 0) {
15343
- return storeUniforms;
15344
- }
15345
- if (typeof memoizedInput === "string") {
15346
- const scopeData = storeUniforms[memoizedInput];
15347
- if (scopeData && !isUniformNode$1(scopeData)) return scopeData;
15348
- return {};
15349
- }
15350
- const state = store.getState();
15351
- const set = store.setState;
15352
- if (typeof memoizedInput !== "object" || memoizedInput === null) {
15353
- throw new Error("Invalid uniform input");
15354
- }
15355
- const created = memoizedInput;
15356
- const result = {};
15357
- let hasNewUniforms = false;
15358
- let targetRecord = state.uniforms;
15359
- if (scope) {
15360
- if (!state.uniforms[scope]) state.uniforms[scope] = {};
15361
- targetRecord = state.uniforms[scope];
15362
- }
15363
- for (const [name, node] of Object.entries(created)) {
15364
- if (targetRecord[name]) {
15365
- result[name] = targetRecord[name];
15366
- const existingVal = result[name].value;
15367
- const newVal = vectorize(node);
15368
- let equals = newVal === existingVal;
15369
- if (!equals && hasEqualsMethod(existingVal) && hasEqualsMethod(newVal)) {
15370
- if (isThreeVector(existingVal) && isThreeVector(newVal)) {
15371
- equals = vectorEquals(existingVal, newVal);
15372
- } else if (isSameThreeType(existingVal, newVal)) {
15373
- equals = existingVal.equals(newVal);
15374
- }
15375
- }
15376
- if (!equals) result[name].value = newVal;
15377
- } else {
15378
- result[name] = createUniform(name, node, scope);
15379
- hasNewUniforms = true;
15380
- }
15381
- }
15382
- if (hasNewUniforms) {
15383
- if (scope) {
15384
- set((s) => ({
15385
- uniforms: {
15386
- ...s.uniforms,
15387
- [scope]: { ...s.uniforms[scope], ...result }
15388
- }
15389
- }));
15390
- } else {
15391
- set((s) => ({ uniforms: { ...s.uniforms, ...result } }));
15392
- }
15540
+ const created = useScopedResource({
15541
+ store,
15542
+ kind: "uniforms",
15543
+ scope: isReader ? void 0 : scope,
15544
+ isLeaf: isUniformNode$1,
15545
+ input: memoizedInput,
15546
+ create: () => {
15547
+ if (isReader) return {};
15548
+ if (typeof memoizedInput !== "object" || memoizedInput === null) throw new Error("Invalid uniform input");
15549
+ return memoizedInput;
15550
+ },
15551
+ prepare: (name, candidate) => createUniform(name, candidate, scope),
15552
+ reconcile: (existing, candidate) => {
15553
+ const existingVal = existing.value;
15554
+ const newVal = vectorize(candidate);
15555
+ let equals = newVal === existingVal;
15556
+ if (!equals && hasEqualsMethod(existingVal) && hasEqualsMethod(newVal)) {
15557
+ if (isThreeVector(existingVal) && isThreeVector(newVal)) {
15558
+ equals = vectorEquals(existingVal, newVal);
15559
+ } else if (isSameThreeType(existingVal, newVal)) {
15560
+ equals = existingVal.equals(newVal);
15561
+ }
15562
+ }
15563
+ if (!equals) existing.value = newVal;
15393
15564
  }
15394
- return result;
15395
- }, [store, memoizedInput, scope, readerDep, creatorDep]);
15565
+ });
15566
+ let uniforms = created;
15567
+ if (memoizedInput === void 0) {
15568
+ uniforms = storeUniforms;
15569
+ } else if (typeof memoizedInput === "string") {
15570
+ const scopeData = storeUniforms[memoizedInput];
15571
+ uniforms = scopeData && !isUniformNode$1(scopeData) ? scopeData : {};
15572
+ }
15396
15573
  return { ...uniforms, removeUniforms: removeUniforms2, clearUniforms, rebuildUniforms };
15397
15574
  }
15398
15575
  function rebuildAllUniforms(store, scope) {
15399
- store = store.getState().primaryStore ?? store;
15400
- store.setState((state) => {
15401
- let newUniforms = {};
15402
- if (scope && scope !== "root") {
15403
- const { [scope]: _, ...rest } = state.uniforms;
15404
- newUniforms = rest;
15405
- } else if (scope === "root") {
15406
- for (const [key, value] of Object.entries(state.uniforms)) {
15407
- if (!isUniformNode$1(value)) newUniforms[key] = value;
15408
- }
15409
- }
15410
- return { uniforms: newUniforms, _hmrVersion: state._hmrVersion + 1 };
15411
- });
15576
+ rebuildResource(store, "uniforms", scope);
15412
15577
  }
15413
15578
  function removeUniforms(set, names, scope) {
15414
15579
  set((state) => {
@@ -15477,188 +15642,86 @@ const isUniformNode = (value) => value !== null && typeof value === "object" &&
15477
15642
  const isTSLNode$1 = (value) => value !== null && typeof value === "object" && "uuid" in value && "nodeType" in value;
15478
15643
  function useUniform(name, value) {
15479
15644
  const store = useStore();
15480
- const hmrVersion = useThree((s) => s._hmrVersion);
15481
- return useMemo(() => {
15482
- const state = store.getState();
15483
- const set = store.setState;
15484
- const existing = state.uniforms[name];
15485
- if (existing && isUniformNode(existing)) {
15645
+ const registered = useScopedResource({
15646
+ store,
15647
+ kind: "uniforms",
15648
+ scope: void 0,
15649
+ isLeaf: isUniformNode,
15650
+ input: name,
15651
+ create: () => value === void 0 ? {} : { [name]: value },
15652
+ prepare: createNamedUniform,
15653
+ reconcile: (existing2) => {
15486
15654
  if (value !== void 0 && !isTSLNode$1(value) && !isUniformNode(value)) {
15487
- existing.value = typeof value === "string" ? new Color(value) : value;
15655
+ existing2.value = typeof value === "string" ? new Color(value) : value;
15488
15656
  }
15489
- return existing;
15490
- }
15491
- if (value === void 0) {
15492
- throw new Error(
15493
- `[useUniform] Uniform "${name}" not found. Create it first with: useUniform('${name}', initialValue)`
15494
- );
15495
- }
15496
- if (isUniformNode(value)) {
15497
- const node2 = value;
15498
- if (typeof node2.setName === "function") {
15499
- node2.setName(name);
15500
- }
15501
- set((s) => ({
15502
- uniforms: { ...s.uniforms, [name]: node2 }
15503
- }));
15504
- return node2;
15505
15657
  }
15506
- let node;
15507
- if (isTSLNode$1(value)) {
15508
- node = uniformOf(value);
15509
- } else if (typeof value === "string") {
15510
- node = uniform(new Color(value));
15511
- } else {
15512
- node = uniformOf(value);
15513
- }
15514
- if (typeof node.setName === "function") {
15515
- node.setName(name);
15516
- }
15517
- set((s) => ({
15518
- uniforms: {
15519
- ...s.uniforms,
15520
- [name]: node
15521
- }
15522
- }));
15523
- return node;
15524
- }, [store, name, hmrVersion]);
15658
+ });
15659
+ if (registered[name]) return registered[name];
15660
+ const existing = peekStaged(store, "uniforms", ROOT_SCOPE)?.[name] ?? store.getState().uniforms[name];
15661
+ if (existing && isUniformNode(existing)) return existing;
15662
+ throw new Error(
15663
+ `[useUniform] Uniform "${name}" not found. Create it first with: useUniform('${name}', initialValue)`
15664
+ );
15665
+ }
15666
+ function createNamedUniform(name, value) {
15667
+ let node;
15668
+ if (isUniformNode(value)) {
15669
+ node = value;
15670
+ } else if (isTSLNode$1(value)) {
15671
+ node = uniformOf(value);
15672
+ } else if (typeof value === "string") {
15673
+ node = uniform(new Color(value));
15674
+ } else {
15675
+ node = uniformOf(value);
15676
+ }
15677
+ if (typeof node.setName === "function") {
15678
+ node.setName(name);
15679
+ }
15680
+ return node;
15525
15681
  }
15526
15682
 
15527
15683
  const isTSLNode = (value) => value !== null && typeof value === "object" && ("uuid" in value || "nodeType" in value);
15528
15684
  function useNodes(creatorOrScope, scope) {
15529
15685
  const store = usePrimaryStore();
15530
15686
  const removeNodes2 = useCallback(
15531
- (names, targetScope) => {
15532
- const nameArray = Array.isArray(names) ? names : [names];
15533
- store.setState((state) => {
15534
- if (targetScope) {
15535
- const currentScope = { ...state.nodes[targetScope] };
15536
- for (const name of nameArray) delete currentScope[name];
15537
- return { nodes: { ...state.nodes, [targetScope]: currentScope } };
15538
- }
15539
- const nodes2 = { ...state.nodes };
15540
- for (const name of nameArray) if (isTSLNode(nodes2[name])) delete nodes2[name];
15541
- return { nodes: nodes2 };
15542
- });
15543
- },
15687
+ (names, targetScope) => removeResourceEntries(store, "nodes", Array.isArray(names) ? names : [names], targetScope, isTSLNode),
15544
15688
  [store]
15545
15689
  );
15546
15690
  const clearNodes = useCallback(
15547
- (targetScope) => {
15548
- store.setState((state) => {
15549
- if (targetScope && targetScope !== "root") {
15550
- const { [targetScope]: _, ...rest } = state.nodes;
15551
- return { nodes: rest };
15552
- }
15553
- if (targetScope === "root") {
15554
- const nodes2 = {};
15555
- for (const [key, value] of Object.entries(state.nodes)) {
15556
- if (!isTSLNode(value)) nodes2[key] = value;
15557
- }
15558
- return { nodes: nodes2 };
15559
- }
15560
- return { nodes: {} };
15561
- });
15562
- },
15691
+ (targetScope) => clearResourceEntries(store, "nodes", targetScope, isTSLNode),
15563
15692
  [store]
15564
15693
  );
15565
15694
  const rebuildNodes = useCallback(
15566
- (targetScope) => {
15567
- store.setState((state) => {
15568
- let newNodes = state.nodes;
15569
- if (targetScope && targetScope !== "root") {
15570
- const { [targetScope]: _, ...rest } = state.nodes;
15571
- newNodes = rest;
15572
- } else if (targetScope === "root") {
15573
- newNodes = {};
15574
- for (const [key, value] of Object.entries(state.nodes)) {
15575
- if (!isTSLNode(value)) newNodes[key] = value;
15576
- }
15577
- } else {
15578
- newNodes = {};
15579
- }
15580
- return { nodes: newNodes, _hmrVersion: state._hmrVersion + 1 };
15581
- });
15582
- },
15695
+ (targetScope) => rebuildResource(store, "nodes", targetScope),
15583
15696
  [store]
15584
15697
  );
15585
15698
  const isReader = creatorOrScope === void 0 || typeof creatorOrScope === "string";
15586
15699
  const storeNodes = usePrimaryThree((s) => s.nodes);
15587
- const hmrVersion = usePrimaryThree((s) => s._hmrVersion);
15588
- const scopeDep = typeof creatorOrScope === "string" ? creatorOrScope : scope;
15589
- const readerDep = isReader ? storeNodes : null;
15590
- const creatorDep = isReader ? null : hmrVersion;
15591
- const nodes = useMemo(() => {
15592
- if (creatorOrScope === void 0) {
15593
- return storeNodes;
15594
- }
15595
- if (typeof creatorOrScope === "string") {
15596
- const scopeData = storeNodes[creatorOrScope];
15597
- if (scopeData && !isTSLNode(scopeData)) return scopeData;
15598
- return {};
15599
- }
15600
- const state = store.getState();
15601
- const set = store.setState;
15602
- const creator = creatorOrScope;
15603
- const wrappedState = createLazyCreatorState(state);
15604
- const created = creator(wrappedState);
15605
- const result = {};
15606
- let hasNewNodes = false;
15607
- if (scope) {
15608
- const currentScope = state.nodes[scope] ?? {};
15609
- for (const [name, node] of Object.entries(created)) {
15610
- if (currentScope[name]) {
15611
- result[name] = currentScope[name];
15612
- } else {
15613
- node.setName?.(`${scope}.${name}`);
15614
- result[name] = node;
15615
- hasNewNodes = true;
15616
- }
15617
- }
15618
- if (hasNewNodes) {
15619
- set((s) => ({
15620
- nodes: {
15621
- ...s.nodes,
15622
- [scope]: { ...s.nodes[scope], ...result }
15623
- }
15624
- }));
15625
- }
15626
- return result;
15627
- }
15628
- for (const [name, node] of Object.entries(created)) {
15629
- const existing = state.nodes[name];
15630
- if (existing && isTSLNode(existing)) {
15631
- result[name] = existing;
15632
- } else {
15633
- node.setName?.(name);
15634
- result[name] = node;
15635
- hasNewNodes = true;
15636
- }
15637
- }
15638
- if (hasNewNodes) {
15639
- set((s) => ({ nodes: { ...s.nodes, ...result } }));
15700
+ const created = useScopedResource({
15701
+ store,
15702
+ kind: "nodes",
15703
+ scope: isReader ? void 0 : scope,
15704
+ isLeaf: isTSLNode,
15705
+ create: () => {
15706
+ if (isReader) return {};
15707
+ return creatorOrScope(createLazyCreatorState(store.getState(), store));
15708
+ },
15709
+ prepare: (name, node) => {
15710
+ node.setName?.(scope ? `${scope}.${name}` : name);
15711
+ return node;
15640
15712
  }
15641
- return result;
15642
- }, [store, scopeDep, readerDep, creatorDep]);
15713
+ });
15714
+ let nodes = created;
15715
+ if (creatorOrScope === void 0) {
15716
+ nodes = storeNodes;
15717
+ } else if (typeof creatorOrScope === "string") {
15718
+ const scopeData = storeNodes[creatorOrScope];
15719
+ nodes = scopeData && !isTSLNode(scopeData) ? scopeData : {};
15720
+ }
15643
15721
  return { ...nodes, removeNodes: removeNodes2, clearNodes, rebuildNodes };
15644
15722
  }
15645
15723
  function rebuildAllNodes(store, scope) {
15646
- store = store.getState().primaryStore ?? store;
15647
- store.setState((state) => {
15648
- let newNodes = state.nodes;
15649
- if (scope && scope !== "root") {
15650
- const { [scope]: _, ...rest } = state.nodes;
15651
- newNodes = rest;
15652
- } else if (scope === "root") {
15653
- newNodes = {};
15654
- for (const [key, value] of Object.entries(state.nodes)) {
15655
- if (!isTSLNode(value)) newNodes[key] = value;
15656
- }
15657
- } else {
15658
- newNodes = {};
15659
- }
15660
- return { nodes: newNodes, _hmrVersion: state._hmrVersion + 1 };
15661
- });
15724
+ rebuildResource(store, "nodes", scope);
15662
15725
  }
15663
15726
  function removeNodes(set, names, scope) {
15664
15727
  set((state) => {
@@ -15694,7 +15757,7 @@ function useLocalNodes(creator) {
15694
15757
  const textures = usePrimaryThree((s) => s.textures);
15695
15758
  const hmrVersion = usePrimaryThree((s) => s._hmrVersion);
15696
15759
  return useMemo(() => {
15697
- const wrappedState = createLazyCreatorState(store.getState());
15760
+ const wrappedState = createLazyCreatorState(store.getState(), store);
15698
15761
  return creator(wrappedState);
15699
15762
  }, [store, creator, uniforms, nodes, textures, hmrVersion]);
15700
15763
  }
@@ -15715,58 +15778,15 @@ const disposeBuffer = (buffer) => {
15715
15778
  function useBuffers(creatorOrScope, scope) {
15716
15779
  const store = usePrimaryStore();
15717
15780
  const removeBuffers = useCallback(
15718
- (names, targetScope) => {
15719
- const nameArray = Array.isArray(names) ? names : [names];
15720
- store.setState((state) => {
15721
- if (targetScope) {
15722
- const currentScope = { ...state.buffers[targetScope] };
15723
- for (const name of nameArray) delete currentScope[name];
15724
- return { buffers: { ...state.buffers, [targetScope]: currentScope } };
15725
- }
15726
- const buffers2 = { ...state.buffers };
15727
- for (const name of nameArray) if (isBufferLike(buffers2[name])) delete buffers2[name];
15728
- return { buffers: buffers2 };
15729
- });
15730
- },
15781
+ (names, targetScope) => removeResourceEntries(store, "buffers", Array.isArray(names) ? names : [names], targetScope, isBufferLike),
15731
15782
  [store]
15732
15783
  );
15733
15784
  const clearBuffers = useCallback(
15734
- (targetScope) => {
15735
- store.setState((state) => {
15736
- if (targetScope && targetScope !== "root") {
15737
- const { [targetScope]: _, ...rest } = state.buffers;
15738
- return { buffers: rest };
15739
- }
15740
- if (targetScope === "root") {
15741
- const buffers2 = {};
15742
- for (const [key, value] of Object.entries(state.buffers)) {
15743
- if (!isBufferLike(value)) buffers2[key] = value;
15744
- }
15745
- return { buffers: buffers2 };
15746
- }
15747
- return { buffers: {} };
15748
- });
15749
- },
15785
+ (targetScope) => clearResourceEntries(store, "buffers", targetScope, isBufferLike),
15750
15786
  [store]
15751
15787
  );
15752
15788
  const rebuildBuffers = useCallback(
15753
- (targetScope) => {
15754
- store.setState((state) => {
15755
- let newBuffers = state.buffers;
15756
- if (targetScope && targetScope !== "root") {
15757
- const { [targetScope]: _, ...rest } = state.buffers;
15758
- newBuffers = rest;
15759
- } else if (targetScope === "root") {
15760
- newBuffers = {};
15761
- for (const [key, value] of Object.entries(state.buffers)) {
15762
- if (!isBufferLike(value)) newBuffers[key] = value;
15763
- }
15764
- } else {
15765
- newBuffers = {};
15766
- }
15767
- return { buffers: newBuffers, _hmrVersion: state._hmrVersion + 1 };
15768
- });
15769
- },
15789
+ (targetScope) => rebuildResource(store, "buffers", targetScope),
15770
15790
  [store]
15771
15791
  );
15772
15792
  const disposeBuffers = useCallback(
@@ -15785,85 +15805,33 @@ function useBuffers(creatorOrScope, scope) {
15785
15805
  );
15786
15806
  const isReader = creatorOrScope === void 0 || typeof creatorOrScope === "string";
15787
15807
  const storeBuffers = usePrimaryThree((s) => s.buffers);
15788
- const hmrVersion = usePrimaryThree((s) => s._hmrVersion);
15789
- const scopeDep = typeof creatorOrScope === "string" ? creatorOrScope : scope;
15790
- const readerDep = isReader ? storeBuffers : null;
15791
- const creatorDep = isReader ? null : hmrVersion;
15792
- const buffers = useMemo(() => {
15793
- if (creatorOrScope === void 0) {
15794
- return storeBuffers;
15795
- }
15796
- if (typeof creatorOrScope === "string") {
15797
- const scopeData = storeBuffers[creatorOrScope];
15798
- if (scopeData && !isBufferLike(scopeData)) return scopeData;
15799
- return {};
15800
- }
15801
- const state = store.getState();
15802
- const set = store.setState;
15803
- const creator = creatorOrScope;
15804
- const wrappedState = createLazyCreatorState(state);
15805
- const created = creator(wrappedState);
15806
- const result = {};
15807
- let hasNewBuffers = false;
15808
- if (scope) {
15809
- const currentScope = state.buffers[scope] ?? {};
15810
- for (const [name, buffer] of Object.entries(created)) {
15811
- if (currentScope[name]) {
15812
- result[name] = currentScope[name];
15813
- } else {
15814
- if ("setName" in buffer && typeof buffer.setName === "function") {
15815
- buffer.setName(`${scope}.${name}`);
15816
- }
15817
- result[name] = buffer;
15818
- hasNewBuffers = true;
15819
- }
15820
- }
15821
- if (hasNewBuffers) {
15822
- set((s) => ({
15823
- buffers: {
15824
- ...s.buffers,
15825
- [scope]: { ...s.buffers[scope], ...result }
15826
- }
15827
- }));
15828
- }
15829
- return result;
15830
- }
15831
- for (const [name, buffer] of Object.entries(created)) {
15832
- const existing = state.buffers[name];
15833
- if (existing && isBufferLike(existing)) {
15834
- result[name] = existing;
15835
- } else {
15836
- if ("setName" in buffer && typeof buffer.setName === "function") {
15837
- buffer.setName(name);
15838
- }
15839
- result[name] = buffer;
15840
- hasNewBuffers = true;
15808
+ const created = useScopedResource({
15809
+ store,
15810
+ kind: "buffers",
15811
+ scope: isReader ? void 0 : scope,
15812
+ isLeaf: isBufferLike,
15813
+ create: () => {
15814
+ if (isReader) return {};
15815
+ return creatorOrScope(createLazyCreatorState(store.getState(), store));
15816
+ },
15817
+ prepare: (name, buffer) => {
15818
+ if ("setName" in buffer && typeof buffer.setName === "function") {
15819
+ buffer.setName(scope ? `${scope}.${name}` : name);
15841
15820
  }
15821
+ return buffer;
15842
15822
  }
15843
- if (hasNewBuffers) {
15844
- set((s) => ({ buffers: { ...s.buffers, ...result } }));
15845
- }
15846
- return result;
15847
- }, [store, scopeDep, readerDep, creatorDep]);
15823
+ });
15824
+ let buffers = created;
15825
+ if (creatorOrScope === void 0) {
15826
+ buffers = storeBuffers;
15827
+ } else if (typeof creatorOrScope === "string") {
15828
+ const scopeData = storeBuffers[creatorOrScope];
15829
+ buffers = scopeData && !isBufferLike(scopeData) ? scopeData : {};
15830
+ }
15848
15831
  return { ...buffers, removeBuffers, clearBuffers, rebuildBuffers, disposeBuffers };
15849
15832
  }
15850
15833
  function rebuildAllBuffers(store, scope) {
15851
- store = store.getState().primaryStore ?? store;
15852
- store.setState((state) => {
15853
- let newBuffers = state.buffers;
15854
- if (scope && scope !== "root") {
15855
- const { [scope]: _, ...rest } = state.buffers;
15856
- newBuffers = rest;
15857
- } else if (scope === "root") {
15858
- newBuffers = {};
15859
- for (const [key, value] of Object.entries(state.buffers)) {
15860
- if (!isBufferLike(value)) newBuffers[key] = value;
15861
- }
15862
- } else {
15863
- newBuffers = {};
15864
- }
15865
- return { buffers: newBuffers, _hmrVersion: state._hmrVersion + 1 };
15866
- });
15834
+ rebuildResource(store, "buffers", scope);
15867
15835
  }
15868
15836
 
15869
15837
  const isStorageLike = (value) => {
@@ -15882,58 +15850,15 @@ const disposeStorage = (storage) => {
15882
15850
  function useGPUStorage(creatorOrScope, scope) {
15883
15851
  const store = usePrimaryStore();
15884
15852
  const removeStorage = useCallback(
15885
- (names, targetScope) => {
15886
- const nameArray = Array.isArray(names) ? names : [names];
15887
- store.setState((state) => {
15888
- if (targetScope) {
15889
- const currentScope = { ...state.gpuStorage[targetScope] };
15890
- for (const name of nameArray) delete currentScope[name];
15891
- return { gpuStorage: { ...state.gpuStorage, [targetScope]: currentScope } };
15892
- }
15893
- const gpuStorage2 = { ...state.gpuStorage };
15894
- for (const name of nameArray) if (isStorageLike(gpuStorage2[name])) delete gpuStorage2[name];
15895
- return { gpuStorage: gpuStorage2 };
15896
- });
15897
- },
15853
+ (names, targetScope) => removeResourceEntries(store, "gpuStorage", Array.isArray(names) ? names : [names], targetScope, isStorageLike),
15898
15854
  [store]
15899
15855
  );
15900
15856
  const clearStorage = useCallback(
15901
- (targetScope) => {
15902
- store.setState((state) => {
15903
- if (targetScope && targetScope !== "root") {
15904
- const { [targetScope]: _, ...rest } = state.gpuStorage;
15905
- return { gpuStorage: rest };
15906
- }
15907
- if (targetScope === "root") {
15908
- const gpuStorage2 = {};
15909
- for (const [key, value] of Object.entries(state.gpuStorage)) {
15910
- if (!isStorageLike(value)) gpuStorage2[key] = value;
15911
- }
15912
- return { gpuStorage: gpuStorage2 };
15913
- }
15914
- return { gpuStorage: {} };
15915
- });
15916
- },
15857
+ (targetScope) => clearResourceEntries(store, "gpuStorage", targetScope, isStorageLike),
15917
15858
  [store]
15918
15859
  );
15919
15860
  const rebuildStorage = useCallback(
15920
- (targetScope) => {
15921
- store.setState((state) => {
15922
- let newStorage = state.gpuStorage;
15923
- if (targetScope && targetScope !== "root") {
15924
- const { [targetScope]: _, ...rest } = state.gpuStorage;
15925
- newStorage = rest;
15926
- } else if (targetScope === "root") {
15927
- newStorage = {};
15928
- for (const [key, value] of Object.entries(state.gpuStorage)) {
15929
- if (!isStorageLike(value)) newStorage[key] = value;
15930
- }
15931
- } else {
15932
- newStorage = {};
15933
- }
15934
- return { gpuStorage: newStorage, _hmrVersion: state._hmrVersion + 1 };
15935
- });
15936
- },
15861
+ (targetScope) => rebuildResource(store, "gpuStorage", targetScope),
15937
15862
  [store]
15938
15863
  );
15939
15864
  const disposeStorageFn = useCallback(
@@ -15952,72 +15877,33 @@ function useGPUStorage(creatorOrScope, scope) {
15952
15877
  );
15953
15878
  const isReader = creatorOrScope === void 0 || typeof creatorOrScope === "string";
15954
15879
  const storeStorage = usePrimaryThree((s) => s.gpuStorage);
15955
- const hmrVersion = usePrimaryThree((s) => s._hmrVersion);
15956
- const scopeDep = typeof creatorOrScope === "string" ? creatorOrScope : scope;
15957
- const readerDep = isReader ? storeStorage : null;
15958
- const creatorDep = isReader ? null : hmrVersion;
15959
- const gpuStorage = useMemo(() => {
15960
- if (creatorOrScope === void 0) {
15961
- return storeStorage;
15962
- }
15963
- if (typeof creatorOrScope === "string") {
15964
- const scopeData = storeStorage[creatorOrScope];
15965
- if (scopeData && !isStorageLike(scopeData)) return scopeData;
15966
- return {};
15967
- }
15968
- const state = store.getState();
15969
- const set = store.setState;
15970
- const creator = creatorOrScope;
15971
- const wrappedState = createLazyCreatorState(state);
15972
- const created = creator(wrappedState);
15973
- const result = {};
15974
- let hasNewStorage = false;
15975
- if (scope) {
15976
- const currentScope = state.gpuStorage[scope] ?? {};
15977
- for (const [name, storage] of Object.entries(created)) {
15978
- if (currentScope[name]) {
15979
- result[name] = currentScope[name];
15980
- } else {
15981
- if ("setName" in storage && typeof storage.setName === "function") {
15982
- storage.setName(`${scope}.${name}`);
15983
- }
15984
- if ("name" in storage && typeof storage.name === "string") {
15985
- storage.name = `${scope}.${name}`;
15986
- }
15987
- result[name] = storage;
15988
- hasNewStorage = true;
15989
- }
15880
+ const created = useScopedResource({
15881
+ store,
15882
+ kind: "gpuStorage",
15883
+ scope: isReader ? void 0 : scope,
15884
+ isLeaf: isStorageLike,
15885
+ create: () => {
15886
+ if (isReader) return {};
15887
+ return creatorOrScope(createLazyCreatorState(store.getState(), store));
15888
+ },
15889
+ prepare: (name, storage) => {
15890
+ const label = scope ? `${scope}.${name}` : name;
15891
+ if ("setName" in storage && typeof storage.setName === "function") {
15892
+ storage.setName(label);
15990
15893
  }
15991
- if (hasNewStorage) {
15992
- set((s) => ({
15993
- gpuStorage: {
15994
- ...s.gpuStorage,
15995
- [scope]: { ...s.gpuStorage[scope], ...result }
15996
- }
15997
- }));
15894
+ if ("name" in storage && typeof storage.name === "string") {
15895
+ storage.name = label;
15998
15896
  }
15999
- return result;
15897
+ return storage;
16000
15898
  }
16001
- for (const [name, storage] of Object.entries(created)) {
16002
- const existing = state.gpuStorage[name];
16003
- if (existing && isStorageLike(existing)) {
16004
- result[name] = existing;
16005
- } else {
16006
- if ("setName" in storage && typeof storage.setName === "function") {
16007
- storage.setName(name);
16008
- }
16009
- if ("name" in storage && typeof storage.name === "string") {
16010
- storage.name = name;
16011
- }
16012
- result[name] = storage;
16013
- hasNewStorage = true;
16014
- }
16015
- }
16016
- if (hasNewStorage) {
16017
- set((s) => ({ gpuStorage: { ...s.gpuStorage, ...result } }));
16018
- }
16019
- return result;
16020
- }, [store, scopeDep, readerDep, creatorDep]);
15899
+ });
15900
+ let gpuStorage = created;
15901
+ if (creatorOrScope === void 0) {
15902
+ gpuStorage = storeStorage;
15903
+ } else if (typeof creatorOrScope === "string") {
15904
+ const scopeData = storeStorage[creatorOrScope];
15905
+ gpuStorage = scopeData && !isStorageLike(scopeData) ? scopeData : {};
15906
+ }
16021
15907
  return {
16022
15908
  ...gpuStorage,
16023
15909
  removeStorage,
@@ -16027,22 +15913,7 @@ function useGPUStorage(creatorOrScope, scope) {
16027
15913
  };
16028
15914
  }
16029
15915
  function rebuildAllStorage(store, scope) {
16030
- store = store.getState().primaryStore ?? store;
16031
- store.setState((state) => {
16032
- let newStorage = state.gpuStorage;
16033
- if (scope && scope !== "root") {
16034
- const { [scope]: _, ...rest } = state.gpuStorage;
16035
- newStorage = rest;
16036
- } else if (scope === "root") {
16037
- newStorage = {};
16038
- for (const [key, value] of Object.entries(state.gpuStorage)) {
16039
- if (!isStorageLike(value)) newStorage[key] = value;
16040
- }
16041
- } else {
16042
- newStorage = {};
16043
- }
16044
- return { gpuStorage: newStorage, _hmrVersion: state._hmrVersion + 1 };
16045
- });
15916
+ rebuildResource(store, "gpuStorage", scope);
16046
15917
  }
16047
15918
 
16048
15919
  function useRenderPipeline(mainCB, setupCB) {
@@ -16140,4 +16011,4 @@ function useRenderPipeline(mainCB, setupCB) {
16140
16011
 
16141
16012
  extend(THREE);
16142
16013
 
16143
- export { Block, Canvas, Environment, EnvironmentCube, EnvironmentMap, EnvironmentPortal, ErrorBoundary, FROM_REF, IsObject, ONCE, Portal, R3F_BUILD_LEGACY, R3F_BUILD_WEBGPU, REACT_INTERNAL_PROPS, RESERVED_PROPS, Texture, _roots, act, addAfterEffect, addEffect, addTail, advance, applyProps, attach, buildGraph, calculateDpr, clearNodeScope, clearRootNodes, clearRootUniforms, clearScope, context, createEvents, createPointerEvents, createPortal, createRoot, createScopedStore, createStore, createTextureOperations, detach, diffProps, dispose, createPointerEvents as events, extend, findInitialRoot, flushSync, fromRef, getInstanceProps, getPrimary, getPrimaryIds, getRootState, getUuidPrefix, hasConstructor, hasPrimary, invalidate, invalidateInstance, is, isColorRepresentation, isCopyable, isFromRef, isObject3D, isOnce, isOrthographicCamera, isRef, isRenderer, isTexture, isVectorLike, once, prepare, presetsObj, rebuildAllBuffers, rebuildAllNodes, rebuildAllStorage, rebuildAllUniforms, reconciler, registerPrimary, removeInteractivity, removeNodes, removeUniforms, resolve, unmountComponentAtNode, unregisterPrimary, updateCamera, updateFrustum, useBridge, useBuffers, useEnvironment, useFrame, useGPUStorage, useGraph, useInstanceHandle, useIsomorphicLayoutEffect, useLoader, useLocalNodes, useMutableCallback, useNodes, useRenderPipeline, useRenderTarget, useStore, useTexture, useTextures, useThree, useUniform, useUniforms, waitForPrimary };
16014
+ export { Block, Canvas, Environment, EnvironmentCube, EnvironmentMap, EnvironmentPortal, ErrorBoundary, FROM_REF, IsObject, ONCE, Portal, R3F_BUILD_LEGACY, R3F_BUILD_WEBGPU, REACT_INTERNAL_PROPS, RESERVED_PROPS, Texture, _roots, addAfterEffect, addEffect, addTail, advance, applyProps, attach, buildGraph, calculateDpr, clearNodeScope, clearRootNodes, clearRootUniforms, clearScope, context, createEvents, createPointerEvents, createPortal, createRoot, createScopedStore, createStore, createTextureOperations, detach, diffProps, dispose, createPointerEvents as events, extend, findInitialRoot, flushSync, fromRef, getInstanceProps, getPrimary, getPrimaryIds, getRootState, getUuidPrefix, hasConstructor, hasPrimary, invalidate, invalidateInstance, is, isColorRepresentation, isCopyable, isFromRef, isObject3D, isOnce, isOrthographicCamera, isRef, isRenderer, isTexture, isVectorLike, once, prepare, presetsObj, rebuildAllBuffers, rebuildAllNodes, rebuildAllStorage, rebuildAllUniforms, reconciler, registerPrimary, removeInteractivity, removeNodes, removeUniforms, resolve, unmountComponentAtNode, unregisterPrimary, updateCamera, updateFrustum, useBridge, useBuffers, useEnvironment, useFrame, useGPUStorage, useGraph, useInstanceHandle, useIsomorphicLayoutEffect, useLoader, useLocalNodes, useMutableCallback, useNodes, useRenderPipeline, useRenderTarget, useStore, useTexture, useTextures, useThree, useUniform, useUniforms, waitForPrimary };