feat: debug UI
This commit is contained in:
parent
68eba007f9
commit
9460f5e9b9
|
@ -30,10 +30,20 @@
|
||||||
}
|
}
|
||||||
.app .avocado-stage {
|
.app .avocado-stage {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
outline: none;
|
||||||
|
transform: scale(1);
|
||||||
|
transform-origin: 0 0;
|
||||||
|
transition-property: transform;
|
||||||
|
transition-duration: 0.125s;
|
||||||
|
}
|
||||||
|
.debug .ui {
|
||||||
|
background-image: url(/debug.png);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="app"></div>
|
<div class="app">
|
||||||
|
<div class="debug-container"></div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {InputPacket, KeysPacket, StatePacket} from '../common/packet';
|
||||||
import {augmentParserWithThroughput} from '../common/parser-throughput';
|
import {augmentParserWithThroughput} from '../common/parser-throughput';
|
||||||
import {WorldTime} from '../common/world-time';
|
import {WorldTime} from '../common/world-time';
|
||||||
import Ui from './ui';
|
import Ui from './ui';
|
||||||
|
import DebugUi from './ui/debug';
|
||||||
// DOM.
|
// DOM.
|
||||||
const appNode = document.querySelector('.app');
|
const appNode = document.querySelector('.app');
|
||||||
// Lol Apple
|
// Lol Apple
|
||||||
|
@ -29,7 +30,6 @@ const visibleSize = [320, 180];
|
||||||
const visibleScale = [2, 2];
|
const visibleScale = [2, 2];
|
||||||
const stage = new Stage(Vector.mul(visibleSize, visibleScale));
|
const stage = new Stage(Vector.mul(visibleSize, visibleScale));
|
||||||
stage.scale = visibleScale;
|
stage.scale = visibleScale;
|
||||||
stage.addToDom(appNode);
|
|
||||||
// Handle "own" entity.
|
// Handle "own" entity.
|
||||||
let selfEntity;
|
let selfEntity;
|
||||||
function hasSelfEntity() {
|
function hasSelfEntity() {
|
||||||
|
@ -263,9 +263,18 @@ const renderHandle = setAnimation(render);
|
||||||
// UI.
|
// UI.
|
||||||
const UiComponent = <Ui
|
const UiComponent = <Ui
|
||||||
worldTime={worldTime}
|
worldTime={worldTime}
|
||||||
Parser={AugmentedParser}
|
|
||||||
/>;
|
/>;
|
||||||
ReactDOM.render(UiComponent, stage.ui);
|
ReactDOM.render(UiComponent, stage.ui);
|
||||||
|
// Debug UI.
|
||||||
|
const debugUiNode = document.querySelector('.debug-container');
|
||||||
|
const DebugUiComponent = <DebugUi
|
||||||
|
actionRegistry={actionRegistry}
|
||||||
|
Parser={AugmentedParser}
|
||||||
|
stage={stage}
|
||||||
|
/>;
|
||||||
|
ReactDOM.render(DebugUiComponent, debugUiNode);
|
||||||
|
// Inject the stage last.
|
||||||
|
stage.addToDom(appNode);
|
||||||
// Eval.
|
// Eval.
|
||||||
const evaluationContext = {
|
const evaluationContext = {
|
||||||
room,
|
room,
|
||||||
|
|
75
client/ui/debug/index.js
Normal file
75
client/ui/debug/index.js
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
// 3rd party.
|
||||||
|
import React, {useEffect, useState} from 'react';
|
||||||
|
import {hot} from 'react-hot-loader/root';
|
||||||
|
// 2nd party.
|
||||||
|
import {compose} from '@avocado/core';
|
||||||
|
import contempo from 'contempo';
|
||||||
|
// 3rd party.
|
||||||
|
import Throughput from './throughput';
|
||||||
|
|
||||||
|
const decorate = compose(
|
||||||
|
contempo(``),
|
||||||
|
hot,
|
||||||
|
);
|
||||||
|
|
||||||
|
const DebugUi = ({actionRegistry, stage, Parser}) => {
|
||||||
|
const [size, setSize] = useState([0, 0]);
|
||||||
|
const [position, setPosition] = useState([0, 0]);
|
||||||
|
const [transformRatio, setTransformRatio] = useState(1);
|
||||||
|
const [isDebugging, setIsDebugging] = useState(false);
|
||||||
|
// Sync debug UI size with stage size.
|
||||||
|
useEffect(() => {
|
||||||
|
const onStageResized = (size) => {
|
||||||
|
const rect = stage.element.getBoundingClientRect();
|
||||||
|
setPosition([rect.left, rect.top]);
|
||||||
|
setSize(size);
|
||||||
|
setTransformRatio(stage.transformRatio);
|
||||||
|
};
|
||||||
|
stage.on('displaySizeChanged', onStageResized);
|
||||||
|
onStageResized(stage.displaySize);
|
||||||
|
return () => {
|
||||||
|
stage.off('resized', onStageResized);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
// F2 toggle debug.
|
||||||
|
useEffect(() => {
|
||||||
|
const onKeyDown = (event) => {
|
||||||
|
event = event || window.event;
|
||||||
|
if ('F2' === event.key) {
|
||||||
|
setIsDebugging(!isDebugging);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.addEventListener('keydown', onKeyDown);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('keydown', onKeyDown);
|
||||||
|
};
|
||||||
|
}, [isDebugging]);
|
||||||
|
// Scale stage when debugging.
|
||||||
|
useEffect(() => {
|
||||||
|
stage.element.style.transform = `scale(${isDebugging ? '0.5' : '1'})`;
|
||||||
|
}, [isDebugging]);
|
||||||
|
return <div
|
||||||
|
className="debug"
|
||||||
|
style={{
|
||||||
|
left: position[0],
|
||||||
|
top: position[1],
|
||||||
|
width: size[0],
|
||||||
|
height: size[1],
|
||||||
|
position: 'absolute',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="ui"
|
||||||
|
style={{
|
||||||
|
transform: `scale(${1 / transformRatio})`,
|
||||||
|
transformOrigin: '0 0',
|
||||||
|
width: stage.size[0],
|
||||||
|
height: stage.size[1],
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Throughput Parser={Parser} />
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default decorate(DebugUi);
|
|
@ -5,21 +5,20 @@ import React, {useEffect, useState} from 'react';
|
||||||
import {compose} from '@avocado/core';
|
import {compose} from '@avocado/core';
|
||||||
import {Vector} from '@avocado/math';
|
import {Vector} from '@avocado/math';
|
||||||
import contempo from 'contempo';
|
import contempo from 'contempo';
|
||||||
// 1st party.
|
|
||||||
import {WorldTime} from '../../common/world-time';
|
|
||||||
|
|
||||||
const decorate = compose(
|
const decorate = compose(
|
||||||
contempo(`
|
contempo(`
|
||||||
.throughput {
|
.throughput {
|
||||||
background-color: rgba(0, 0, 0, .3);
|
background-color: rgba(0, 0, 0, .3);
|
||||||
|
border: 1px solid white;
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 0.6em;
|
font-size: 0.8em;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0.5em;
|
top: 0.5em;
|
||||||
left: 0.5em;
|
left: calc(320px + 0.5em);
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
width: 11em;
|
width: 11em;
|
||||||
padding: 0.5em;
|
padding: 0.125em;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
.throughput .kbps:before {
|
.throughput .kbps:before {
|
|
@ -2,13 +2,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {hot} from 'react-hot-loader/root';
|
import {hot} from 'react-hot-loader/root';
|
||||||
// 1st party.
|
// 1st party.
|
||||||
import Throughput from './throughput';
|
|
||||||
import WorldTime from './world-time';
|
import WorldTime from './world-time';
|
||||||
|
|
||||||
const Ui = ({Parser, worldTime}) => {
|
const Ui = ({worldTime}) => {
|
||||||
return <React.Fragment>
|
return <React.Fragment>
|
||||||
<WorldTime worldTime={worldTime} />
|
<WorldTime worldTime={worldTime} />
|
||||||
<Throughput Parser={Parser} />
|
|
||||||
</React.Fragment>;
|
</React.Fragment>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
BIN
resource/debug.png
Normal file
BIN
resource/debug.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 89 KiB |
Loading…
Reference in New Issue
Block a user