@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.
@@ -464,7 +464,6 @@ function Environment(props) {
464
464
  var __defProp$1 = Object.defineProperty;
465
465
  var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
466
466
  var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
467
- const act = React__namespace["act"];
468
467
  const useIsomorphicLayoutEffect = /* @__PURE__ */ (() => typeof window !== "undefined" && (window.document?.createElement || window.navigator?.product === "ReactNative"))() ? React__namespace.useLayoutEffect : React__namespace.useEffect;
469
468
  function useMutableCallback(fn) {
470
469
  const ref = React__namespace.useRef(fn);
@@ -968,9 +967,9 @@ function diffProps(instance, newProps) {
968
967
  const { root, key } = resolve(instance.object, prop);
969
968
  if (root.constructor && root.constructor.length === 0) {
970
969
  const ctor = getMemoizedPrototype(root);
971
- if (!is.und(ctor)) changedProps[key] = ctor[key];
970
+ if (!is.und(ctor)) changedProps[prop] = ctor[key];
972
971
  } else {
973
- changedProps[key] = 0;
972
+ changedProps[prop] = 0;
974
973
  }
975
974
  }
976
975
  return changedProps;
@@ -13703,7 +13702,7 @@ function n0() {
13703
13702
  var t0 = n0();
13704
13703
  const r0 = Xb(t0);
13705
13704
 
13706
- const t = 1, o = 8, r = 32, e = 2;
13705
+ const t = 1, o = 8, r = 32, e = 2, i$1 = 268435456;
13707
13706
 
13708
13707
  function createReconciler(config) {
13709
13708
  const reconciler2 = r0(config);
@@ -13868,7 +13867,15 @@ function setFiberRef(fiber, publicInstance) {
13868
13867
  }
13869
13868
  }
13870
13869
  const reconstructed = [];
13871
- function swapInstances() {
13870
+ function flushReconstructedInstances() {
13871
+ if (reconstructed.length === 0) return;
13872
+ try {
13873
+ swapReconstructedInstances();
13874
+ } finally {
13875
+ reconstructed.length = 0;
13876
+ }
13877
+ }
13878
+ function swapReconstructedInstances() {
13872
13879
  for (const [instance] of reconstructed) {
13873
13880
  const parent = instance.parent;
13874
13881
  if (parent) {
@@ -13917,14 +13924,114 @@ function swapInstances() {
13917
13924
  invalidateInstance(instance);
13918
13925
  }
13919
13926
  }
13920
- reconstructed.length = 0;
13921
13927
  }
13922
13928
  const handleTextInstance = () => {
13923
13929
  };
13924
13930
  const NO_CONTEXT = {};
13925
13931
  let currentUpdatePriority = NoEventPriority;
13926
- const NoFlags = 0;
13927
- const Update = 4;
13932
+ function getEventPriority(type) {
13933
+ switch (type) {
13934
+ case "beforetoggle":
13935
+ case "cancel":
13936
+ case "click":
13937
+ case "close":
13938
+ case "contextmenu":
13939
+ case "copy":
13940
+ case "cut":
13941
+ case "auxclick":
13942
+ case "dblclick":
13943
+ case "dragend":
13944
+ case "dragstart":
13945
+ case "drop":
13946
+ case "focusin":
13947
+ case "focusout":
13948
+ case "input":
13949
+ case "invalid":
13950
+ case "keydown":
13951
+ case "keypress":
13952
+ case "keyup":
13953
+ case "mousedown":
13954
+ case "mouseup":
13955
+ case "paste":
13956
+ case "pause":
13957
+ case "play":
13958
+ case "pointercancel":
13959
+ case "pointerdown":
13960
+ case "pointerup":
13961
+ case "ratechange":
13962
+ case "reset":
13963
+ case "resize":
13964
+ case "seeked":
13965
+ case "submit":
13966
+ case "touchcancel":
13967
+ case "touchend":
13968
+ case "touchstart":
13969
+ case "volumechange":
13970
+ case "change":
13971
+ case "selectionchange":
13972
+ case "compositionstart":
13973
+ case "compositionend":
13974
+ case "compositionupdate":
13975
+ case "beforeinput":
13976
+ case "blur":
13977
+ case "fullscreenchange":
13978
+ case "focus":
13979
+ case "hashchange":
13980
+ case "popstate":
13981
+ case "select":
13982
+ case "selectstart":
13983
+ return e;
13984
+ case "drag":
13985
+ case "dragenter":
13986
+ case "dragexit":
13987
+ case "dragleave":
13988
+ case "dragover":
13989
+ case "mousemove":
13990
+ case "mouseout":
13991
+ case "mouseover":
13992
+ case "pointermove":
13993
+ case "pointerout":
13994
+ case "pointerover":
13995
+ case "scroll":
13996
+ case "touchmove":
13997
+ case "wheel":
13998
+ case "mouseenter":
13999
+ case "mouseleave":
14000
+ case "pointerenter":
14001
+ case "pointerleave":
14002
+ return o;
14003
+ case "message": {
14004
+ switch (Tb.unstable_getCurrentPriorityLevel()) {
14005
+ case Tb.unstable_ImmediatePriority:
14006
+ return e;
14007
+ case Tb.unstable_UserBlockingPriority:
14008
+ return o;
14009
+ case Tb.unstable_NormalPriority:
14010
+ case Tb.unstable_LowPriority:
14011
+ return r;
14012
+ case Tb.unstable_IdlePriority:
14013
+ return i$1;
14014
+ default:
14015
+ return r;
14016
+ }
14017
+ }
14018
+ default:
14019
+ return r;
14020
+ }
14021
+ }
14022
+ function scheduleMicrotask(callback) {
14023
+ if (typeof queueMicrotask === "function") {
14024
+ queueMicrotask(callback);
14025
+ } else if (typeof Promise !== "undefined") {
14026
+ Promise.resolve().then(callback).catch((error) => {
14027
+ setTimeout(() => {
14028
+ throw error;
14029
+ });
14030
+ });
14031
+ } else {
14032
+ setTimeout(callback);
14033
+ }
14034
+ }
13928
14035
  const reconciler = /* @__PURE__ */ createReconciler({
13929
14036
  isPrimaryRenderer: false,
13930
14037
  warnsIfNotActing: false,
@@ -13963,16 +14070,15 @@ const reconciler = /* @__PURE__ */ createReconciler({
13963
14070
  else if (newProps.args?.length !== oldProps.args?.length) reconstruct = true;
13964
14071
  else if (newProps.args?.some((value, index) => value !== oldProps.args?.[index])) reconstruct = true;
13965
14072
  if (reconstruct) {
13966
- reconstructed.push([instance, { ...newProps }, fiber]);
14073
+ reconstructed.push([instance, getInstanceProps(newProps), fiber]);
13967
14074
  } else {
13968
14075
  const changedProps = diffProps(instance, newProps);
13969
- if (Object.keys(changedProps).length) {
13970
- Object.assign(instance.props, changedProps);
13971
- applyProps(instance.object, changedProps);
13972
- }
14076
+ const attach2 = instance.props.attach;
14077
+ instance.props = getInstanceProps(newProps);
14078
+ if (attach2 !== void 0) instance.props.attach = attach2;
14079
+ else delete instance.props.attach;
14080
+ if (Object.keys(changedProps).length) applyProps(instance.object, changedProps);
13973
14081
  }
13974
- const isTailSibling = fiber.sibling === null || (fiber.flags & Update) === NoFlags;
13975
- if (isTailSibling) swapInstances();
13976
14082
  },
13977
14083
  finalizeInitialChildren: (instance) => {
13978
14084
  for (const prop in instance.props) {
@@ -13997,8 +14103,9 @@ const reconciler = /* @__PURE__ */ createReconciler({
13997
14103
  const target = container.getState().internal.container ?? container.getState().scene;
13998
14104
  return prepare(target, container, "", {});
13999
14105
  },
14000
- resetAfterCommit: () => {
14001
- },
14106
+ // Reconstructed instances are swapped once all mutations are committed,
14107
+ // before layout effects run so refs point to the new objects
14108
+ resetAfterCommit: flushReconstructedInstances,
14002
14109
  shouldSetTextContent: () => false,
14003
14110
  clearContainer: () => false,
14004
14111
  hideInstance,
@@ -14006,6 +14113,9 @@ const reconciler = /* @__PURE__ */ createReconciler({
14006
14113
  createTextInstance: handleTextInstance,
14007
14114
  hideTextInstance: handleTextInstance,
14008
14115
  unhideTextInstance: handleTextInstance,
14116
+ // Mirrors react-dom, which flushes discrete work in microtasks
14117
+ supportsMicrotasks: true,
14118
+ scheduleMicrotask,
14009
14119
  scheduleTimeout: typeof setTimeout === "function" ? setTimeout : void 0,
14010
14120
  cancelTimeout: typeof clearTimeout === "function" ? clearTimeout : void 0,
14011
14121
  noTimeout: -1,
@@ -14046,28 +14156,9 @@ const reconciler = /* @__PURE__ */ createReconciler({
14046
14156
  },
14047
14157
  resolveUpdatePriority() {
14048
14158
  if (currentUpdatePriority !== NoEventPriority) return currentUpdatePriority;
14049
- switch (typeof window !== "undefined" && window.event?.type) {
14050
- case "click":
14051
- case "contextmenu":
14052
- case "dblclick":
14053
- case "dragenter":
14054
- case "dragleave":
14055
- case "drop":
14056
- case "pointercancel":
14057
- case "pointerdown":
14058
- case "pointerup":
14059
- return e;
14060
- case "dragover":
14061
- case "pointermove":
14062
- case "pointerout":
14063
- case "pointerover":
14064
- case "pointerenter":
14065
- case "pointerleave":
14066
- case "wheel":
14067
- return o;
14068
- default:
14069
- return r;
14070
- }
14159
+ const eventType = typeof window !== "undefined" ? window.event?.type : void 0;
14160
+ if (eventType === void 0) return r;
14161
+ return getEventPriority(eventType);
14071
14162
  },
14072
14163
  resetFormInstance() {
14073
14164
  },
@@ -14816,14 +14907,133 @@ function parseRendererConfig(rendererProp) {
14816
14907
  return { primaryCanvas: void 0, scheduler: void 0, renderer: rendererProp };
14817
14908
  }
14818
14909
 
14910
+ const RESOURCE_KINDS = ["nodes", "uniforms", "buffers", "gpuStorage"];
14911
+ const ROOT_SCOPE = "";
14912
+ const registries = /* @__PURE__ */ new WeakMap();
14913
+ function getKindRegistry(store, kind) {
14914
+ let registry = registries.get(store);
14915
+ if (!registry) {
14916
+ registry = {
14917
+ nodes: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
14918
+ uniforms: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
14919
+ buffers: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
14920
+ gpuStorage: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() }
14921
+ };
14922
+ registries.set(store, registry);
14923
+ }
14924
+ return registry[kind];
14925
+ }
14926
+ function resolvePrimary$1(store) {
14927
+ return store.getState().primaryStore ?? store;
14928
+ }
14929
+ function isScopeValid(store, kind, scopeKey) {
14930
+ return getKindRegistry(store, kind).valid.has(scopeKey);
14931
+ }
14932
+ function peekStaged(store, kind, scopeKey) {
14933
+ return getKindRegistry(store, kind).staged.get(scopeKey);
14934
+ }
14935
+ function stageEntries(store, kind, scopeKey, entries) {
14936
+ const { staged } = getKindRegistry(store, kind);
14937
+ const current = staged.get(scopeKey);
14938
+ if (current) Object.assign(current, entries);
14939
+ else staged.set(scopeKey, { ...entries });
14940
+ }
14941
+ function readCommittedScope(map, scopeKey, isLeaf) {
14942
+ if (scopeKey === ROOT_SCOPE) {
14943
+ const leaves = {};
14944
+ for (const [key, value] of Object.entries(map)) if (isLeaf(value)) leaves[key] = value;
14945
+ return leaves;
14946
+ }
14947
+ const scopeData = map[scopeKey];
14948
+ if (scopeData && typeof scopeData === "object" && !isLeaf(scopeData)) return scopeData;
14949
+ return {};
14950
+ }
14951
+ function withStagedOverlay(store, kind, committed) {
14952
+ const { staged } = getKindRegistry(store, kind);
14953
+ if (staged.size === 0) return committed;
14954
+ const view = { ...committed };
14955
+ for (const [scopeKey, entries] of staged) {
14956
+ if (scopeKey === ROOT_SCOPE) Object.assign(view, entries);
14957
+ else view[scopeKey] = { ...view[scopeKey], ...entries };
14958
+ }
14959
+ return view;
14960
+ }
14961
+ function flushStagedScope(store, kind, scopeKey, isLeaf) {
14962
+ const registry = getKindRegistry(store, kind);
14963
+ const staged = registry.staged.get(scopeKey);
14964
+ if (!staged) return;
14965
+ registry.staged.delete(scopeKey);
14966
+ const replace = !registry.valid.has(scopeKey);
14967
+ store.setState((state) => {
14968
+ const map = state[kind];
14969
+ if (scopeKey === ROOT_SCOPE) {
14970
+ if (!replace) return { [kind]: { ...map, ...staged } };
14971
+ const next = {};
14972
+ for (const [key, value] of Object.entries(map)) if (!isLeaf(value)) next[key] = value;
14973
+ return { [kind]: { ...next, ...staged } };
14974
+ }
14975
+ const current = replace ? {} : map[scopeKey] ?? {};
14976
+ return { [kind]: { ...map, [scopeKey]: { ...current, ...staged } } };
14977
+ });
14978
+ registry.valid.add(scopeKey);
14979
+ }
14980
+ function invalidateResource(store, kind, scopeKey) {
14981
+ const registry = getKindRegistry(store, kind);
14982
+ if (scopeKey === void 0) {
14983
+ registry.valid.clear();
14984
+ registry.staged.clear();
14985
+ } else {
14986
+ registry.valid.delete(scopeKey);
14987
+ registry.staged.delete(scopeKey);
14988
+ }
14989
+ }
14990
+ function rebuildResource(store, kind, userScope) {
14991
+ const primary = resolvePrimary$1(store);
14992
+ invalidateResource(primary, kind, userScope === "root" ? ROOT_SCOPE : userScope);
14993
+ primary.setState((state) => ({ _hmrVersion: state._hmrVersion + 1 }));
14994
+ }
14995
+ function invalidateAllResources(store) {
14996
+ for (const kind of RESOURCE_KINDS) invalidateResource(store, kind);
14997
+ }
14998
+ function removeResourceEntries(store, kind, names, scope, isLeaf) {
14999
+ const staged = peekStaged(store, kind, scope ?? ROOT_SCOPE);
15000
+ if (staged) for (const name of names) delete staged[name];
15001
+ store.setState((state) => {
15002
+ const map = state[kind];
15003
+ if (scope) {
15004
+ const currentScope = { ...map[scope] };
15005
+ for (const name of names) delete currentScope[name];
15006
+ return { [kind]: { ...map, [scope]: currentScope } };
15007
+ }
15008
+ const next = { ...map };
15009
+ for (const name of names) if (isLeaf(next[name])) delete next[name];
15010
+ return { [kind]: next };
15011
+ });
15012
+ }
15013
+ function clearResourceEntries(store, kind, scope, isLeaf) {
15014
+ const registry = getKindRegistry(store, kind);
15015
+ if (scope && scope !== "root") registry.staged.delete(scope);
15016
+ else if (scope === "root") registry.staged.delete(ROOT_SCOPE);
15017
+ else registry.staged.clear();
15018
+ store.setState((state) => {
15019
+ const map = state[kind];
15020
+ if (scope && scope !== "root") {
15021
+ const { [scope]: _, ...rest } = map;
15022
+ return { [kind]: rest };
15023
+ }
15024
+ if (scope === "root") {
15025
+ const next = {};
15026
+ for (const [key, value] of Object.entries(map)) if (!isLeaf(value)) next[key] = value;
15027
+ return { [kind]: next };
15028
+ }
15029
+ return { [kind]: {} };
15030
+ });
15031
+ }
15032
+
14819
15033
  function clearHmrCaches(store) {
14820
- store.setState((state) => ({
14821
- nodes: {},
14822
- uniforms: {},
14823
- buffers: {},
14824
- gpuStorage: {},
14825
- _hmrVersion: state._hmrVersion + 1
14826
- }));
15034
+ const primary = store.getState().primaryStore ?? store;
15035
+ invalidateAllResources(primary);
15036
+ primary.setState((state) => ({ _hmrVersion: state._hmrVersion + 1 }));
14827
15037
  }
14828
15038
 
14829
15039
  function CanvasImpl({
@@ -15136,30 +15346,31 @@ let ScopedStore = _ScopedStore;
15136
15346
  function createScopedStore(data) {
15137
15347
  return new ScopedStore(data);
15138
15348
  }
15139
- function createLazyCreatorState(state) {
15349
+ function createLazyCreatorState(state, store) {
15140
15350
  let _uniforms = null;
15141
15351
  let _nodes = null;
15142
15352
  let _buffers = null;
15143
15353
  let _gpuStorage = null;
15354
+ const view = (kind) => store ? withStagedOverlay(store, kind, state[kind]) : state[kind];
15144
15355
  return Object.create(state, {
15145
15356
  uniforms: {
15146
15357
  get() {
15147
- return _uniforms ?? (_uniforms = createScopedStore(state.uniforms));
15358
+ return _uniforms ?? (_uniforms = createScopedStore(view("uniforms")));
15148
15359
  }
15149
15360
  },
15150
15361
  nodes: {
15151
15362
  get() {
15152
- return _nodes ?? (_nodes = createScopedStore(state.nodes));
15363
+ return _nodes ?? (_nodes = createScopedStore(view("nodes")));
15153
15364
  }
15154
15365
  },
15155
15366
  buffers: {
15156
15367
  get() {
15157
- return _buffers ?? (_buffers = createScopedStore(state.buffers));
15368
+ return _buffers ?? (_buffers = createScopedStore(view("buffers")));
15158
15369
  }
15159
15370
  },
15160
15371
  gpuStorage: {
15161
15372
  get() {
15162
- return _gpuStorage ?? (_gpuStorage = createScopedStore(state.gpuStorage));
15373
+ return _gpuStorage ?? (_gpuStorage = createScopedStore(view("gpuStorage")));
15163
15374
  }
15164
15375
  }
15165
15376
  });
@@ -15282,65 +15493,56 @@ function useCompareMemoize(value, deep) {
15282
15493
  return ref.current;
15283
15494
  }
15284
15495
 
15496
+ function useScopedResource(options) {
15497
+ const { store, kind, scope, isLeaf, create, prepare, reconcile, input } = options;
15498
+ const scopeKey = scope ?? ROOT_SCOPE;
15499
+ const version = store((s) => s._hmrVersion);
15500
+ const entries = React.useMemo(() => {
15501
+ const staged = peekStaged(store, kind, scopeKey);
15502
+ const reusable = isScopeValid(store, kind, scopeKey);
15503
+ const map = store.getState()[kind];
15504
+ const committed = reusable ? readCommittedScope(map, scopeKey, isLeaf) : void 0;
15505
+ const result = {};
15506
+ let fresh = null;
15507
+ for (const [name, candidate] of Object.entries(create())) {
15508
+ const existing = staged?.[name] ?? committed?.[name];
15509
+ if (existing !== void 0) {
15510
+ result[name] = existing;
15511
+ reconcile?.(existing, candidate);
15512
+ } else {
15513
+ const value = prepare ? prepare(name, candidate) : candidate;
15514
+ result[name] = value;
15515
+ (fresh ?? (fresh = {}))[name] = value;
15516
+ }
15517
+ }
15518
+ if (fresh) stageEntries(store, kind, scopeKey, fresh);
15519
+ return result;
15520
+ }, [store, kind, scopeKey, version, input]);
15521
+ useIsomorphicLayoutEffect(() => {
15522
+ flushStagedScope(store, kind, scopeKey, isLeaf);
15523
+ });
15524
+ return entries;
15525
+ }
15526
+
15285
15527
  const isUniformNode$1 = (value) => value !== null && typeof value === "object" && "value" in value && "uuid" in value;
15286
15528
  function useUniforms(creatorOrScope, scope) {
15287
15529
  const store = usePrimaryStore();
15288
15530
  const removeUniforms2 = React.useCallback(
15289
- (names, targetScope) => {
15290
- const nameArray = Array.isArray(names) ? names : [names];
15291
- store.setState((state) => {
15292
- if (targetScope) {
15293
- const currentScope = { ...state.uniforms[targetScope] };
15294
- for (const name of nameArray) delete currentScope[name];
15295
- return { uniforms: { ...state.uniforms, [targetScope]: currentScope } };
15296
- }
15297
- const uniforms2 = { ...state.uniforms };
15298
- for (const name of nameArray) if (isUniformNode$1(uniforms2[name])) delete uniforms2[name];
15299
- return { uniforms: uniforms2 };
15300
- });
15301
- },
15531
+ (names, targetScope) => removeResourceEntries(store, "uniforms", Array.isArray(names) ? names : [names], targetScope, isUniformNode$1),
15302
15532
  [store]
15303
15533
  );
15304
15534
  const clearUniforms = React.useCallback(
15305
- (targetScope) => {
15306
- store.setState((state) => {
15307
- if (targetScope && targetScope !== "root") {
15308
- const { [targetScope]: _, ...rest } = state.uniforms;
15309
- return { uniforms: rest };
15310
- }
15311
- if (targetScope === "root") {
15312
- const uniforms2 = {};
15313
- for (const [key, value] of Object.entries(state.uniforms)) {
15314
- if (!isUniformNode$1(value)) uniforms2[key] = value;
15315
- }
15316
- return { uniforms: uniforms2 };
15317
- }
15318
- return { uniforms: {} };
15319
- });
15320
- },
15535
+ (targetScope) => clearResourceEntries(store, "uniforms", targetScope, isUniformNode$1),
15321
15536
  [store]
15322
15537
  );
15323
15538
  const rebuildUniforms = React.useCallback(
15324
- (targetScope) => {
15325
- store.setState((state) => {
15326
- let newUniforms = {};
15327
- if (targetScope && targetScope !== "root") {
15328
- const { [targetScope]: _, ...rest } = state.uniforms;
15329
- newUniforms = rest;
15330
- } else if (targetScope === "root") {
15331
- for (const [key, value] of Object.entries(state.uniforms)) {
15332
- if (!isUniformNode$1(value)) newUniforms[key] = value;
15333
- }
15334
- }
15335
- return { uniforms: newUniforms, _hmrVersion: state._hmrVersion + 1 };
15336
- });
15337
- },
15539
+ (targetScope) => rebuildResource(store, "uniforms", targetScope),
15338
15540
  [store]
15339
15541
  );
15340
15542
  const inputForMemoization = React.useMemo(() => {
15341
15543
  let raw = creatorOrScope;
15342
15544
  if (is.fun(creatorOrScope)) {
15343
- const wrappedState = createLazyCreatorState(store.getState());
15545
+ const wrappedState = createLazyCreatorState(store.getState(), store);
15344
15546
  raw = creatorOrScope(wrappedState);
15345
15547
  }
15346
15548
  if (raw && typeof raw === "object" && !Array.isArray(raw)) {
@@ -15355,80 +15557,43 @@ function useUniforms(creatorOrScope, scope) {
15355
15557
  const memoizedInput = useCompareMemoize(inputForMemoization);
15356
15558
  const isReader = memoizedInput === void 0 || typeof memoizedInput === "string";
15357
15559
  const storeUniforms = usePrimaryThree((s) => s.uniforms);
15358
- const hmrVersion = usePrimaryThree((s) => s._hmrVersion);
15359
- const readerDep = isReader ? storeUniforms : null;
15360
- const creatorDep = isReader ? null : hmrVersion;
15361
- const uniforms = React.useMemo(() => {
15362
- if (memoizedInput === void 0) {
15363
- return storeUniforms;
15364
- }
15365
- if (typeof memoizedInput === "string") {
15366
- const scopeData = storeUniforms[memoizedInput];
15367
- if (scopeData && !isUniformNode$1(scopeData)) return scopeData;
15368
- return {};
15369
- }
15370
- const state = store.getState();
15371
- const set = store.setState;
15372
- if (typeof memoizedInput !== "object" || memoizedInput === null) {
15373
- throw new Error("Invalid uniform input");
15374
- }
15375
- const created = memoizedInput;
15376
- const result = {};
15377
- let hasNewUniforms = false;
15378
- let targetRecord = state.uniforms;
15379
- if (scope) {
15380
- if (!state.uniforms[scope]) state.uniforms[scope] = {};
15381
- targetRecord = state.uniforms[scope];
15382
- }
15383
- for (const [name, node] of Object.entries(created)) {
15384
- if (targetRecord[name]) {
15385
- result[name] = targetRecord[name];
15386
- const existingVal = result[name].value;
15387
- const newVal = vectorize(node);
15388
- let equals = newVal === existingVal;
15389
- if (!equals && hasEqualsMethod(existingVal) && hasEqualsMethod(newVal)) {
15390
- if (isThreeVector(existingVal) && isThreeVector(newVal)) {
15391
- equals = vectorEquals(existingVal, newVal);
15392
- } else if (isSameThreeType(existingVal, newVal)) {
15393
- equals = existingVal.equals(newVal);
15394
- }
15395
- }
15396
- if (!equals) result[name].value = newVal;
15397
- } else {
15398
- result[name] = createUniform(name, node, scope);
15399
- hasNewUniforms = true;
15400
- }
15401
- }
15402
- if (hasNewUniforms) {
15403
- if (scope) {
15404
- set((s) => ({
15405
- uniforms: {
15406
- ...s.uniforms,
15407
- [scope]: { ...s.uniforms[scope], ...result }
15408
- }
15409
- }));
15410
- } else {
15411
- set((s) => ({ uniforms: { ...s.uniforms, ...result } }));
15412
- }
15560
+ const created = useScopedResource({
15561
+ store,
15562
+ kind: "uniforms",
15563
+ scope: isReader ? void 0 : scope,
15564
+ isLeaf: isUniformNode$1,
15565
+ input: memoizedInput,
15566
+ create: () => {
15567
+ if (isReader) return {};
15568
+ if (typeof memoizedInput !== "object" || memoizedInput === null) throw new Error("Invalid uniform input");
15569
+ return memoizedInput;
15570
+ },
15571
+ prepare: (name, candidate) => createUniform(name, candidate, scope),
15572
+ reconcile: (existing, candidate) => {
15573
+ const existingVal = existing.value;
15574
+ const newVal = vectorize(candidate);
15575
+ let equals = newVal === existingVal;
15576
+ if (!equals && hasEqualsMethod(existingVal) && hasEqualsMethod(newVal)) {
15577
+ if (isThreeVector(existingVal) && isThreeVector(newVal)) {
15578
+ equals = vectorEquals(existingVal, newVal);
15579
+ } else if (isSameThreeType(existingVal, newVal)) {
15580
+ equals = existingVal.equals(newVal);
15581
+ }
15582
+ }
15583
+ if (!equals) existing.value = newVal;
15413
15584
  }
15414
- return result;
15415
- }, [store, memoizedInput, scope, readerDep, creatorDep]);
15585
+ });
15586
+ let uniforms = created;
15587
+ if (memoizedInput === void 0) {
15588
+ uniforms = storeUniforms;
15589
+ } else if (typeof memoizedInput === "string") {
15590
+ const scopeData = storeUniforms[memoizedInput];
15591
+ uniforms = scopeData && !isUniformNode$1(scopeData) ? scopeData : {};
15592
+ }
15416
15593
  return { ...uniforms, removeUniforms: removeUniforms2, clearUniforms, rebuildUniforms };
15417
15594
  }
15418
15595
  function rebuildAllUniforms(store, scope) {
15419
- store = store.getState().primaryStore ?? store;
15420
- store.setState((state) => {
15421
- let newUniforms = {};
15422
- if (scope && scope !== "root") {
15423
- const { [scope]: _, ...rest } = state.uniforms;
15424
- newUniforms = rest;
15425
- } else if (scope === "root") {
15426
- for (const [key, value] of Object.entries(state.uniforms)) {
15427
- if (!isUniformNode$1(value)) newUniforms[key] = value;
15428
- }
15429
- }
15430
- return { uniforms: newUniforms, _hmrVersion: state._hmrVersion + 1 };
15431
- });
15596
+ rebuildResource(store, "uniforms", scope);
15432
15597
  }
15433
15598
  function removeUniforms(set, names, scope) {
15434
15599
  set((state) => {
@@ -15497,188 +15662,86 @@ const isUniformNode = (value) => value !== null && typeof value === "object" &&
15497
15662
  const isTSLNode$1 = (value) => value !== null && typeof value === "object" && "uuid" in value && "nodeType" in value;
15498
15663
  function useUniform(name, value) {
15499
15664
  const store = useStore();
15500
- const hmrVersion = useThree((s) => s._hmrVersion);
15501
- return React.useMemo(() => {
15502
- const state = store.getState();
15503
- const set = store.setState;
15504
- const existing = state.uniforms[name];
15505
- if (existing && isUniformNode(existing)) {
15665
+ const registered = useScopedResource({
15666
+ store,
15667
+ kind: "uniforms",
15668
+ scope: void 0,
15669
+ isLeaf: isUniformNode,
15670
+ input: name,
15671
+ create: () => value === void 0 ? {} : { [name]: value },
15672
+ prepare: createNamedUniform,
15673
+ reconcile: (existing2) => {
15506
15674
  if (value !== void 0 && !isTSLNode$1(value) && !isUniformNode(value)) {
15507
- existing.value = typeof value === "string" ? new webgpu.Color(value) : value;
15675
+ existing2.value = typeof value === "string" ? new webgpu.Color(value) : value;
15508
15676
  }
15509
- return existing;
15510
- }
15511
- if (value === void 0) {
15512
- throw new Error(
15513
- `[useUniform] Uniform "${name}" not found. Create it first with: useUniform('${name}', initialValue)`
15514
- );
15515
- }
15516
- if (isUniformNode(value)) {
15517
- const node2 = value;
15518
- if (typeof node2.setName === "function") {
15519
- node2.setName(name);
15520
- }
15521
- set((s) => ({
15522
- uniforms: { ...s.uniforms, [name]: node2 }
15523
- }));
15524
- return node2;
15525
15677
  }
15526
- let node;
15527
- if (isTSLNode$1(value)) {
15528
- node = uniformOf(value);
15529
- } else if (typeof value === "string") {
15530
- node = tsl.uniform(new webgpu.Color(value));
15531
- } else {
15532
- node = uniformOf(value);
15533
- }
15534
- if (typeof node.setName === "function") {
15535
- node.setName(name);
15536
- }
15537
- set((s) => ({
15538
- uniforms: {
15539
- ...s.uniforms,
15540
- [name]: node
15541
- }
15542
- }));
15543
- return node;
15544
- }, [store, name, hmrVersion]);
15678
+ });
15679
+ if (registered[name]) return registered[name];
15680
+ const existing = peekStaged(store, "uniforms", ROOT_SCOPE)?.[name] ?? store.getState().uniforms[name];
15681
+ if (existing && isUniformNode(existing)) return existing;
15682
+ throw new Error(
15683
+ `[useUniform] Uniform "${name}" not found. Create it first with: useUniform('${name}', initialValue)`
15684
+ );
15685
+ }
15686
+ function createNamedUniform(name, value) {
15687
+ let node;
15688
+ if (isUniformNode(value)) {
15689
+ node = value;
15690
+ } else if (isTSLNode$1(value)) {
15691
+ node = uniformOf(value);
15692
+ } else if (typeof value === "string") {
15693
+ node = tsl.uniform(new webgpu.Color(value));
15694
+ } else {
15695
+ node = uniformOf(value);
15696
+ }
15697
+ if (typeof node.setName === "function") {
15698
+ node.setName(name);
15699
+ }
15700
+ return node;
15545
15701
  }
15546
15702
 
15547
15703
  const isTSLNode = (value) => value !== null && typeof value === "object" && ("uuid" in value || "nodeType" in value);
15548
15704
  function useNodes(creatorOrScope, scope) {
15549
15705
  const store = usePrimaryStore();
15550
15706
  const removeNodes2 = React.useCallback(
15551
- (names, targetScope) => {
15552
- const nameArray = Array.isArray(names) ? names : [names];
15553
- store.setState((state) => {
15554
- if (targetScope) {
15555
- const currentScope = { ...state.nodes[targetScope] };
15556
- for (const name of nameArray) delete currentScope[name];
15557
- return { nodes: { ...state.nodes, [targetScope]: currentScope } };
15558
- }
15559
- const nodes2 = { ...state.nodes };
15560
- for (const name of nameArray) if (isTSLNode(nodes2[name])) delete nodes2[name];
15561
- return { nodes: nodes2 };
15562
- });
15563
- },
15707
+ (names, targetScope) => removeResourceEntries(store, "nodes", Array.isArray(names) ? names : [names], targetScope, isTSLNode),
15564
15708
  [store]
15565
15709
  );
15566
15710
  const clearNodes = React.useCallback(
15567
- (targetScope) => {
15568
- store.setState((state) => {
15569
- if (targetScope && targetScope !== "root") {
15570
- const { [targetScope]: _, ...rest } = state.nodes;
15571
- return { nodes: rest };
15572
- }
15573
- if (targetScope === "root") {
15574
- const nodes2 = {};
15575
- for (const [key, value] of Object.entries(state.nodes)) {
15576
- if (!isTSLNode(value)) nodes2[key] = value;
15577
- }
15578
- return { nodes: nodes2 };
15579
- }
15580
- return { nodes: {} };
15581
- });
15582
- },
15711
+ (targetScope) => clearResourceEntries(store, "nodes", targetScope, isTSLNode),
15583
15712
  [store]
15584
15713
  );
15585
15714
  const rebuildNodes = React.useCallback(
15586
- (targetScope) => {
15587
- store.setState((state) => {
15588
- let newNodes = state.nodes;
15589
- if (targetScope && targetScope !== "root") {
15590
- const { [targetScope]: _, ...rest } = state.nodes;
15591
- newNodes = rest;
15592
- } else if (targetScope === "root") {
15593
- newNodes = {};
15594
- for (const [key, value] of Object.entries(state.nodes)) {
15595
- if (!isTSLNode(value)) newNodes[key] = value;
15596
- }
15597
- } else {
15598
- newNodes = {};
15599
- }
15600
- return { nodes: newNodes, _hmrVersion: state._hmrVersion + 1 };
15601
- });
15602
- },
15715
+ (targetScope) => rebuildResource(store, "nodes", targetScope),
15603
15716
  [store]
15604
15717
  );
15605
15718
  const isReader = creatorOrScope === void 0 || typeof creatorOrScope === "string";
15606
15719
  const storeNodes = usePrimaryThree((s) => s.nodes);
15607
- const hmrVersion = usePrimaryThree((s) => s._hmrVersion);
15608
- const scopeDep = typeof creatorOrScope === "string" ? creatorOrScope : scope;
15609
- const readerDep = isReader ? storeNodes : null;
15610
- const creatorDep = isReader ? null : hmrVersion;
15611
- const nodes = React.useMemo(() => {
15612
- if (creatorOrScope === void 0) {
15613
- return storeNodes;
15614
- }
15615
- if (typeof creatorOrScope === "string") {
15616
- const scopeData = storeNodes[creatorOrScope];
15617
- if (scopeData && !isTSLNode(scopeData)) return scopeData;
15618
- return {};
15619
- }
15620
- const state = store.getState();
15621
- const set = store.setState;
15622
- const creator = creatorOrScope;
15623
- const wrappedState = createLazyCreatorState(state);
15624
- const created = creator(wrappedState);
15625
- const result = {};
15626
- let hasNewNodes = false;
15627
- if (scope) {
15628
- const currentScope = state.nodes[scope] ?? {};
15629
- for (const [name, node] of Object.entries(created)) {
15630
- if (currentScope[name]) {
15631
- result[name] = currentScope[name];
15632
- } else {
15633
- node.setName?.(`${scope}.${name}`);
15634
- result[name] = node;
15635
- hasNewNodes = true;
15636
- }
15637
- }
15638
- if (hasNewNodes) {
15639
- set((s) => ({
15640
- nodes: {
15641
- ...s.nodes,
15642
- [scope]: { ...s.nodes[scope], ...result }
15643
- }
15644
- }));
15645
- }
15646
- return result;
15647
- }
15648
- for (const [name, node] of Object.entries(created)) {
15649
- const existing = state.nodes[name];
15650
- if (existing && isTSLNode(existing)) {
15651
- result[name] = existing;
15652
- } else {
15653
- node.setName?.(name);
15654
- result[name] = node;
15655
- hasNewNodes = true;
15656
- }
15657
- }
15658
- if (hasNewNodes) {
15659
- set((s) => ({ nodes: { ...s.nodes, ...result } }));
15720
+ const created = useScopedResource({
15721
+ store,
15722
+ kind: "nodes",
15723
+ scope: isReader ? void 0 : scope,
15724
+ isLeaf: isTSLNode,
15725
+ create: () => {
15726
+ if (isReader) return {};
15727
+ return creatorOrScope(createLazyCreatorState(store.getState(), store));
15728
+ },
15729
+ prepare: (name, node) => {
15730
+ node.setName?.(scope ? `${scope}.${name}` : name);
15731
+ return node;
15660
15732
  }
15661
- return result;
15662
- }, [store, scopeDep, readerDep, creatorDep]);
15733
+ });
15734
+ let nodes = created;
15735
+ if (creatorOrScope === void 0) {
15736
+ nodes = storeNodes;
15737
+ } else if (typeof creatorOrScope === "string") {
15738
+ const scopeData = storeNodes[creatorOrScope];
15739
+ nodes = scopeData && !isTSLNode(scopeData) ? scopeData : {};
15740
+ }
15663
15741
  return { ...nodes, removeNodes: removeNodes2, clearNodes, rebuildNodes };
15664
15742
  }
15665
15743
  function rebuildAllNodes(store, scope) {
15666
- store = store.getState().primaryStore ?? store;
15667
- store.setState((state) => {
15668
- let newNodes = state.nodes;
15669
- if (scope && scope !== "root") {
15670
- const { [scope]: _, ...rest } = state.nodes;
15671
- newNodes = rest;
15672
- } else if (scope === "root") {
15673
- newNodes = {};
15674
- for (const [key, value] of Object.entries(state.nodes)) {
15675
- if (!isTSLNode(value)) newNodes[key] = value;
15676
- }
15677
- } else {
15678
- newNodes = {};
15679
- }
15680
- return { nodes: newNodes, _hmrVersion: state._hmrVersion + 1 };
15681
- });
15744
+ rebuildResource(store, "nodes", scope);
15682
15745
  }
15683
15746
  function removeNodes(set, names, scope) {
15684
15747
  set((state) => {
@@ -15714,7 +15777,7 @@ function useLocalNodes(creator) {
15714
15777
  const textures = usePrimaryThree((s) => s.textures);
15715
15778
  const hmrVersion = usePrimaryThree((s) => s._hmrVersion);
15716
15779
  return React.useMemo(() => {
15717
- const wrappedState = createLazyCreatorState(store.getState());
15780
+ const wrappedState = createLazyCreatorState(store.getState(), store);
15718
15781
  return creator(wrappedState);
15719
15782
  }, [store, creator, uniforms, nodes, textures, hmrVersion]);
15720
15783
  }
@@ -15735,58 +15798,15 @@ const disposeBuffer = (buffer) => {
15735
15798
  function useBuffers(creatorOrScope, scope) {
15736
15799
  const store = usePrimaryStore();
15737
15800
  const removeBuffers = React.useCallback(
15738
- (names, targetScope) => {
15739
- const nameArray = Array.isArray(names) ? names : [names];
15740
- store.setState((state) => {
15741
- if (targetScope) {
15742
- const currentScope = { ...state.buffers[targetScope] };
15743
- for (const name of nameArray) delete currentScope[name];
15744
- return { buffers: { ...state.buffers, [targetScope]: currentScope } };
15745
- }
15746
- const buffers2 = { ...state.buffers };
15747
- for (const name of nameArray) if (isBufferLike(buffers2[name])) delete buffers2[name];
15748
- return { buffers: buffers2 };
15749
- });
15750
- },
15801
+ (names, targetScope) => removeResourceEntries(store, "buffers", Array.isArray(names) ? names : [names], targetScope, isBufferLike),
15751
15802
  [store]
15752
15803
  );
15753
15804
  const clearBuffers = React.useCallback(
15754
- (targetScope) => {
15755
- store.setState((state) => {
15756
- if (targetScope && targetScope !== "root") {
15757
- const { [targetScope]: _, ...rest } = state.buffers;
15758
- return { buffers: rest };
15759
- }
15760
- if (targetScope === "root") {
15761
- const buffers2 = {};
15762
- for (const [key, value] of Object.entries(state.buffers)) {
15763
- if (!isBufferLike(value)) buffers2[key] = value;
15764
- }
15765
- return { buffers: buffers2 };
15766
- }
15767
- return { buffers: {} };
15768
- });
15769
- },
15805
+ (targetScope) => clearResourceEntries(store, "buffers", targetScope, isBufferLike),
15770
15806
  [store]
15771
15807
  );
15772
15808
  const rebuildBuffers = React.useCallback(
15773
- (targetScope) => {
15774
- store.setState((state) => {
15775
- let newBuffers = state.buffers;
15776
- if (targetScope && targetScope !== "root") {
15777
- const { [targetScope]: _, ...rest } = state.buffers;
15778
- newBuffers = rest;
15779
- } else if (targetScope === "root") {
15780
- newBuffers = {};
15781
- for (const [key, value] of Object.entries(state.buffers)) {
15782
- if (!isBufferLike(value)) newBuffers[key] = value;
15783
- }
15784
- } else {
15785
- newBuffers = {};
15786
- }
15787
- return { buffers: newBuffers, _hmrVersion: state._hmrVersion + 1 };
15788
- });
15789
- },
15809
+ (targetScope) => rebuildResource(store, "buffers", targetScope),
15790
15810
  [store]
15791
15811
  );
15792
15812
  const disposeBuffers = React.useCallback(
@@ -15805,85 +15825,33 @@ function useBuffers(creatorOrScope, scope) {
15805
15825
  );
15806
15826
  const isReader = creatorOrScope === void 0 || typeof creatorOrScope === "string";
15807
15827
  const storeBuffers = usePrimaryThree((s) => s.buffers);
15808
- const hmrVersion = usePrimaryThree((s) => s._hmrVersion);
15809
- const scopeDep = typeof creatorOrScope === "string" ? creatorOrScope : scope;
15810
- const readerDep = isReader ? storeBuffers : null;
15811
- const creatorDep = isReader ? null : hmrVersion;
15812
- const buffers = React.useMemo(() => {
15813
- if (creatorOrScope === void 0) {
15814
- return storeBuffers;
15815
- }
15816
- if (typeof creatorOrScope === "string") {
15817
- const scopeData = storeBuffers[creatorOrScope];
15818
- if (scopeData && !isBufferLike(scopeData)) return scopeData;
15819
- return {};
15820
- }
15821
- const state = store.getState();
15822
- const set = store.setState;
15823
- const creator = creatorOrScope;
15824
- const wrappedState = createLazyCreatorState(state);
15825
- const created = creator(wrappedState);
15826
- const result = {};
15827
- let hasNewBuffers = false;
15828
- if (scope) {
15829
- const currentScope = state.buffers[scope] ?? {};
15830
- for (const [name, buffer] of Object.entries(created)) {
15831
- if (currentScope[name]) {
15832
- result[name] = currentScope[name];
15833
- } else {
15834
- if ("setName" in buffer && typeof buffer.setName === "function") {
15835
- buffer.setName(`${scope}.${name}`);
15836
- }
15837
- result[name] = buffer;
15838
- hasNewBuffers = true;
15839
- }
15840
- }
15841
- if (hasNewBuffers) {
15842
- set((s) => ({
15843
- buffers: {
15844
- ...s.buffers,
15845
- [scope]: { ...s.buffers[scope], ...result }
15846
- }
15847
- }));
15848
- }
15849
- return result;
15850
- }
15851
- for (const [name, buffer] of Object.entries(created)) {
15852
- const existing = state.buffers[name];
15853
- if (existing && isBufferLike(existing)) {
15854
- result[name] = existing;
15855
- } else {
15856
- if ("setName" in buffer && typeof buffer.setName === "function") {
15857
- buffer.setName(name);
15858
- }
15859
- result[name] = buffer;
15860
- hasNewBuffers = true;
15828
+ const created = useScopedResource({
15829
+ store,
15830
+ kind: "buffers",
15831
+ scope: isReader ? void 0 : scope,
15832
+ isLeaf: isBufferLike,
15833
+ create: () => {
15834
+ if (isReader) return {};
15835
+ return creatorOrScope(createLazyCreatorState(store.getState(), store));
15836
+ },
15837
+ prepare: (name, buffer) => {
15838
+ if ("setName" in buffer && typeof buffer.setName === "function") {
15839
+ buffer.setName(scope ? `${scope}.${name}` : name);
15861
15840
  }
15841
+ return buffer;
15862
15842
  }
15863
- if (hasNewBuffers) {
15864
- set((s) => ({ buffers: { ...s.buffers, ...result } }));
15865
- }
15866
- return result;
15867
- }, [store, scopeDep, readerDep, creatorDep]);
15843
+ });
15844
+ let buffers = created;
15845
+ if (creatorOrScope === void 0) {
15846
+ buffers = storeBuffers;
15847
+ } else if (typeof creatorOrScope === "string") {
15848
+ const scopeData = storeBuffers[creatorOrScope];
15849
+ buffers = scopeData && !isBufferLike(scopeData) ? scopeData : {};
15850
+ }
15868
15851
  return { ...buffers, removeBuffers, clearBuffers, rebuildBuffers, disposeBuffers };
15869
15852
  }
15870
15853
  function rebuildAllBuffers(store, scope) {
15871
- store = store.getState().primaryStore ?? store;
15872
- store.setState((state) => {
15873
- let newBuffers = state.buffers;
15874
- if (scope && scope !== "root") {
15875
- const { [scope]: _, ...rest } = state.buffers;
15876
- newBuffers = rest;
15877
- } else if (scope === "root") {
15878
- newBuffers = {};
15879
- for (const [key, value] of Object.entries(state.buffers)) {
15880
- if (!isBufferLike(value)) newBuffers[key] = value;
15881
- }
15882
- } else {
15883
- newBuffers = {};
15884
- }
15885
- return { buffers: newBuffers, _hmrVersion: state._hmrVersion + 1 };
15886
- });
15854
+ rebuildResource(store, "buffers", scope);
15887
15855
  }
15888
15856
 
15889
15857
  const isStorageLike = (value) => {
@@ -15902,58 +15870,15 @@ const disposeStorage = (storage) => {
15902
15870
  function useGPUStorage(creatorOrScope, scope) {
15903
15871
  const store = usePrimaryStore();
15904
15872
  const removeStorage = React.useCallback(
15905
- (names, targetScope) => {
15906
- const nameArray = Array.isArray(names) ? names : [names];
15907
- store.setState((state) => {
15908
- if (targetScope) {
15909
- const currentScope = { ...state.gpuStorage[targetScope] };
15910
- for (const name of nameArray) delete currentScope[name];
15911
- return { gpuStorage: { ...state.gpuStorage, [targetScope]: currentScope } };
15912
- }
15913
- const gpuStorage2 = { ...state.gpuStorage };
15914
- for (const name of nameArray) if (isStorageLike(gpuStorage2[name])) delete gpuStorage2[name];
15915
- return { gpuStorage: gpuStorage2 };
15916
- });
15917
- },
15873
+ (names, targetScope) => removeResourceEntries(store, "gpuStorage", Array.isArray(names) ? names : [names], targetScope, isStorageLike),
15918
15874
  [store]
15919
15875
  );
15920
15876
  const clearStorage = React.useCallback(
15921
- (targetScope) => {
15922
- store.setState((state) => {
15923
- if (targetScope && targetScope !== "root") {
15924
- const { [targetScope]: _, ...rest } = state.gpuStorage;
15925
- return { gpuStorage: rest };
15926
- }
15927
- if (targetScope === "root") {
15928
- const gpuStorage2 = {};
15929
- for (const [key, value] of Object.entries(state.gpuStorage)) {
15930
- if (!isStorageLike(value)) gpuStorage2[key] = value;
15931
- }
15932
- return { gpuStorage: gpuStorage2 };
15933
- }
15934
- return { gpuStorage: {} };
15935
- });
15936
- },
15877
+ (targetScope) => clearResourceEntries(store, "gpuStorage", targetScope, isStorageLike),
15937
15878
  [store]
15938
15879
  );
15939
15880
  const rebuildStorage = React.useCallback(
15940
- (targetScope) => {
15941
- store.setState((state) => {
15942
- let newStorage = state.gpuStorage;
15943
- if (targetScope && targetScope !== "root") {
15944
- const { [targetScope]: _, ...rest } = state.gpuStorage;
15945
- newStorage = rest;
15946
- } else if (targetScope === "root") {
15947
- newStorage = {};
15948
- for (const [key, value] of Object.entries(state.gpuStorage)) {
15949
- if (!isStorageLike(value)) newStorage[key] = value;
15950
- }
15951
- } else {
15952
- newStorage = {};
15953
- }
15954
- return { gpuStorage: newStorage, _hmrVersion: state._hmrVersion + 1 };
15955
- });
15956
- },
15881
+ (targetScope) => rebuildResource(store, "gpuStorage", targetScope),
15957
15882
  [store]
15958
15883
  );
15959
15884
  const disposeStorageFn = React.useCallback(
@@ -15972,72 +15897,33 @@ function useGPUStorage(creatorOrScope, scope) {
15972
15897
  );
15973
15898
  const isReader = creatorOrScope === void 0 || typeof creatorOrScope === "string";
15974
15899
  const storeStorage = usePrimaryThree((s) => s.gpuStorage);
15975
- const hmrVersion = usePrimaryThree((s) => s._hmrVersion);
15976
- const scopeDep = typeof creatorOrScope === "string" ? creatorOrScope : scope;
15977
- const readerDep = isReader ? storeStorage : null;
15978
- const creatorDep = isReader ? null : hmrVersion;
15979
- const gpuStorage = React.useMemo(() => {
15980
- if (creatorOrScope === void 0) {
15981
- return storeStorage;
15982
- }
15983
- if (typeof creatorOrScope === "string") {
15984
- const scopeData = storeStorage[creatorOrScope];
15985
- if (scopeData && !isStorageLike(scopeData)) return scopeData;
15986
- return {};
15987
- }
15988
- const state = store.getState();
15989
- const set = store.setState;
15990
- const creator = creatorOrScope;
15991
- const wrappedState = createLazyCreatorState(state);
15992
- const created = creator(wrappedState);
15993
- const result = {};
15994
- let hasNewStorage = false;
15995
- if (scope) {
15996
- const currentScope = state.gpuStorage[scope] ?? {};
15997
- for (const [name, storage] of Object.entries(created)) {
15998
- if (currentScope[name]) {
15999
- result[name] = currentScope[name];
16000
- } else {
16001
- if ("setName" in storage && typeof storage.setName === "function") {
16002
- storage.setName(`${scope}.${name}`);
16003
- }
16004
- if ("name" in storage && typeof storage.name === "string") {
16005
- storage.name = `${scope}.${name}`;
16006
- }
16007
- result[name] = storage;
16008
- hasNewStorage = true;
16009
- }
15900
+ const created = useScopedResource({
15901
+ store,
15902
+ kind: "gpuStorage",
15903
+ scope: isReader ? void 0 : scope,
15904
+ isLeaf: isStorageLike,
15905
+ create: () => {
15906
+ if (isReader) return {};
15907
+ return creatorOrScope(createLazyCreatorState(store.getState(), store));
15908
+ },
15909
+ prepare: (name, storage) => {
15910
+ const label = scope ? `${scope}.${name}` : name;
15911
+ if ("setName" in storage && typeof storage.setName === "function") {
15912
+ storage.setName(label);
16010
15913
  }
16011
- if (hasNewStorage) {
16012
- set((s) => ({
16013
- gpuStorage: {
16014
- ...s.gpuStorage,
16015
- [scope]: { ...s.gpuStorage[scope], ...result }
16016
- }
16017
- }));
15914
+ if ("name" in storage && typeof storage.name === "string") {
15915
+ storage.name = label;
16018
15916
  }
16019
- return result;
15917
+ return storage;
16020
15918
  }
16021
- for (const [name, storage] of Object.entries(created)) {
16022
- const existing = state.gpuStorage[name];
16023
- if (existing && isStorageLike(existing)) {
16024
- result[name] = existing;
16025
- } else {
16026
- if ("setName" in storage && typeof storage.setName === "function") {
16027
- storage.setName(name);
16028
- }
16029
- if ("name" in storage && typeof storage.name === "string") {
16030
- storage.name = name;
16031
- }
16032
- result[name] = storage;
16033
- hasNewStorage = true;
16034
- }
16035
- }
16036
- if (hasNewStorage) {
16037
- set((s) => ({ gpuStorage: { ...s.gpuStorage, ...result } }));
16038
- }
16039
- return result;
16040
- }, [store, scopeDep, readerDep, creatorDep]);
15919
+ });
15920
+ let gpuStorage = created;
15921
+ if (creatorOrScope === void 0) {
15922
+ gpuStorage = storeStorage;
15923
+ } else if (typeof creatorOrScope === "string") {
15924
+ const scopeData = storeStorage[creatorOrScope];
15925
+ gpuStorage = scopeData && !isStorageLike(scopeData) ? scopeData : {};
15926
+ }
16041
15927
  return {
16042
15928
  ...gpuStorage,
16043
15929
  removeStorage,
@@ -16047,22 +15933,7 @@ function useGPUStorage(creatorOrScope, scope) {
16047
15933
  };
16048
15934
  }
16049
15935
  function rebuildAllStorage(store, scope) {
16050
- store = store.getState().primaryStore ?? store;
16051
- store.setState((state) => {
16052
- let newStorage = state.gpuStorage;
16053
- if (scope && scope !== "root") {
16054
- const { [scope]: _, ...rest } = state.gpuStorage;
16055
- newStorage = rest;
16056
- } else if (scope === "root") {
16057
- newStorage = {};
16058
- for (const [key, value] of Object.entries(state.gpuStorage)) {
16059
- if (!isStorageLike(value)) newStorage[key] = value;
16060
- }
16061
- } else {
16062
- newStorage = {};
16063
- }
16064
- return { gpuStorage: newStorage, _hmrVersion: state._hmrVersion + 1 };
16065
- });
15936
+ rebuildResource(store, "gpuStorage", scope);
16066
15937
  }
16067
15938
 
16068
15939
  function useRenderPipeline(mainCB, setupCB) {
@@ -16179,7 +16050,6 @@ exports.REACT_INTERNAL_PROPS = REACT_INTERNAL_PROPS;
16179
16050
  exports.RESERVED_PROPS = RESERVED_PROPS;
16180
16051
  exports.Texture = Texture;
16181
16052
  exports._roots = _roots;
16182
- exports.act = act;
16183
16053
  exports.addAfterEffect = addAfterEffect;
16184
16054
  exports.addEffect = addEffect;
16185
16055
  exports.addTail = addTail;