Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/ui/hooks/useReplayController.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@ import useDebugging from './useDebugging.jsx';
import useInterval from './useInterval.jsx';

const useReplayController = (replay) => {
const [freeCamera, setFreeCamera] = useState({
relX: 0, relY: 0, width: 0, height: 0,
});
const [freeCamera, setFreeCamera] = useState({ relX: 0, relY: 0 });
const [cameraID, setCameraID] = useState(-1);
const [playing, setPlaying] = useState(false);
const [playbackSpeed, setPlaybackSpeed] = useState(1);
const [selectionID, setSelectionID] = useState(null);
const [zoom, setZoom] = useState(1);

const isFreeCamera = cameraID === -1;
const camera = isFreeCamera ? freeCamera : replay?.players.get(cameraID)?.camera;
Expand Down Expand Up @@ -72,6 +71,8 @@ const useReplayController = (replay) => {
setPlaybackSpeed,
setPlaying,
setSelection,
setZoom,
zoom,
};
};

Expand Down
6 changes: 6 additions & 0 deletions src/ui/replay/ReplayView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ const ReplayView = observer(({ replay }) => {
setPlaybackSpeed,
setPlaying,
setSelection,
setZoom,
zoom,
} = useReplayController(replay);

return (
Expand All @@ -39,11 +41,14 @@ const ReplayView = observer(({ replay }) => {
patch={replay.patch}
setFreeCamera={setFreeCamera}
units={replay.units}
zoom={zoom}
/>
<Options
cameraID={cameraID}
players={replay.players}
setCameraID={setCameraID}
setZoom={setZoom}
zoom={zoom}
/>
{selectedUnit && (
<Selection
Expand Down Expand Up @@ -77,6 +82,7 @@ const ReplayView = observer(({ replay }) => {
setFreeCamera={setFreeCamera}
setSelection={setSelection}
units={replay.units}
zoom={zoom}
/>
</StyledReplayView>
);
Expand Down
9 changes: 7 additions & 2 deletions src/ui/replay/hud/minimap/MiniMap.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import styled from 'styled-components';
import { observer } from 'mobx-react-lite';

import { Hero } from '../../../../lib/replay/entities/index.js';
import { useWindowDimensions } from '../../../hooks/index.js';

import Unit, { StyledUnit } from './Unit.jsx';

Expand Down Expand Up @@ -54,8 +55,10 @@ const StyledCamera = styled.div`
const MiniMap = observer((props) => {
const {
camera, isFreeCamera, patch, selectedUnit, setFreeCamera, units,
zoom,
} = props;
const { map } = patch;
const [viewport] = useWindowDimensions();

const [dragging, setDragging] = useState(false);

Expand Down Expand Up @@ -96,6 +99,8 @@ const MiniMap = observer((props) => {

// TODO: Minimap should preferably also show buildings, creep camps etc.
const heroes = units.filter((u) => u instanceof Hero);
const cameraWidth = viewport.width / (map.backdrop.size * zoom);
const cameraHeight = viewport.height / (map.backdrop.size * zoom);

return (
<StyledMiniMap
Expand All @@ -115,8 +120,8 @@ const MiniMap = observer((props) => {
style={{
left: `${camera.relX * 100}%`,
bottom: `${camera.relY * 100}%`,
width: `${camera.width * 100}%`,
height: `${camera.height * 100}%`,
width: `${cameraWidth * 100}%`,
height: `${cameraHeight * 100}%`,
}}
/>
{heroes.map((unit) => (
Expand Down
39 changes: 32 additions & 7 deletions src/ui/replay/hud/options/Options.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ const StyledOptions = styled.div`
text-align: center;
`;

const StyledControl = styled.label`
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
margin: 3px 0;
`;

const CameraOptionGroup = observer((props) => {
const { label, players } = props;
if (!players.length) {
Expand All @@ -31,7 +39,9 @@ const CameraOptionGroup = observer((props) => {
});

const Options = observer((props) => {
const { cameraID, players, setCameraID } = props;
const {
cameraID, players, setCameraID, setZoom, zoom,
} = props;

const radiant = players.filter((p) => p.teamID === TEAM_RADIANT);
const dire = players.filter((p) => p.teamID === TEAM_DIRE);
Expand All @@ -41,14 +51,29 @@ const Options = observer((props) => {
setCameraID(+e.target.value);
}, [setCameraID]);

const onZoomChange = useCallback((e) => {
setZoom(+e.target.value);
}, [setZoom]);

return (
<StyledOptions>
<Dropdown onChange={onCameraChange} value={cameraID}>
<option value={-1}>Free camera</option>
<CameraOptionGroup label="Radiant" players={radiant} />
<CameraOptionGroup label="Dire" players={dire} />
<CameraOptionGroup label="Broadcasters" players={broadcasters} />
</Dropdown>
<StyledControl>
Camera
<Dropdown aria-label="Camera" onChange={onCameraChange} value={cameraID}>
<option value={-1}>Free camera</option>
<CameraOptionGroup label="Radiant" players={radiant} />
<CameraOptionGroup label="Dire" players={dire} />
<CameraOptionGroup label="Broadcasters" players={broadcasters} />
</Dropdown>
</StyledControl>
<StyledControl>
Zoom
<Dropdown aria-label="Zoom" onChange={onZoomChange} value={zoom}>
<option value="1">1x</option>
<option value="0.75">1.5x</option>
<option value="0.5">2x</option>
</Dropdown>
</StyledControl>
</StyledOptions>
);
});
Expand Down
24 changes: 6 additions & 18 deletions src/ui/replay/world/World.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import React, {
useCallback, useEffect, useRef, useState,
} from 'react';
import React, { useCallback, useRef, useState } from 'react';
import styled from 'styled-components';
import { observer } from 'mobx-react-lite';

import { useWindowDimensions } from '../../hooks/index.js';

import Map from './Map.jsx';
import Unit from './Unit.jsx';

Expand All @@ -30,24 +26,13 @@ const StyledWorld = styled.div`
const World = observer((props) => {
const {
camera, isFreeCamera, patch, selectedUnit, setFreeCamera, setSelection, units,
zoom,
} = props;

const [dragging, setDragging] = useState(false);

const mapRef = useRef(null);

// Ensure free camera is updated when window dimensions change
const [viewport] = useWindowDimensions();
useEffect(() => {
const width = mapRef.current?.width;
const height = mapRef.current?.height;
setFreeCamera((current) => ({
...current,
width: width ? viewport.width / width : 0,
height: height ? viewport.height / height : 0,
}));
}, [setFreeCamera, viewport]);

const onDoubleClick = useCallback((e) => e.preventDefault(), []);

const onMouseDown = useCallback((e) => {
Expand Down Expand Up @@ -85,7 +70,10 @@ const World = observer((props) => {
<Map
patch={patch}
ref={mapRef}
style={{ transform: `translate(${-relX * 100}%, ${relY * 100}%)` }}
style={{
transformOrigin: '0 100%',
transform: `translate(${-relX * zoom * 100}%, ${relY * zoom * 100}%) scale(${zoom})`,
}}
>
{units.map((unit) => (
<Unit
Expand Down