From e063e63aa16fb9eadf4eeac2f533971671d5b10d Mon Sep 17 00:00:00 2001 From: Orion Reed Date: Mon, 25 Mar 2024 04:25:31 -0700 Subject: [PATCH] Separate canvas and physics buttons --- src/App.tsx | 24 ++++++++++++---- src/components/Canvas.tsx | 3 ++ src/components/Toggle.tsx | 5 +++- src/css/style.css | 35 ++++++++++++++++------- src/hooks/{usePhysics.ts => useCanvas.ts} | 32 ++++++++++++--------- src/physics/PhysicsControls.tsx | 35 +++++++++++++++++++++-- src/physics/simulation.ts | 26 +++++++++-------- src/public/canvas-button.svg | 7 +++++ src/utils.tsx | 6 ++-- 9 files changed, 127 insertions(+), 46 deletions(-) rename src/hooks/{usePhysics.ts => useCanvas.ts} (76%) create mode 100644 src/public/canvas-button.svg diff --git a/src/App.tsx b/src/App.tsx index 04f761c..fa69277 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,11 +1,11 @@ import "@tldraw/tldraw/tldraw.css"; import "@/css/style.css" -import React, { } from "react"; +import React, { useEffect, useState } from "react"; import ReactDOM from "react-dom/client"; import { Default } from "@/components/Default"; import { Canvas } from "@/components/Canvas"; import { Toggle } from "@/components/Toggle"; -import { usePhysics } from "@/hooks/usePhysics" +import { useCanvas } from "@/hooks/useCanvas" import { createShapes } from "@/utils"; import { BrowserRouter, Route, Routes } from 'react-router-dom'; import { Contact } from "@/components/Contact"; @@ -28,12 +28,26 @@ function App() { }; function Home() { - const { isPhysicsEnabled, elementsInfo, fadeClass } = usePhysics(); + const { isCanvasEnabled, elementsInfo } = useCanvas(); const shapes = createShapes(elementsInfo) + const [isEditorMounted, setIsEditorMounted] = useState(false); + + useEffect(() => { + const handleEditorDidMount = () => { + setIsEditorMounted(true); + }; + + window.addEventListener('editorDidMountEvent', handleEditorDidMount); + + return () => { + window.removeEventListener('editorDidMountEvent', handleEditorDidMount); + }; + }, []); + return ( <> -
+
{}
- {isPhysicsEnabled && elementsInfo.length > 0 ? : null}) + {isCanvasEnabled && elementsInfo.length > 0 ? : null}) } \ No newline at end of file diff --git a/src/components/Canvas.tsx b/src/components/Canvas.tsx index ff9362e..67492b9 100644 --- a/src/components/Canvas.tsx +++ b/src/components/Canvas.tsx @@ -29,6 +29,9 @@ export function Canvas({ shapes }: { shapes: TLShape[]; }) { { + window.dispatchEvent(new CustomEvent('editorDidMountEvent')); + }} > diff --git a/src/components/Toggle.tsx b/src/components/Toggle.tsx index af2a9c6..8b27dbd 100644 --- a/src/components/Toggle.tsx +++ b/src/components/Toggle.tsx @@ -1,7 +1,10 @@ export function Toggle() { return ( <> - + diff --git a/src/css/style.css b/src/css/style.css index 9e4c5d0..8dc7347 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -72,6 +72,10 @@ a { } } +p a { + text-decoration: underline; +} + .dinkus { display: block; text-align: center; @@ -89,10 +93,10 @@ ul { } } -#toggle-physics { +#toggle-physics, +#toggle-canvas { position: absolute; z-index: 99999; - top: 10px; right: 10px; width: 50px; height: 50px; @@ -108,6 +112,20 @@ ul { height: 100%; } } +#toggle-canvas { + top: 10px; + & img { + width: 50%; + height: 50%; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } +} +#toggle-physics { + top: 60px; +} @media (max-width: 600px) { main { @@ -140,16 +158,11 @@ ul { } } -.fade-out { +.transparent { opacity: 0 !important; - transition: opacity 0.5s ease-in-out; - transition-delay: 0.25s; - /* visibility: hidden; */ - /* display: none; */ + transition: opacity 0.25s ease-in-out; } -.fade-in { - opacity: 1; - transition: opacity 0.5s ease-in-out; - /* visibility: visible; */ +.hidden { + display: none; } diff --git a/src/hooks/usePhysics.ts b/src/hooks/useCanvas.ts similarity index 76% rename from src/hooks/usePhysics.ts rename to src/hooks/useCanvas.ts index da27601..6d01834 100644 --- a/src/hooks/usePhysics.ts +++ b/src/hooks/useCanvas.ts @@ -9,33 +9,39 @@ interface ElementInfo { html: string; } -export function usePhysics() { - const [isPhysicsEnabled, setIsPhysicsEnabled] = useState(false); +export function useCanvas() { + const [isCanvasEnabled, setIsCanvasEnabled] = useState(false); const [elementsInfo, setElementsInfo] = useState([]); - const [fadeClass, setFadeClass] = useState(''); useEffect(() => { - const togglePhysics = async () => { - if (!isPhysicsEnabled) { + const toggleCanvas = async () => { + if (!isCanvasEnabled) { const info = await gatherElementsInfo(); setElementsInfo(info); - setIsPhysicsEnabled(true); - setFadeClass('fade-out'); + setIsCanvasEnabled(true); + document.getElementById('toggle-physics')?.classList.remove('hidden'); } else { - setIsPhysicsEnabled(false); setElementsInfo([]); - setFadeClass(''); + setIsCanvasEnabled(false); + document.getElementById('toggle-physics')?.classList.add('hidden'); } }; + // const enableCanvas = async () => { + // const info = await gatherElementsInfo(); + // setElementsInfo(info); + // setIsCanvasEnabled(true); + // }; - window.addEventListener('togglePhysicsEvent', togglePhysics); + window.addEventListener('toggleCanvasEvent', toggleCanvas); + // window.addEventListener('togglePhysicsEvent', enableCanvas); return () => { - window.removeEventListener('togglePhysicsEvent', togglePhysics); + window.removeEventListener('toggleCanvasEvent', toggleCanvas); + // window.removeEventListener('togglePhysicsEvent', enableCanvas); }; - }, [isPhysicsEnabled]); + }, [isCanvasEnabled]); - return { isPhysicsEnabled, elementsInfo, fadeClass }; + return { isCanvasEnabled, elementsInfo }; } async function gatherElementsInfo() { diff --git a/src/physics/PhysicsControls.tsx b/src/physics/PhysicsControls.tsx index 444f4a0..590cd76 100644 --- a/src/physics/PhysicsControls.tsx +++ b/src/physics/PhysicsControls.tsx @@ -1,17 +1,48 @@ import { TLUnknownShape, useEditor } from "@tldraw/tldraw"; -import { useEffect } from "react"; +import { useEffect, useState } from "react"; import { usePhysicsSimulation } from "./simulation"; export const SimController = ({ shapes }: { shapes: TLUnknownShape[] }) => { const editor = useEditor(); + const [isPhysicsActive, setIsPhysicsActive] = useState(false); + const { addShapes, destroy } = usePhysicsSimulation(editor); useEffect(() => { editor.createShapes(shapes) return () => { editor.deleteShapes(editor.getCurrentPageShapes()) } }, []); + useEffect(() => { + const togglePhysics = () => { + setIsPhysicsActive((currentIsPhysicsActive) => { + if (currentIsPhysicsActive) { + console.log('destroy'); + destroy(); + return false; + } else { + console.log('activate'); + return true; + } + }); + }; - const { addShapes } = usePhysicsSimulation(editor, true); + // Listen for the togglePhysicsEvent to enable/disable physics simulation + window.addEventListener('togglePhysicsEvent', togglePhysics); + + return () => { + window.removeEventListener('togglePhysicsEvent', togglePhysics); + }; + }, []); + + useEffect(() => { + if (isPhysicsActive) { + console.log('adding shapes'); + + addShapes(editor.getCurrentPageShapes()); // Activate physics simulation + } else { + destroy(); // Deactivate physics simulation + } + }, [isPhysicsActive, addShapes, shapes]); return (<>); }; diff --git a/src/physics/simulation.ts b/src/physics/simulation.ts index 2014f23..31c318e 100644 --- a/src/physics/simulation.ts +++ b/src/physics/simulation.ts @@ -9,8 +9,6 @@ type BodyWithShapeData = RAPIER.RigidBody & { }; type RigidbodyLookup = { [key: TLShapeId]: RAPIER.RigidBody }; -const START_DELAY = 500; - export class PhysicsWorld { private editor: Editor; private world: RAPIER.World; @@ -30,8 +28,6 @@ export class PhysicsWorld { public start() { this.world = new RAPIER.World(GRAVITY); - this.addShapes(this.editor.getCurrentPageShapes()); - const simLoop = () => { this.world.step(); this.updateCharacterControllers(); @@ -50,7 +46,10 @@ export class PhysicsWorld { } public addShapes(shapes: TLShape[]) { + console.log('adding shapesss'); + for (const shape of shapes) { + console.log('shape'); if ('color' in shape.props && shape.props.color === "violet") { this.createCharacter(shape as TLGeoShape); continue; @@ -152,8 +151,9 @@ export class PhysicsWorld { const rigidbody = this.createRigidbody(drawShape); const drawnGeo = this.editor.getShapeGeometry(drawShape); const verts = drawnGeo.vertices; - const isRb = - "color" in drawShape.props && isRigidbody(drawShape.props.color); + // const isRb = + // "color" in drawShape.props && isRigidbody(drawShape.props.color); + const isRb = true; verts.forEach((point) => { if (isRb) this.createColliderAtPoint(point, drawShape, rigidbody); else this.createColliderAtPoint(point, drawShape); @@ -375,15 +375,12 @@ export class PhysicsWorld { } } -export function usePhysicsSimulation(editor: Editor, enabled: boolean) { +export function usePhysicsSimulation(editor: Editor) { const sim = useRef(new PhysicsWorld(editor)); useEffect(() => { - if (enabled) { - setTimeout(() => sim.current.start(), START_DELAY); - return () => sim.current.stop(); - } - }, [enabled, sim]); + sim.current.start() + }, []); useEffect(() => { sim.current.setEditor(editor); @@ -392,5 +389,10 @@ export function usePhysicsSimulation(editor: Editor, enabled: boolean) { // Return any values or functions that the UI components might need return { addShapes: (shapes: TLShape[]) => sim.current.addShapes(shapes), + destroy: () => { + sim.current.stop() + sim.current = new PhysicsWorld(editor); // Replace with a new instance + sim.current.start() + } }; } \ No newline at end of file diff --git a/src/public/canvas-button.svg b/src/public/canvas-button.svg new file mode 100644 index 0000000..3325f46 --- /dev/null +++ b/src/public/canvas-button.svg @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/src/utils.tsx b/src/utils.tsx index 4717053..04e80dc 100644 --- a/src/utils.tsx +++ b/src/utils.tsx @@ -13,13 +13,15 @@ export function createShapes(elementsInfo: any) { } })); + const extend = 150; + shapes.push({ id: createShapeId(), type: 'geo', - x: 0, + x: -extend, y: window.innerHeight, props: { - w: window.innerWidth, + w: window.innerWidth + (extend * 2), h: 50, color: 'grey', fill: 'solid'