@@ -560,7 +560,7 @@ export const SolverDebugger3d: React.FC<SolverDebugger3dProps> = ({
560560 defaultWireframeOutput = false ,
561561 style,
562562} ) => {
563- const [ show3d , setShow3d ] = useState ( false )
563+ const [ renderMode , setRenderMode ] = useState < "2d" | "3d" > ( "2d" )
564564 const [ rebuildKey , setRebuildKey ] = useState ( 0 )
565565
566566 const [ showRoot , setShowRoot ] = useState ( defaultShowRoot )
@@ -610,204 +610,134 @@ export const SolverDebugger3d: React.FC<SolverDebugger3dProps> = ({
610610 return ( ) => clearInterval ( interval )
611611 } , [ updateMeshNodes , solver ] )
612612
613- const toggle3d = useCallback ( ( ) => setShow3d ( ( s ) => ! s ) , [ ] )
614613 const rebuild = useCallback ( ( ) => setRebuildKey ( ( k ) => k + 1 ) , [ ] )
615614
616615 return (
617616 < >
618617 < div style = { { display : "grid" , gap : 12 , ...style } } >
619- < GenericSolverDebugger
620- solver = { solver as any }
621- onSolverCompleted = { handleSolverCompleted }
622- />
623-
618+ { /* Topbar with Render dropdown */ }
624619 < div
625620 style = { {
626621 display : "flex" ,
627- gap : 8 ,
622+ gap : 12 ,
628623 alignItems : "center" ,
629- flexWrap : "wrap" ,
624+ padding : "12px 16px" ,
625+ background : "#f8fafc" ,
626+ borderRadius : 8 ,
627+ border : "1px solid #e2e8f0" ,
630628 } }
631629 >
632- < button
633- onClick = { toggle3d }
634- style = { {
635- padding : "8px 10px" ,
636- borderRadius : 6 ,
637- border : "1px solid #cbd5e1" ,
638- background : show3d ? "#1e293b" : "#2563eb" ,
639- color : "white" ,
640- cursor : "pointer" ,
641- } }
642- >
643- { show3d ? "Hide 3D" : "Show 3D" }
644- </ button >
645- { show3d && (
646- < button
647- onClick = { rebuild }
630+ < label style = { { display : "flex" , gap : 8 , alignItems : "center" } } >
631+ < span style = { { fontWeight : 600 , fontSize : 14 } } > Render:</ span >
632+ < select
633+ value = { renderMode }
634+ onChange = { ( e ) => setRenderMode ( e . target . value as "2d" | "3d" ) }
648635 style = { {
649- padding : "8px 10px " ,
636+ padding : "6px 12px " ,
650637 borderRadius : 6 ,
651638 border : "1px solid #cbd5e1" ,
652- background : "#0f766e" ,
653- color : "white" ,
639+ background : "white" ,
654640 cursor : "pointer" ,
641+ fontSize : 14 ,
655642 } }
656- title = "Rebuild 3D scene (use after changing solver params)"
657643 >
658- Rebuild 3D
659- </ button >
660- ) }
661-
662- { /* experiment-like toggles */ }
663- < label
664- style = { {
665- display : "inline-flex" ,
666- gap : 6 ,
667- alignItems : "center" ,
668- marginLeft : 8 ,
669- } }
670- >
671- < input
672- type = "checkbox"
673- checked = { showRoot }
674- onChange = { ( e ) => setShowRoot ( e . target . checked ) }
675- />
676- Root
677- </ label >
678- < label
679- style = { { display : "inline-flex" , gap : 6 , alignItems : "center" } }
680- >
681- < input
682- type = "checkbox"
683- checked = { showObstacles }
684- onChange = { ( e ) => setShowObstacles ( e . target . checked ) }
685- />
686- Obstacles
644+ < option value = "2d" > 2D (Normal)</ option >
645+ < option value = "3d" > 3D View</ option >
646+ </ select >
687647 </ label >
688- < label
689- style = { { display : "inline-flex" , gap : 6 , alignItems : "center" } }
690- >
691- < input
692- type = "checkbox"
693- checked = { showOutput }
694- onChange = { ( e ) => setShowOutput ( e . target . checked ) }
695- />
696- Output
697- </ label >
698- < label
699- style = { { display : "inline-flex" , gap : 6 , alignItems : "center" } }
700- >
701- < input
702- type = "checkbox"
703- checked = { wireframeOutput }
704- onChange = { ( e ) => setWireframeOutput ( e . target . checked ) }
705- />
706- Wireframe Output
707- </ label >
708-
709- { /* Mesh opacity slider */ }
710- { show3d && (
711- < label
712- style = { {
713- display : "inline-flex" ,
714- alignItems : "center" ,
715- gap : 6 ,
716- marginLeft : 8 ,
717- fontSize : 12 ,
718- } }
719- >
720- Opacity
721- < input
722- type = "range"
723- min = { 0 }
724- max = { 1 }
725- step = { 0.05 }
726- value = { meshOpacity }
727- onChange = { ( e ) => setMeshOpacity ( parseFloat ( e . target . value ) ) }
728- />
729- < span style = { { width : 32 , textAlign : "right" } } >
730- { meshOpacity . toFixed ( 2 ) }
731- </ span >
732- </ label >
733- ) }
734648
735- { /* Shrink boxes option */ }
736- { show3d && (
649+ { renderMode === "3d" && (
737650 < >
651+ < button
652+ onClick = { rebuild }
653+ style = { {
654+ padding : "6px 12px" ,
655+ borderRadius : 6 ,
656+ border : "1px solid #cbd5e1" ,
657+ background : "#0f766e" ,
658+ color : "white" ,
659+ cursor : "pointer" ,
660+ fontSize : 14 ,
661+ } }
662+ title = "Rebuild 3D scene"
663+ >
664+ Rebuild
665+ </ button >
666+
738667 < label
739668 style = { {
740669 display : "inline-flex" ,
741670 gap : 6 ,
742671 alignItems : "center" ,
743- fontSize : 12 ,
672+ fontSize : 13 ,
744673 } }
745674 >
746675 < input
747676 type = "checkbox"
748- checked = { shrinkBoxes }
749- onChange = { ( e ) => setShrinkBoxes ( e . target . checked ) }
677+ checked = { showRoot }
678+ onChange = { ( e ) => setShowRoot ( e . target . checked ) }
750679 />
751- Shrink boxes
680+ Root
752681 </ label >
753- { shrinkBoxes && (
754- < label
755- style = { {
756- display : "inline-flex" ,
757- gap : 4 ,
758- alignItems : "center" ,
759- fontSize : 12 ,
760- } }
761- >
762- amt
763- < input
764- type = "number"
765- value = { boxShrinkAmount }
766- step = { 0.05 }
767- style = { { width : 60 } }
768- onChange = { ( e ) => {
769- const v = parseFloat ( e . target . value )
770- if ( Number . isNaN ( v ) ) return
771- setBoxShrinkAmount ( Math . max ( 0 , v ) )
772- } }
773- />
774- </ label >
775- ) }
776- </ >
777- ) }
778-
779- { /* Show borders option */ }
780- { show3d && (
781- < label
782- style = { {
783- display : "inline-flex" ,
784- gap : 6 ,
785- alignItems : "center" ,
786- fontSize : 12 ,
787- } }
788- >
789- < input
790- type = "checkbox"
791- checked = { showBorders }
792- disabled = { wireframeOutput }
793- onChange = { ( e ) => setShowBorders ( e . target . checked ) }
794- />
795- < span
682+ < label
683+ style = { {
684+ display : "inline-flex" ,
685+ gap : 6 ,
686+ alignItems : "center" ,
687+ fontSize : 13 ,
688+ } }
689+ >
690+ < input
691+ type = "checkbox"
692+ checked = { showObstacles }
693+ onChange = { ( e ) => setShowObstacles ( e . target . checked ) }
694+ />
695+ Obstacles
696+ </ label >
697+ < label
698+ style = { {
699+ display : "inline-flex" ,
700+ gap : 6 ,
701+ alignItems : "center" ,
702+ fontSize : 13 ,
703+ } }
704+ >
705+ < input
706+ type = "checkbox"
707+ checked = { showOutput }
708+ onChange = { ( e ) => setShowOutput ( e . target . checked ) }
709+ />
710+ Output
711+ </ label >
712+ < label
796713 style = { {
797- opacity : wireframeOutput ? 0.5 : 1 ,
714+ display : "inline-flex" ,
715+ gap : 6 ,
716+ alignItems : "center" ,
717+ fontSize : 13 ,
798718 } }
799719 >
800- Show borders
801- </ span >
802- </ label >
720+ < input
721+ type = "checkbox"
722+ checked = { wireframeOutput }
723+ onChange = { ( e ) => setWireframeOutput ( e . target . checked ) }
724+ />
725+ Wireframe
726+ </ label >
727+ </ >
803728 ) }
804-
805- < div style = { { fontSize : 12 , color : "#334155" , marginLeft : 6 } } >
806- Drag to orbit · Wheel to zoom · Right-drag to pan
807- </ div >
808729 </ div >
809730
810- { show3d && (
731+ { /* Render 2D view */ }
732+ { renderMode === "2d" && (
733+ < GenericSolverDebugger
734+ solver = { solver as any }
735+ onSolverCompleted = { handleSolverCompleted }
736+ />
737+ ) }
738+
739+ { /* Render 3D view */ }
740+ { renderMode === "3d" && (
811741 < ThreeBoardView
812742 key = { rebuildKey }
813743 nodes = { meshNodes }
0 commit comments