@react-three/drei 9.96.5 → 9.97.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -9
- package/core/CameraControls.d.ts +2 -2
- package/core/MeshTransmissionMaterial.d.ts +2 -2
- package/core/ScreenSizer.cjs.js +1 -0
- package/core/ScreenSizer.d.ts +7 -0
- package/core/ScreenSizer.js +39 -0
- package/core/SpriteAnimator.cjs.js +1 -1
- package/core/SpriteAnimator.d.ts +2 -1
- package/core/SpriteAnimator.js +37 -127
- package/core/calculateScaleFactor.cjs.js +1 -0
- package/core/calculateScaleFactor.d.ts +3 -0
- package/core/calculateScaleFactor.js +31 -0
- package/core/index.cjs.js +1 -1
- package/core/index.d.ts +3 -0
- package/core/index.js +3 -0
- package/core/useSpriteLoader.cjs.js +1 -0
- package/core/useSpriteLoader.d.ts +9 -0
- package/core/useSpriteLoader.js +212 -0
- package/index.cjs.js +1 -1
- package/index.js +4 -1
- package/native/index.cjs.js +1 -1
- package/native/index.js +3 -0
- package/package.json +1 -1
- package/react-three-drei-0.0.0-semantic-release.tgz +0 -0
- package/web/index.cjs.js +1 -1
- package/web/index.js +5 -2
- package/web/pivotControls/index.cjs.js +1 -1
- package/web/pivotControls/index.d.ts +2 -4
- package/web/pivotControls/index.js +5 -31
package/README.md
CHANGED
|
@@ -71,6 +71,7 @@ The `native` route of the library **does not** export `Html` or `Loader`. The de
|
|
|
71
71
|
<li><a href="#positionalaudio">PositionalAudio</a></li>
|
|
72
72
|
<li><a href="#billboard">Billboard</a></li>
|
|
73
73
|
<li><a href="#screenspace">ScreenSpace</a></li>
|
|
74
|
+
<li><a href="#screensizer">ScreenSizer</a></li>
|
|
74
75
|
<li><a href="#effects">Effects</a></li>
|
|
75
76
|
<li><a href="#gradienttexture">GradientTexture</a></li>
|
|
76
77
|
<li><a href="#edges">Edges</a></li>
|
|
@@ -139,6 +140,7 @@ The `native` route of the library **does not** export `Html` or `Loader`. The de
|
|
|
139
140
|
<li><a href="#usevideotexture">useVideoTexture</a></li>
|
|
140
141
|
<li><a href="#usetrailtexture">useTrailTexture</a></li>
|
|
141
142
|
<li><a href="#usefont">useFont</a></li>
|
|
143
|
+
<li><a href="#usespriteloader">useSpriteLoader</a></li>
|
|
142
144
|
</ul>
|
|
143
145
|
<li><a href="#performance">Performance</a></li>
|
|
144
146
|
<ul>
|
|
@@ -214,7 +216,7 @@ The `native` route of the library **does not** export `Html` or `Loader`. The de
|
|
|
214
216
|
<li><a href="#environment">Environment</a></li>
|
|
215
217
|
<li><a href="#lightformer">Lightformer</a></li>
|
|
216
218
|
<li><a href="#spotlight">SpotLight</a></li>
|
|
217
|
-
<li><a href="#
|
|
219
|
+
<li><a href="#spotlightshadow">SpotLightShadow</a></li>
|
|
218
220
|
<li><a href="#shadow">Shadow</a></li>
|
|
219
221
|
<li><a href="#caustics">Caustics</a></li>
|
|
220
222
|
<li><a href="#contactshadows">ContactShadows</a></li>
|
|
@@ -1484,6 +1486,22 @@ Adds a `<group />` that aligns objects to screen space.
|
|
|
1484
1486
|
</ScreenSpace>
|
|
1485
1487
|
```
|
|
1486
1488
|
|
|
1489
|
+
#### ScreenSizer
|
|
1490
|
+
|
|
1491
|
+
[](https://drei.pmnd.rs/?path=/story/abstractions-screensizer--screen-sizer-story)
|
|
1492
|
+
|
|
1493
|
+
Adds a `<object3D />` that scales objects to screen space.
|
|
1494
|
+
|
|
1495
|
+
```jsx
|
|
1496
|
+
<ScreenSizer
|
|
1497
|
+
scale={1} // scale factor
|
|
1498
|
+
>
|
|
1499
|
+
<Box
|
|
1500
|
+
args={[100, 100, 100]} // will render roughly as a 100px box
|
|
1501
|
+
/>
|
|
1502
|
+
</ScreenSizer>
|
|
1503
|
+
```
|
|
1504
|
+
|
|
1487
1505
|
#### GradientTexture
|
|
1488
1506
|
|
|
1489
1507
|
<p>
|
|
@@ -2070,9 +2088,9 @@ type MeshTransmissionMaterialProps = JSX.IntrinsicElements['meshPhysicalMaterial
|
|
|
2070
2088
|
/* Distortion, default: 0 */
|
|
2071
2089
|
distortion?: number
|
|
2072
2090
|
/* Distortion scale, default: 0.5 */
|
|
2073
|
-
distortionScale
|
|
2091
|
+
distortionScale?: number
|
|
2074
2092
|
/* Temporal distortion (speed of movement), default: 0.0 */
|
|
2075
|
-
temporalDistortion
|
|
2093
|
+
temporalDistortion?: number
|
|
2076
2094
|
/** The scene rendered into a texture (use it to share a texture between materials), default: null */
|
|
2077
2095
|
buffer?: THREE.Texture
|
|
2078
2096
|
/** transmissionSampler, you can use the threejs transmission sampler texture that is
|
|
@@ -2572,6 +2590,8 @@ type Props = {
|
|
|
2572
2590
|
instanceItems?: any[]
|
|
2573
2591
|
/** The max number of items to instance (optional) */
|
|
2574
2592
|
maxItems?: number
|
|
2593
|
+
/** External parsed sprite data, usually from useSpriteLoader ready for use */
|
|
2594
|
+
spriteDataset?: any
|
|
2575
2595
|
}
|
|
2576
2596
|
```
|
|
2577
2597
|
|
|
@@ -2580,8 +2600,9 @@ The SpriteAnimator component provided by drei is a powerful tool for animating s
|
|
|
2580
2600
|
Notes:
|
|
2581
2601
|
|
|
2582
2602
|
- The SpriteAnimator component internally uses the useFrame hook from react-three-fiber (r3f) for efficient frame updates and rendering.
|
|
2583
|
-
- The sprites should contain equal size frames
|
|
2603
|
+
- The sprites (without a JSON file) should contain equal size frames
|
|
2584
2604
|
- Trimming of spritesheet frames is not yet supported
|
|
2605
|
+
- Internally uses the `useSpriteLoader` or can use data from it directly
|
|
2585
2606
|
|
|
2586
2607
|
```jsx
|
|
2587
2608
|
<SpriteAnimator
|
|
@@ -2598,7 +2619,7 @@ Notes:
|
|
|
2598
2619
|
ScrollControls example
|
|
2599
2620
|
|
|
2600
2621
|
```jsx
|
|
2601
|
-
|
|
2622
|
+
<ScrollControls damping={0.2} maxSpeed={0.5} pages={2}>
|
|
2602
2623
|
<SpriteAnimator
|
|
2603
2624
|
position={[0.0, -1.5, -1.5]}
|
|
2604
2625
|
startFrame={0}
|
|
@@ -2832,7 +2853,7 @@ return (
|
|
|
2832
2853
|
|
|
2833
2854
|

|
|
2834
2855
|
|
|
2835
|
-
A small hook that sets the css body cursor according to the hover state of a mesh, so that you can give the
|
|
2856
|
+
A small hook that sets the css body cursor according to the hover state of a mesh, so that you can give the user visual feedback when the mouse enters a shape. Arguments 1 and 2 determine the style, the defaults are: onPointerOver = 'pointer', onPointerOut = 'auto'.
|
|
2836
2857
|
|
|
2837
2858
|
```jsx
|
|
2838
2859
|
const [hovered, set] = useState()
|
|
@@ -3234,6 +3255,58 @@ In order to preload you do this:
|
|
|
3234
3255
|
useFont.preload('/fonts/helvetiker_regular.typeface.json')
|
|
3235
3256
|
```
|
|
3236
3257
|
|
|
3258
|
+
#### useSpriteLoader
|
|
3259
|
+
|
|
3260
|
+
Loads texture and JSON files with multiple or single animations and parses them into appropriate format. These assets can be used by multiple SpriteAnimator components to save memory and loading times.
|
|
3261
|
+
|
|
3262
|
+
```jsx
|
|
3263
|
+
/** The texture url to load the sprite frames from */
|
|
3264
|
+
input?: Url | null,
|
|
3265
|
+
/** The JSON data describing the position of the frames within the texture (optional) */
|
|
3266
|
+
json?: string | null,
|
|
3267
|
+
/** The animation names into which the frames will be divided into (optional) */
|
|
3268
|
+
animationNames?: string[] | null,
|
|
3269
|
+
/** The number of frames on a standalone (no JSON data) spritesheet (optional)*/
|
|
3270
|
+
numberOfFrames?: number | null,
|
|
3271
|
+
/** The callback to call when all textures and data have been loaded and parsed */
|
|
3272
|
+
onLoad?: (texture: Texture, textureData?: any) => void
|
|
3273
|
+
```
|
|
3274
|
+
|
|
3275
|
+
```jsx
|
|
3276
|
+
const { spriteObj } = useSpriteLoader(
|
|
3277
|
+
'multiasset.png',
|
|
3278
|
+
'multiasset.json',
|
|
3279
|
+
|
|
3280
|
+
['orange', 'Idle Blinking', '_Bat'],
|
|
3281
|
+
null
|
|
3282
|
+
)
|
|
3283
|
+
|
|
3284
|
+
<SpriteAnimator
|
|
3285
|
+
position={[4.5, 0.5, 0.1]}
|
|
3286
|
+
autoPlay={true}
|
|
3287
|
+
loop={true}
|
|
3288
|
+
scale={5}
|
|
3289
|
+
frameName={'_Bat'}
|
|
3290
|
+
animationNames={['_Bat']}
|
|
3291
|
+
spriteDataset={spriteObj}
|
|
3292
|
+
alphaTest={0.01}
|
|
3293
|
+
asSprite={false}
|
|
3294
|
+
/>
|
|
3295
|
+
|
|
3296
|
+
<SpriteAnimator
|
|
3297
|
+
position={[5.5, 0.5, 5.8]}
|
|
3298
|
+
autoPlay={true}
|
|
3299
|
+
loop={true}
|
|
3300
|
+
scale={5}
|
|
3301
|
+
frameName={'Idle Blinking'}
|
|
3302
|
+
animationNames={['Idle Blinking']}
|
|
3303
|
+
spriteDataset={spriteObj}
|
|
3304
|
+
alphaTest={0.01}
|
|
3305
|
+
asSprite={false}
|
|
3306
|
+
/>
|
|
3307
|
+
```
|
|
3308
|
+
|
|
3309
|
+
|
|
3237
3310
|
# Performance
|
|
3238
3311
|
|
|
3239
3312
|
#### Instances
|
|
@@ -4500,7 +4573,7 @@ function Foo() {
|
|
|
4500
4573
|
return <SpotLight depthBuffer={depthBuffer} />
|
|
4501
4574
|
```
|
|
4502
4575
|
|
|
4503
|
-
####
|
|
4576
|
+
#### SpotLightShadow
|
|
4504
4577
|
|
|
4505
4578
|
[](https://drei.pmnd.rs/?path=/story/staging-spotlight--spotlight-shadows-st)
|
|
4506
4579
|
|
|
@@ -4512,7 +4585,7 @@ A shadow caster that can help cast shadows of different patterns (textures) onto
|
|
|
4512
4585
|
|
|
4513
4586
|
```jsx
|
|
4514
4587
|
<SpotLight>
|
|
4515
|
-
<
|
|
4588
|
+
<SpotLightShadow
|
|
4516
4589
|
distance={0.4} // Distance between the shadow caster and light
|
|
4517
4590
|
alphaTest={0.5} // Sets the alpha value to be used when running an alpha test. See Material.alphaTest
|
|
4518
4591
|
scale={1} // Scale of the shadow caster plane
|
|
@@ -4524,7 +4597,7 @@ A shadow caster that can help cast shadows of different patterns (textures) onto
|
|
|
4524
4597
|
</SpotLight>
|
|
4525
4598
|
```
|
|
4526
4599
|
|
|
4527
|
-
An
|
|
4600
|
+
An optional `shader` prop lets you run a custom shader to modify/add effects to your shadow texture. The shader provides the following uniforms and varyings.
|
|
4528
4601
|
|
|
4529
4602
|
| Type | Name | Notes |
|
|
4530
4603
|
| ------------------- | ------------ | -------------------------------------- |
|
package/core/CameraControls.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OrthographicCamera, PerspectiveCamera } from 'three';
|
|
1
|
+
import { EventDispatcher, OrthographicCamera, PerspectiveCamera } from 'three';
|
|
2
2
|
import { ReactThreeFiber } from '@react-three/fiber';
|
|
3
3
|
import CameraControlsImpl from 'camera-controls';
|
|
4
4
|
import { ForwardRefComponent } from '../helpers/ts-utils';
|
|
@@ -17,6 +17,6 @@ export type CameraControlsProps = Omit<ReactThreeFiber.Overwrite<ReactThreeFiber
|
|
|
17
17
|
}) => void;
|
|
18
18
|
events?: boolean;
|
|
19
19
|
regress?: boolean;
|
|
20
|
-
}>, 'ref'>;
|
|
20
|
+
}>, 'ref' | keyof EventDispatcher>;
|
|
21
21
|
export declare const CameraControls: ForwardRefComponent<CameraControlsProps, CameraControlsImpl>;
|
|
22
22
|
export type CameraControls = CameraControlsImpl;
|
|
@@ -8,8 +8,8 @@ type MeshTransmissionMaterialType = Omit<JSX.IntrinsicElements['meshPhysicalMate
|
|
|
8
8
|
anisotropy?: number;
|
|
9
9
|
anisotropicBlur?: number;
|
|
10
10
|
distortion?: number;
|
|
11
|
-
distortionScale
|
|
12
|
-
temporalDistortion
|
|
11
|
+
distortionScale?: number;
|
|
12
|
+
temporalDistortion?: number;
|
|
13
13
|
buffer?: THREE.Texture;
|
|
14
14
|
time?: number;
|
|
15
15
|
args?: [samples: number, transmissionSampler: boolean];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),r=require("@react-three/fiber"),t=require("react"),c=require("react-merge-refs"),a=require("three"),u=require("./calculateScaleFactor.cjs.js");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function l(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var c=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,c.get?c:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var o=n(e),f=l(t),i=n(c);const s=new a.Vector3,d=t.forwardRef((({scale:e=1,...c},a)=>{const n=t.useRef(null);return r.useFrame((r=>{const t=n.current;if(!t)return;const c=u.calculateScaleFactor(t.getWorldPosition(s),e,r.camera,r.size);t.scale.setScalar(c*e)})),f.createElement("object3D",o.default({ref:i.default([n,a])},c))}));exports.ScreenSizer=d;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Object3DProps } from '@react-three/fiber';
|
|
2
|
+
import { ForwardRefComponent } from 'helpers/ts-utils';
|
|
3
|
+
import { Object3D } from 'three';
|
|
4
|
+
export interface ScreenSizerProps extends Object3DProps {
|
|
5
|
+
scale: number;
|
|
6
|
+
}
|
|
7
|
+
export declare const ScreenSizer: ForwardRefComponent<ScreenSizerProps, Object3D>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import _extends from '@babel/runtime/helpers/esm/extends';
|
|
2
|
+
import { useFrame } from '@react-three/fiber';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { forwardRef, useRef } from 'react';
|
|
5
|
+
import mergeRefs from 'react-merge-refs';
|
|
6
|
+
import { Vector3 } from 'three';
|
|
7
|
+
import { calculateScaleFactor } from './calculateScaleFactor.js';
|
|
8
|
+
|
|
9
|
+
const worldPos = /* @__PURE__ */new Vector3();
|
|
10
|
+
/**
|
|
11
|
+
* Wraps children in an `Object3D` and attempts to scale from
|
|
12
|
+
* world units to screen units * scale factor.
|
|
13
|
+
*
|
|
14
|
+
* For example, this will render a box of roughly 1x1 pixel size,
|
|
15
|
+
* independently of how far the camera is.
|
|
16
|
+
*
|
|
17
|
+
* ```jsx
|
|
18
|
+
* <ScreenSizer>
|
|
19
|
+
* <Box />
|
|
20
|
+
* </ScreenSizer>
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
const ScreenSizer = /* @__PURE__ */forwardRef(({
|
|
24
|
+
scale = 1,
|
|
25
|
+
...props
|
|
26
|
+
}, ref) => {
|
|
27
|
+
const container = useRef(null);
|
|
28
|
+
useFrame(state => {
|
|
29
|
+
const obj = container.current;
|
|
30
|
+
if (!obj) return;
|
|
31
|
+
const sf = calculateScaleFactor(obj.getWorldPosition(worldPos), scale, state.camera, state.size);
|
|
32
|
+
obj.scale.setScalar(sf * scale);
|
|
33
|
+
});
|
|
34
|
+
return /*#__PURE__*/React.createElement("object3D", _extends({
|
|
35
|
+
ref: mergeRefs([container, ref])
|
|
36
|
+
}, props));
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export { ScreenSizer };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),r=require("react"),t=require("@react-three/fiber"),n=require("three"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),r=require("react"),t=require("@react-three/fiber"),n=require("three"),u=require("./Instances.cjs.js"),a=require("./useSpriteLoader.cjs.js");function c(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function s(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var n=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,n.get?n:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}require("react-merge-refs"),require("react-composer"),require("../helpers/deprecated.cjs.js");var l=c(e),o=s(r),f=s(n);const i=o.createContext(null);const m=o.forwardRef((({startFrame:e,endFrame:r,fps:n,frameName:c,textureDataURL:s,textureImageURL:m,loop:p,numberOfFrames:d,autoPlay:h,animationNames:y,onStart:E,onEnd:w,onLoopEnd:v,onFrame:b,play:g,pause:x,flipX:F,alphaTest:S,children:j,asSprite:R,offset:M,playBackwards:O,resetOnEnd:A,maxItems:z,instanceItems:N,spriteDataset:q,...L},T)=>{const k=o.useRef(),I=o.useRef(null),D=o.useRef(),P=o.useRef(),_=o.useRef(window.performance.now()),U=o.useRef(e||0),B=o.useRef(c||""),C=1e3/(n||30),[G,H]=o.useState(new f.Texture),J=o.useRef(0),[W,X]=o.useState([1,1,1]),K=F?-1:1,[Q,V]=o.useState(null==R||R),Y=o.useRef(x),Z=o.useRef(M),$=o.useRef(!1),ee=o.useRef([]),{spriteObj:re,loadJsonAndTexture:te}=a.useSpriteLoader(null,null,y,d);function ne(){}const ue=o.useMemo((()=>({current:Z.current,offset:Z.current,imageUrl:m,reset:ne,hasEnded:!1,ref:T})),[m,q]);o.useImperativeHandle(T,(()=>k.current),[]),o.useLayoutEffect((()=>{Z.current=M}),[M]);const ae=(e,r)=>{const t=r/e;return P.current&&P.current.scale.set(1,t,1),[1,t,1]};o.useEffect((()=>{var e;q?ce(null==q||null==(e=q.spriteTexture)?void 0:e.clone(),q.spriteData):te(m,s)}),[q]),o.useEffect((()=>{var e;re&&ce(null==re||null==(e=re.spriteTexture)?void 0:e.clone(),null==re?void 0:re.spriteData)}),[re]),o.useEffect((()=>{V(null==R||R)}),[R]),o.useEffect((()=>{ue.hasEnded=!1,I.current&&!0===O?U.current=I.current.frames.length-1:U.current=0}),[O]),o.useLayoutEffect((()=>{se()}),[G,F]),o.useEffect((()=>{h&&(Y.current=!1)}),[h]),o.useLayoutEffect((()=>{if(B.current!==c&&c&&(U.current=0,B.current=c,ue.hasEnded=!1,I.current)){const{w:e,h:r}=oe(I.current.frames).sourceSize,t=ae(e,r);X(t)}}),[c]);const ce=(e,r=null)=>{if(null===r){if(d){const t=e.image.width,n=e.image.height;J.current=d,O&&(U.current=d-1),I.current={frames:[],meta:{version:"1.0",size:{w:t,h:n},scale:"1"}},I.current.frames=r}}else{I.current=r,J.current=I.current.frames.length,O&&(U.current=J.current-1);const{w:t,h:n}=oe(I.current.frames).sourceSize,u=ae(t,n);X(u),D.current&&(D.current.map=e)}if(N)for(var t=0;t<N.length;t++){const e=Object.keys(I.current.frames),r=e[Math.floor(Math.random()*e.length)];ee.current.push({key:t,frames:I.current.frames,selectedFrame:r,offset:{x:0,y:0}})}H(e)},se=()=>{if(!I.current)return;const{meta:{size:e},frames:r}=I.current,{w:t,h:n}=Array.isArray(r)?r[0].sourceSize:c&&r[c]?r[c][0].sourceSize:{w:0,h:0};D.current.map.wrapS=D.current.map.wrapT=f.RepeatWrapping,D.current.map.center.set(0,0),D.current.map.repeat.set(1*K/(e.w/t),1/(e.h/n));const u=1/((e.h-1)/n);D.current.map.offset.x=0,D.current.map.offset.y=1-u,E&&E({currentFrameName:c,currentFrame:U.current})},le=(e,r,t,n)=>{var u=void 0===M?ue.current:M;const a=U.current;let c=0,s=0;ae(e,r);const l=(t.w-1)/e,o=(t.h-1)/r;if(!n[a])return;const{frame:{x:f,y:i},sourceSize:{w:m,h:p}}=n[a],d=1/l,h=1/o;if(c=K>0?d*(f/m):d*(f/m)-D.current.map.repeat.x,s=Math.abs(1-h)-h*(i/p),D.current.map.offset.x=c,D.current.map.offset.y=s,null!=u){let e=Math.floor(u*n.length);e=Math.max(0,Math.min(e,n.length-1)),isNaN(e)&&(e=0),U.current=e}else O?U.current-=1:U.current+=1};t.useFrame(((t,n)=>{var u,a;null!=(u=I.current)&&u.frames&&null!=(a=D.current)&&a.map&&(Y.current||ue.hasEnded||!h&&!g||((()=>{const t=window.performance.now(),n=t-_.current,{meta:{size:u},frames:a}=I.current,{w:s,h:l}=oe(a).sourceSize,o=Array.isArray(a)?a:c?a[c]:[],f=r||o.length-1;var i=void 0===M?ue.current:M,m=O?U.current<0:U.current>f,d=O?U.current===f:0===U.current,h=O?U.current<0:U.current>=f;if(m){if(U.current=p&&null!=e?e:0,O&&(U.current=f),p?null==v||v({currentFrameName:c,currentFrame:U.current}):(null==w||w({currentFrameName:c,currentFrame:U.current}),ue.hasEnded=!A,A&&(Y.current=!0)),!p)return}else d&&(null==E||E({currentFrameName:c,currentFrame:U.current}));void 0!==i&&h?!1===$.current&&(null==w||w({currentFrameName:c,currentFrame:U.current}),$.current=!0):$.current=!1,n<=C||(_.current=t-n%C,le(s,l,u,o))})(),b&&b({currentFrameName:B.current,currentFrame:U.current})))}));const oe=e=>{if(Array.isArray(e))return e[0];if("object"==typeof e&&null!==e){const r=Object.keys(e);return c?e[c][0]:e[r[0]][0]}return{w:0,h:0}};return o.createElement("group",l.default({},L,{ref:k}),o.createElement(i.Provider,{value:ue},o.createElement(o.Suspense,{fallback:null},Q&&o.createElement("sprite",{ref:P,scale:W},o.createElement("spriteMaterial",{premultipliedAlpha:!1,toneMapped:!1,ref:D,map:G,transparent:!0,alphaTest:null!=S?S:0})),!Q&&o.createElement(u.Instances,{limit:null!=z?z:1},o.createElement("planeGeometry",{args:[1,1]}),o.createElement("meshBasicMaterial",{premultipliedAlpha:!1,toneMapped:!1,side:f.DoubleSide,ref:D,map:G,transparent:!0,alphaTest:null!=S?S:0}),(null!=N?N:[0]).map(((e,r)=>o.createElement(u.Instance,{key:r,ref:P,position:e,scale:W}))))),j))}));exports.SpriteAnimator=m,exports.useSpriteAnimator=function(){return o.useContext(i)};
|
package/core/SpriteAnimator.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type SpriteAnimatorProps = {
|
|
|
5
5
|
fps?: number;
|
|
6
6
|
frameName?: string;
|
|
7
7
|
textureDataURL?: string;
|
|
8
|
-
textureImageURL
|
|
8
|
+
textureImageURL?: string;
|
|
9
9
|
loop?: boolean;
|
|
10
10
|
numberOfFrames?: number;
|
|
11
11
|
autoPlay?: boolean;
|
|
@@ -25,6 +25,7 @@ export type SpriteAnimatorProps = {
|
|
|
25
25
|
resetOnEnd?: boolean;
|
|
26
26
|
maxItems?: number;
|
|
27
27
|
instanceItems?: any[];
|
|
28
|
+
spriteDataset?: any;
|
|
28
29
|
} & JSX.IntrinsicElements['group'];
|
|
29
30
|
type SpriteAnimatorState = {
|
|
30
31
|
current: number | undefined;
|
package/core/SpriteAnimator.js
CHANGED
|
@@ -3,6 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import { useFrame } from '@react-three/fiber';
|
|
4
4
|
import * as THREE from 'three';
|
|
5
5
|
import { Instances, Instance } from './Instances.js';
|
|
6
|
+
import { useSpriteLoader } from './useSpriteLoader.js';
|
|
6
7
|
|
|
7
8
|
const context = /*#__PURE__*/React.createContext(null);
|
|
8
9
|
function useSpriteAnimator() {
|
|
@@ -34,15 +35,14 @@ const SpriteAnimator = /* @__PURE__ */React.forwardRef(({
|
|
|
34
35
|
resetOnEnd,
|
|
35
36
|
maxItems,
|
|
36
37
|
instanceItems,
|
|
38
|
+
spriteDataset,
|
|
37
39
|
...props
|
|
38
40
|
}, fref) => {
|
|
39
41
|
const ref = React.useRef();
|
|
40
42
|
const spriteData = React.useRef(null);
|
|
41
|
-
//const hasEnded = React.useRef(false)
|
|
42
43
|
const matRef = React.useRef();
|
|
43
44
|
const spriteRef = React.useRef();
|
|
44
45
|
const timerOffset = React.useRef(window.performance.now());
|
|
45
|
-
const textureData = React.useRef();
|
|
46
46
|
const currentFrame = React.useRef(startFrame || 0);
|
|
47
47
|
const currentFrameName = React.useRef(frameName || '');
|
|
48
48
|
const fpsInterval = 1000 / (fps || 30);
|
|
@@ -55,6 +55,10 @@ const SpriteAnimator = /* @__PURE__ */React.forwardRef(({
|
|
|
55
55
|
const pos = React.useRef(offset);
|
|
56
56
|
const softEnd = React.useRef(false);
|
|
57
57
|
const frameBuffer = React.useRef([]);
|
|
58
|
+
const {
|
|
59
|
+
spriteObj,
|
|
60
|
+
loadJsonAndTexture
|
|
61
|
+
} = useSpriteLoader(null, null, animationNames, numberOfFrames);
|
|
58
62
|
//
|
|
59
63
|
|
|
60
64
|
function reset() {}
|
|
@@ -65,21 +69,11 @@ const SpriteAnimator = /* @__PURE__ */React.forwardRef(({
|
|
|
65
69
|
reset: reset,
|
|
66
70
|
hasEnded: false,
|
|
67
71
|
ref: fref
|
|
68
|
-
}), [textureImageURL]);
|
|
72
|
+
}), [textureImageURL, spriteDataset]);
|
|
69
73
|
React.useImperativeHandle(fref, () => ref.current, []);
|
|
70
74
|
React.useLayoutEffect(() => {
|
|
71
75
|
pos.current = offset;
|
|
72
76
|
}, [offset]);
|
|
73
|
-
function loadJsonAndTextureAndExecuteCallback(jsonUrl, textureUrl, callback) {
|
|
74
|
-
const textureLoader = new THREE.TextureLoader();
|
|
75
|
-
const jsonPromise = fetch(jsonUrl).then(response => response.json());
|
|
76
|
-
const texturePromise = new Promise(resolve => {
|
|
77
|
-
textureLoader.load(textureUrl, resolve);
|
|
78
|
-
});
|
|
79
|
-
Promise.all([jsonPromise, texturePromise]).then(response => {
|
|
80
|
-
callback(response[0], response[1]);
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
77
|
const calculateAspectRatio = (width, height) => {
|
|
84
78
|
const aspectRatio = height / width;
|
|
85
79
|
if (spriteRef.current) {
|
|
@@ -90,18 +84,19 @@ const SpriteAnimator = /* @__PURE__ */React.forwardRef(({
|
|
|
90
84
|
|
|
91
85
|
// initial loads
|
|
92
86
|
React.useEffect(() => {
|
|
93
|
-
if (
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
87
|
+
if (spriteDataset) {
|
|
88
|
+
var _spriteDataset$sprite;
|
|
89
|
+
parseSpriteDataLite(spriteDataset == null || (_spriteDataset$sprite = spriteDataset.spriteTexture) == null ? void 0 : _spriteDataset$sprite.clone(), spriteDataset.spriteData);
|
|
90
|
+
} else {
|
|
91
|
+
loadJsonAndTexture(textureImageURL, textureDataURL);
|
|
92
|
+
}
|
|
93
|
+
}, [spriteDataset]);
|
|
94
|
+
React.useEffect(() => {
|
|
95
|
+
if (spriteObj) {
|
|
96
|
+
var _spriteObj$spriteText;
|
|
97
|
+
parseSpriteDataLite(spriteObj == null || (_spriteObj$spriteText = spriteObj.spriteTexture) == null ? void 0 : _spriteObj$spriteText.clone(), spriteObj == null ? void 0 : spriteObj.spriteData);
|
|
103
98
|
}
|
|
104
|
-
}, []);
|
|
99
|
+
}, [spriteObj]);
|
|
105
100
|
React.useEffect(() => {
|
|
106
101
|
setDisplayAsSprite(asSprite !== null && asSprite !== void 0 ? asSprite : true);
|
|
107
102
|
}, [asSprite]);
|
|
@@ -123,12 +118,12 @@ const SpriteAnimator = /* @__PURE__ */React.forwardRef(({
|
|
|
123
118
|
pauseRef.current = false;
|
|
124
119
|
}
|
|
125
120
|
}, [autoPlay]);
|
|
126
|
-
React.
|
|
121
|
+
React.useLayoutEffect(() => {
|
|
127
122
|
if (currentFrameName.current !== frameName && frameName) {
|
|
128
123
|
currentFrame.current = 0;
|
|
129
124
|
currentFrameName.current = frameName;
|
|
130
125
|
state.hasEnded = false;
|
|
131
|
-
modifySpritePosition()
|
|
126
|
+
// modifySpritePosition()
|
|
132
127
|
if (spriteData.current) {
|
|
133
128
|
const {
|
|
134
129
|
w,
|
|
@@ -140,17 +135,13 @@ const SpriteAnimator = /* @__PURE__ */React.forwardRef(({
|
|
|
140
135
|
}
|
|
141
136
|
}, [frameName]);
|
|
142
137
|
|
|
143
|
-
//
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
if (json === null) {
|
|
138
|
+
// lite version for pre-loaded assets
|
|
139
|
+
const parseSpriteDataLite = (textureData, frameData = null) => {
|
|
140
|
+
if (frameData === null) {
|
|
147
141
|
if (numberOfFrames) {
|
|
148
142
|
//get size from texture
|
|
149
|
-
const width =
|
|
150
|
-
const height =
|
|
151
|
-
const frameWidth = width / numberOfFrames;
|
|
152
|
-
const frameHeight = height;
|
|
153
|
-
textureData.current = _spriteTexture;
|
|
143
|
+
const width = textureData.image.width;
|
|
144
|
+
const height = textureData.image.height;
|
|
154
145
|
totalFrames.current = numberOfFrames;
|
|
155
146
|
if (playBackwards) {
|
|
156
147
|
currentFrame.current = numberOfFrames - 1;
|
|
@@ -166,48 +157,22 @@ const SpriteAnimator = /* @__PURE__ */React.forwardRef(({
|
|
|
166
157
|
scale: '1'
|
|
167
158
|
}
|
|
168
159
|
};
|
|
169
|
-
|
|
170
|
-
// if it fits
|
|
171
|
-
for (let i = 0; i < numberOfFrames; i++) {
|
|
172
|
-
spriteData.current.frames.push({
|
|
173
|
-
frame: {
|
|
174
|
-
x: i * frameWidth,
|
|
175
|
-
y: 0,
|
|
176
|
-
w: frameWidth,
|
|
177
|
-
h: frameHeight
|
|
178
|
-
},
|
|
179
|
-
rotated: false,
|
|
180
|
-
trimmed: false,
|
|
181
|
-
spriteSourceSize: {
|
|
182
|
-
x: 0,
|
|
183
|
-
y: 0,
|
|
184
|
-
w: frameWidth,
|
|
185
|
-
h: frameHeight
|
|
186
|
-
},
|
|
187
|
-
sourceSize: {
|
|
188
|
-
w: frameWidth,
|
|
189
|
-
h: height
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
}
|
|
160
|
+
spriteData.current.frames = frameData;
|
|
194
161
|
}
|
|
195
162
|
} else {
|
|
196
|
-
spriteData.current =
|
|
197
|
-
|
|
198
|
-
totalFrames.current = Array.isArray(json.frames) ? json.frames.length : Object.keys(json.frames).length;
|
|
199
|
-
textureData.current = _spriteTexture;
|
|
163
|
+
spriteData.current = frameData;
|
|
164
|
+
totalFrames.current = spriteData.current.frames.length;
|
|
200
165
|
if (playBackwards) {
|
|
201
166
|
currentFrame.current = totalFrames.current - 1;
|
|
202
167
|
}
|
|
203
168
|
const {
|
|
204
169
|
w,
|
|
205
170
|
h
|
|
206
|
-
} = getFirstItem(
|
|
171
|
+
} = getFirstItem(spriteData.current.frames).sourceSize;
|
|
207
172
|
const aspect = calculateAspectRatio(w, h);
|
|
208
173
|
setAspect(aspect);
|
|
209
174
|
if (matRef.current) {
|
|
210
|
-
matRef.current.map =
|
|
175
|
+
matRef.current.map = textureData;
|
|
211
176
|
}
|
|
212
177
|
}
|
|
213
178
|
|
|
@@ -227,50 +192,7 @@ const SpriteAnimator = /* @__PURE__ */React.forwardRef(({
|
|
|
227
192
|
});
|
|
228
193
|
}
|
|
229
194
|
}
|
|
230
|
-
|
|
231
|
-
setSpriteTexture(_spriteTexture);
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
// for frame based JSON Hash sprite data
|
|
235
|
-
const parseFrames = () => {
|
|
236
|
-
const sprites = {};
|
|
237
|
-
const data = spriteData.current;
|
|
238
|
-
const delimiters = animationNames;
|
|
239
|
-
if (delimiters) {
|
|
240
|
-
for (let i = 0; i < delimiters.length; i++) {
|
|
241
|
-
sprites[delimiters[i]] = [];
|
|
242
|
-
for (const innerKey in data['frames']) {
|
|
243
|
-
const value = data['frames'][innerKey];
|
|
244
|
-
const frameData = value['frame'];
|
|
245
|
-
const x = frameData['x'];
|
|
246
|
-
const y = frameData['y'];
|
|
247
|
-
const width = frameData['w'];
|
|
248
|
-
const height = frameData['h'];
|
|
249
|
-
const sourceWidth = value['sourceSize']['w'];
|
|
250
|
-
const sourceHeight = value['sourceSize']['h'];
|
|
251
|
-
if (innerKey.toLowerCase().indexOf(delimiters[i].toLowerCase()) !== -1) {
|
|
252
|
-
sprites[delimiters[i]].push({
|
|
253
|
-
x: x,
|
|
254
|
-
y: y,
|
|
255
|
-
w: width,
|
|
256
|
-
h: height,
|
|
257
|
-
frame: frameData,
|
|
258
|
-
sourceSize: {
|
|
259
|
-
w: sourceWidth,
|
|
260
|
-
h: sourceHeight
|
|
261
|
-
}
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
return sprites;
|
|
267
|
-
} else if (frameName) {
|
|
268
|
-
const spritesArr = [];
|
|
269
|
-
for (const key in data.frames) {
|
|
270
|
-
spritesArr.push(data.frames[key]);
|
|
271
|
-
}
|
|
272
|
-
return spritesArr;
|
|
273
|
-
}
|
|
195
|
+
setSpriteTexture(textureData);
|
|
274
196
|
};
|
|
275
197
|
|
|
276
198
|
// modify the sprite material after json is parsed and state updated
|
|
@@ -310,6 +232,7 @@ const SpriteAnimator = /* @__PURE__ */React.forwardRef(({
|
|
|
310
232
|
// run the animation on each frame
|
|
311
233
|
const runAnimation = () => {
|
|
312
234
|
//if (!frameName) return
|
|
235
|
+
|
|
313
236
|
const now = window.performance.now();
|
|
314
237
|
const diff = now - timerOffset.current;
|
|
315
238
|
const {
|
|
@@ -345,9 +268,6 @@ const SpriteAnimator = /* @__PURE__ */React.forwardRef(({
|
|
|
345
268
|
currentFrameName: frameName,
|
|
346
269
|
currentFrame: currentFrame.current
|
|
347
270
|
});
|
|
348
|
-
if (!_offset) {
|
|
349
|
-
console.log('will end');
|
|
350
|
-
}
|
|
351
271
|
state.hasEnded = resetOnEnd ? false : true;
|
|
352
272
|
if (resetOnEnd) {
|
|
353
273
|
pauseRef.current = true;
|
|
@@ -419,7 +339,6 @@ const SpriteAnimator = /* @__PURE__ */React.forwardRef(({
|
|
|
419
339
|
// Ensure the frame index is within the valid range
|
|
420
340
|
frameIndex = Math.max(0, Math.min(frameIndex, spriteFrames.length - 1));
|
|
421
341
|
if (isNaN(frameIndex)) {
|
|
422
|
-
console.log('nan frame detected');
|
|
423
342
|
frameIndex = 0; //fallback
|
|
424
343
|
}
|
|
425
344
|
|
|
@@ -476,16 +395,18 @@ const SpriteAnimator = /* @__PURE__ */React.forwardRef(({
|
|
|
476
395
|
ref: spriteRef,
|
|
477
396
|
scale: aspect
|
|
478
397
|
}, /*#__PURE__*/React.createElement("spriteMaterial", {
|
|
398
|
+
premultipliedAlpha: false,
|
|
479
399
|
toneMapped: false,
|
|
480
400
|
ref: matRef,
|
|
481
401
|
map: spriteTexture,
|
|
482
402
|
transparent: true,
|
|
483
403
|
alphaTest: alphaTest !== null && alphaTest !== void 0 ? alphaTest : 0.0
|
|
484
404
|
})), !displayAsSprite && /*#__PURE__*/React.createElement(Instances, {
|
|
485
|
-
limit: maxItems // Optional: max amount of items (for calculating buffer size)
|
|
405
|
+
limit: maxItems !== null && maxItems !== void 0 ? maxItems : 1 // Optional: max amount of items (for calculating buffer size)
|
|
486
406
|
}, /*#__PURE__*/React.createElement("planeGeometry", {
|
|
487
407
|
args: [1, 1]
|
|
488
408
|
}), /*#__PURE__*/React.createElement("meshBasicMaterial", {
|
|
409
|
+
premultipliedAlpha: false,
|
|
489
410
|
toneMapped: false,
|
|
490
411
|
side: THREE.DoubleSide,
|
|
491
412
|
ref: matRef,
|
|
@@ -493,23 +414,12 @@ const SpriteAnimator = /* @__PURE__ */React.forwardRef(({
|
|
|
493
414
|
transparent: true,
|
|
494
415
|
alphaTest: alphaTest !== null && alphaTest !== void 0 ? alphaTest : 0.0
|
|
495
416
|
}), (instanceItems !== null && instanceItems !== void 0 ? instanceItems : [0]).map((item, index) => {
|
|
496
|
-
const texture = spriteTexture.clone();
|
|
497
|
-
if (matRef.current && frameBuffer.current[index]) {
|
|
498
|
-
texture.offset.set(frameBuffer.current[index].offset.x, frameBuffer.current[index].offset.y); // Set the offset for this item
|
|
499
|
-
}
|
|
500
|
-
|
|
501
417
|
return /*#__PURE__*/React.createElement(Instance, {
|
|
502
418
|
key: index,
|
|
503
419
|
ref: spriteRef,
|
|
504
420
|
position: item,
|
|
505
421
|
scale: aspect
|
|
506
|
-
}
|
|
507
|
-
toneMapped: false,
|
|
508
|
-
side: THREE.DoubleSide,
|
|
509
|
-
map: texture,
|
|
510
|
-
transparent: true,
|
|
511
|
-
alphaTest: alphaTest !== null && alphaTest !== void 0 ? alphaTest : 0.0
|
|
512
|
-
}));
|
|
422
|
+
});
|
|
513
423
|
}))), children));
|
|
514
424
|
});
|
|
515
425
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";function e(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var o=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,o.get?o:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}Object.defineProperty(exports,"__esModule",{value:!0});var t=e(require("three"));const r=new t.Vector3,o=new t.Vector3,n=new t.Vector3,c=(e,t,o,n=1)=>{const c=r.set(e.x/o.width*2-1,-e.y/o.height*2+1,n);return c.unproject(t),c};exports.calculateScaleFactor=(e,t,r,u)=>{const a=((e,t,r)=>{const o=r.width/2,n=r.height/2;t.updateMatrixWorld(!1);const c=e.project(t);return c.x=c.x*o+o,c.y=-c.y*n+n,c})(n.copy(e),r,u);let s=0;for(let n=0;n<2;++n){const i=o.copy(a).setComponent(n,a.getComponent(n)+t),l=c(i,r,u,i.z);s=Math.max(s,e.distanceTo(l))}return s};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
|
|
3
|
+
const tV0 = /* @__PURE__ */new THREE.Vector3();
|
|
4
|
+
const tV1 = /* @__PURE__ */new THREE.Vector3();
|
|
5
|
+
const tV2 = /* @__PURE__ */new THREE.Vector3();
|
|
6
|
+
const getPoint2 = (point3, camera, size) => {
|
|
7
|
+
const widthHalf = size.width / 2;
|
|
8
|
+
const heightHalf = size.height / 2;
|
|
9
|
+
camera.updateMatrixWorld(false);
|
|
10
|
+
const vector = point3.project(camera);
|
|
11
|
+
vector.x = vector.x * widthHalf + widthHalf;
|
|
12
|
+
vector.y = -(vector.y * heightHalf) + heightHalf;
|
|
13
|
+
return vector;
|
|
14
|
+
};
|
|
15
|
+
const getPoint3 = (point2, camera, size, zValue = 1) => {
|
|
16
|
+
const vector = tV0.set(point2.x / size.width * 2 - 1, -(point2.y / size.height) * 2 + 1, zValue);
|
|
17
|
+
vector.unproject(camera);
|
|
18
|
+
return vector;
|
|
19
|
+
};
|
|
20
|
+
const calculateScaleFactor = (point3, radiusPx, camera, size) => {
|
|
21
|
+
const point2 = getPoint2(tV2.copy(point3), camera, size);
|
|
22
|
+
let scale = 0;
|
|
23
|
+
for (let i = 0; i < 2; ++i) {
|
|
24
|
+
const point2off = tV1.copy(point2).setComponent(i, point2.getComponent(i) + radiusPx);
|
|
25
|
+
const point3off = getPoint3(point2off, camera, size, point2off.z);
|
|
26
|
+
scale = Math.max(scale, point3.distanceTo(point3off));
|
|
27
|
+
}
|
|
28
|
+
return scale;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export { calculateScaleFactor };
|