From 4f76385a861169ae5f5995845140ecf785233678 Mon Sep 17 00:00:00 2001 From: itzmeowww Date: Thu, 9 Oct 2025 22:52:58 +0900 Subject: [PATCH 01/10] feat: drawer --- src/App.tsx | 125 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 49 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index c392bf2..aea474e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,5 +1,8 @@ import Box from '@mui/material/Box'; -import Grid from '@mui/material/Grid2'; +import Stack from '@mui/material/Stack'; +import Drawer from '@mui/material/Drawer'; +import IconButton from '@mui/material/IconButton'; +import MenuIcon from '@mui/icons-material/Menu'; import ConfigBar from './ConfigBar'; import Visualizer from './Visualizer'; import { Graph } from './Graph'; @@ -27,6 +30,7 @@ function App() { const [showCellId, setShowCellId] = React.useState(false); const [showGoals, setShowGoals] = React.useState(true); const [showGoalVectors, setShowGoalVectors] = React.useState(false); + const [drawerOpen, setDrawerOpen] = React.useState(false); const handleSkipBackward = () => { if (pixiAppRef.current?.skipBackward) { @@ -60,54 +64,77 @@ function App() { return ( - - - - - - - setGraph(graph), [])} - onSolutionChange={useCallback((solution: Solution | null) => setSolution(solution), [])} - playAnimation={playAnimation} - onPlayAnimationChange={setPlayAnimation} - onSkipBackward={handleSkipBackward} - onSkipForward={handleSkipForward} - onRestart={handleRestart} - stepSize={stepSize} - onStepSizeChange={setStepSize} - loopAnimation={loopAnimation} - onLoopAnimationChange={setLoopAnimation} - onFitView={handleFitView} - showAgentId={showAgentId} - onShowAgentIdChange={setShowAgentId} - tracePaths={tracePaths} - onTracePathsChange={setTracePaths} - canScreenshot={canScreenshot} - takeScreenshot={handleTakeScreenshot} - showCellId={showCellId} - setShowCellId={setShowCellId} - showGoals={showGoals} - setShowGoals={setShowGoals} - showGoalVectors={showGoalVectors} - setShowGoalVectors={setShowGoalVectors} - /> - - + + setDrawerOpen(true)} + sx={{ + position: 'absolute', + bottom: 16, + right: 16, + zIndex: 1000, + backgroundColor: 'background.paper', + '&:hover': { + backgroundColor: 'action.hover', + }, + }} + > + + + + + + setDrawerOpen(false)} + keepMounted + sx={{ + '& .MuiDrawer-paper': { + width: 400, + }, + }} + > + setGraph(graph), [])} + onSolutionChange={useCallback((solution: Solution | null) => setSolution(solution), [])} + playAnimation={playAnimation} + onPlayAnimationChange={setPlayAnimation} + onSkipBackward={handleSkipBackward} + onSkipForward={handleSkipForward} + onRestart={handleRestart} + stepSize={stepSize} + onStepSizeChange={setStepSize} + loopAnimation={loopAnimation} + onLoopAnimationChange={setLoopAnimation} + onFitView={handleFitView} + showAgentId={showAgentId} + onShowAgentIdChange={setShowAgentId} + tracePaths={tracePaths} + onTracePathsChange={setTracePaths} + canScreenshot={canScreenshot} + takeScreenshot={handleTakeScreenshot} + showCellId={showCellId} + setShowCellId={setShowCellId} + showGoals={showGoals} + setShowGoals={setShowGoals} + showGoalVectors={showGoalVectors} + setShowGoalVectors={setShowGoalVectors} + /> + ); From 0355ff64d31897e2ca52406f3b854b1c2ca3751b Mon Sep 17 00:00:00 2001 From: Thanasan Kumdee Date: Mon, 13 Oct 2025 11:22:47 +0900 Subject: [PATCH 02/10] Update src/App.tsx Co-authored-by: Justin Shetty --- src/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App.tsx b/src/App.tsx index aea474e..8c0b286 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -30,7 +30,7 @@ function App() { const [showCellId, setShowCellId] = React.useState(false); const [showGoals, setShowGoals] = React.useState(true); const [showGoalVectors, setShowGoalVectors] = React.useState(false); - const [drawerOpen, setDrawerOpen] = React.useState(false); + const [drawerOpen, setDrawerOpen] = React.useState(true); const handleSkipBackward = () => { if (pixiAppRef.current?.skipBackward) { From 12ca7d70f20c0d3807575ebf90bbd1b2dfcf5eec Mon Sep 17 00:00:00 2001 From: itzmeowww Date: Mon, 13 Oct 2025 11:31:10 +0900 Subject: [PATCH 03/10] fix: layout --- src/App.tsx | 2 +- src/PixiApp.tsx | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 8c0b286..1b43c99 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -69,7 +69,7 @@ function App() { onClick={() => setDrawerOpen(true)} sx={{ position: 'absolute', - bottom: 16, + top: 16, right: 16, zIndex: 1000, backgroundColor: 'background.paper', diff --git a/src/PixiApp.tsx b/src/PixiApp.tsx index 5554b9b..078ee9d 100644 --- a/src/PixiApp.tsx +++ b/src/PixiApp.tsx @@ -391,9 +391,9 @@ const PixiApp = forwardRef(({ hudRef.current.addChild( new PIXI.Text({ - x: width - width / 100, - y: height / 100, - anchor: new PIXI.Point(1, 0), + x: width / 100, + y: height - height / 100, + anchor: new PIXI.Point(0, 1), text: "Click and drag to pan. Scroll to zoom.", style: textStyle, }) @@ -449,8 +449,8 @@ const PixiApp = forwardRef(({ if (hudRef.current) { hudRef.current.children[0].x = width / 100; hudRef.current.children[0].y = height / 100; - hudRef.current.children[1].x = width - width / 100; - hudRef.current.children[1].y = height / 100; + hudRef.current.children[1].x = width / 100; + hudRef.current.children[1].y = height - height / 100; } fit(); } From c6cc198822112bdbd5e44ab8accc47d3c576c6e5 Mon Sep 17 00:00:00 2001 From: itzmeowww Date: Sat, 18 Oct 2025 12:21:34 +0900 Subject: [PATCH 04/10] feat: move text --- src/PixiApp.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/PixiApp.tsx b/src/PixiApp.tsx index 078ee9d..6606e4c 100644 --- a/src/PixiApp.tsx +++ b/src/PixiApp.tsx @@ -385,15 +385,16 @@ const PixiApp = forwardRef(({ new PIXI.Text({ x: width / 100, y: height / 100, + anchor: new PIXI.Point(0, 0), style: textStyle, }) ); hudRef.current.addChild( new PIXI.Text({ - x: width / 100, - y: height - height / 100, - anchor: new PIXI.Point(0, 1), + x: width - width / 100, + y: height / 100, + anchor: new PIXI.Point(1, 0), text: "Click and drag to pan. Scroll to zoom.", style: textStyle, }) @@ -449,8 +450,8 @@ const PixiApp = forwardRef(({ if (hudRef.current) { hudRef.current.children[0].x = width / 100; hudRef.current.children[0].y = height / 100; - hudRef.current.children[1].x = width / 100; - hudRef.current.children[1].y = height - height / 100; + hudRef.current.children[1].x = width - width / 100; + hudRef.current.children[1].y = height / 100; } fit(); } From 3ff6b7e5260b31099409c394f6a5695b5766040c Mon Sep 17 00:00:00 2001 From: itzmeowww Date: Sat, 18 Oct 2025 12:41:30 +0900 Subject: [PATCH 05/10] feat: refactor, restyle ui --- src/AnimationControl.tsx | 332 +++++++++++++++++------------------- src/App.tsx | 60 ++++--- src/ConfigBar.tsx | 160 ++++++++--------- src/ControlsSection.tsx | 71 ++++++++ src/DisplaySection.tsx | 81 +++++++++ src/FilesSection.tsx | 99 +++++++++++ src/QuickStartSection.tsx | 33 ++++ src/SpeedControlSection.tsx | 39 +++++ 8 files changed, 578 insertions(+), 297 deletions(-) create mode 100644 src/ControlsSection.tsx create mode 100644 src/DisplaySection.tsx create mode 100644 src/FilesSection.tsx create mode 100644 src/QuickStartSection.tsx create mode 100644 src/SpeedControlSection.tsx diff --git a/src/AnimationControl.tsx b/src/AnimationControl.tsx index 14c4d97..0d28bbd 100644 --- a/src/AnimationControl.tsx +++ b/src/AnimationControl.tsx @@ -1,30 +1,13 @@ -import SkipPreviousIcon from '@mui/icons-material/SkipPrevious'; -import PlayArrowIcon from '@mui/icons-material/PlayArrow'; -import PauseTwoToneIcon from '@mui/icons-material/PauseTwoTone'; -import SkipNextIcon from '@mui/icons-material/SkipNext'; -import Button from '@mui/material/Button'; -import ButtonGroup from '@mui/material/ButtonGroup'; import Box from '@mui/material/Box'; -import RestartAltIcon from '@mui/icons-material/RestartAlt'; -import Slider from '@mui/material/Slider'; -import RepeatIcon from '@mui/icons-material/Repeat'; -import RepeatOnIcon from '@mui/icons-material/RepeatOn'; import Stack from '@mui/material/Stack'; +import IconButton from '@mui/material/IconButton'; import Tooltip from '@mui/material/Tooltip'; -import LooksOneIcon from '@mui/icons-material/LooksOne'; -import LooksOneOutlinedIcon from '@mui/icons-material/LooksOneOutlined'; +import PlayArrowIcon from '@mui/icons-material/PlayArrow'; +import PauseTwoToneIcon from '@mui/icons-material/PauseTwoTone'; +import SkipPreviousIcon from '@mui/icons-material/SkipPrevious'; +import SkipNextIcon from '@mui/icons-material/SkipNext'; +import MenuIcon from '@mui/icons-material/Menu'; import { useEffect } from 'react'; -import DirectionsIcon from '@mui/icons-material/Directions'; -import DirectionsOutlinedIcon from '@mui/icons-material/DirectionsOutlined'; -import FilterCenterFocusOutlinedIcon from '@mui/icons-material/FilterCenterFocusOutlined'; -import ScreenshotMonitorOutlinedIcon from '@mui/icons-material/ScreenshotMonitorOutlined'; -import StartIcon from '@mui/icons-material/Start'; -import SmartToyOutlinedIcon from '@mui/icons-material/SmartToyOutlined'; -import SmartToyIcon from '@mui/icons-material/SmartToy'; -import FlagIcon from '@mui/icons-material/Flag'; -import OutlinedFlagIcon from '@mui/icons-material/OutlinedFlag'; -import PolylineIcon from '@mui/icons-material/Polyline'; -import PolylineOutlinedIcon from '@mui/icons-material/PolylineOutlined'; const STEP_SIZE_INCREMENT = 0.2; const STEP_SIZE_MAX = 10; @@ -47,13 +30,14 @@ const SHOW_GOAL_VECTORS_KEY = 'v'; interface AnimationControlProps { playAnimation: boolean; - onPlayAnimationChange: (playAnimation: boolean) => void; + onPlayAnimationChange: (play: boolean) => void; onSkipBackward: () => void; onSkipForward: () => void; + onOpenDrawer: () => void; onRestart: () => void; stepSize: number; onStepSizeChange: (speed: number) => void; - loopAnimation: boolean, + loopAnimation: boolean; onLoopAnimationChange: (loopAnimation: boolean) => void; onFitView: () => void; showAgentId: boolean; @@ -75,6 +59,7 @@ function AnimationControl({ onPlayAnimationChange, onSkipBackward, onSkipForward, + onOpenDrawer, onRestart, stepSize, onStepSizeChange, @@ -85,7 +70,6 @@ function AnimationControl({ onShowAgentIdChange, tracePaths, onTracePathsChange, - canScreenshot, takeScreenshot, showCellId, setShowCellId, @@ -94,178 +78,170 @@ function AnimationControl({ showGoalVectors, setShowGoalVectors, }: AnimationControlProps) { - const roundAndSetStepSize = (value: number) => { - onStepSizeChange(Number(value.toFixed(1))); - } - const handleSliderChange = (event: Event, value: number | number[]) => { - event.preventDefault(); - if (typeof value === 'number') roundAndSetStepSize(value); - }; + useEffect(() => { + const roundAndSetStepSize = (value: number) => { + onStepSizeChange(Number(value.toFixed(1))); + }; - useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if (!event.ctrlKey && !event.altKey && !event.metaKey) { event.preventDefault(); } - if (event.key === STEP_BACKWARD_KEY) { - onSkipBackward(); - } else if (event.key === PLAY_PAUSE_KEY) { - onPlayAnimationChange(!playAnimation); - } else if (event.key === STEP_FORWARD_KEY) { - onSkipForward(); - } else if (event.key === RESTART_KEY) { - onRestart(); - } else if (event.key === LOOP_KEY) { - onLoopAnimationChange(!loopAnimation); - } else if (event.key === FIT_VIEW_KEY) { - onFitView(); - } else if (event.key === SHOW_AGENT_ID_KEY) { - onShowAgentIdChange(!showAgentId); - } else if (event.key === STEP_SIZE_UP_KEY && stepSize + STEP_SIZE_INCREMENT <= STEP_SIZE_MAX) { - roundAndSetStepSize(stepSize + STEP_SIZE_INCREMENT); - } else if (event.key === STEP_SIZE_DOWN_KEY && stepSize - STEP_SIZE_INCREMENT >= STEP_SIZE_MIN) { - roundAndSetStepSize(stepSize - STEP_SIZE_INCREMENT); - } else if (event.key === TRACE_PATHS_KEY) { - onTracePathsChange(!tracePaths); - } else if (event.key === SCREENSHOT_KEY) { - takeScreenshot(); - } else if (event.key === SHOW_CELL_ID_KEY) { - setShowCellId(!showCellId); - } else if (event.key === SHOW_GOALS_KEY) { - setShowGoals(!showGoals); - } else if (event.key === SHOW_GOAL_VECTORS_KEY) { - setShowGoalVectors(!showGoalVectors); + switch (event.key) { + case STEP_BACKWARD_KEY: + onSkipBackward(); + break; + case PLAY_PAUSE_KEY: + onPlayAnimationChange(!playAnimation); + break; + case STEP_FORWARD_KEY: + onSkipForward(); + break; + case RESTART_KEY: + onRestart(); + break; + case LOOP_KEY: + onLoopAnimationChange(!loopAnimation); + break; + case FIT_VIEW_KEY: + onFitView(); + break; + case SHOW_AGENT_ID_KEY: + onShowAgentIdChange(!showAgentId); + break; + case STEP_SIZE_UP_KEY: + if (stepSize + STEP_SIZE_INCREMENT <= STEP_SIZE_MAX) { + roundAndSetStepSize(stepSize + STEP_SIZE_INCREMENT); + } + break; + case STEP_SIZE_DOWN_KEY: + if (stepSize - STEP_SIZE_INCREMENT >= STEP_SIZE_MIN) { + roundAndSetStepSize(stepSize - STEP_SIZE_INCREMENT); + } + break; + case TRACE_PATHS_KEY: + onTracePathsChange(!tracePaths); + break; + case SCREENSHOT_KEY: + takeScreenshot(); + break; + case SHOW_CELL_ID_KEY: + setShowCellId(!showCellId); + break; + case SHOW_GOALS_KEY: + setShowGoals(!showGoals); + break; + case SHOW_GOAL_VECTORS_KEY: + setShowGoalVectors(!showGoalVectors); + break; } }; window.addEventListener('keydown', handleKeyDown); return () => { window.removeEventListener('keydown', handleKeyDown); }; - }, [playAnimation, onPlayAnimationChange, loopAnimation, onFitView, - onLoopAnimationChange, onRestart, onShowAgentIdChange, onSkipBackward, - onSkipForward, onStepSizeChange, showAgentId, stepSize, onTracePathsChange, tracePaths, - takeScreenshot, showCellId, setShowCellId, showGoals, setShowGoals, showGoalVectors, - setShowGoalVectors]); + }, [ + playAnimation, + onPlayAnimationChange, + onSkipBackward, + onSkipForward, + onRestart, + stepSize, + onStepSizeChange, + loopAnimation, + onLoopAnimationChange, + onFitView, + showAgentId, + onShowAgentIdChange, + tracePaths, + onTracePathsChange, + takeScreenshot, + showCellId, + setShowCellId, + showGoals, + setShowGoals, + showGoalVectors, + setShowGoalVectors, + ]); return ( - - - - Adjust animation step size - ({STEP_SIZE_UP_KEY}/{STEP_SIZE_DOWN_KEY}) - - } - > - - - - - - - - - - + - - + + + onPlayAnimationChange(!playAnimation)} + sx={{ + width: 48, + height: 48, + backgroundColor: 'primary.main', + '&:hover': { + backgroundColor: 'primary.dark', + } + }} + > + {playAnimation ? : } + - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - + + + + + + + + + ); } diff --git a/src/App.tsx b/src/App.tsx index 1b43c99..5861d4b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,9 +1,7 @@ import Box from '@mui/material/Box'; -import Stack from '@mui/material/Stack'; import Drawer from '@mui/material/Drawer'; -import IconButton from '@mui/material/IconButton'; -import MenuIcon from '@mui/icons-material/Menu'; import ConfigBar from './ConfigBar'; +import AnimationControl from './AnimationControl'; import Visualizer from './Visualizer'; import { Graph } from './Graph'; import { Solution } from './Solution'; @@ -64,23 +62,8 @@ function App() { return ( - - setDrawerOpen(true)} - sx={{ - position: 'absolute', - top: 16, - right: 16, - zIndex: 1000, - backgroundColor: 'background.paper', - '&:hover': { - backgroundColor: 'action.hover', - }, - }} - > - - - + + - + + + setDrawerOpen(true)} + onRestart={handleRestart} + stepSize={stepSize} + onStepSizeChange={setStepSize} + loopAnimation={loopAnimation} + onLoopAnimationChange={setLoopAnimation} + onFitView={handleFitView} + showAgentId={showAgentId} + onShowAgentIdChange={setShowAgentId} + tracePaths={tracePaths} + onTracePathsChange={setTracePaths} + canScreenshot={canScreenshot} + takeScreenshot={handleTakeScreenshot} + showCellId={showCellId} + setShowCellId={setShowCellId} + showGoals={showGoals} + setShowGoals={setShowGoals} + showGoalVectors={showGoalVectors} + setShowGoalVectors={setShowGoalVectors} + /> + @@ -111,10 +122,6 @@ function App() { graph={graph} onGraphChange={useCallback((graph: Graph | null) => setGraph(graph), [])} onSolutionChange={useCallback((solution: Solution | null) => setSolution(solution), [])} - playAnimation={playAnimation} - onPlayAnimationChange={setPlayAnimation} - onSkipBackward={handleSkipBackward} - onSkipForward={handleSkipForward} onRestart={handleRestart} stepSize={stepSize} onStepSizeChange={setStepSize} @@ -133,6 +140,7 @@ function App() { setShowGoals={setShowGoals} showGoalVectors={showGoalVectors} setShowGoalVectors={setShowGoalVectors} + onCloseDrawer={() => setDrawerOpen(false)} /> diff --git a/src/ConfigBar.tsx b/src/ConfigBar.tsx index e32e9e2..ca3d6e6 100644 --- a/src/ConfigBar.tsx +++ b/src/ConfigBar.tsx @@ -1,21 +1,18 @@ -import AnimationControl from './AnimationControl'; import { Graph } from './Graph'; import { parseSolution, Solution } from './Solution'; -import { Divider, Stack, Button } from '@mui/material'; -import { MuiFileInput } from "mui-file-input"; +import { Divider, Stack, Box, IconButton } from '@mui/material'; import React, { useEffect } from 'react'; -import ClearIcon from '@mui/icons-material/Clear'; -import FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined'; -import Tooltip from '@mui/material/Tooltip'; +import CloseIcon from '@mui/icons-material/Close'; +import QuickStartSection from './QuickStartSection'; +import FilesSection from './FilesSection'; +import SpeedControlSection from './SpeedControlSection'; +import ControlsSection from './ControlsSection'; +import DisplaySection from './DisplaySection'; interface ConfigBarProps { graph: Graph | null; onGraphChange: (graph: Graph | null) => void; onSolutionChange: (solution: Solution | null) => void; - playAnimation: boolean; - onPlayAnimationChange: (playAnimation: boolean) => void; - onSkipBackward: () => void; - onSkipForward: () => void; onRestart: () => void; stepSize: number; onStepSizeChange: (speed: number) => void; @@ -34,16 +31,13 @@ interface ConfigBarProps { setShowGoals: (showGoals: boolean) => void; showGoalVectors: boolean; setShowGoalVectors: (showGoalVectors: boolean) => void; + onCloseDrawer: () => void; } function ConfigBar({ graph, onGraphChange, onSolutionChange, - playAnimation, - onPlayAnimationChange, - onSkipBackward, - onSkipForward, onRestart, stepSize, onStepSizeChange, @@ -62,6 +56,7 @@ function ConfigBar({ setShowGoals, showGoalVectors, setShowGoalVectors, + onCloseDrawer, }: ConfigBarProps) { const repoName = "JustinShetty/mapf-visualizer"; const [mapFile, setMapFile] = React.useState(null); @@ -142,100 +137,79 @@ function ConfigBar({ blurActiveElement(); }; - const downloadFile = (file: File) => { - const url = URL.createObjectURL(file); - const a = document.createElement('a'); - a.href = url; - a.download = file.name; - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - URL.revokeObjectURL(url); - } - return ( - - - - - - - -

Map

- - - }} - /> - {mapFile && - - - - } - - {mapError &&

{mapError}

} -
- - -

Solution

- - - }} - /> - {solutionFile && - - - - } - - {solutionError &&

{solutionError}

} -
- - + + + + + + + + + + + + + + + + + + + + + + + - - - {repoName} - + + + + + + {repoName} + +
); } diff --git a/src/ControlsSection.tsx b/src/ControlsSection.tsx new file mode 100644 index 0000000..c9d9c9f --- /dev/null +++ b/src/ControlsSection.tsx @@ -0,0 +1,71 @@ +import { Stack, Button, Box } from '@mui/material'; +import StartIcon from '@mui/icons-material/Start'; +import RepeatIcon from '@mui/icons-material/Repeat'; +import RepeatOnIcon from '@mui/icons-material/RepeatOn'; +import FilterCenterFocusOutlinedIcon from '@mui/icons-material/FilterCenterFocusOutlined'; +import ScreenshotMonitorOutlinedIcon from '@mui/icons-material/ScreenshotMonitorOutlined'; + +interface ControlsSectionProps { + onRestart: () => void; + loopAnimation: boolean; + onLoopAnimationChange: (loopAnimation: boolean) => void; + onFitView: () => void; + canScreenshot: boolean; + takeScreenshot: () => void; +} + +function ControlsSection({ + onRestart, + loopAnimation, + onLoopAnimationChange, + onFitView, + canScreenshot, + takeScreenshot, +}: ControlsSectionProps) { + return ( + + Controls + + + + + + + + ); +} + +export default ControlsSection; diff --git a/src/DisplaySection.tsx b/src/DisplaySection.tsx new file mode 100644 index 0000000..74bdc40 --- /dev/null +++ b/src/DisplaySection.tsx @@ -0,0 +1,81 @@ +import { Stack, Box, Checkbox } from '@mui/material'; +import SmartToyOutlinedIcon from '@mui/icons-material/SmartToyOutlined'; +import LooksOneOutlinedIcon from '@mui/icons-material/LooksOneOutlined'; +import DirectionsOutlinedIcon from '@mui/icons-material/DirectionsOutlined'; +import OutlinedFlagIcon from '@mui/icons-material/OutlinedFlag'; +import PolylineOutlinedIcon from '@mui/icons-material/PolylineOutlined'; + +interface DisplaySectionProps { + showAgentId: boolean; + onShowAgentIdChange: (showAgentId: boolean) => void; + showCellId: boolean; + setShowCellId: (showCellId: boolean) => void; + tracePaths: boolean; + onTracePathsChange: (tracePaths: boolean) => void; + showGoals: boolean; + setShowGoals: (showGoals: boolean) => void; + showGoalVectors: boolean; + setShowGoalVectors: (showGoalVectors: boolean) => void; +} + +function DisplaySection({ + showAgentId, + onShowAgentIdChange, + showCellId, + setShowCellId, + tracePaths, + onTracePathsChange, + showGoals, + setShowGoals, + showGoalVectors, + setShowGoalVectors, +}: DisplaySectionProps) { + return ( + + Display + + onShowAgentIdChange(!showAgentId)}> + onShowAgentIdChange(e.target.checked)} sx={{ py: 0.5 }} /> + + + Agent IDs + + + + setShowCellId(!showCellId)}> + setShowCellId(e.target.checked)} sx={{ py: 0.5 }} /> + + + Cell IDs + + + + onTracePathsChange(!tracePaths)}> + onTracePathsChange(e.target.checked)} sx={{ py: 0.5 }} /> + + + Paths + + + + setShowGoals(!showGoals)}> + setShowGoals(e.target.checked)} sx={{ py: 0.5 }} /> + + + Goals + + + + setShowGoalVectors(!showGoalVectors)}> + setShowGoalVectors(e.target.checked)} sx={{ py: 0.5 }} /> + + + Vectors + + + + + ); +} + +export default DisplaySection; diff --git a/src/FilesSection.tsx b/src/FilesSection.tsx new file mode 100644 index 0000000..136de6c --- /dev/null +++ b/src/FilesSection.tsx @@ -0,0 +1,99 @@ +import { Stack, Box, Button, Tooltip } from '@mui/material'; +import { MuiFileInput } from "mui-file-input"; +import ClearIcon from '@mui/icons-material/Clear'; +import FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined'; + +interface FilesSectionProps { + mapFile: File | null; + onMapChange: (file: File | null) => void; + mapError: string | null; + solutionFile: File | null; + onSolutionChange: (file: File | null) => void; + solutionError: string | null; +} + +function FilesSection({ + mapFile, + onMapChange, + mapError, + solutionFile, + onSolutionChange, + solutionError, +}: FilesSectionProps) { + const downloadFile = (file: File) => { + const url = URL.createObjectURL(file); + const a = document.createElement('a'); + a.href = url; + a.download = file.name; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + }; + + return ( + + + Map + + + }} + /> + {mapFile && ( + + + + )} + + {mapError && {mapError}} + + + + Solution + + + }} + /> + {solutionFile && ( + + + + )} + + {solutionError && {solutionError}} + + + ); +} + +export default FilesSection; diff --git a/src/QuickStartSection.tsx b/src/QuickStartSection.tsx new file mode 100644 index 0000000..8313572 --- /dev/null +++ b/src/QuickStartSection.tsx @@ -0,0 +1,33 @@ +import { Stack, Button, Box } from '@mui/material'; + +interface QuickStartSectionProps { + onLoadDemo: (mapName: string) => void; +} + +function QuickStartSection({ onLoadDemo }: QuickStartSectionProps) { + return ( + + Quick Start + + + + + + ); +} + +export default QuickStartSection; diff --git a/src/SpeedControlSection.tsx b/src/SpeedControlSection.tsx new file mode 100644 index 0000000..818622d --- /dev/null +++ b/src/SpeedControlSection.tsx @@ -0,0 +1,39 @@ +import { Stack, Box, Slider } from '@mui/material'; + +interface SpeedControlSectionProps { + stepSize: number; + onStepSizeChange: (stepSize: number) => void; +} + +function SpeedControlSection({ stepSize, onStepSizeChange }: SpeedControlSectionProps) { + const roundAndSetStepSize = (value: number) => { + onStepSizeChange(Number(value.toFixed(1))); + }; + + const handleSliderChange = (_event: Event, value: number | number[]) => { + if (typeof value === 'number') roundAndSetStepSize(value); + }; + + return ( + + Speed + + + + {stepSize.toFixed(1)}x + + + + ); +} + +export default SpeedControlSection; From ccc59d2f7fd9e3e1d90c806416401bea6258ba04 Mon Sep 17 00:00:00 2001 From: Thanasan Kumdee Date: Sun, 19 Oct 2025 12:05:36 +0900 Subject: [PATCH 06/10] Update src/AnimationControl.tsx Co-authored-by: Justin Shetty --- src/AnimationControl.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AnimationControl.tsx b/src/AnimationControl.tsx index 0d28bbd..3f070ac 100644 --- a/src/AnimationControl.tsx +++ b/src/AnimationControl.tsx @@ -213,7 +213,7 @@ function AnimationControl({ - + Date: Sun, 19 Oct 2025 12:05:48 +0900 Subject: [PATCH 07/10] Update src/AnimationControl.tsx Co-authored-by: Justin Shetty --- src/AnimationControl.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AnimationControl.tsx b/src/AnimationControl.tsx index 3f070ac..3af633a 100644 --- a/src/AnimationControl.tsx +++ b/src/AnimationControl.tsx @@ -183,7 +183,7 @@ function AnimationControl({ - + Date: Sun, 19 Oct 2025 12:19:37 +0900 Subject: [PATCH 08/10] feat: naming --- src/AnimationControl.tsx | 10 +++++----- src/App.tsx | 6 +++++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/AnimationControl.tsx b/src/AnimationControl.tsx index 3af633a..3695f18 100644 --- a/src/AnimationControl.tsx +++ b/src/AnimationControl.tsx @@ -30,7 +30,7 @@ const SHOW_GOAL_VECTORS_KEY = 'v'; interface AnimationControlProps { playAnimation: boolean; - onPlayAnimationChange: (play: boolean) => void; + onPlayChange: (play: boolean) => void; onSkipBackward: () => void; onSkipForward: () => void; onOpenDrawer: () => void; @@ -56,7 +56,7 @@ interface AnimationControlProps { function AnimationControl({ playAnimation, - onPlayAnimationChange, + onPlayChange, onSkipBackward, onSkipForward, onOpenDrawer, @@ -94,7 +94,7 @@ function AnimationControl({ onSkipBackward(); break; case PLAY_PAUSE_KEY: - onPlayAnimationChange(!playAnimation); + onPlayChange(!playAnimation); break; case STEP_FORWARD_KEY: onSkipForward(); @@ -144,7 +144,7 @@ function AnimationControl({ }; }, [ playAnimation, - onPlayAnimationChange, + onPlayChange, onSkipBackward, onSkipForward, onRestart, @@ -199,7 +199,7 @@ function AnimationControl({ onPlayAnimationChange(!playAnimation)} + onClick={() => onPlayChange(!playAnimation)} sx={{ width: 48, height: 48, diff --git a/src/App.tsx b/src/App.tsx index 5861d4b..d5955eb 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -30,6 +30,10 @@ function App() { const [showGoalVectors, setShowGoalVectors] = React.useState(false); const [drawerOpen, setDrawerOpen] = React.useState(true); + const handlePlayAnimation = (play: boolean) => { + setPlayAnimation(play); + } + const handleSkipBackward = () => { if (pixiAppRef.current?.skipBackward) { pixiAppRef.current.skipBackward(); @@ -82,7 +86,7 @@ function App() { setDrawerOpen(true)} From c05f002e615803a6084c1110944d35e94cabcdc4 Mon Sep 17 00:00:00 2001 From: itzmeowww Date: Sun, 19 Oct 2025 12:24:08 +0900 Subject: [PATCH 09/10] fix: naming --- src/App.tsx | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index d5955eb..ada3f69 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -30,35 +30,35 @@ function App() { const [showGoalVectors, setShowGoalVectors] = React.useState(false); const [drawerOpen, setDrawerOpen] = React.useState(true); - const handlePlayAnimation = (play: boolean) => { + const onPlayChange = (play: boolean) => { setPlayAnimation(play); } - const handleSkipBackward = () => { + const onSkipBackward = () => { if (pixiAppRef.current?.skipBackward) { pixiAppRef.current.skipBackward(); } } - const handleSkipForward = () => { + const onSkipForward = () => { if (pixiAppRef.current?.skipForward) { pixiAppRef.current.skipForward(); } } - const handleRestart = () => { + const onRestart = () => { if (pixiAppRef.current?.restart) { pixiAppRef.current.restart(); } } - const handleFitView = () => { + const onFitView = () => { if (pixiAppRef.current?.fit) { pixiAppRef.current.fit(); } } - const handleTakeScreenshot = () => { + const onTakeScreenshot = () => { if (pixiAppRef.current?.takeScreenshot) { pixiAppRef.current.takeScreenshot(); } @@ -86,22 +86,22 @@ function App() { setDrawerOpen(true)} - onRestart={handleRestart} + onRestart={onRestart} stepSize={stepSize} onStepSizeChange={setStepSize} loopAnimation={loopAnimation} onLoopAnimationChange={setLoopAnimation} - onFitView={handleFitView} + onFitView={onFitView} showAgentId={showAgentId} onShowAgentIdChange={setShowAgentId} tracePaths={tracePaths} onTracePathsChange={setTracePaths} canScreenshot={canScreenshot} - takeScreenshot={handleTakeScreenshot} + takeScreenshot={onTakeScreenshot} showCellId={showCellId} setShowCellId={setShowCellId} showGoals={showGoals} @@ -126,18 +126,18 @@ function App() { graph={graph} onGraphChange={useCallback((graph: Graph | null) => setGraph(graph), [])} onSolutionChange={useCallback((solution: Solution | null) => setSolution(solution), [])} - onRestart={handleRestart} + onRestart={onRestart} stepSize={stepSize} onStepSizeChange={setStepSize} loopAnimation={loopAnimation} onLoopAnimationChange={setLoopAnimation} - onFitView={handleFitView} + onFitView={onFitView} showAgentId={showAgentId} onShowAgentIdChange={setShowAgentId} tracePaths={tracePaths} onTracePathsChange={setTracePaths} canScreenshot={canScreenshot} - takeScreenshot={handleTakeScreenshot} + takeScreenshot={onTakeScreenshot} showCellId={showCellId} setShowCellId={setShowCellId} showGoals={showGoals} From 1c707748639759c8b41994d9cf2444a08eb1ea90 Mon Sep 17 00:00:00 2001 From: itzmeowww Date: Sun, 19 Oct 2025 18:58:01 +0900 Subject: [PATCH 10/10] fix: func --- src/App.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index ada3f69..42ccca8 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -30,10 +30,6 @@ function App() { const [showGoalVectors, setShowGoalVectors] = React.useState(false); const [drawerOpen, setDrawerOpen] = React.useState(true); - const onPlayChange = (play: boolean) => { - setPlayAnimation(play); - } - const onSkipBackward = () => { if (pixiAppRef.current?.skipBackward) { pixiAppRef.current.skipBackward(); @@ -86,7 +82,7 @@ function App() { setDrawerOpen(true)}