Skip to content

Commit

Permalink
Camera save and restore; Camera Manager refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
BlueAlien99 committed Oct 30, 2021
1 parent 3ccb8d8 commit 6fc60f1
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 113 deletions.
3 changes: 0 additions & 3 deletions TODO
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
- reactor model!
- customize orbit controls
- sidebar tabs
- theming (alpha, save and load user themes)
- customize camera (user),
Expand All @@ -12,9 +11,7 @@
- own Stats impl

- slice for ss res + form
- portal for settings for cameras
- getUpdatedCamera refactor? (Camera type, setting aspect ratio etc., useCallback)
- saving camera and restoring
- combined ss; ss dl using redux-observable
- camera slice - fov?
- threeviews - camera naming and constructors
61 changes: 37 additions & 24 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"stats.js": "^0.17.0",
"styled-components": "^5.3.1",
"three": "^0.132.2",
"three-stdlib": "^2.5.4",
"web-vitals": "^1.1.2"
},
"devDependencies": {
Expand Down
62 changes: 31 additions & 31 deletions src/components/GenericView.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,38 @@
import { Canvas } from '@react-three/fiber';
import { ComponentProps, ReactNode, useState } from 'react';
import { ComponentProps, ReactNode, useRef, useState } from 'react';
import styled from 'styled-components';
import { OrbitControls as OrbitControlsImpl } from 'three-stdlib';
import { OrbitControls } from '@react-three/drei';
import { useAppSelector } from 'hooks/redux';
import { selectCurrentStyle } from 'features/styles/stylesSlice';
import TakeScreenshot from './three/TakeScreenshot';
import CameraManager, { SupportedCameras } from './three/CameraManager';
import CameraManager from './three/CameraManager';

const ViewStyles = styled.div<{ textColor: string }>`
position: relative;
min-width: 0;
min-height: 0;
.label {
.overlay {
position: absolute;
left: 50%;
transform: translateX(-50%);
color: ${props => props.textColor};
opacity: 0.17;
z-index: 100;
&:hover {
opacity: 0.67;
}
}
.label {
left: 50%;
transform: translateX(-50%);
}
.actions {
display: flex;
flex-direction: column;
position: absolute;
right: 0;
opacity: 0.17;
z-index: 100;
&:hover {
opacity: 0.67;
}
}
`;

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

interface Props {
label: string;
camera: SupportedCameras;
controlsProps?: ComponentProps<typeof OrbitControls>;
className?: string;
children?: ReactNode;
}

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

const [cameraAction, setCameraAction] = useState({
reset: false,
});

const requestCameraReset = () => setCameraAction({ reset: true });
const cameraReset = () => setCameraAction({ reset: false });

const style = useAppSelector(selectCurrentStyle);

const cameraControlsRef = useRef<HTMLDivElement | null>(null);
const orbitControlsRef = useRef<OrbitControlsImpl | null>(null);

return (
<ViewStyles className={className} textColor={style.overlayColor}>
<span className="label">{label}</span>
<div className="actions">
<div className="overlay camera" ref={cameraControlsRef} />
<span className="overlay label">{label}</span>
<div className="overlay actions">
<button type="button" onClick={requestPNGScreenshot}>
Save as PNG
</button>
<button type="button" onClick={requestSVGScreenshot}>
Save as SVG
</button>
<button type="button" onClick={requestCameraReset}>
Reset camera
</button>
</div>
<Canvas frameloop="demand" gl={rendererProps} onCreated={onCreated}>
<color attach="background" args={[style.clearColor]} />
Expand All @@ -91,11 +88,14 @@ function GenericView({ label, camera, className, children }: Props): JSX.Element
label={label}
done={screenshotTaken}
/>
<CameraManager
defaultCamera={camera}
resetRequested={cameraAction.reset}
resetDone={cameraReset}
/>
{cameraControlsRef.current && orbitControlsRef.current && (
<CameraManager
cameraControlsContainer={cameraControlsRef.current}
orbitControls={orbitControlsRef.current}
/>
)}
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
<OrbitControls ref={orbitControlsRef} {...controlsProps} />
{children}
</Canvas>
</ViewStyles>
Expand Down
34 changes: 14 additions & 20 deletions src/components/ThreeViews.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import styled from 'styled-components';
import { OrbitControls } from '@react-three/drei';
import { OrthographicCamera, PerspectiveCamera, Vector3 } from 'three';
import { Vector3 } from 'three';
import { OrthographicCamera, PerspectiveCamera } from '@react-three/drei';
import { useAppSelector } from 'hooks/redux';
import { selectAliceData } from 'features/aliceData/aliceDataSlice';
import { selectCurrentStyle } from 'features/styles/stylesSlice';
Expand Down Expand Up @@ -39,35 +39,29 @@ function ThreeViews(): JSX.Element {
<GenericView
label="3D View"
className="main-view"
camera={(() => {
const camera = new PerspectiveCamera(60, 1, 1, 5000);
camera.position.set(1000, 1000, 1000);
return camera;
})()}
controlsProps={{ dampingFactor: 0.1 }}
>
<OrbitControls />
<PerspectiveCamera
fov={60}
near={1}
far={5000}
position={[1000, 1000, 1000]}
makeDefault
/>
{scene}
</GenericView>
<GenericView
label="R-Phi View"
camera={(() => {
const camera = new OrthographicCamera(0, 0, 0, 0, 1, 5000);
camera.position.set(0, 0, 1000);
return camera;
})()}
controlsProps={{ enableRotate: false, enableDamping: false }}
>
<OrbitControls enableRotate={false} enableDamping={false} />
<OrthographicCamera near={1} far={5000} position={[0, 0, 1000]} makeDefault />
{scene}
</GenericView>
<GenericView
label="Rho-Z View"
camera={(() => {
const camera = new OrthographicCamera(0, 0, 0, 0, 1, 5000);
camera.position.set(1000, 0, 0);
return camera;
})()}
controlsProps={{ enableRotate: false, enableDamping: false }}
>
<OrbitControls enableRotate={false} enableDamping={false} />
<OrthographicCamera near={1} far={5000} position={[1000, 0, 0]} makeDefault />
{scene}
</GenericView>
</ThreeViewsStyles>
Expand Down
Loading

0 comments on commit 6fc60f1

Please sign in to comment.