Skip to content

Commit ceded14

Browse files
committed
GEP-200 add toolbar actions
1 parent c75a45d commit ceded14

File tree

13 files changed

+422
-124
lines changed

13 files changed

+422
-124
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React, { createContext, useContext } from 'react';
2+
import { CameraControls } from '@react-three/drei';
3+
4+
type CameraControlsContextType = {
5+
cameraControls: React.RefObject<CameraControls> | null;
6+
};
7+
8+
const CameraControlsContext = createContext<CameraControlsContextType>({
9+
cameraControls: null,
10+
});
11+
12+
export const CameraControlsProvider: React.FC<{
13+
children: React.ReactNode;
14+
cameraControlsRef: React.RefObject<CameraControls>;
15+
}> = ({ children, cameraControlsRef }) => {
16+
return (
17+
<CameraControlsContext.Provider value={{ cameraControls: cameraControlsRef }}>
18+
{children}
19+
</CameraControlsContext.Provider>
20+
);
21+
};
22+
23+
export const useCameraControls = () => {
24+
const context = useContext(CameraControlsContext);
25+
return context.cameraControls;
26+
};

examples/vite-3DCanvas-react-app/src/components/toolbar/Toolbar3D.tsx

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ const toolbarButtonBaseStyles: React.CSSProperties = {
1818
alignItems: "center",
1919
justifyContent: "center",
2020
cursor: "pointer",
21+
border: "none",
22+
backgroundColor: "transparent",
23+
transition: "all 0.2s ease",
24+
};
25+
26+
const toolbarButtonActiveStyles: React.CSSProperties = {
27+
...toolbarButtonBaseStyles,
28+
color: "#1976d2",
29+
backgroundColor: "#e3f2fd",
2130
};
2231

2332
const CanvasIdContext = React.createContext<string | undefined>(undefined);
@@ -44,23 +53,35 @@ export const Toolbar3DButton = ({
4453
tooltip,
4554
onClick,
4655
style,
56+
active = false,
4757
}: {
4858
icon: React.ReactNode;
4959
tooltip: string;
5060
onClick: (fiber: RootState) => void;
5161
style?: React.CSSProperties;
62+
active?: boolean;
5263
}) => {
5364
const canvasId = useCanvasId();
5465
const fiber = useFiber(canvasId ?? "default");
5566

67+
const buttonStyle = active ? toolbarButtonActiveStyles : toolbarButtonBaseStyles;
68+
69+
const handleClick = () => {
70+
if (fiber) {
71+
onClick(fiber);
72+
} else {
73+
console.log("No fiber found - canvas might not be ready");
74+
}
75+
};
76+
5677
return (
57-
<div
58-
style={{ ...toolbarButtonBaseStyles, ...style }}
78+
<button
79+
style={{ ...buttonStyle, ...style }}
5980
title={tooltip}
60-
onClick={() => fiber && onClick(fiber)}
81+
onClick={handleClick}
6182
>
6283
{icon}
63-
</div>
84+
</button>
6485
);
6586
};
6687

examples/vite-3DCanvas-react-app/src/components/toolbar/groups/Backward3D.tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
import React from "react";
2-
import { Toolbar3DButton } from "../toolbar";
2+
import { Toolbar3DButton } from "../Toolbar3D";
3+
import { useCameraControls } from "../CameraControlsContext";
34

45
const Backward3D: React.FC = () => {
6+
const cameraControlsRef = useCameraControls();
7+
8+
const handleBackward = (fiber: any) => {
9+
if (cameraControlsRef?.current) {
10+
cameraControlsRef.current.dolly(0.5, true);
11+
} else if (fiber?.camera) {
12+
const camera = fiber.camera;
13+
const moveDistance = 1;
14+
camera.position.z += moveDistance;
15+
camera.updateMatrixWorld();
16+
}
17+
};
18+
519
return (
620
<Toolbar3DButton
721
icon={<i className="fas fa-arrow-down" />}
822
tooltip="Move Backward"
9-
onClick={() => console.log("Move backward clicked")}
23+
onClick={handleBackward}
1024
/>
1125
);
1226
};
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import React from "react";
2+
import { Toolbar3DButton } from "../Toolbar3D";
3+
import { useCameraControls } from "../CameraControlsContext";
4+
5+
const EnhancedZoom3DButtons: React.FC = () => {
6+
const cameraControlsRef = useCameraControls();
7+
8+
const handleZoomIn = (fiber: any) => {
9+
if (fiber?.camera) {
10+
const camera = fiber.camera;
11+
if (camera.isPerspectiveCamera) {
12+
camera.fov = Math.max(camera.fov - 5, 10);
13+
camera.updateProjectionMatrix();
14+
}
15+
}
16+
};
17+
18+
const handleZoomOut = (fiber: any) => {
19+
if (fiber?.camera) {
20+
const camera = fiber.camera;
21+
if (camera.isPerspectiveCamera) {
22+
camera.fov = Math.min(camera.fov + 5, 120);
23+
camera.updateProjectionMatrix();
24+
}
25+
}
26+
};
27+
28+
const handleDollyIn = (_fiber: any) => {
29+
if (cameraControlsRef?.current) {
30+
cameraControlsRef.current.dolly(-0.5, true);
31+
}
32+
};
33+
34+
const handleDollyOut = (_fiber: any) => {
35+
if (cameraControlsRef?.current) {
36+
cameraControlsRef.current.dolly(0.5, true);
37+
}
38+
};
39+
40+
return (
41+
<>
42+
<Toolbar3DButton
43+
icon={<i className="fas fa-search-plus" />}
44+
tooltip="Zoom In (FOV)"
45+
onClick={handleZoomIn}
46+
/>
47+
<Toolbar3DButton
48+
icon={<i className="fas fa-search-minus" />}
49+
tooltip="Zoom Out (FOV)"
50+
onClick={handleZoomOut}
51+
/>
52+
53+
<Toolbar3DButton
54+
icon={<i className="fas fa-plus" />}
55+
tooltip="Dolly In (Move Closer)"
56+
onClick={handleDollyIn}
57+
/>
58+
<Toolbar3DButton
59+
icon={<i className="fas fa-minus" />}
60+
tooltip="Dolly Out (Move Away)"
61+
onClick={handleDollyOut}
62+
/>
63+
</>
64+
);
65+
};
66+
67+
export default EnhancedZoom3DButtons;

examples/vite-3DCanvas-react-app/src/components/toolbar/groups/Forward3D.tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
import React from "react";
2-
import { Toolbar3DButton } from "../toolbar";
2+
import { Toolbar3DButton } from "../Toolbar3D";
3+
import { useCameraControls } from "../CameraControlsContext";
34

45
const Forward3D: React.FC = () => {
6+
const cameraControlsRef = useCameraControls();
7+
8+
const handleForward = (fiber: any) => {
9+
if (cameraControlsRef?.current) {
10+
cameraControlsRef.current.dolly(-0.5, true);
11+
} else if (fiber?.camera) {
12+
const camera = fiber.camera;
13+
const moveDistance = 1;
14+
camera.position.z -= moveDistance;
15+
camera.updateMatrixWorld();
16+
}
17+
};
18+
519
return (
620
<Toolbar3DButton
721
icon={<i className="fas fa-arrow-up" />}
822
tooltip="Move Forward"
9-
onClick={() => console.log("Move forward clicked")}
23+
onClick={handleForward}
1024
/>
1125
);
1226
};

examples/vite-3DCanvas-react-app/src/components/toolbar/groups/PanLeft3D.tsx

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,32 @@
11
import React from "react";
2-
import { Toolbar3DButton } from "../toolbar";
2+
import { Toolbar3DButton } from "../Toolbar3D";
3+
import { useCameraControls } from "../CameraControlsContext";
4+
import * as THREE from "three";
35

46
const PanLeft3D: React.FC = () => {
7+
const cameraControlsRef = useCameraControls();
8+
9+
const handlePanLeft = (fiber: any) => {
10+
if (cameraControlsRef?.current) {
11+
cameraControlsRef.current.truck(-0.5, 0, true);
12+
} else if (fiber?.camera) {
13+
const camera = fiber.camera;
14+
const right = new THREE.Vector3();
15+
camera.getWorldDirection(right);
16+
right.cross(camera.up).normalize();
17+
18+
const moveDistance = 1;
19+
camera.position.add(right.multiplyScalar(-moveDistance));
20+
} else {
21+
console.log("No camera controls or camera found!");
22+
}
23+
};
24+
525
return (
626
<Toolbar3DButton
727
icon={<i className="fas fa-arrow-left" />}
828
tooltip="Pan Left"
9-
onClick={() => console.log("Pan left clicked")}
29+
onClick={handlePanLeft}
1030
/>
1131
);
1232
};

examples/vite-3DCanvas-react-app/src/components/toolbar/groups/PanRight3D.tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
import React from "react";
2-
import { Toolbar3DButton } from "../toolbar";
2+
import { Toolbar3DButton } from "../Toolbar3D";
3+
import { useCameraControls } from "../CameraControlsContext";
34

45
const PanRight3D: React.FC = () => {
6+
const cameraControlsRef = useCameraControls();
7+
8+
const handlePanRight = (fiber: any) => {
9+
if (cameraControlsRef?.current) {
10+
cameraControlsRef.current.truck(0.5, 0, true);
11+
} else if (fiber?.camera) {
12+
const camera = fiber.camera;
13+
const moveDistance = 1;
14+
camera.position.x += moveDistance;
15+
camera.updateMatrixWorld();
16+
}
17+
};
18+
519
return (
620
<Toolbar3DButton
721
icon={<i className="fas fa-arrow-right" />}
822
tooltip="Pan Right"
9-
onClick={() => console.log("Pan right clicked")}
23+
onClick={handlePanRight}
1024
/>
1125
);
1226
};

0 commit comments

Comments
 (0)