Skip to content

Commit 57f2d1b

Browse files
committed
feat: pass PluginProps to <Canvas/>
1 parent 99f8ddc commit 57f2d1b

File tree

3 files changed

+56
-16
lines changed

3 files changed

+56
-16
lines changed

playground/examples/PluginExample.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const GlobalPlugin = plugin(element => ({
6161

6262
// Example with setup - plugin that needs context from setup function
6363
const ContextPlugin = plugin
64-
.setup((context) => {
64+
.setup(context => {
6565
return { scene: context.scene }
6666
})
6767
.then((element, context) => ({
@@ -88,6 +88,7 @@ export function PluginExample() {
8888
<Canvas
8989
style={{ width: "100vw", height: "100vh" }}
9090
defaultCamera={{ position: new THREE.Vector3(0, 0, 30) }}
91+
onClick={() => console.info("click missed")}
9192
>
9293
<OrbitControls />
9394
<Entity from={THREE.Mesh} />
@@ -99,7 +100,7 @@ export function PluginExample() {
99100
lookAt={useThree().currentCamera}
100101
log="Mesh rendered!"
101102
shake={0.1}
102-
onMouseDown={event => console.info("ok")}
103+
onClick={event => event.stopPropagation()}
103104
>
104105
<T.TorusKnotGeometry args={[1, 0.5, 128, 32]} />
105106
<T.MeshStandardMaterial metalness={1} roughness={0} color="white">

src/create-three.tsx

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
VSMShadowMap,
2424
WebGLRenderer,
2525
} from "three"
26+
import { processProps } from "../playground/controls/process-props.ts"
2627
import type { CanvasProps } from "./create-canvas.tsx"
2728
import { frameContext, threeContext } from "./hooks.ts"
2829
import { pluginContext } from "./internal-context.ts"
@@ -31,7 +32,6 @@ import { CursorRaycaster, type EventRaycaster } from "./raycasters.tsx"
3132
import type { CameraKind, Context, FrameListener, FrameListenerCallback, Plugin } from "./types.ts"
3233
import {
3334
binarySearch,
34-
defaultProps,
3535
getCurrentViewport,
3636
meta,
3737
removeElementFromArray,
@@ -48,7 +48,22 @@ import { useMeasure } from "./utils/use-measure.ts"
4848
* based on the provided properties.
4949
*/
5050
export function createThree(canvas: HTMLCanvasElement, props: CanvasProps, plugins: Plugin[]) {
51-
const canvasProps = defaultProps(props, { frameloop: "always" })
51+
const [canvasProps, rest] = processProps(props, { frameloop: "always" }, [
52+
"children",
53+
"frameloop",
54+
"class",
55+
"defaultCamera",
56+
"defaultRaycaster",
57+
"fallback",
58+
"flat",
59+
"frameloop",
60+
"gl",
61+
"linear",
62+
"orthographic",
63+
"scene",
64+
"shadows",
65+
"style",
66+
])
5267

5368
/**********************************************************************************/
5469
/* */
@@ -237,8 +252,6 @@ export function createThree(canvas: HTMLCanvasElement, props: CanvasProps, plugi
237252
const clock = new Clock()
238253
clock.start()
239254

240-
const pluginMap = new ReactiveMap<Plugin, ReturnType<Plugin>>()
241-
242255
const context: Context = {
243256
get bounds() {
244257
return measure.bounds()
@@ -249,15 +262,7 @@ export function createThree(canvas: HTMLCanvasElement, props: CanvasProps, plugi
249262
return this.gl.getPixelRatio()
250263
},
251264
props,
252-
registerPlugin(plugin) {
253-
let result = pluginMap.get(plugin)
254-
if (result) {
255-
return result
256-
}
257-
result = plugin(context)
258-
pluginMap.set(plugin, result)
259-
return result
260-
},
265+
registerPlugin,
261266
render,
262267
requestRender,
263268
get viewport() {
@@ -293,6 +298,28 @@ export function createThree(canvas: HTMLCanvasElement, props: CanvasProps, plugi
293298
],
294299
)
295300

301+
/**********************************************************************************/
302+
/* */
303+
/* Plugins */
304+
/* */
305+
/**********************************************************************************/
306+
307+
const pluginMap = new ReactiveMap<Plugin, ReturnType<Plugin>>()
308+
309+
function registerPlugin(plugin: Plugin) {
310+
let result = pluginMap.get(plugin)
311+
if (result) {
312+
return result
313+
}
314+
result = plugin(context)
315+
pluginMap.set(plugin, result)
316+
return result
317+
}
318+
319+
const pluginMethods = createMemo(() =>
320+
mergeProps(...plugins.map(init => () => registerPlugin(init)(canvas))),
321+
)
322+
296323
/**********************************************************************************/
297324
/* */
298325
/* Effects */
@@ -310,6 +337,16 @@ export function createThree(canvas: HTMLCanvasElement, props: CanvasProps, plugi
310337
}
311338
})
312339

340+
// Manage props resolved to plugins
341+
createRenderEffect(() => {
342+
const _pluginMethods = pluginMethods()
343+
for (const key in canvasProps) {
344+
if (key in _pluginMethods) {
345+
_pluginMethods[key]?.(canvasProps[key as keyof typeof canvasProps])
346+
}
347+
}
348+
})
349+
313350
// Manage camera
314351
createRenderEffect(() => {
315352
if (cameraStack.peek()) return

src/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,9 @@ export interface Context {
8989
dpr: number
9090
gl: Meta<WebGLRenderer>
9191
props: CanvasProps
92-
registerPlugin(plugin: Plugin): (element: any) => void
92+
registerPlugin(
93+
plugin: Plugin,
94+
): (element: any) => Record<string, undefined | ((args: any) => void)>
9395
render: (delta: number) => void
9496
requestRender: () => void
9597
scene: Meta<Scene>

0 commit comments

Comments
 (0)