diff --git a/packages/playground/src/dom/Scene.tsx b/packages/playground/src/dom/Scene.tsx index 108ef4f..e75392b 100644 --- a/packages/playground/src/dom/Scene.tsx +++ b/packages/playground/src/dom/Scene.tsx @@ -2,7 +2,7 @@ import studio from '@theatre/studio' import type {UseDragOpts} from '@theatre/studio/uiComponents/useDrag' import useDrag from '@theatre/studio/uiComponents/useDrag' import React, {useLayoutEffect, useMemo, useState} from 'react' -import type {IProject, ISheet, ISheetObject} from '@theatre/core' +import type {IProject, ISheet} from '@theatre/core' import {types as t} from '@theatre/core' import type {IScrub, IStudio} from '@theatre/studio' @@ -16,7 +16,7 @@ const boxObjectConfig = t.compound({ const Box: React.FC<{ id: string sheet: ISheet - selection: ISheetObject[] + selection: IStudio['selection'] }> = ({id, sheet, selection}) => { // This is cheap to call and always returns the same value, so no need for useMemo() const obj = sheet.object(id, boxObjectConfig) diff --git a/packages/playground/src/redesign/Scene.tsx b/packages/playground/src/redesign/Scene.tsx index ac17256..18e8726 100644 --- a/packages/playground/src/redesign/Scene.tsx +++ b/packages/playground/src/redesign/Scene.tsx @@ -2,7 +2,7 @@ import type {UseDragOpts} from '@theatre/studio/uiComponents/useDrag' import useDrag from '@theatre/studio/uiComponents/useDrag' import React, {useLayoutEffect, useMemo, useState} from 'react' import studio from '@theatre/studio' -import type {IProject, ISheet, ISheetObject} from '@theatre/core' +import type {IProject, ISheet} from '@theatre/core' import {types as t} from '@theatre/core' import type {IScrub, IStudio} from '@theatre/studio' @@ -29,7 +29,7 @@ const boxObjectConfig = t.compound({ const Box: React.FC<{ id: string sheet: ISheet - selection: ISheetObject[] + selection: IStudio['selection'] }> = ({id, sheet, selection: selection}) => { // This is cheap to call and always returns the same value, so no need for useMemo() const obj = sheet.object('object ' + id, boxObjectConfig) diff --git a/packages/plugin-r3f/src/components/useSelected.tsx b/packages/plugin-r3f/src/components/useSelected.tsx index 81b30e3..d30a3ed 100644 --- a/packages/plugin-r3f/src/components/useSelected.tsx +++ b/packages/plugin-r3f/src/components/useSelected.tsx @@ -2,6 +2,7 @@ import {useLayoutEffect, useRef, useState} from 'react' import {useEditorStore} from '../store' import shallow from 'zustand/shallow' import studio from '@theatre/studio' +import type {ISheetObject} from '@theatre/core' export function useSelected(): undefined | string { const [state, set] = useState(undefined) @@ -12,7 +13,10 @@ export function useSelected(): undefined | string { useLayoutEffect(() => { const setFromStudio = (selection: typeof studio.selection) => { - const item = selection.find((s) => s.sheet === sheet) + const item = selection.find( + (s): s is ISheetObject => + s.type === 'Theatre_SheetObject_PublicAPI' && s.sheet === sheet, + ) if (!item) { set(undefined) } else { @@ -29,7 +33,10 @@ export function useSelected(): undefined | string { export function getSelected(): undefined | string { const sheet = useEditorStore.getState().sheet if (!sheet) return undefined - const item = studio.selection.find((s) => s.sheet === sheet) + const item = studio.selection.find( + (s): s is ISheetObject => + s.type === 'Theatre_SheetObject_PublicAPI' && s.sheet === sheet, + ) if (!item) { return undefined } else { diff --git a/theatre/studio/src/TheatreStudio.ts b/theatre/studio/src/TheatreStudio.ts index bf5eba0..d4593ea 100644 --- a/theatre/studio/src/TheatreStudio.ts +++ b/theatre/studio/src/TheatreStudio.ts @@ -17,6 +17,7 @@ import getStudio from './getStudio' import type React from 'react' import type {PropTypeConfig_Compound} from '@theatre/core/propTypes' import {debounce} from 'lodash-es' +import type Sheet from '@theatre/core/sheets/Sheet' export interface ITransactionAPI { set(pointer: Pointer, value: V): void @@ -82,11 +83,30 @@ export interface IStudio { scrub(): IScrub debouncedScrub(threshhold: number): Pick + /** + * Sets the current selection. + * + * Usage: + * ```ts + * const sheet1: ISheet = ... + * const obj1: ISheetObject = ... + * + * studio.setSelection([sheet1, obj1]) + * ``` + * + * You can read the current selection from studio.selection + */ setSelection(selection: Array): void - onSelectionChange(fn: (s: Array) => void): VoidFunction + /** + * Calls fn every time the current selection changes. + */ + onSelectionChange(fn: (s: Array) => void): VoidFunction - readonly selection: Array + /** + * The current selection, consisting of Sheets and Sheet Objects + */ + readonly selection: Array extend(extension: IExtension): void @@ -137,17 +157,20 @@ export default class TheatreStudio implements IStudio { }) } - private _getSelectionDerivation(): IDerivation { + private _getSelectionDerivation(): IDerivation<(ISheetObject | ISheet)[]> { return this._cache.get('_getStateDerivation()', () => - prism((): ISheetObject[] => { + prism((): (ISheetObject | ISheet)[] => { return getOutlineSelection() - .filter((s): s is SheetObject => s.type === 'Theatre_SheetObject') + .filter( + (s): s is SheetObject | Sheet => + s.type === 'Theatre_SheetObject' || s.type === 'Theatre_Sheet', + ) .map((s) => s.publicApi) }), ) } - private _getSelection(): ISheetObject[] { + private _getSelection(): (ISheetObject | ISheet)[] { return this._getSelectionDerivation().getValue() } @@ -163,11 +186,11 @@ export default class TheatreStudio implements IStudio { }) } - onSelectionChange(fn: (s: ISheetObject[]) => void): VoidFn { + onSelectionChange(fn: (s: (ISheetObject | ISheet)[]) => void): VoidFn { return this._getSelectionDerivation().tapImmediate(studioTicker, fn) } - get selection(): ISheetObject[] { + get selection(): (ISheetObject | ISheet)[] { return this._getSelection() }