@@ -6,7 +6,7 @@ import { AiFillSound } from 'react-icons/ai'
66import { IoVideocamOutline } from 'react-icons/io5'
77import { FaFile } from 'react-icons/fa'
88
9- import { toWearableWithBlobs } from './utils'
9+ import { toEmoteWithBlobs , toWearableWithBlobs } from './utils'
1010import { Props } from './types'
1111
1212import './AssetPreview.css'
@@ -15,13 +15,21 @@ import { useRef } from 'react'
1515const WIDTH = 300
1616const HEIGHT = 300
1717
18- export function AssetPreview ( { value, resources, onScreenshot, onLoad } : Props ) {
18+ export function AssetPreview ( { value, resources, onScreenshot, onLoad, isEmote } : Props ) {
1919 const preview = useMemo ( ( ) => {
2020 const ext = value . name . split ( '.' ) . pop ( )
2121 switch ( ext ) {
2222 case 'gltf' :
2323 case 'glb' :
24- return < GltfPreview value = { value } resources = { resources } onScreenshot = { onScreenshot } onLoad = { onLoad } />
24+ return (
25+ < GltfPreview
26+ value = { value }
27+ resources = { resources }
28+ onScreenshot = { onScreenshot }
29+ onLoad = { onLoad }
30+ isEmote = { isEmote }
31+ />
32+ )
2533 case 'png' :
2634 case 'jpg' :
2735 case 'jpeg' :
@@ -40,27 +48,52 @@ export function AssetPreview({ value, resources, onScreenshot, onLoad }: Props)
4048 return < div className = "AssetPreview" > { preview } </ div >
4149}
4250
43- function GltfPreview ( { value, resources, onScreenshot, onLoad } : Props ) {
51+ function GltfPreview ( { value, resources, onScreenshot, onLoad, isEmote } : Props ) {
4452 const [ loading , setLoading ] = useState ( true )
45- const handleLoad = useCallback ( ( ) => {
46- onLoad ?.( )
47- const wp = WearablePreview . createController ( value . name )
48- void wp . scene . getScreenshot ( WIDTH , HEIGHT ) . then ( ( $ ) => {
53+
54+ const handleScreenshot = useCallback (
55+ ( screenshot : string ) => {
4956 setTimeout ( ( ) => {
50- onScreenshot ( $ )
57+ onScreenshot ( screenshot )
5158 setLoading ( false )
52- } , 1000 ) // ugly hack to avoid iframe flickering...
53- } )
54- } , [ onLoad ] )
59+ } , 1000 )
60+ } ,
61+ [ onScreenshot ]
62+ )
63+
64+ const handleLoad = useCallback ( async ( ) => {
65+ onLoad ?.( )
66+ const wp = WearablePreview . createController ( value . name )
67+ if ( isEmote ) {
68+ const length = await wp . emote . getLength ( )
69+ //takes a screenshot at the middle of the emote
70+ void wp . emote . goTo ( length * 0.5 ) . then ( ( ) => {
71+ void wp . scene . getScreenshot ( WIDTH , HEIGHT ) . then ( handleScreenshot )
72+ } )
73+ } else {
74+ void wp . scene . getScreenshot ( WIDTH , HEIGHT ) . then ( handleScreenshot )
75+ }
76+ } , [ onLoad , value , isEmote , handleScreenshot ] )
77+
78+ const wearablePreviewExtraOptions = isEmote
79+ ? {
80+ profile : 'default' ,
81+ disableFace : true ,
82+ disableDefaultWearables : true ,
83+ skin : '000000' ,
84+ wheelZoom : 2
85+ }
86+ : { }
5587
5688 return (
5789 < >
5890 < div className = { cx ( 'GltfPreview' , { hidden : loading } ) } >
5991 < WearablePreview
6092 id = { value . name }
61- blob = { toWearableWithBlobs ( value , resources ) }
93+ blob = { isEmote ? toEmoteWithBlobs ( value , resources ) : toWearableWithBlobs ( value , resources ) }
6294 disableAutoRotate
6395 disableBackground
96+ { ...wearablePreviewExtraOptions }
6497 projection = { PreviewProjection . ORTHOGRAPHIC }
6598 camera = { PreviewCamera . STATIC }
6699 onLoad = { handleLoad }
0 commit comments