Added support for multiple sheets in r3f
This commit is contained in:
parent
1452c9ebbe
commit
2605401e06
4 changed files with 35 additions and 21 deletions
|
@ -1,12 +1,26 @@
|
||||||
import React, {useLayoutEffect} from 'react'
|
import React, {
|
||||||
|
createContext,
|
||||||
|
useContext,
|
||||||
|
useLayoutEffect,
|
||||||
|
useState,
|
||||||
|
} from 'react'
|
||||||
import {useThree} from '@react-three/fiber'
|
import {useThree} from '@react-three/fiber'
|
||||||
import type {ISheet} from '@theatre/core'
|
import type {ISheet} from '@theatre/core'
|
||||||
import {bindToCanvas} from './store'
|
import {bindToCanvas} from './store'
|
||||||
|
|
||||||
|
const ctx = createContext<{sheet: ISheet | undefined} | undefined>(undefined)
|
||||||
|
|
||||||
|
export const useWrapperContext = ():
|
||||||
|
| {sheet: ISheet | undefined}
|
||||||
|
| undefined => {
|
||||||
|
return useContext(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
const Wrapper: React.FC<{
|
const Wrapper: React.FC<{
|
||||||
getSheet: () => ISheet
|
getSheet: () => ISheet
|
||||||
}> = (props) => {
|
}> = (props) => {
|
||||||
const {scene, gl} = useThree((s) => ({scene: s.scene, gl: s.gl}))
|
const {scene, gl} = useThree((s) => ({scene: s.scene, gl: s.gl}))
|
||||||
|
const [sheet, setSheet] = useState<ISheet | undefined>(undefined)
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
const sheet = props.getSheet()
|
const sheet = props.getSheet()
|
||||||
|
@ -15,10 +29,11 @@ const Wrapper: React.FC<{
|
||||||
`getSheet() in <Wrapper getSheet={getSheet}> has returned an invalid value`,
|
`getSheet() in <Wrapper getSheet={getSheet}> has returned an invalid value`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
bindToCanvas({sheet, gl, scene})
|
setSheet(sheet)
|
||||||
|
bindToCanvas({gl, scene})
|
||||||
}, [scene, gl])
|
}, [scene, gl])
|
||||||
|
|
||||||
return <>{props.children}</>
|
return <ctx.Provider value={{sheet}}>{props.children}</ctx.Provider>
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Wrapper
|
export default Wrapper
|
||||||
|
|
|
@ -18,6 +18,7 @@ import mergeRefs from 'react-merge-refs'
|
||||||
import type {$FixMe} from '@theatre/shared/utils/types'
|
import type {$FixMe} from '@theatre/shared/utils/types'
|
||||||
import type {ISheetObject} from '@theatre/core'
|
import type {ISheetObject} from '@theatre/core'
|
||||||
import useInvalidate from './useInvalidate'
|
import useInvalidate from './useInvalidate'
|
||||||
|
import {useWrapperContext} from '../Wrapper'
|
||||||
|
|
||||||
interface Elements {
|
interface Elements {
|
||||||
group: Group
|
group: Group
|
||||||
|
@ -50,7 +51,14 @@ const editable = <
|
||||||
({uniqueName, visible, editableType, ...props}: Props, ref) => {
|
({uniqueName, visible, editableType, ...props}: Props, ref) => {
|
||||||
const objectRef = useRef<Elements[U]>()
|
const objectRef = useRef<Elements[U]>()
|
||||||
|
|
||||||
const sheet = useEditorStore((state) => state.sheet)
|
const wrapperContext = useWrapperContext()
|
||||||
|
if (!wrapperContext) {
|
||||||
|
throw new Error(
|
||||||
|
`Editable components must be a descendent of a <Wrapper>`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const {sheet} = wrapperContext
|
||||||
|
|
||||||
const [sheetObject, setSheetObject] = useState<
|
const [sheetObject, setSheetObject] = useState<
|
||||||
undefined | ISheetObject<$FixMe>
|
undefined | ISheetObject<$FixMe>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import {useLayoutEffect, useRef, useState} from 'react'
|
import {useLayoutEffect, useRef, useState} from 'react'
|
||||||
import {useEditorStore} from '../store'
|
import {allRegisteredObjects} from '../store'
|
||||||
import shallow from 'zustand/shallow'
|
|
||||||
import studio from '@theatre/studio'
|
import studio from '@theatre/studio'
|
||||||
import type {ISheetObject} from '@theatre/core'
|
import type {ISheetObject} from '@theatre/core'
|
||||||
|
|
||||||
|
@ -9,13 +8,12 @@ export function useSelected(): undefined | string {
|
||||||
const stateRef = useRef(state)
|
const stateRef = useRef(state)
|
||||||
stateRef.current = state
|
stateRef.current = state
|
||||||
|
|
||||||
const sheet = useEditorStore((state) => state.sheet, shallow)
|
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
const setFromStudio = (selection: typeof studio.selection) => {
|
const setFromStudio = (selection: typeof studio.selection) => {
|
||||||
const item = selection.find(
|
const item = selection.find(
|
||||||
(s): s is ISheetObject =>
|
(s): s is ISheetObject =>
|
||||||
s.type === 'Theatre_SheetObject_PublicAPI' && s.sheet === sheet,
|
s.type === 'Theatre_SheetObject_PublicAPI' &&
|
||||||
|
allRegisteredObjects.has(s),
|
||||||
)
|
)
|
||||||
if (!item) {
|
if (!item) {
|
||||||
set(undefined)
|
set(undefined)
|
||||||
|
@ -25,17 +23,15 @@ export function useSelected(): undefined | string {
|
||||||
}
|
}
|
||||||
setFromStudio(studio.selection)
|
setFromStudio(studio.selection)
|
||||||
return studio.onSelectionChange(setFromStudio)
|
return studio.onSelectionChange(setFromStudio)
|
||||||
}, [sheet])
|
}, [])
|
||||||
|
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSelected(): undefined | string {
|
export function getSelected(): undefined | string {
|
||||||
const sheet = useEditorStore.getState().sheet
|
|
||||||
if (!sheet) return undefined
|
|
||||||
const item = studio.selection.find(
|
const item = studio.selection.find(
|
||||||
(s): s is ISheetObject =>
|
(s): s is ISheetObject =>
|
||||||
s.type === 'Theatre_SheetObject_PublicAPI' && s.sheet === sheet,
|
s.type === 'Theatre_SheetObject_PublicAPI' && allRegisteredObjects.has(s),
|
||||||
)
|
)
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return undefined
|
return undefined
|
||||||
|
|
|
@ -2,7 +2,7 @@ import type {StateCreator} from 'zustand'
|
||||||
import create from 'zustand'
|
import create from 'zustand'
|
||||||
import type {Object3D, Scene, WebGLRenderer} from 'three'
|
import type {Object3D, Scene, WebGLRenderer} from 'three'
|
||||||
import {Group} from 'three'
|
import {Group} from 'three'
|
||||||
import type {ISheet, ISheetObject} from '@theatre/core'
|
import type {ISheetObject} from '@theatre/core'
|
||||||
import {types} from '@theatre/core'
|
import {types} from '@theatre/core'
|
||||||
|
|
||||||
export type EditableType =
|
export type EditableType =
|
||||||
|
@ -134,7 +134,6 @@ export interface EditableState {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type EditorStore = {
|
export type EditorStore = {
|
||||||
sheet: ISheet | null
|
|
||||||
sheetObjects: {[uniqueName in string]?: BaseSheetObjectType}
|
sheetObjects: {[uniqueName in string]?: BaseSheetObjectType}
|
||||||
scene: Scene | null
|
scene: Scene | null
|
||||||
gl: WebGLRenderer | null
|
gl: WebGLRenderer | null
|
||||||
|
@ -150,7 +149,6 @@ export type EditorStore = {
|
||||||
scene: Scene,
|
scene: Scene,
|
||||||
gl: WebGLRenderer,
|
gl: WebGLRenderer,
|
||||||
allowImplicitInstancing: boolean,
|
allowImplicitInstancing: boolean,
|
||||||
sheet: ISheet,
|
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
addEditable: <T extends EditableType>(type: T, uniqueName: string) => void
|
addEditable: <T extends EditableType>(type: T, uniqueName: string) => void
|
||||||
|
@ -178,12 +176,11 @@ const config: StateCreator<EditorStore> = (set, get) => {
|
||||||
editablesSnapshot: null,
|
editablesSnapshot: null,
|
||||||
initialEditorCamera: {},
|
initialEditorCamera: {},
|
||||||
|
|
||||||
init: (scene, gl, allowImplicitInstancing, sheet) => {
|
init: (scene, gl, allowImplicitInstancing) => {
|
||||||
set({
|
set({
|
||||||
scene,
|
scene,
|
||||||
gl,
|
gl,
|
||||||
allowImplicitInstancing,
|
allowImplicitInstancing,
|
||||||
sheet,
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -266,17 +263,15 @@ export const useEditorStore = create<EditorStore>(config)
|
||||||
|
|
||||||
export type BindFunction = (options: {
|
export type BindFunction = (options: {
|
||||||
allowImplicitInstancing?: boolean
|
allowImplicitInstancing?: boolean
|
||||||
sheet: ISheet
|
|
||||||
gl: WebGLRenderer
|
gl: WebGLRenderer
|
||||||
scene: Scene
|
scene: Scene
|
||||||
}) => void
|
}) => void
|
||||||
|
|
||||||
export const bindToCanvas: BindFunction = ({
|
export const bindToCanvas: BindFunction = ({
|
||||||
allowImplicitInstancing = false,
|
allowImplicitInstancing = false,
|
||||||
sheet,
|
|
||||||
gl,
|
gl,
|
||||||
scene,
|
scene,
|
||||||
}) => {
|
}) => {
|
||||||
const init = useEditorStore.getState().init
|
const init = useEditorStore.getState().init
|
||||||
init(scene, gl, allowImplicitInstancing, sheet)
|
init(scene, gl, allowImplicitInstancing)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue