mirror of
https://github.com/Heretek-AI/GDevelop.git
synced 2026-07-22 10:05:37 -04:00
153 lines
4.5 KiB
TypeScript
153 lines
4.5 KiB
TypeScript
namespace gdjs {
|
||
/**
|
||
* A minimal utility to define DOM elements.
|
||
* Also copied in InGameEditor.tsx.
|
||
*/
|
||
function h<K extends keyof HTMLElementTagNameMap>(
|
||
tag: K,
|
||
attrs: {
|
||
style?: Partial<CSSStyleDeclaration>;
|
||
onClick?: () => void;
|
||
},
|
||
...nodes: (HTMLElement | string)[]
|
||
): HTMLElement {
|
||
const node = document.createElement(tag);
|
||
Object.keys(attrs).forEach((key) => {
|
||
if (key === 'style') {
|
||
for (const [styleName, value] of Object.entries(attrs.style!)) {
|
||
node.style[styleName] = value;
|
||
}
|
||
} else if (key === 'onClick') {
|
||
node.addEventListener('click', attrs[key]!);
|
||
} else {
|
||
node.setAttribute(key, '' + attrs[key]);
|
||
}
|
||
});
|
||
|
||
node.append(...nodes);
|
||
return node;
|
||
}
|
||
|
||
const styles: {
|
||
errorContainer: Partial<CSSStyleDeclaration>;
|
||
errorTitle: Partial<CSSStyleDeclaration>;
|
||
errorMessage: Partial<CSSStyleDeclaration>;
|
||
stacktrace: Partial<CSSStyleDeclaration>;
|
||
closeButton: Partial<CSSStyleDeclaration>;
|
||
} = {
|
||
errorContainer: {
|
||
padding: '15px',
|
||
backgroundColor: '#a70000cc',
|
||
borderRadius: '8px',
|
||
position: 'absolute',
|
||
bottom: '5px',
|
||
left: '5px',
|
||
right: '5px',
|
||
color: 'white',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
pointerEvents: 'all',
|
||
},
|
||
errorTitle: {
|
||
fontFamily: 'system-ui',
|
||
fontSize: '20px',
|
||
marginTop: '5px',
|
||
marginBottom: '5px',
|
||
userSelect: 'all',
|
||
},
|
||
errorMessage: {
|
||
fontFamily: 'system-ui',
|
||
fontSize: '14px',
|
||
userSelect: 'all',
|
||
},
|
||
stacktrace: {
|
||
fontSize: '14px',
|
||
fontFamily: 'monospace',
|
||
whiteSpace: 'pre',
|
||
maxHeight: '510px',
|
||
overflow: 'auto',
|
||
userSelect: 'all',
|
||
},
|
||
closeButton: {
|
||
padding: '3px',
|
||
width: '20px',
|
||
fontSize: '18px',
|
||
position: 'absolute',
|
||
right: '5px',
|
||
top: '5px',
|
||
color: 'white',
|
||
border: '1px solid white',
|
||
borderRadius: '6px',
|
||
backgroundColor: 'transparent',
|
||
},
|
||
};
|
||
|
||
/**
|
||
* Displays uncaught exceptions on top of the game.
|
||
* Could be reworked in the future to support a minimal debugger inside the game.
|
||
*/
|
||
export class InGameDebugger {
|
||
_runtimeGame: RuntimeGame;
|
||
_uncaughtException: Error | null = null;
|
||
_uncaughtExceptionElement: HTMLElement | null = null;
|
||
|
||
constructor(runtimeGame: RuntimeGame) {
|
||
this._runtimeGame = runtimeGame;
|
||
}
|
||
|
||
setUncaughtException(exception: Error | null) {
|
||
// Only show the first uncaught exception and ignore anything else.
|
||
if (this._uncaughtException && !!exception) return;
|
||
|
||
this._uncaughtException = exception;
|
||
this.render();
|
||
}
|
||
|
||
render() {
|
||
const domElementContainer = this._runtimeGame
|
||
.getRenderer()
|
||
.getDomElementContainer();
|
||
if (!domElementContainer) return;
|
||
|
||
if (this._uncaughtExceptionElement) {
|
||
domElementContainer.removeChild(this._uncaughtExceptionElement);
|
||
this._uncaughtExceptionElement = null;
|
||
}
|
||
|
||
if (this._uncaughtException) {
|
||
const errorIsInJs =
|
||
gdjs.AbstractDebuggerClient.isErrorComingFromJavaScriptCode(
|
||
this._uncaughtException
|
||
);
|
||
this._uncaughtExceptionElement = (
|
||
<div style={styles.errorContainer}>
|
||
<button
|
||
style={styles.closeButton}
|
||
onClick={() => this.setUncaughtException(null)}
|
||
>
|
||
×
|
||
</button>
|
||
<h2 style={styles.errorTitle}>
|
||
{errorIsInJs
|
||
? 'An error happened in a JavaScript code event.'
|
||
: 'A crash or error happened in the game.'}
|
||
</h2>
|
||
<p style={styles.errorMessage}>
|
||
{(errorIsInJs
|
||
? 'This error comes from a JavaScript code event. Verify your code to ensure no error is happening. You can use the Developer Tools (menu "View" > "Toggle Developer Tools"). Full error is: '
|
||
: "If you're using JavaScript, verify your code. Otherwise, this might be an issue with GDevelop - consider reporting a bug. Full error is: ") +
|
||
this._uncaughtException.message}
|
||
</p>
|
||
<pre style={styles.stacktrace}>
|
||
{this._uncaughtException.stack || '(No stracktrace).'}
|
||
</pre>
|
||
</div>
|
||
);
|
||
|
||
if (this._uncaughtExceptionElement)
|
||
domElementContainer.appendChild(this._uncaughtExceptionElement);
|
||
}
|
||
}
|
||
}
|
||
}
|