Skip to content

Commit 6fc60f1

Browse files
committed
Camera save and restore; Camera Manager refactor
1 parent 3ccb8d8 commit 6fc60f1

File tree

6 files changed

+190
-113
lines changed

6 files changed

+190
-113
lines changed

TODO

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
- reactor model!
2-
- customize orbit controls
32
- sidebar tabs
43
- theming (alpha, save and load user themes)
54
- customize camera (user),
@@ -12,9 +11,7 @@
1211
- own Stats impl
1312

1413
- slice for ss res + form
15-
- portal for settings for cameras
1614
- getUpdatedCamera refactor? (Camera type, setting aspect ratio etc., useCallback)
17-
- saving camera and restoring
1815
- combined ss; ss dl using redux-observable
1916
- camera slice - fov?
2017
- threeviews - camera naming and constructors

package-lock.json

Lines changed: 37 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"stats.js": "^0.17.0",
3636
"styled-components": "^5.3.1",
3737
"three": "^0.132.2",
38+
"three-stdlib": "^2.5.4",
3839
"web-vitals": "^1.1.2"
3940
},
4041
"devDependencies": {

src/components/GenericView.tsx

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,38 @@
11
import { Canvas } from '@react-three/fiber';
2-
import { ComponentProps, ReactNode, useState } from 'react';
2+
import { ComponentProps, ReactNode, useRef, useState } from 'react';
33
import styled from 'styled-components';
4+
import { OrbitControls as OrbitControlsImpl } from 'three-stdlib';
5+
import { OrbitControls } from '@react-three/drei';
46
import { useAppSelector } from 'hooks/redux';
57
import { selectCurrentStyle } from 'features/styles/stylesSlice';
68
import TakeScreenshot from './three/TakeScreenshot';
7-
import CameraManager, { SupportedCameras } from './three/CameraManager';
9+
import CameraManager from './three/CameraManager';
810

911
const ViewStyles = styled.div<{ textColor: string }>`
1012
position: relative;
1113
min-width: 0;
1214
min-height: 0;
1315
14-
.label {
16+
.overlay {
1517
position: absolute;
16-
left: 50%;
17-
transform: translateX(-50%);
1818
color: ${props => props.textColor};
19+
opacity: 0.17;
1920
z-index: 100;
21+
22+
&:hover {
23+
opacity: 0.67;
24+
}
25+
}
26+
27+
.label {
28+
left: 50%;
29+
transform: translateX(-50%);
2030
}
2131
2232
.actions {
2333
display: flex;
2434
flex-direction: column;
25-
position: absolute;
2635
right: 0;
27-
opacity: 0.17;
28-
z-index: 100;
29-
30-
&:hover {
31-
opacity: 0.67;
32-
}
3336
}
3437
`;
3538

@@ -45,12 +48,12 @@ const onCreated: CanvasProp<'onCreated'> = state => {
4548

4649
interface Props {
4750
label: string;
48-
camera: SupportedCameras;
51+
controlsProps?: ComponentProps<typeof OrbitControls>;
4952
className?: string;
5053
children?: ReactNode;
5154
}
5255

53-
function GenericView({ label, camera, className, children }: Props): JSX.Element {
56+
function GenericView({ label, controlsProps, className, children }: Props): JSX.Element {
5457
const [screenshot, setScreenshot] = useState({
5558
requested: false,
5659
variant: '' as ComponentProps<typeof TakeScreenshot>['variant'],
@@ -60,28 +63,22 @@ function GenericView({ label, camera, className, children }: Props): JSX.Element
6063
const requestSVGScreenshot = () => setScreenshot({ requested: true, variant: 'svg' });
6164
const screenshotTaken = () => setScreenshot(prevState => ({ ...prevState, requested: false }));
6265

63-
const [cameraAction, setCameraAction] = useState({
64-
reset: false,
65-
});
66-
67-
const requestCameraReset = () => setCameraAction({ reset: true });
68-
const cameraReset = () => setCameraAction({ reset: false });
69-
7066
const style = useAppSelector(selectCurrentStyle);
7167

68+
const cameraControlsRef = useRef<HTMLDivElement | null>(null);
69+
const orbitControlsRef = useRef<OrbitControlsImpl | null>(null);
70+
7271
return (
7372
<ViewStyles className={className} textColor={style.overlayColor}>
74-
<span className="label">{label}</span>
75-
<div className="actions">
73+
<div className="overlay camera" ref={cameraControlsRef} />
74+
<span className="overlay label">{label}</span>
75+
<div className="overlay actions">
7676
<button type="button" onClick={requestPNGScreenshot}>
7777
Save as PNG
7878
</button>
7979
<button type="button" onClick={requestSVGScreenshot}>
8080
Save as SVG
8181
</button>
82-
<button type="button" onClick={requestCameraReset}>
83-
Reset camera
84-
</button>
8582
</div>
8683
<Canvas frameloop="demand" gl={rendererProps} onCreated={onCreated}>
8784
<color attach="background" args={[style.clearColor]} />
@@ -91,11 +88,14 @@ function GenericView({ label, camera, className, children }: Props): JSX.Element
9188
label={label}
9289
done={screenshotTaken}
9390
/>
94-
<CameraManager
95-
defaultCamera={camera}
96-
resetRequested={cameraAction.reset}
97-
resetDone={cameraReset}
98-
/>
91+
{cameraControlsRef.current && orbitControlsRef.current && (
92+
<CameraManager
93+
cameraControlsContainer={cameraControlsRef.current}
94+
orbitControls={orbitControlsRef.current}
95+
/>
96+
)}
97+
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
98+
<OrbitControls ref={orbitControlsRef} {...controlsProps} />
9999
{children}
100100
</Canvas>
101101
</ViewStyles>

src/components/ThreeViews.tsx

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import styled from 'styled-components';
2-
import { OrbitControls } from '@react-three/drei';
3-
import { OrthographicCamera, PerspectiveCamera, Vector3 } from 'three';
2+
import { Vector3 } from 'three';
3+
import { OrthographicCamera, PerspectiveCamera } from '@react-three/drei';
44
import { useAppSelector } from 'hooks/redux';
55
import { selectAliceData } from 'features/aliceData/aliceDataSlice';
66
import { selectCurrentStyle } from 'features/styles/stylesSlice';
@@ -39,35 +39,29 @@ function ThreeViews(): JSX.Element {
3939
<GenericView
4040
label="3D View"
4141
className="main-view"
42-
camera={(() => {
43-
const camera = new PerspectiveCamera(60, 1, 1, 5000);
44-
camera.position.set(1000, 1000, 1000);
45-
return camera;
46-
})()}
42+
controlsProps={{ dampingFactor: 0.1 }}
4743
>
48-
<OrbitControls />
44+
<PerspectiveCamera
45+
fov={60}
46+
near={1}
47+
far={5000}
48+
position={[1000, 1000, 1000]}
49+
makeDefault
50+
/>
4951
{scene}
5052
</GenericView>
5153
<GenericView
5254
label="R-Phi View"
53-
camera={(() => {
54-
const camera = new OrthographicCamera(0, 0, 0, 0, 1, 5000);
55-
camera.position.set(0, 0, 1000);
56-
return camera;
57-
})()}
55+
controlsProps={{ enableRotate: false, enableDamping: false }}
5856
>
59-
<OrbitControls enableRotate={false} enableDamping={false} />
57+
<OrthographicCamera near={1} far={5000} position={[0, 0, 1000]} makeDefault />
6058
{scene}
6159
</GenericView>
6260
<GenericView
6361
label="Rho-Z View"
64-
camera={(() => {
65-
const camera = new OrthographicCamera(0, 0, 0, 0, 1, 5000);
66-
camera.position.set(1000, 0, 0);
67-
return camera;
68-
})()}
62+
controlsProps={{ enableRotate: false, enableDamping: false }}
6963
>
70-
<OrbitControls enableRotate={false} enableDamping={false} />
64+
<OrthographicCamera near={1} far={5000} position={[1000, 0, 0]} makeDefault />
7165
{scene}
7266
</GenericView>
7367
</ThreeViewsStyles>

0 commit comments

Comments
 (0)