import React from 'react';
import ReactDOM from 'react-dom';
import { BaseGame } from '../base_game';
import { Hierarchy } from './hierarchy';
import { DebugFlagButtons, DebugFlagsType } from './debug_flag_buttons';
import { IS_DEBUG } from '../environment';
import { Entity } from '../entity';
import { Container } from 'pixi.js';
import { TextEntity } from '../text_entity';
import { Debug } from '../debug';
type ReactWrapperProps = {
game: BaseGame<{}>;
debugFlags: DebugFlagsType;
};
type ReactWrapperState = {
selected: Entity | Container | null;
moused: Entity | Container | null;
};
export class GameReactWrapper extends React.Component<ReactWrapperProps, ReactWrapperState> {
mounted = false;
constructor(props: ReactWrapperProps) {
super(props);
this.state = {
selected: this.props.game.stage,
moused: null,
};
setInterval(() => this.monitorHierarchyUpdates(), 500);
}
componentDidMount() {
this.mounted = true;
}
componentWillUnmount() {
console.error("This should never happen!!!! very bad?!?");
}
monitorHierarchyUpdates = () => {
if (this.mounted) {
this.forceUpdate();
}
};
setSelected = (obj: Entity | Container) => {
this.setState({
selected: obj,
});
};
setMoused = (obj: Entity | Container | null) => {
this.setState({
moused: obj,
});
};
renderSelected = () => {
const target = this.state.moused || this.state.selected;
if (target === null) { return null; }
if (target instanceof Container) {
return (
<div style={{ fontWeight: 600, fontFamily: 'arial', paddingTop: '8px', paddingBottom: '8px', fontSize: '18px' }}>Stage</div>
);
}
let active = true;
if (target instanceof Entity) {
active = target.activeModes.includes(this.props.game.state.mode);
}
return (
<div>
<div style={{ fontWeight: 600, fontFamily: 'arial', paddingTop: '8px', paddingBottom: '8px', fontSize: '18px' }}>{target.name}</div>
<div>
x: {target.x}, y: {target.y}
</div>
<div>
{active ? "Active" : "Inactive"}
</div>
<div>
xAbs: {target.positionAbsolute().x}, yAbs: {target.positionAbsolute().y}
</div>
<div>
width: {target.width}, height: {target.height}
</div>
<div>
visible: {target.visible ? "true" : "false"}
</div>
<div>
scaleX: {target.scale.x.toFixed(2)} scaleY: {target.scale.y.toFixed(2)}
</div>
{
target instanceof TextEntity
? <div>text: {target.html}</div>
: <div></div>
}
</div>
);
};
renderHierarchy() {
return (<div>
<Hierarchy
selectedEntity={this.state.selected}
setMoused={this.setMoused}
setSelected={this.setSelected}
root={this.props.game.stage}
gameState={this.props.game.state}
/>
<Hierarchy
selectedEntity={this.state.selected}
setMoused={this.setMoused}
setSelected={this.setSelected}
root={this.props.game.fixedCameraStage}
gameState={this.props.game.state}
/>
</div>)
}
render() {
return (
<div style={{
display: "flex",
flexDirection: "row",
borderLeft: IS_DEBUG ? "1px solid lightgray" : 0,
marginLeft: '16px',
paddingLeft: '8px',
}}>
<div style={{
overflow: "auto",
height: "90vh",
fontFamily: 'arial',
fontSize: '14px',
}}>
{this.props.game && this.props.game.stage && IS_DEBUG &&
<div style={{ paddingLeft: '8px', }}>
<div style={{ fontFamily: "arial", marginBottom: '8px', fontSize: '14px', width: '300px', padding: '8px' }}>
Note: This debugging panel is only shown in development, or production with ?debug=true.
</div>
<div style={{ fontWeight: 600, fontFamily: 'arial', paddingBottom: '8px', fontSize: '18px' }}>Debug Options</div>
<DebugFlagButtons flags={this.props.debugFlags} />
<div>
Draw Count: {Debug.GetDrawCount()}
</div>
{this.renderSelected()}
<div style={{ fontWeight: 600, fontFamily: 'arial', paddingTop: '8px', paddingBottom: '8px', fontSize: '18px' }}>Debug Hierarchy</div>
{this.renderHierarchy()}
</div>
}
</div>
</div>
);
}
}
export const CreateGame = (game: BaseGame<any, any, any>, debugFlags: DebugFlagsType) => {
ReactDOM.render(
<React.StrictMode>
<GameReactWrapper
game={game}
debugFlags={debugFlags}
/>
</React.StrictMode>,
document.getElementById('root')
);
ReactDOM.render(
<React.StrictMode>
<Log />
</React.StrictMode>,
document.getElementById('log')
);
}
export const originalConsoleLog = console.log;
const allLogs: any[][] = [];
// console.log = (...data: any[]) => {
// allLogs.push(data);
// };
export const Log: React.FC<{}> = (props: {}) => {
const [logs, setLogs] = React.useState<any[][]>([]);
React.useEffect(() => {
const interval = setInterval(() => {
setLogs(allLogs.slice());
}, 400);
return () => clearInterval(interval);
}, []);
return (
<div>
{
logs.map(logItems => {
return (
<div>
{
logItems.map(log => <span>{JSON.stringify(log)}</span>)
}
</div>
);
})
}
</div>
)
}