Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SpriteAnimator/useSpriteLoader types #2171

Merged
merged 71 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from 63 commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
6b3af00
feat: added optional Sprite or Plane geometry for SpriteAnimator
netgfx Sep 6, 2023
2c3b3d5
Merge remote-tracking branch 'origin/master'
netgfx Sep 13, 2023
66a09ec
Merge branch 'pmndrs:master' into master
netgfx Sep 19, 2023
f2422a0
Merge branch 'pmndrs:master' into master
netgfx Sep 29, 2023
4ea2d8c
Merge branch 'pmndrs:master' into master
netgfx Oct 7, 2023
67689d4
Merge branch 'pmndrs:master' into master
netgfx Oct 9, 2023
3de0966
Merge branch 'pmndrs:master' into master
netgfx Oct 19, 2023
723b3a1
Merge branch 'pmndrs:master' into master
netgfx Oct 26, 2023
b73ccde
Merge branch 'pmndrs:master' into master
netgfx Nov 15, 2023
583564f
Merge branch 'pmndrs:master' into master
netgfx Dec 18, 2023
29bb924
Merge branch 'pmndrs:master' into master
netgfx Jan 5, 2024
edb486a
Merge branch 'pmndrs:master' into master
netgfx Jan 21, 2024
6163ed9
Merge branch 'pmndrs:master' into master
netgfx Jan 31, 2024
197c444
Merge branch 'pmndrs:master' into master
netgfx Feb 3, 2024
1d97ca9
Merge branch 'pmndrs:master' into master
netgfx Feb 5, 2024
bfd6851
Merge branch 'pmndrs:master' into master
netgfx Feb 10, 2024
a1a3e18
Merge branch 'pmndrs:master' into master
netgfx Feb 11, 2024
f236ea3
Merge branch 'pmndrs:master' into master
netgfx Feb 24, 2024
7e25331
Merge branch 'pmndrs:master' into master
netgfx Mar 5, 2024
cf80ba3
Merge branch 'pmndrs:master' into master
netgfx Mar 16, 2024
4ab5687
Merge branch 'pmndrs:master' into master
netgfx Apr 12, 2024
dee87b1
Merge branch 'pmndrs:master' into master
netgfx May 31, 2024
abde9ab
Merge branch 'pmndrs:master' into master
netgfx Jun 10, 2024
e6758ca
Merge branch 'pmndrs:master' into master
netgfx Jun 11, 2024
b966985
Merge branch 'pmndrs:master' into master
netgfx Jun 20, 2024
136961e
Merge branch 'pmndrs:master' into master
netgfx Oct 22, 2024
5cda03d
Merge branch 'pmndrs:master' into master
netgfx Oct 29, 2024
d0eec1d
Merge branch 'pmndrs:master' into master
netgfx Oct 30, 2024
01eb03b
fix: added more strict types to spriteanimator
netgfx Oct 30, 2024
5e37309
improved documentation
netgfx Oct 30, 2024
116f112
replaced interface with type, added prop comments
netgfx Oct 31, 2024
b737319
removed unused types, preferred type inferring when possible
netgfx Oct 31, 2024
7154c26
fixes for types and more accurate type handling
netgfx Nov 1, 2024
b673613
prettier fixes
netgfx Nov 1, 2024
2f047b0
improved dependencies, fixed eslint errors
netgfx Nov 1, 2024
cd9ac2b
no more any
abernier Nov 1, 2024
0f492f7
removing more type-assertions
abernier Nov 1, 2024
ab72df5
Merge branch 'pmndrs:master' into master
netgfx Nov 2, 2024
479cd9e
cleaned up some comments on documentation
netgfx Nov 2, 2024
b4f04ed
more types enhancements
abernier Nov 2, 2024
1391a2f
removing more type-assertions
abernier Nov 2, 2024
941e8a3
CommonProps
abernier Nov 2, 2024
8d6d44e
Merge branch 'pmndrs:master' into master
netgfx Nov 2, 2024
35db2d4
fix for useSpriteLoader types
abernier Nov 2, 2024
671989d
common props
netgfx Nov 3, 2024
b09d6a8
Merge branch 'master' into fix/spriteanimator-types
netgfx Nov 3, 2024
0667aa4
Merge remote-tracking branch 'origin/fix/spriteanimator-types' into f…
netgfx Nov 3, 2024
3968b43
added default values
netgfx Nov 5, 2024
46f2a81
removed unused functions
netgfx Nov 5, 2024
138d9cb
Spriteanimator is now pulling types from useSpriteLoader
netgfx Nov 5, 2024
50dce65
renamed function
netgfx Nov 5, 2024
b956cb7
removed extra dependencies, removed duplicate variables
netgfx Nov 8, 2024
3bacfe1
simplified promise to callback
netgfx Nov 8, 2024
85071b9
Merge branch 'master' of https://github.com/pmndrs/drei into pr/2171
abernier Nov 10, 2024
fbb87ab
Merge branch 'pmndrs:master' into master
netgfx Nov 10, 2024
d822dfe
Merge branch 'master' into fix/spriteanimator-types
netgfx Nov 10, 2024
3ba5fc4
added eslint fixes
netgfx Nov 10, 2024
9845805
Merge branch 'fix/spriteanimator-types' of https://github.com/netgfx/…
abernier Nov 11, 2024
a7110a7
added proper types on some internal variables
netgfx Nov 12, 2024
bf0526a
streamlined types for onLoad
netgfx Nov 12, 2024
a151832
sharing getFirstFrame
abernier Nov 12, 2024
c097c0d
killing deps
abernier Nov 12, 2024
9deb57f
simplifying useSpriteLoader
abernier Nov 12, 2024
3111c1b
added spriteAnimator interactive story
netgfx Nov 12, 2024
f313986
Merge remote-tracking branch 'origin/fix/spriteanimator-types' into f…
netgfx Nov 12, 2024
192cfe4
reverted story, added a new story with json data
netgfx Nov 12, 2024
e8916cd
removed unused assets
netgfx Nov 12, 2024
bc95cc5
Revert "simplifying useSpriteLoader"
abernier Nov 14, 2024
140fe43
Revert "killing deps"
abernier Nov 14, 2024
d219708
fix for unnecessary re-render
netgfx Nov 15, 2024
07a56ec
prettier formatting
netgfx Nov 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 18 additions & 12 deletions .storybook/stories/SpriteAnimator.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from 'react'
import { Vector3 } from 'three'
import { Meta, StoryObj } from '@storybook/react'
import { Setup } from '../Setup'
import { SpriteAnimator, useSpriteLoader } from '../../src'
import { SpriteAnimator } from '../../src'

const SPRITE_IMAGE = 'story.png'
const SPRITE_DATA = 'story.json'
Expand Down Expand Up @@ -32,12 +32,13 @@ type Story = StoryObj<typeof SpriteAnimator>
//

function SpriteAnimatorScene1(props: React.ComponentProps<typeof SpriteAnimator>) {
const { spriteObj } = useSpriteLoader(SPRITE_IMAGE, SPRITE_DATA, [props.frameName!], null)

return <SpriteAnimator {...props} spriteDataset={spriteObj} />
return <SpriteAnimator {...props} />
}
export const SpriteAnimatorSt1 = {
args: {
textureImageURL: SPRITE_IMAGE,
textureDataURL: SPRITE_DATA,
animationNames: ['Fly'],
frameName: 'Fly',
fps: 18,
scale: 1.5,
Expand All @@ -49,12 +50,13 @@ export const SpriteAnimatorSt1 = {
//

function SpriteAnimatorScene2(props: React.ComponentProps<typeof SpriteAnimator>) {
const { spriteObj } = useSpriteLoader(SPRITE_IMAGE, SPRITE_DATA, [props.frameName!], null)

return <SpriteAnimator {...props} spriteDataset={spriteObj} />
return <SpriteAnimator {...props} />
}
export const SpriteAnimatorSt2 = {
args: {
textureImageURL: SPRITE_IMAGE,
textureDataURL: SPRITE_DATA,
animationNames: ['sword'],
frameName: 'sword',
fps: 0,
},
Expand All @@ -65,14 +67,18 @@ export const SpriteAnimatorSt2 = {
//

function SpriteAnimatorScene3(props: React.ComponentProps<typeof SpriteAnimator>) {
const { spriteObj } = useSpriteLoader(SPRITE_IMAGE, SPRITE_DATA, ['Fly', 'heart', 'sword', 'skull'], null)
const commonProps = {
textureImageURL: SPRITE_IMAGE,
textureDataURL: SPRITE_DATA,
animationNames: ['Fly', 'heart', 'sword', 'skull'],
}

return (
<>
<SpriteAnimator {...props} position={[-2, 0, 0.01]} spriteDataset={spriteObj} frameName={'Fly'} fps={18} />
<SpriteAnimator {...props} position={[-3, 0, 0.01]} spriteDataset={spriteObj} frameName={'sword'} fps={0} />
<SpriteAnimator {...props} position={[-1, 0, 0.01]} spriteDataset={spriteObj} frameName={'heart'} fps={0} />
<SpriteAnimator {...props} position={[0, 0, 0.01]} spriteDataset={spriteObj} frameName={'skull'} fps={0} />
<SpriteAnimator {...props} position={[-2, 0, 0.01]} {...commonProps} frameName={'Fly'} fps={18} />
<SpriteAnimator {...props} position={[-3, 0, 0.01]} {...commonProps} frameName={'sword'} fps={0} />
<SpriteAnimator {...props} position={[-1, 0, 0.01]} {...commonProps} frameName={'heart'} fps={0} />
<SpriteAnimator {...props} position={[0, 0, 0.01]} {...commonProps} frameName={'skull'} fps={0} />
</>
)
}
Expand Down
116 changes: 47 additions & 69 deletions docs/misc/sprite-animator.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,7 @@ sourcecode: src/core/SpriteAnimator.tsx
</Grid>

```tsx

/** Common properties that can be safely applied to both sprite and instance components */
type CommonMeshProps = {
/** Whether the object gets culled by the frustum
* @default true
*/
frustumCulled?: boolean

/** Override the rendering order
* @default 0
*/
renderOrder?: number

/** Whether the object gets rendered at all
* @default true
*/
visible?: boolean

/** Custom user data object to store whatever you want
* @default undefined
*/
userData?: any

/** Whether the object's matrix automatically updates
* @default true
*/
matrixAutoUpdate?: boolean
}

type SpriteAnimatorProps = {
export type SpriteAnimatorProps = {
/** The start frame of the animation */
abernier marked this conversation as resolved.
Show resolved Hide resolved
startFrame?: number

Expand All @@ -53,6 +24,9 @@ type SpriteAnimatorProps = {
/** The desired frames per second of the animation. If set to 0 or negative, animation will be static */
fps?: number

/** The animation names of the spritesheet (if the spritesheet -with JSON- contains more animation sequences) */
animationNames?: Array<string>

/** The frame identifier to use, must be one of animationNames */
frameName?: string

Expand All @@ -68,31 +42,20 @@ type SpriteAnimatorProps = {
/** The number of frames of the animation (required if using plain spritesheet without JSON) */
numberOfFrames?: number

/** Whether or not the animation should auto-start when all assets are loaded */
/** Animation auto-start when all assets are loaded */
autoPlay?: boolean

/** The animation names of the spritesheet (if the spritesheet -with JSON- contains more animation sequences) */
animationNames?: Array<string>

/** Event callback when the animation starts or restarts
* @param data {{ currentFrameName: string, currentFrame: number }} Animation state data
*/
onStart?: (data: { currentFrameName: string; currentFrame: number }) => void
/** Event callback when the animation starts or restarts */
onStart?: (data: AnimationEventData) => void

/** Event callback when the animation ends
* @param data {{ currentFrameName: string, currentFrame: number }} Animation state data
*/
onEnd?: (data: { currentFrameName: string; currentFrame: number }) => void
/** Event callback when the animation ends */
onEnd?: (data: AnimationEventData) => void

/** Event callback when the animation completes a loop cycle
* @param data {{ currentFrameName: string, currentFrame: number }} Animation state data
*/
onLoopEnd?: (data: { currentFrameName: string; currentFrame: number }) => void
/** Event callback when the animation completes a loop cycle */
onLoopEnd?: (data: AnimationEventData) => void

/** Event callback fired on each frame change
* @param data {{ currentFrameName: string, currentFrame: number }} Animation state data
*/
onFrame?: (data: { currentFrameName: string; currentFrame: number }) => void
/** Event callback fired on each frame change */
onFrame?: (data: AnimationEventData) => void

/** @deprecated Use pause={false} instead. Control when the animation runs */
play?: boolean
Expand All @@ -103,15 +66,13 @@ type SpriteAnimatorProps = {
/** Whether or not the Sprite should flip sides on the x-axis */
flipX?: boolean

/** Sets the alpha value to be used when running an alpha test.
* @see https://threejs.org/docs/#api/en/materials/Material.alphaTest
/** Sets the alpha value to be used when running an alpha test
* @default 0.0
*/
alphaTest?: number

/** Displays the texture on a Billboard component always facing the camera.
* If set to false, it renders on a PlaneGeometry
* @default true
* @default false
*/
asSprite?: boolean

Expand All @@ -127,22 +88,20 @@ type SpriteAnimatorProps = {
resetOnEnd?: boolean

/** Array of Vector3-like positions for creating multiple instances of the sprite */
instanceItems?: Array<[number, number, number] | THREE.Vector3>
instanceItems?: (THREE.Vector3 | [number, number, number])[]

/** The maximum number of instances to render (for buffer size calculation)
* @default 1
*/
maxItems?: number

/** Pre-parsed sprite data, usually from useSpriteLoader ready for use */
/** Pre-parsed sprite data, usually from useSpriteLoader */
spriteDataset?: {
spriteTexture: THREE.Texture
spriteData: any
spriteData: SpriteData
}

/** Configuration options for the canvas context when loading textures
* @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/CanvasRenderingContext2D
*/
/** Configuration options for the canvas context when loading textures */
canvasRenderingContext2DSettings?: CanvasRenderingContext2DSettings

/** Controls whether frame positions are rounded for precise pixel alignment.
Expand All @@ -151,42 +110,61 @@ type SpriteAnimatorProps = {
*/
roundFramePosition?: boolean

/** Additional properties to be passed to both sprite and instance components.
/** Additional properties to be passed to both mesh and instance components.
* Only includes safe properties that work across both types.
* @example { frustumCulled: false, renderOrder: 1 }
* @see https://threejs.org/docs/#api/en/core/Object3D
* @type CommonMeshProps
*/
meshProps?: CommonMeshProps

} & JSX.IntrinsicElements['group']
} & GroupProps
```

The SpriteAnimator component provided by drei is a powerful tool for animating sprites in a simple and efficient manner. It allows you to create sprite animations by cycling through a sequence of frames from a sprite sheet image or JSON data.
The SpriteAnimator component provided by drei is a powerful tool for animating sprites in a simple and efficient manner. It allows you to create sprite animations by cycling through a sequence of frames from a spritesheet image and JSON data.

Notes:

- The SpriteAnimator component internally uses the useFrame hook from react-three-fiber (r3f) for efficient frame updates and rendering.
- The sprites (without a JSON file) should contain equal size frames
- Trimming of spritesheet frames is not yet supported
- Internally uses the `useSpriteLoader` or can use data from it directly
- Internally uses the `useSpriteLoader` or can use data from it directly (which is the recommended way of loading assets)

```jsx
<SpriteAnimator
position={[-3.5, -2.0, 2.5]}
startFrame={0}
scaleFactor={0.125}
meshProps={{ frustumCulled: false, scale: 2.5 }}
autoPlay={true}
loop={true}
numberOfFrames={16}
textureImageURL={'./alien.png'}
/>
```

ScrollControls example
Load sprite textures via `useSpriteLoader`

```jsx
const { spriteObj: statics } = useSpriteLoader('/statics.png', '/statics.json', ['heart', 'skull', 'sword'], null)

<SpriteAnimator
position={[2, 2.8, 0.01]}
fps={0}
meshProps={{ frustumCulled: false, scale: 2.5 }}
autoPlay={true}
loop={true}
flipX={false}
startFrame={0}
frameName={'sword'}
spriteDataset={statics}
asSprite={false}
alphaTest={0.01}
/>

```

`ScrollControls` example

```jsx
<ScrollControls damping={0.2} maxSpeed={0.5} pages={2}>
;<ScrollControls damping={0.2} maxSpeed={0.5} pages={2}>
<SpriteAnimator
position={[0.0, -1.5, -1.5]}
startFrame={0}
Expand Down
Loading