Skip to content

Commit 6f1de55

Browse files
authored
Merge pull request #37 from SaltieRL/pa-orthographic
Add all (five) orthographic camera views
2 parents e9cae8d + 8254e74 commit 6f1de55

File tree

6 files changed

+171
-32
lines changed

6 files changed

+171
-32
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "replay-viewer",
3-
"version": "0.3.0",
3+
"version": "0.3.3",
44
"description": "Rocket League replay viewer React component and tooling",
55
"main": "./lib/index.js",
66
"types": "./lib/index.d.ts",

src/builders/field/addCameras.ts

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { OrthographicCamera, PerspectiveCamera, Scene } from "three"
1+
import { OrthographicCamera, PerspectiveCamera, Scene, Vector3 } from "three"
22

33
import { DEFAULT_CAMERA_OPTIONS } from "../../constants/defaultCameraOptions"
44
import {
55
ABOVE_FIELD_CAMERA,
66
BLUE_GOAL_CAMERA,
77
ORANGE_GOAL_CAMERA,
8-
ORTHOGRAPHIC_CAMERA,
8+
ORTHOGRAPHIC,
99
} from "../../constants/gameObjectNames"
1010

1111
export const addCameras = (scene: Scene) => {
@@ -24,24 +24,50 @@ export const addCameras = (scene: Scene) => {
2424
aboveFieldCamera.position.set(0, 2000, 0)
2525
scene.add(aboveFieldCamera)
2626

27-
const orthographicCamera = new OrthographicCamera(
28-
-320,
29-
320,
30-
240,
31-
-240,
32-
0.1,
33-
20000
34-
)
35-
orthographicCamera.name = ORTHOGRAPHIC_CAMERA
36-
orthographicCamera.position.set(3500, 5000, 5000)
37-
orthographicCamera.lookAt(-500, 0, -500)
38-
orthographicCamera.zoom = 0.05
39-
scene.add(orthographicCamera)
27+
const generateOrthographicCamera = () => {
28+
const camera = new OrthographicCamera(-320, 320, 240, -240, 0.1, 20000)
29+
camera.zoom = 0.05
30+
scene.add(camera)
31+
return camera
32+
}
33+
34+
const ORTHOGRAPHIC_X = 3500
35+
const ORTHOGRAPHIC_Y = 5000
36+
const ORTHOGRAPHIC_Z = 5000
37+
38+
const orthographicCameras = [
39+
{
40+
name: ORTHOGRAPHIC.BLUE_LEFT,
41+
position: new Vector3(ORTHOGRAPHIC_X, ORTHOGRAPHIC_Y, -ORTHOGRAPHIC_Z),
42+
},
43+
{
44+
name: ORTHOGRAPHIC.BLUE_RIGHT,
45+
position: new Vector3(-ORTHOGRAPHIC_X, ORTHOGRAPHIC_Y, -ORTHOGRAPHIC_Z),
46+
},
47+
{
48+
name: ORTHOGRAPHIC.ORANGE_LEFT,
49+
position: new Vector3(-ORTHOGRAPHIC_X, ORTHOGRAPHIC_Y, ORTHOGRAPHIC_Z),
50+
},
51+
{
52+
name: ORTHOGRAPHIC.ORANGE_RIGHT,
53+
position: new Vector3(ORTHOGRAPHIC_X, ORTHOGRAPHIC_Y, ORTHOGRAPHIC_Z),
54+
},
55+
{
56+
name: ORTHOGRAPHIC.ABOVE_FIELD,
57+
position: new Vector3(0, 8000, 0),
58+
},
59+
].map(({ name, position }) => {
60+
const camera = generateOrthographicCamera()
61+
camera.name = name
62+
camera.position.set(position.x, position.y, position.z)
63+
camera.lookAt(0, 0, 0)
64+
return camera
65+
})
4066

4167
return [
4268
blueGoalCamera,
4369
orangeGoalCamera,
4470
aboveFieldCamera,
45-
orthographicCamera,
71+
...orthographicCameras,
4672
]
4773
}

src/constants/gameObjectNames.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,10 @@ export const GROUP_SUFFIX = "-group"
66
export const BLUE_GOAL_CAMERA = "Blue Goal Camera"
77
export const ORANGE_GOAL_CAMERA = "Orange Goal Camera"
88
export const ABOVE_FIELD_CAMERA = "Above Field Camera"
9-
export const ORTHOGRAPHIC_CAMERA = "Orthographic Camera"
9+
export const ORTHOGRAPHIC = {
10+
ABOVE_FIELD: "ORTHOGRAPHIC_ABOVE_FIELD",
11+
BLUE_LEFT: "ORTHOGRAPHIC_BLUE_LEFT",
12+
BLUE_RIGHT: "ORTHOGRAPHIC_BLUE_RIGHT",
13+
ORANGE_LEFT: "ORTHOGRAPHIC_ORANGE_LEFT",
14+
ORANGE_RIGHT: "ORTHOGRAPHIC_ORANGE_RIGHT",
15+
}

src/managers/CameraManager.ts

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,18 @@ import {
44
ABOVE_FIELD_CAMERA,
55
BLUE_GOAL_CAMERA,
66
ORANGE_GOAL_CAMERA,
7-
ORTHOGRAPHIC_CAMERA,
7+
ORTHOGRAPHIC,
88
} from "../constants/gameObjectNames"
99
import { dispatchCameraChange } from "../eventbus/events/cameraChange"
1010
import { dispatchCameraFrameUpdate } from "../eventbus/events/cameraFrameUpdate"
1111
import SceneManager from "./SceneManager"
1212

13+
const ORTHOGRAPHIC_CAMERA_NAMES: string[] = Object.keys(ORTHOGRAPHIC).map(
14+
(key: string) => {
15+
return (ORTHOGRAPHIC as any)[key] as string
16+
}
17+
)
18+
1319
class CameraManager {
1420
activeCamera: Camera
1521

@@ -42,7 +48,8 @@ class CameraManager {
4248
ballCam: true,
4349
isUsingBoost: false,
4450
})
45-
if (this.activeCamera.name !== ORTHOGRAPHIC_CAMERA) {
51+
52+
if (!ORTHOGRAPHIC_CAMERA_NAMES.includes(this.activeCamera.name)) {
4653
this.activeCamera.lookAt(position)
4754
}
4855
}
@@ -65,8 +72,22 @@ class CameraManager {
6572
case "center":
6673
this.setActiveCamera(field.getCamera(ABOVE_FIELD_CAMERA) as any)
6774
break
68-
case "orthographic":
69-
this.setActiveCamera(field.getCamera(ORTHOGRAPHIC_CAMERA) as any)
75+
case "orthographic-above-field":
76+
this.setActiveCamera(field.getCamera(ORTHOGRAPHIC.ABOVE_FIELD) as any)
77+
break
78+
case "orthographic-orange-left":
79+
this.setActiveCamera(field.getCamera(ORTHOGRAPHIC.ORANGE_LEFT) as any)
80+
break
81+
case "orthographic-orange-right":
82+
this.setActiveCamera(field.getCamera(
83+
ORTHOGRAPHIC.ORANGE_RIGHT
84+
) as any)
85+
break
86+
case "orthographic-blue-left":
87+
this.setActiveCamera(field.getCamera(ORTHOGRAPHIC.BLUE_LEFT) as any)
88+
break
89+
case "orthographic-blue-right":
90+
this.setActiveCamera(field.getCamera(ORTHOGRAPHIC.BLUE_RIGHT) as any)
7091
break
7192
default:
7293
this.setActiveCamera(this.defaultCamera)
@@ -117,7 +138,15 @@ class CameraManager {
117138

118139
export interface CameraLocationOptions {
119140
playerName?: string
120-
fieldLocation?: "orange" | "blue" | "center" | "orthographic"
141+
fieldLocation?:
142+
| "orange"
143+
| "blue"
144+
| "center"
145+
| "orthographic-blue-right"
146+
| "orthographic-blue-left"
147+
| "orthographic-orange-right"
148+
| "orthographic-orange-left"
149+
| "orthographic-above-field"
121150
}
122151

123152
export default CameraManager

src/viewer/components/FieldCameraControls.tsx

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
import Button from "@material-ui/core/Button"
2+
import Dialog from "@material-ui/core/Dialog"
3+
import List from "@material-ui/core/List"
4+
import ListItem from "@material-ui/core/ListItem"
5+
import Typography from "@material-ui/core/Typography"
26
import { styled } from "@material-ui/styles"
37
import React, { PureComponent } from "react"
48

@@ -10,25 +14,56 @@ const options: CameraLocationOptions["fieldLocation"][] = [
1014
"blue",
1115
"orange",
1216
"center",
13-
"orthographic",
1417
]
1518
const optionNames = {
1619
blue: "Blue Goal",
1720
orange: "Orange Goal",
1821
center: "Above Field",
19-
orthographic: "Orthographic",
22+
}
23+
const orthographicOptions: CameraLocationOptions["fieldLocation"][] = [
24+
"orthographic-above-field",
25+
"orthographic-blue-left",
26+
"orthographic-blue-right",
27+
"orthographic-orange-left",
28+
"orthographic-orange-right",
29+
]
30+
const orthographicOptionNames = {
31+
["orthographic-above-field"]: "Above Field",
32+
["orthographic-blue-left"]: "Blue Left",
33+
["orthographic-blue-right"]: "Blue Right",
34+
["orthographic-orange-left"]: "Orange Left",
35+
["orthographic-orange-right"]: "Orange Right",
2036
}
2137

2238
interface Props {}
2339

24-
class FieldCameraControls extends PureComponent<Props> {
40+
interface State {
41+
dialogOpen: boolean
42+
}
43+
44+
class FieldCameraControls extends PureComponent<Props, State> {
2545
constructor(props: Props) {
2646
super(props)
47+
this.state = {
48+
dialogOpen: false,
49+
}
50+
}
51+
52+
toggleDialog = () => {
53+
this.setState({
54+
dialogOpen: !this.state.dialogOpen,
55+
})
2756
}
2857

2958
onFieldClick = (fieldLocation: CameraLocationOptions["fieldLocation"]) => {
30-
return () =>
59+
return () => {
60+
if (this.state.dialogOpen) {
61+
this.setState({
62+
dialogOpen: false,
63+
})
64+
}
3165
CameraManager.getInstance().setCameraLocation({ fieldLocation })
66+
}
3267
}
3368

3469
renderFieldButtons() {
@@ -39,14 +74,48 @@ class FieldCameraControls extends PureComponent<Props> {
3974
variant="outlined"
4075
onClick={this.onFieldClick(option)}
4176
>
42-
{optionNames[option || "center"]}
77+
{(optionNames as any)[option || "center"]}
4378
</FieldButton>
4479
)
4580
})
4681
}
4782

83+
renderOrthographicOptions() {
84+
return (
85+
<Dialog open={this.state.dialogOpen} onClose={this.toggleDialog}>
86+
<List>
87+
{orthographicOptions.map(option => {
88+
return (
89+
<ListItem
90+
key={option}
91+
onClick={this.onFieldClick(option)}
92+
style={{ cursor: "pointer" }}
93+
>
94+
<Typography>
95+
{
96+
(orthographicOptionNames as any)[
97+
option || "orthographic-orange-right"
98+
]
99+
}
100+
</Typography>
101+
</ListItem>
102+
)
103+
})}
104+
</List>
105+
</Dialog>
106+
)
107+
}
108+
48109
render() {
49-
return <div>{this.renderFieldButtons()}</div>
110+
return (
111+
<div>
112+
{this.renderFieldButtons()}
113+
<FieldButton onClick={this.toggleDialog} variant="outlined">
114+
Orthographic
115+
</FieldButton>
116+
{this.renderOrthographicOptions()}
117+
</div>
118+
)
50119
}
51120
}
52121

src/viewer/components/ReplayViewer.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import FullscreenIcon from "@material-ui/icons/Fullscreen"
44
import FullscreenExitIcon from "@material-ui/icons/FullscreenExit"
55
import { styled } from "@material-ui/styles"
66
import React, { createRef, PureComponent, RefObject } from "react"
7-
import Fullscreen from "react-full-screen"
7+
import FullScreen from "react-full-screen"
88

99
import { GameManager } from "../../managers/GameManager"
1010
import Scoreboard from "./ScoreBoard"
@@ -66,7 +66,10 @@ class ReplayViewer extends PureComponent<Props, State> {
6666
const onClick = () => this.toggleFullscreen(!this.state.fullScreen)
6767
return (
6868
<ViewerContainer>
69-
<Fullscreen enabled={fullScreen} onChange={this.toggleFullscreen}>
69+
<FullscreenWrapper
70+
enabled={fullScreen}
71+
onChange={this.toggleFullscreen}
72+
>
7073
<Viewer>
7174
<div ref={this.mount} />
7275
</Viewer>
@@ -78,7 +81,7 @@ class ReplayViewer extends PureComponent<Props, State> {
7881
</Typography>
7982
</Button>
8083
</FullscreenToggle>
81-
</Fullscreen>
84+
</FullscreenWrapper>
8285
</ViewerContainer>
8386
)
8487
}
@@ -99,6 +102,12 @@ const Viewer = styled("div")({
99102
},
100103
})
101104

105+
const FullscreenWrapper = styled(FullScreen)({
106+
width: "100%",
107+
108+
height: "100%",
109+
})
110+
102111
const FullscreenToggle = styled("div")({
103112
position: "absolute",
104113
bottom: 0,

0 commit comments

Comments
 (0)