@babylonjs/core
Version:
Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.
233 lines • 10 kB
JavaScript
import { IsDocumentAvailable } from "../Misc/domManagement.js";
import { AbstractEngine } from "./abstractEngine.js";
import { EngineStore } from "./engineStore.js";
/** @internal */
function DisableTouchAction(canvas) {
if (!canvas || !canvas.setAttribute) {
return;
}
canvas.setAttribute("touch-action", "none");
canvas.style.touchAction = "none";
canvas.style.webkitTapHighlightColor = "transparent";
}
/** @internal */
export function _CommonInit(commonEngine, canvas, creationOptions) {
commonEngine._onCanvasFocus = () => {
commonEngine.onCanvasFocusObservable.notifyObservers(commonEngine);
};
commonEngine._onCanvasBlur = () => {
commonEngine.onCanvasBlurObservable.notifyObservers(commonEngine);
};
commonEngine._onCanvasContextMenu = (evt) => {
if (commonEngine.disableContextMenu) {
evt.preventDefault();
}
};
canvas.addEventListener("focus", commonEngine._onCanvasFocus);
canvas.addEventListener("blur", commonEngine._onCanvasBlur);
canvas.addEventListener("contextmenu", commonEngine._onCanvasContextMenu);
commonEngine._onBlur = () => {
if (commonEngine.disablePerformanceMonitorInBackground) {
commonEngine.performanceMonitor.disable();
}
commonEngine._windowIsBackground = true;
};
commonEngine._onFocus = () => {
if (commonEngine.disablePerformanceMonitorInBackground) {
commonEngine.performanceMonitor.enable();
}
commonEngine._windowIsBackground = false;
};
commonEngine._onCanvasPointerOut = (ev) => {
// Check that the element at the point of the pointer out isn't the canvas and if it isn't, notify observers
// Note: This is a workaround for a bug with Safari
if (document.elementFromPoint(ev.clientX, ev.clientY) !== canvas) {
commonEngine.onCanvasPointerOutObservable.notifyObservers(ev);
}
};
const hostWindow = commonEngine.getHostWindow(); // it calls IsWindowObjectExist()
if (hostWindow && typeof hostWindow.addEventListener === "function") {
hostWindow.addEventListener("blur", commonEngine._onBlur);
hostWindow.addEventListener("focus", commonEngine._onFocus);
}
canvas.addEventListener("pointerout", commonEngine._onCanvasPointerOut);
if (!creationOptions.doNotHandleTouchAction) {
DisableTouchAction(canvas);
}
// Create Audio Engine if needed.
if (!AbstractEngine.audioEngine && creationOptions.audioEngine && AbstractEngine.AudioEngineFactory) {
AbstractEngine.audioEngine = AbstractEngine.AudioEngineFactory(commonEngine.getRenderingCanvas(), commonEngine.getAudioContext(), commonEngine.getAudioDestination());
}
if (IsDocumentAvailable()) {
// Fullscreen
commonEngine._onFullscreenChange = () => {
commonEngine.isFullscreen = !!document.fullscreenElement;
// Pointer lock
if (commonEngine.isFullscreen && commonEngine._pointerLockRequested && canvas) {
RequestPointerlock(canvas);
}
};
document.addEventListener("fullscreenchange", commonEngine._onFullscreenChange, false);
document.addEventListener("webkitfullscreenchange", commonEngine._onFullscreenChange, false);
// Pointer lock
commonEngine._onPointerLockChange = () => {
commonEngine.isPointerLock = document.pointerLockElement === canvas;
};
document.addEventListener("pointerlockchange", commonEngine._onPointerLockChange, false);
document.addEventListener("webkitpointerlockchange", commonEngine._onPointerLockChange, false);
}
commonEngine.enableOfflineSupport = AbstractEngine.OfflineProviderFactory !== undefined;
commonEngine._deterministicLockstep = !!creationOptions.deterministicLockstep;
commonEngine._lockstepMaxSteps = creationOptions.lockstepMaxSteps || 0;
commonEngine._timeStep = creationOptions.timeStep || 1 / 60;
}
/** @internal */
export function _CommonDispose(commonEngine, canvas) {
// Release audio engine
if (EngineStore.Instances.length === 1 && AbstractEngine.audioEngine) {
AbstractEngine.audioEngine.dispose();
AbstractEngine.audioEngine = null;
}
// Events
const hostWindow = commonEngine.getHostWindow(); // it calls IsWindowObjectExist()
if (hostWindow && typeof hostWindow.removeEventListener === "function") {
hostWindow.removeEventListener("blur", commonEngine._onBlur);
hostWindow.removeEventListener("focus", commonEngine._onFocus);
}
if (canvas) {
canvas.removeEventListener("focus", commonEngine._onCanvasFocus);
canvas.removeEventListener("blur", commonEngine._onCanvasBlur);
canvas.removeEventListener("pointerout", commonEngine._onCanvasPointerOut);
canvas.removeEventListener("contextmenu", commonEngine._onCanvasContextMenu);
}
if (IsDocumentAvailable()) {
document.removeEventListener("fullscreenchange", commonEngine._onFullscreenChange);
document.removeEventListener("mozfullscreenchange", commonEngine._onFullscreenChange);
document.removeEventListener("webkitfullscreenchange", commonEngine._onFullscreenChange);
document.removeEventListener("msfullscreenchange", commonEngine._onFullscreenChange);
document.removeEventListener("pointerlockchange", commonEngine._onPointerLockChange);
document.removeEventListener("mspointerlockchange", commonEngine._onPointerLockChange);
document.removeEventListener("mozpointerlockchange", commonEngine._onPointerLockChange);
document.removeEventListener("webkitpointerlockchange", commonEngine._onPointerLockChange);
}
}
/**
* Get Font size information
* @param font font name
* @returns an object containing ascent, height and descent
*/
export function GetFontOffset(font) {
const text = document.createElement("span");
text.textContent = "Hg";
text.style.font = font;
const block = document.createElement("div");
block.style.display = "inline-block";
block.style.width = "1px";
block.style.height = "0px";
block.style.verticalAlign = "bottom";
const div = document.createElement("div");
div.style.whiteSpace = "nowrap";
div.appendChild(text);
div.appendChild(block);
document.body.appendChild(div);
let fontAscent = 0;
let fontHeight = 0;
try {
fontHeight = block.getBoundingClientRect().top - text.getBoundingClientRect().top;
block.style.verticalAlign = "baseline";
fontAscent = block.getBoundingClientRect().top - text.getBoundingClientRect().top;
}
finally {
document.body.removeChild(div);
}
return { ascent: fontAscent, height: fontHeight, descent: fontHeight - fontAscent };
}
/** @internal */
export async function CreateImageBitmapFromSource(engine, imageSource, options) {
return await new Promise((resolve, reject) => {
const image = new Image();
image.onload = () => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then
image.decode().then(() => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then
engine.createImageBitmap(image, options).then((imageBitmap) => {
resolve(imageBitmap);
});
});
};
image.onerror = () => {
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
reject(`Error loading image ${image.src}`);
};
image.src = imageSource;
});
}
/** @internal */
export function ResizeImageBitmap(engine, image, bufferWidth, bufferHeight) {
const canvas = engine.createCanvas(bufferWidth, bufferHeight);
const context = canvas.getContext("2d");
if (!context) {
throw new Error("Unable to get 2d context for resizeImageBitmap");
}
context.drawImage(image, 0, 0);
// Create VertexData from map data
// Cast is due to wrong definition in lib.d.ts from ts 1.3 - https://github.com/Microsoft/TypeScript/issues/949
const buffer = context.getImageData(0, 0, bufferWidth, bufferHeight).data;
return buffer;
}
/**
* Ask the browser to promote the current element to fullscreen rendering mode
* @param element defines the DOM element to promote
*/
export function RequestFullscreen(element) {
const requestFunction = element.requestFullscreen || element.webkitRequestFullscreen;
if (!requestFunction) {
return;
}
requestFunction.call(element);
}
/**
* Asks the browser to exit fullscreen mode
*/
export function ExitFullscreen() {
const anyDoc = document;
if (document.exitFullscreen) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
document.exitFullscreen();
}
else if (anyDoc.webkitCancelFullScreen) {
anyDoc.webkitCancelFullScreen();
}
}
/**
* Ask the browser to promote the current element to pointerlock mode
* @param element defines the DOM element to promote
*/
export function RequestPointerlock(element) {
if (element.requestPointerLock) {
// In some browsers, requestPointerLock returns a promise.
// Handle possible rejections to avoid an unhandled top-level exception.
const promise = element.requestPointerLock();
if (promise instanceof Promise) {
promise
// eslint-disable-next-line github/no-then
.then(() => {
element.focus();
})
// eslint-disable-next-line github/no-then
.catch(() => { });
}
else {
element.focus();
}
}
}
/**
* Asks the browser to exit pointerlock mode
*/
export function ExitPointerlock() {
if (document.exitPointerLock) {
document.exitPointerLock();
}
}
//# sourceMappingURL=engine.common.js.map