Support fog editing in r3f second try (#163)

* Add support for editable fog

* Oops
This commit is contained in:
Andrew Prifer 2022-05-15 22:04:00 +02:00 committed by GitHub
parent ef96fa1974
commit 10b4954ee2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 61 additions and 8 deletions

View file

@ -1,10 +1,11 @@
import {editable as e, RefreshSnapshot, SheetProvider} from '@theatre/r3f' import {editable as e, RefreshSnapshot, SheetProvider} from '@theatre/r3f'
import {Stars} from '@react-three/drei' import {Stars} from '@react-three/drei'
import {getProject} from '@theatre/core' import {getProject} from '@theatre/core'
import React, {Suspense, useState} from 'react' import React, {Suspense, useMemo, useState} from 'react'
import {Canvas} from '@react-three/fiber' import {Canvas} from '@react-three/fiber'
import {useGLTF, PerspectiveCamera} from '@react-three/drei' import {useGLTF, PerspectiveCamera} from '@react-three/drei'
import sceneGLB from './scene.glb' import sceneGLB from './scene.glb'
import {Color} from 'three'
document.body.style.backgroundColor = '#171717' document.body.style.backgroundColor = '#171717'
@ -55,7 +56,13 @@ function App() {
> >
<Canvas dpr={[1.5, 2]} linear shadows frameloop="demand"> <Canvas dpr={[1.5, 2]} linear shadows frameloop="demand">
<SheetProvider getSheet={() => getProject('Space').sheet('Scene')}> <SheetProvider getSheet={() => getProject('Space').sheet('Scene')}>
<fog attach="fog" args={[bg, 16, 30]} /> <e.fog
attach="fog"
color={useMemo(() => new Color(bg), [bg])}
near={16}
far={30}
uniqueName="Fog"
/>
<color attach="background" args={[bg]} /> <color attach="background" args={[bg]} />
<ambientLight intensity={0.75} /> <ambientLight intensity={0.75} />
<EditableCamera <EditableCamera

View file

@ -59,11 +59,15 @@ const EditableProxy: VFC<EditableProxyProps> = ({
// Helpers // Helpers
const scene = useThree((state) => state.scene) const scene = useThree((state) => state.scene)
const helper = useMemo<Helper>( const helper = useMemo<Helper | undefined>(
() => editable.objectConfig.createHelper(object), () => editable.objectConfig.createHelper?.(object),
[object], [object],
) )
useEffect(() => { useEffect(() => {
if (helper == undefined) {
return
}
if (selected === uniqueName || hovered) { if (selected === uniqueName || hovered) {
scene.add(helper) scene.add(helper)
invalidate() invalidate()
@ -75,6 +79,10 @@ const EditableProxy: VFC<EditableProxyProps> = ({
} }
}, [selected, hovered, helper, scene]) }, [selected, hovered, helper, scene])
useFrame(() => { useFrame(() => {
if (helper == undefined) {
return
}
if (helper.update) { if (helper.update) {
helper.update() helper.update()
} }

View file

@ -1,5 +1,6 @@
import type {EditableFactoryConfig} from './editableFactoryConfigUtils' import type {EditableFactoryConfig} from './editableFactoryConfigUtils'
import { import {
createColorPropConfig,
createNumberPropConfig, createNumberPropConfig,
createVector, createVector,
createVectorPropConfig, createVectorPropConfig,
@ -100,6 +101,15 @@ const defaultEditableFactoryConfig = {
line: baseObjectConfig, line: baseObjectConfig,
lineLoop: baseObjectConfig, lineLoop: baseObjectConfig,
lineSegments: baseObjectConfig, lineSegments: baseObjectConfig,
fog: {
props: {
color: createColorPropConfig('color'),
near: createNumberPropConfig('near', 1, {nudgeMultiplier: 0.1}),
far: createNumberPropConfig('far', 1000, {nudgeMultiplier: 0.1}),
},
useTransformControls: false,
icon: 'cloud' as const,
},
} }
// Assert that the config is indeed of EditableFactoryConfig without actually // Assert that the config is indeed of EditableFactoryConfig without actually

View file

@ -2,6 +2,7 @@ import type {UnknownShorthandCompoundProps} from '@theatre/core'
import {types} from '@theatre/core' import {types} from '@theatre/core'
import type {Object3D} from 'three' import type {Object3D} from 'three'
import type {IconID} from './icons' import type {IconID} from './icons'
import {Color} from 'three'
export type Helper = Object3D & { export type Helper = Object3D & {
update?: () => void update?: () => void
@ -17,7 +18,7 @@ type Meta<T> = {
updateObject?: (object: T) => void updateObject?: (object: T) => void
icon: IconID icon: IconID
dimensionless?: boolean dimensionless?: boolean
createHelper: (object: T) => Helper createHelper?: (object: T) => Helper
} }
export type ObjectConfig<T> = {props: Props} & Meta<T> export type ObjectConfig<T> = {props: Props} & Meta<T>
export type EditableFactoryConfig = Partial< export type EditableFactoryConfig = Partial<
@ -79,7 +80,7 @@ export const createNumberPropConfig = (
{nudgeMultiplier = 0.01} = {}, {nudgeMultiplier = 0.01} = {},
): PropConfig<number> => ({ ): PropConfig<number> => ({
parse: (props) => { parse: (props) => {
return props[key] ?? defaultValue ?? 0 return props[key] ?? defaultValue
}, },
apply: (value, object) => { apply: (value, object) => {
object[key] = value object[key] = value
@ -89,6 +90,28 @@ export const createNumberPropConfig = (
}, },
}) })
export type Rgba = {
r: number
g: number
b: number
a: number
}
export const createColorPropConfig = (
key: string,
defaultValue = new Color(0, 0, 0),
): PropConfig<Rgba> => ({
parse: (props) => {
return {...(props[key] ?? defaultValue), a: 1}
},
apply: (value, object) => {
object[key].setRGB(value.r, value.g, value.b)
},
type: {
[key]: types.rgba({...defaultValue, a: 1}),
},
})
export const extendObjectProps = <T extends {props: {}}>( export const extendObjectProps = <T extends {props: {}}>(
objectConfig: T, objectConfig: T,
extension: Props, extension: Props,

View file

@ -1,4 +1,8 @@
import {BsCameraVideoFill, BsFillCollectionFill} from 'react-icons/bs' import {
BsCameraVideoFill,
BsFillCollectionFill,
BsCloudFill,
} from 'react-icons/bs'
import {GiCube, GiLightBulb, GiLightProjector} from 'react-icons/gi' import {GiCube, GiLightBulb, GiLightProjector} from 'react-icons/gi'
import {BiSun} from 'react-icons/bi' import {BiSun} from 'react-icons/bi'
import React from 'react' import React from 'react'
@ -10,6 +14,7 @@ const icons = {
spotLight: <GiLightProjector />, spotLight: <GiLightProjector />,
sun: <BiSun />, sun: <BiSun />,
camera: <BsCameraVideoFill />, camera: <BsCameraVideoFill />,
cloud: <BsCloudFill />,
} }
export type IconID = keyof typeof icons export type IconID = keyof typeof icons