diff --git a/src/components/GravitySimulator/GravitySimulator.tsx b/src/components/GravitySimulator/GravitySimulator.tsx index 09dedbd..0efe175 100644 --- a/src/components/GravitySimulator/GravitySimulator.tsx +++ b/src/components/GravitySimulator/GravitySimulator.tsx @@ -30,12 +30,8 @@ import { SimulatorSettings } from "../SimulatorSettings/SimulatorSettings"; import { useSettings } from "../../contexts/SettingsContext"; import { throttle, debounce } from "lodash"; import "../../styles/global.scss"; -import { MdFullscreen, MdFullscreenExit, MdInvertColors } from "react-icons/md"; -import { BiReset } from "react-icons/bi"; import { motion } from "framer-motion"; -import { BsPlayFill, BsPauseFill, BsFillCameraFill } from "react-icons/bs"; import { DebugData } from "../../types/Debug"; -import { AiOutlineExport } from "react-icons/ai"; import { VscLibrary } from "react-icons/vsc"; import { ScenarioPanel } from "../ScenarioPanel/ScenarioPanel"; import { Scenario } from "../../types/scenario"; @@ -55,10 +51,10 @@ import { toSimulatorPath, } from "../../utils/types/path"; import { PaperCanvas } from "../PaperCanvas/PaperCanvas"; -import { MusicPlayer } from "../MusicPlayer/MusicPlayer"; import { AudioManager } from "../../utils/audio/AudioManager"; import { VolumeSettings } from "../../utils/audio/AudioManager"; import { SimulatorRenderer } from "../SimulatorRenderer/SimulatorRenderer"; +import { SimulatorControls } from "../SimulatorControls/SimulatorControls"; const generatePastelColor = () => { const r = Math.floor(Math.random() * 75 + 180); @@ -651,26 +647,22 @@ export const GravitySimulator: React.FC = ({ }); }, []); - const exportScenario = useCallback( - (e: React.MouseEvent) => { - e.stopPropagation(); - const scenario: Scenario = { - id: Math.random().toString(36).substr(2, 9), - name: "", - description: "User saved scenario", - data: { - settings: physicsConfig, - gravityPoints: gravityPoints.map(toSerializableGravityPoint), - particles: particles.map(toSerializableParticle), - paths: paths.map(toSerializableSimulatorPath), - }, - }; - setShareableLink(createShareableLink(scenario)); - setIsPaused(true); - setIsSaveModalOpen(true); - }, - [physicsConfig, gravityPoints, particles, paths] - ); + const exportScenario = useCallback(() => { + const scenario: Scenario = { + id: Math.random().toString(36).substr(2, 9), + name: "", + description: "User saved scenario", + data: { + settings: physicsConfig, + gravityPoints: gravityPoints.map(toSerializableGravityPoint), + particles: particles.map(toSerializableParticle), + paths: paths.map(toSerializableSimulatorPath), + }, + }; + setShareableLink(createShareableLink(scenario)); + setIsPaused(true); + setIsSaveModalOpen(true); + }, [physicsConfig, gravityPoints, particles, paths, setIsPaused]); const handleSaveScenario = useCallback( (name: string) => { @@ -956,6 +948,24 @@ export const GravitySimulator: React.FC = ({ [handleSelectScenario] // Only depends on handleSelectScenario ); + // Add handler functions + const handlePause = useCallback(() => { + setIsPaused(!isPaused); + }, [isPaused]); + + const handleReset = useCallback(() => { + setParticles([]); + setIsSimulationStarted(false); + }, []); + + const handleFullscreenToggle = useCallback(() => { + toggleFullscreen(); + }, [toggleFullscreen]); + + const handleInvertColors = useCallback(() => { + setIsColorInverted((prev) => !prev); + }, []); + const content = ( <>
= ({ /> {!removeOverlay && ( -
- {!disableSound && ( - - )} - - - - { - e.stopPropagation(); - setIsPaused(!isPaused); - }} - className="floating-panel floating-button" - whileHover={{ scale: 1.05 }} - whileTap={{ scale: 0.95 }} - title={isPaused ? "Resume Simulation" : "Pause Simulation"} - > - {isPaused ? : } - - - { - e.stopPropagation(); - setParticles([]); - setIsSimulationStarted(false); - }} - className="floating-panel floating-button" - whileHover={{ scale: 1.05 }} - whileTap={{ scale: 0.95 }} - title="Reset Simulation" - > - - - - { - e.stopPropagation(); - toggleFullscreen(); - }} - className="floating-panel floating-button" - whileHover={{ scale: 1.05 }} - whileTap={{ scale: 0.95 }} - title={isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen"} - > - {isFullscreen ? ( - - ) : ( - - )} - - - - - - - { - e.stopPropagation(); - setIsColorInverted((prev) => !prev); - }} - className="floating-panel floating-button" - whileHover={{ scale: 1.05 }} - whileTap={{ scale: 0.95 }} - title="Invert Colors" - > - - -
+ )} {!removeOverlay && ( diff --git a/src/components/SimulatorControls/SimulatorControls.tsx b/src/components/SimulatorControls/SimulatorControls.tsx index 40256be..cd56d3a 100644 --- a/src/components/SimulatorControls/SimulatorControls.tsx +++ b/src/components/SimulatorControls/SimulatorControls.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useCallback } from "react"; import { motion } from "framer-motion"; import { MdFullscreen, MdFullscreenExit, MdInvertColors } from "react-icons/md"; import { BiReset } from "react-icons/bi"; @@ -41,6 +41,23 @@ export const SimulatorControls: React.FC = ({ onAudioToggle, disableSound, }) => { + const handleClick = useCallback( + (handler: (e: React.MouseEvent) => void) => + (e: React.MouseEvent) => { + e.stopPropagation(); + handler(e); + }, + [] + ); + + const handleSimpleClick = useCallback( + (handler: () => void) => (e: React.MouseEvent) => { + e.stopPropagation(); + handler(); + }, + [] + ); + return ( <>
= ({ )} = ({ = ({ = ({ = ({ = ({ = ({ }} > = ({