Support fog editing in r3f second try (#163)
* Add support for editable fog * Oops
This commit is contained in:
parent
ef96fa1974
commit
10b4954ee2
5 changed files with 61 additions and 8 deletions
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue