diff --git a/.eslintrc.js b/.eslintrc.js index 885379ab..819f5953 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -50,7 +50,8 @@ module.exports = { } ], 'prefer-regex-literals': ['error', { disallowRedundantWrapping: false }], - 'no-plusplus': 'off' + 'no-plusplus': 'off', + "no-console": 'off' }, settings: { 'import/resolver': { diff --git a/src/App/App.component.tsx b/src/App/App.component.tsx index 326e077c..92c8d683 100644 --- a/src/App/App.component.tsx +++ b/src/App/App.component.tsx @@ -1,8 +1,7 @@ import React from 'react'; -import { Sparkles, StatsGl } from '@react-three/drei'; +import { StatsGl } from '@react-three/drei'; -import { Avatar } from 'src/components/Avatar'; -import { EnvironmentModel } from 'src/components/Models'; +import { Avatar, CAMERA } from 'src/components/Avatar'; import styles from './App.module.scss'; @@ -20,18 +19,17 @@ function App() {
- -
diff --git a/src/App/App.module.scss b/src/App/App.module.scss index 80326cab..e51b883f 100644 --- a/src/App/App.module.scss +++ b/src/App/App.module.scss @@ -5,6 +5,7 @@ body, margin: 0; height: 100%; width: 100%; + background-color: blueviolet; } .app { diff --git a/src/components/Avatar/Avatar.component.tsx b/src/components/Avatar/Avatar.component.tsx index dc7720dc..f1efc201 100644 --- a/src/components/Avatar/Avatar.component.tsx +++ b/src/components/Avatar/Avatar.component.tsx @@ -13,11 +13,11 @@ import { Provider, useSetAtom } from 'jotai'; import Capture, { CaptureType } from 'src/components/Capture/Capture.component'; import { Box, Background } from 'src/components/Background/Box/Box.component'; import { BackgroundColor } from 'src/components/Background'; -import Loader from 'src/components/Loader'; import Bloom from 'src/components/Bloom/Bloom.component'; import { BlendFunction } from 'postprocessing'; import Lights from 'src/components/Lights/Lights.component'; import { spawnState } from '../../state/spawnAtom'; +import { Loader } from '../Loader/Loader.component'; export const CAMERA = { TARGET: { @@ -47,7 +47,7 @@ export const CAMERA = { export type Emotion = Record; -export interface AvatarProps extends LightingProps, EnvironmentProps, Omit { +export interface AvatarProps extends LightingProps, EnvironmentProps, BaseModelProps { /** * Arbitrary binary data (base64 string, Blob) of a `.glb` file or path (URL) to a `.glb` resource. */ @@ -187,7 +187,7 @@ const Avatar: FC = ({ backLightPosition, lightTarget, fov = 50 -}) => { +}) => { const setSpawnState = useSetAtom(spawnState); useEffect(() => { @@ -268,7 +268,14 @@ const Avatar: FC = ({ controlsMaxDistance={halfBody ? CAMERA.CONTROLS.HALF_BODY.MAX_DISTANCE : CAMERA.CONTROLS.FULL_BODY.MAX_DISTANCE} updateCameraTargetOnZoom={!halfBody} /> - {AvatarModel} + + }> + {AvatarModel} + {children} {shadows && } {background?.src && } @@ -324,7 +331,8 @@ const Avatar: FC = ({ }; const AvatarWrapper = (props: AvatarProps) => ( - }> + // + } > diff --git a/src/components/Exhibit/Exhibit.component.tsx b/src/components/Exhibit/Exhibit.component.tsx index 2f9de62a..c563ec21 100644 --- a/src/components/Exhibit/Exhibit.component.tsx +++ b/src/components/Exhibit/Exhibit.component.tsx @@ -10,7 +10,7 @@ import { BaseCanvas } from 'src/components/BaseCanvas'; import Capture, { CaptureType } from 'src/components/Capture/Capture.component'; import { BackgroundColor } from 'src/components/Background'; -export interface ExhibitProps extends CameraProps, EnvironmentProps, Omit { +export interface ExhibitProps extends CameraProps, EnvironmentProps, BaseModelProps { /** * Arbitrary binary data (base64 string | Blob) of a `.glb` file or path (URL) to a `.glb` resource. */ diff --git a/src/components/Models/AnimationModel/AnimationModel.component.tsx b/src/components/Models/AnimationModel/AnimationModel.component.tsx index 5e0587a2..b7215a86 100644 --- a/src/components/Models/AnimationModel/AnimationModel.component.tsx +++ b/src/components/Models/AnimationModel/AnimationModel.component.tsx @@ -3,7 +3,7 @@ import { useFrame, useGraph } from '@react-three/fiber'; import { AnimationMixer, Group } from 'three'; import { Model } from 'src/components/Models/Model'; -import { useHeadMovement, useGltfLoader, useFallback, useIdleExpression, useEmotion } from 'src/services'; +import { useHeadMovement, useGltfLoader, useIdleExpression, useEmotion } from 'src/services'; import { BaseModelProps } from 'src/types'; import { loadAnimationClip } from 'src/services/Animation.service'; import { Emotion } from 'src/components/Avatar/Avatar.component'; @@ -26,7 +26,6 @@ export const AnimationModel: FC = ({ rotation = 20 * (Math.PI / 180), scale = 1, idleRotation = false, - setModelFallback, onLoaded, headMovement = false, emotion, @@ -74,7 +73,6 @@ export const AnimationModel: FC = ({ useHeadMovement({ nodes, enabled: headMovement }); useEmotion(nodes, emotion); useIdleExpression('blink', nodes); - useFallback(nodes, setModelFallback); return ( = (props) => { - /* eslint-disable-next-line react/jsx-no-useless-fragment */ - const [fallback, setFallback] = useState(<>); - - return ( - - - +export const AnimationModelContainer: FC = (props) => ( + ); -}; diff --git a/src/components/Models/BoundsModel/BoundsModel.container.tsx b/src/components/Models/BoundsModel/BoundsModel.container.tsx index 72eef3df..83ba416a 100644 --- a/src/components/Models/BoundsModel/BoundsModel.container.tsx +++ b/src/components/Models/BoundsModel/BoundsModel.container.tsx @@ -1,4 +1,4 @@ -import React, { FC, ReactNode, useEffect, useState, cloneElement, useMemo, ReactElement, useCallback } from 'react'; +import React, { FC, ReactNode, useEffect, cloneElement, useMemo, ReactElement, useCallback } from 'react'; import { useBounds } from '@react-three/drei'; import { BaseModelProps } from 'src/types'; import { triggerCallback } from 'src/services'; @@ -11,7 +11,6 @@ export interface BoundsModelContainerProps extends BaseModelProps { export const BoundsModelContainer: FC = ({ modelSrc, children, fit, onLoaded }) => { const bounds = useBounds(); - const [fallback, setFallback] = useState(<>); const onChildLoaded = useCallback(() => { if (fit) { @@ -24,7 +23,7 @@ export const BoundsModelContainer: FC = ({ modelSrc, const childModel = useMemo( () => React.Children.map(children, (child) => - cloneElement(child as ReactElement, { setModelFallback: setFallback, onLoaded: onChildLoaded }) + cloneElement(child as ReactElement, { onLoaded: onChildLoaded }) ), [modelSrc, children, onChildLoaded] ); @@ -33,7 +32,7 @@ export const BoundsModelContainer: FC = ({ modelSrc, if (fit) { bounds.refresh().clip().fit(); } - }, [modelSrc, fit, fallback]); + }, [modelSrc, fit]); return <>{childModel}; }; diff --git a/src/components/Models/EnvironmentModel/EnvironmentModel.component.tsx b/src/components/Models/EnvironmentModel/EnvironmentModel.component.tsx index afefe049..ebe33550 100644 --- a/src/components/Models/EnvironmentModel/EnvironmentModel.component.tsx +++ b/src/components/Models/EnvironmentModel/EnvironmentModel.component.tsx @@ -1,5 +1,5 @@ import React, { FC, useEffect } from 'react'; -import { useFallback, useGltfLoader, CustomNode, Transform, triggerCallback } from 'src/services'; +import { useGltfLoader, CustomNode, Transform, triggerCallback } from 'src/services'; import { useGraph } from '@react-three/fiber'; import { BaseModelProps } from 'src/types'; import { EnvironmentModels } from 'src/services/Environment.service'; @@ -9,13 +9,14 @@ export interface EnvironmentModelProps extends BaseModelProps { scale?: number; } -export const EnvironmentModel: FC = ({ environment, scale = 1, setModelFallback, onLoaded }) => { +export const EnvironmentModel: FC = ({ environment, scale = 1, onLoaded }) => { const transform = new Transform(); const { scene } = useGltfLoader(environment); const { nodes } = useGraph(scene); - useFallback(nodes, setModelFallback); - useEffect(() => triggerCallback(onLoaded), [scene, onLoaded]); + useEffect(() => { + triggerCallback(onLoaded); + }, [scene, onLoaded]); return ( diff --git a/src/components/Models/EnvironmentModel/EnvironmentModel.container.tsx b/src/components/Models/EnvironmentModel/EnvironmentModel.container.tsx index 5c69c1be..a107e0ba 100644 --- a/src/components/Models/EnvironmentModel/EnvironmentModel.container.tsx +++ b/src/components/Models/EnvironmentModel/EnvironmentModel.container.tsx @@ -1,4 +1,4 @@ -import React, { FC, Suspense, useState } from 'react'; +import React, { FC, Suspense } from 'react'; import { EnvironmentModels, environmentModels } from 'src/services/Environment.service'; import { EnvironmentModel, EnvironmentModelProps } from './EnvironmentModel.component'; @@ -7,14 +7,13 @@ import { EnvironmentModel, EnvironmentModelProps } from './EnvironmentModel.comp */ export const EnvironmentModelContainer: FC = (props) => { /* eslint-disable-next-line react/jsx-no-useless-fragment */ - const [fallback, setFallback] = useState(<>); const { environment } = props; const isStaticPreset = environment in environmentModels; const environmentSrc = isStaticPreset ? environmentModels[environment as EnvironmentModels] : environment; return ( - - + + ); }; diff --git a/src/components/Models/FloatingModel/FloatingModel.container.tsx b/src/components/Models/FloatingModel/FloatingModel.container.tsx index b0c84985..a1256509 100644 --- a/src/components/Models/FloatingModel/FloatingModel.container.tsx +++ b/src/components/Models/FloatingModel/FloatingModel.container.tsx @@ -1,16 +1,11 @@ -import React, { FC, Suspense, useState } from 'react'; +import React, { FC, Suspense } from 'react'; import { FloatingModel, FloatingModelProps } from './FloatingModel.component'; /** * Contains model to handle suspense fallback. */ -export const FloatingModelContainer: FC = (props) => { - /* eslint-disable-next-line react/jsx-no-useless-fragment */ - const [fallback, setFallback] = useState(<>); - - return ( - - +export const FloatingModelContainer: FC = (props) => ( + + ); -}; diff --git a/src/components/Models/HalfBodyModel/HalfBodyModel.component.tsx b/src/components/Models/HalfBodyModel/HalfBodyModel.component.tsx index 31424084..f3cdf52e 100644 --- a/src/components/Models/HalfBodyModel/HalfBodyModel.component.tsx +++ b/src/components/Models/HalfBodyModel/HalfBodyModel.component.tsx @@ -2,7 +2,7 @@ import React, { FC, useRef } from 'react'; import { useFrame, useGraph } from '@react-three/fiber'; import { Model } from 'src/components/Models/Model'; import { BaseModelProps } from 'src/types'; -import { useEmotion, useHeadMovement, useGltfLoader, useFallback, useIdleExpression } from 'src/services'; +import { useEmotion, useHeadMovement, useGltfLoader, useIdleExpression } from 'src/services'; import { Group } from 'three'; import { Emotion } from '../../Avatar/Avatar.component'; @@ -23,7 +23,6 @@ export const HalfBodyModel: FC = ({ rotation = 20 * (Math.PI / 180), idleRotation = false, emotion, - setModelFallback, onLoaded, headMovement = false, bloom @@ -61,7 +60,6 @@ export const HalfBodyModel: FC = ({ useHeadMovement({ nodes, isHalfBody: true, enabled: headMovement }); useIdleExpression('blink', nodes); useEmotion(nodes, emotion); - useFallback(nodes, setModelFallback); return ; }; diff --git a/src/components/Models/HalfBodyModel/HalfBodyModel.container.tsx b/src/components/Models/HalfBodyModel/HalfBodyModel.container.tsx index 40769b80..a6f6e3a8 100644 --- a/src/components/Models/HalfBodyModel/HalfBodyModel.container.tsx +++ b/src/components/Models/HalfBodyModel/HalfBodyModel.container.tsx @@ -1,16 +1,11 @@ -import React, { FC, Suspense, useState } from 'react'; +import React, { FC, Suspense } from 'react'; import { HalfBodyModel, HalfBodyModelProps } from './HalfBodyModel.component'; /** * Contains model to handle suspense fallback. */ -export const HalfBodyModelContainer: FC = (props) => { - /* eslint-disable-next-line react/jsx-no-useless-fragment */ - const [fallback, setFallback] = useState(<>); - - return ( - - +export const HalfBodyModelContainer: FC = (props) => ( + + ); -}; diff --git a/src/components/Models/Model/Model.component.tsx b/src/components/Models/Model/Model.component.tsx index 8045320b..f5380520 100644 --- a/src/components/Models/Model/Model.component.tsx +++ b/src/components/Models/Model/Model.component.tsx @@ -15,7 +15,7 @@ interface ModelProps extends BaseModelProps { const ROTATION_STEP = 0.005; -export const Model: FC = ({ scene, scale = 1, modelRef, onLoaded, onSpawnAnimationFinish, bloom }) => { +export const Model: FC = ({ scene, scale = 1, modelRef, onLoaded, onSpawnAnimationFinish, bloom }) => { const { materials } = useGraph(scene); const { gl } = useThree(); const [isTouching, setIsTouching] = useState(false); @@ -66,7 +66,9 @@ export const Model: FC = ({ scene, scale = 1, modelRef, onLoaded, on } }); - useEffect(() => triggerCallback(onLoaded), [scene, materials, onLoaded]); + useEffect(() => { + console.log("avatar model loaded"); + triggerCallback(onLoaded); }, [scene, materials, onLoaded]); useEffect(() => { gl.domElement.addEventListener('mousedown', setTouchingOn); @@ -98,7 +100,7 @@ export const Model: FC = ({ scene, scale = 1, modelRef, onLoaded, on return ( - {spawnComponent} + {spawnComponent} ); }; diff --git a/src/components/Models/PoseModel/PoseModel.component.tsx b/src/components/Models/PoseModel/PoseModel.component.tsx index 2dd8fafd..51f0afca 100644 --- a/src/components/Models/PoseModel/PoseModel.component.tsx +++ b/src/components/Models/PoseModel/PoseModel.component.tsx @@ -2,7 +2,7 @@ import React, { FC, Ref } from 'react'; import { useGraph } from '@react-three/fiber'; import { Model } from 'src/components/Models/Model'; import { Group } from 'three'; -import { mutatePose, useEmotion, useFallback, useGltfLoader } from 'src/services'; +import { mutatePose, useEmotion, useGltfLoader } from 'src/services'; import { BaseModelProps } from 'src/types'; import { Emotion } from '../../Avatar/Avatar.component'; @@ -20,7 +20,6 @@ export const PoseModel: FC = ({ modelRef, scale = 1, emotion, - setModelFallback, onLoaded, bloom }) => { @@ -31,7 +30,6 @@ export const PoseModel: FC = ({ mutatePose(nodes, sourceNodes); useEmotion(nodes, emotion); - useFallback(nodes, setModelFallback); return ; }; diff --git a/src/components/Models/PoseModel/PoseModel.container.tsx b/src/components/Models/PoseModel/PoseModel.container.tsx index 5b8c16d6..d77a4f1a 100644 --- a/src/components/Models/PoseModel/PoseModel.container.tsx +++ b/src/components/Models/PoseModel/PoseModel.container.tsx @@ -1,16 +1,11 @@ -import React, { FC, Suspense, useState } from 'react'; +import React, { FC, Suspense } from 'react'; import { PoseModel, PoseModelProps } from './PoseModel.component'; /** * Contains model to handle suspense fallback. */ -export const PoseModelContainer: FC = (props) => { - /* eslint-disable-next-line react/jsx-no-useless-fragment */ - const [fallback, setFallback] = useState(<>); - - return ( - - +export const PoseModelContainer: FC = (props) => ( + + ); -}; diff --git a/src/components/Models/StaticModel/StaticModel.component.tsx b/src/components/Models/StaticModel/StaticModel.component.tsx index 47074a2c..adf62460 100644 --- a/src/components/Models/StaticModel/StaticModel.component.tsx +++ b/src/components/Models/StaticModel/StaticModel.component.tsx @@ -1,6 +1,6 @@ import React, { FC, Ref } from 'react'; import { Model } from 'src/components/Models/Model'; -import { useEmotion, useFallback, useGltfLoader } from 'src/services'; +import { useEmotion, useGltfLoader } from 'src/services'; import { Group } from 'three'; import { useGraph } from '@react-three/fiber'; import { BaseModelProps } from 'src/types'; @@ -17,7 +17,6 @@ export const StaticModel: FC = ({ modelSrc, modelRef, scale = 1, - setModelFallback, onLoaded, emotion, bloom @@ -26,7 +25,6 @@ export const StaticModel: FC = ({ const { nodes } = useGraph(scene); useEmotion(nodes, emotion); - useFallback(nodes, setModelFallback); return ; }; diff --git a/src/components/Models/StaticModel/StaticModel.container.tsx b/src/components/Models/StaticModel/StaticModel.container.tsx index 23cadcbc..32f54a43 100644 --- a/src/components/Models/StaticModel/StaticModel.container.tsx +++ b/src/components/Models/StaticModel/StaticModel.container.tsx @@ -1,16 +1,9 @@ -import React, { FC, Suspense, useState } from 'react'; +import React, { FC } from 'react'; import { StaticModel, StaticModelProps } from './StaticModel.component'; /** * Contains model to handle suspense fallback. */ -export const StaticModelContainer: FC = (props) => { - /* eslint-disable-next-line react/jsx-no-useless-fragment */ - const [fallback, setFallback] = useState(<>); - - return ( - - - +export const StaticModelContainer: FC = (props) => ( + ); -}; diff --git a/src/services/Models.service.tsx b/src/services/Models.service.tsx index 1fd12344..721ea9a3 100644 --- a/src/services/Models.service.tsx +++ b/src/services/Models.service.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useCallback, useRef } from 'react'; +import { useEffect, useCallback, useRef } from 'react'; import { LinearFilter, MeshStandardMaterial, @@ -258,61 +258,6 @@ export class Transform { position: Vector3; } -/** - * Builds a fallback model for given nodes. - * Useful for displaying as the suspense fallback object. - */ -function buildFallback(nodes: Nodes, transform: Transform = new Transform()): JSX.Element { - return ( - - {Object.keys(nodes).map((key) => { - const node = nodes[key] as CustomNode; - if (node.type === 'SkinnedMesh') { - return ( - - ); - } - - if (node.type === 'Mesh') { - return ( - - ); - } - - return null; - })} - - ); -} - -export const useFallback = (nodes: Nodes, setter?: (fallback: JSX.Element) => void) => - useEffect(() => { - if (typeof setter === 'function') { - setter(buildFallback(nodes)); - } - }, [setter, nodes]); - export const triggerCallback = (callback?: () => void) => { if (typeof callback === 'function') { callback(); diff --git a/src/types/index.ts b/src/types/index.ts index af9a053a..2fb175d3 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -50,7 +50,6 @@ export interface BaseModelProps { * Detect when model is being loaded and trigger custom logic. */ onLoading?: () => void; - setModelFallback?: (fallback: JSX.Element) => void; bloom?: BloomConfiguration; }