@babylonjs/addons 7.33.0 → 7.34.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/htmlMesh/fitStrategy.d.ts +10 -0
- package/htmlMesh/fitStrategy.js +84 -0
- package/htmlMesh/fitStrategy.js.map +1 -0
- package/htmlMesh/htmlMesh.d.ts +114 -0
- package/htmlMesh/htmlMesh.js +301 -0
- package/htmlMesh/htmlMesh.js.map +1 -0
- package/htmlMesh/htmlMeshRenderer.d.ts +72 -0
- package/htmlMesh/htmlMeshRenderer.js +464 -0
- package/htmlMesh/htmlMeshRenderer.js.map +1 -0
- package/htmlMesh/index.d.ts +5 -0
- package/htmlMesh/index.js +7 -0
- package/htmlMesh/index.js.map +1 -0
- package/htmlMesh/pointerEventsCapture.d.ts +37 -0
- package/htmlMesh/pointerEventsCapture.js +152 -0
- package/htmlMesh/pointerEventsCapture.js.map +1 -0
- package/htmlMesh/pointerEventsCaptureBehavior.d.ts +47 -0
- package/htmlMesh/pointerEventsCaptureBehavior.js +191 -0
- package/htmlMesh/pointerEventsCaptureBehavior.js.map +1 -0
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type FitStrategyType = {
|
|
2
|
+
wrapElement(element: HTMLElement): HTMLElement;
|
|
3
|
+
updateSize(sizingElement: HTMLElement, width: number, height: number): void;
|
|
4
|
+
};
|
|
5
|
+
export declare const FitStrategy: {
|
|
6
|
+
CONTAIN: FitStrategyType;
|
|
7
|
+
COVER: FitStrategyType;
|
|
8
|
+
STRETCH: FitStrategyType;
|
|
9
|
+
NONE: FitStrategyType;
|
|
10
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
const FitStrategyContain = {
|
|
2
|
+
wrapElement(element) {
|
|
3
|
+
const sizingElement = document.createElement("div");
|
|
4
|
+
sizingElement.style.display = "flex";
|
|
5
|
+
sizingElement.style.justifyContent = "center";
|
|
6
|
+
sizingElement.style.alignItems = "center";
|
|
7
|
+
const scalingElement = document.createElement("div");
|
|
8
|
+
scalingElement.style.visibility = "hidden";
|
|
9
|
+
scalingElement.appendChild(element);
|
|
10
|
+
sizingElement.appendChild(scalingElement);
|
|
11
|
+
return sizingElement;
|
|
12
|
+
},
|
|
13
|
+
updateSize(sizingElement, width, height) {
|
|
14
|
+
const scalingElement = sizingElement.firstElementChild;
|
|
15
|
+
sizingElement.style.width = `${width}px`;
|
|
16
|
+
sizingElement.style.height = `${height}px`;
|
|
17
|
+
const [childWidth, childHeight] = [scalingElement.offsetWidth, scalingElement.offsetHeight];
|
|
18
|
+
const scale = Math.min(width / childWidth, height / childHeight);
|
|
19
|
+
scalingElement.style.transform = `scale(${scale})`;
|
|
20
|
+
scalingElement.style.visibility = "visible";
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
const FitStrategyCover = {
|
|
24
|
+
wrapElement(element) {
|
|
25
|
+
const sizingElement = document.createElement("div");
|
|
26
|
+
sizingElement.style.display = "flex";
|
|
27
|
+
sizingElement.style.justifyContent = "center";
|
|
28
|
+
sizingElement.style.alignItems = "center";
|
|
29
|
+
sizingElement.style.overflow = "hidden";
|
|
30
|
+
const scalingElement = document.createElement("div");
|
|
31
|
+
scalingElement.style.visibility = "hidden";
|
|
32
|
+
scalingElement.appendChild(element);
|
|
33
|
+
sizingElement.appendChild(scalingElement);
|
|
34
|
+
return sizingElement;
|
|
35
|
+
},
|
|
36
|
+
updateSize(sizingElement, width, height) {
|
|
37
|
+
const scalingElement = sizingElement.firstElementChild;
|
|
38
|
+
sizingElement.style.width = `${width}px`;
|
|
39
|
+
sizingElement.style.height = `${height}px`;
|
|
40
|
+
const [childWidth, childHeight] = [scalingElement.offsetWidth, scalingElement.offsetHeight];
|
|
41
|
+
const scale = Math.max(width / childWidth, height / childHeight);
|
|
42
|
+
scalingElement.style.transform = `scale(${scale})`;
|
|
43
|
+
scalingElement.style.visibility = "visible";
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
const FitStrategyStretch = {
|
|
47
|
+
wrapElement(element) {
|
|
48
|
+
const sizingElement = document.createElement("div");
|
|
49
|
+
sizingElement.style.display = "flex";
|
|
50
|
+
sizingElement.style.justifyContent = "center";
|
|
51
|
+
sizingElement.style.alignItems = "center";
|
|
52
|
+
const scalingElement = document.createElement("div");
|
|
53
|
+
scalingElement.style.visibility = "hidden";
|
|
54
|
+
scalingElement.appendChild(element);
|
|
55
|
+
sizingElement.appendChild(scalingElement);
|
|
56
|
+
return sizingElement;
|
|
57
|
+
},
|
|
58
|
+
updateSize(sizingElement, width, height) {
|
|
59
|
+
const scalingElement = sizingElement.firstElementChild;
|
|
60
|
+
sizingElement.style.width = `${width}px`;
|
|
61
|
+
sizingElement.style.height = `${height}px`;
|
|
62
|
+
const [childWidth, childHeight] = [scalingElement.offsetWidth, scalingElement.offsetHeight];
|
|
63
|
+
scalingElement.style.transform = `scale(${width / childWidth}, ${height / childHeight})`;
|
|
64
|
+
scalingElement.style.visibility = "visible";
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
const FitStrategyNone = {
|
|
68
|
+
wrapElement(element) {
|
|
69
|
+
return element;
|
|
70
|
+
},
|
|
71
|
+
updateSize(sizingElement, width, height) {
|
|
72
|
+
if (sizingElement) {
|
|
73
|
+
sizingElement.style.width = `${width}px`;
|
|
74
|
+
sizingElement.style.height = `${height}px`;
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
export const FitStrategy = {
|
|
79
|
+
CONTAIN: FitStrategyContain,
|
|
80
|
+
COVER: FitStrategyCover,
|
|
81
|
+
STRETCH: FitStrategyStretch,
|
|
82
|
+
NONE: FitStrategyNone,
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=fitStrategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fitStrategy.js","sourceRoot":"","sources":["../../../../dev/addons/src/htmlMesh/fitStrategy.ts"],"names":[],"mappings":"AAKA,MAAM,kBAAkB,GAAoB;IACxC,WAAW,CAAC,OAAoB;QAC5B,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACpD,aAAa,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;QACrC,aAAa,CAAC,KAAK,CAAC,cAAc,GAAG,QAAQ,CAAC;QAC9C,aAAa,CAAC,KAAK,CAAC,UAAU,GAAG,QAAQ,CAAC;QAC1C,MAAM,cAAc,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACrD,cAAc,CAAC,KAAK,CAAC,UAAU,GAAG,QAAQ,CAAC;QAC3C,cAAc,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QACpC,aAAa,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;QAC1C,OAAO,aAAa,CAAC;IACzB,CAAC;IACD,UAAU,CAAC,aAA0B,EAAE,KAAa,EAAE,MAAc;QAChE,MAAM,cAAc,GAAG,aAAa,CAAC,iBAAiC,CAAC;QACvE,aAAa,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,KAAK,IAAI,CAAC;QACzC,aAAa,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC;QAE3C,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,GAAG,CAAC,cAAe,CAAC,WAAW,EAAE,cAAe,CAAC,YAAY,CAAC,CAAC;QAC9F,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,UAAU,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC;QACjE,cAAc,CAAC,KAAK,CAAC,SAAS,GAAG,SAAS,KAAK,GAAG,CAAC;QACnD,cAAc,CAAC,KAAK,CAAC,UAAU,GAAG,SAAS,CAAC;IAChD,CAAC;CACJ,CAAC;AAEF,MAAM,gBAAgB,GAAoB;IACtC,WAAW,CAAC,OAAoB;QAC5B,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACpD,aAAa,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;QACrC,aAAa,CAAC,KAAK,CAAC,cAAc,GAAG,QAAQ,CAAC;QAC9C,aAAa,CAAC,KAAK,CAAC,UAAU,GAAG,QAAQ,CAAC;QAC1C,aAAa,CAAC,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACxC,MAAM,cAAc,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACrD,cAAc,CAAC,KAAK,CAAC,UAAU,GAAG,QAAQ,CAAC;QAC3C,cAAc,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QACpC,aAAa,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;QAC1C,OAAO,aAAa,CAAC;IACzB,CAAC;IACD,UAAU,CAAC,aAA0B,EAAE,KAAa,EAAE,MAAc;QAChE,MAAM,cAAc,GAAG,aAAa,CAAC,iBAAiC,CAAC;QACvE,aAAa,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,KAAK,IAAI,CAAC;QACzC,aAAa,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC;QAE3C,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,GAAG,CAAC,cAAe,CAAC,WAAW,EAAE,cAAe,CAAC,YAAY,CAAC,CAAC;QAC9F,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,UAAU,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC;QACjE,cAAc,CAAC,KAAK,CAAC,SAAS,GAAG,SAAS,KAAK,GAAG,CAAC;QACnD,cAAc,CAAC,KAAK,CAAC,UAAU,GAAG,SAAS,CAAC;IAChD,CAAC;CACJ,CAAC;AAEF,MAAM,kBAAkB,GAAoB;IACxC,WAAW,CAAC,OAAoB;QAC5B,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACpD,aAAa,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;QACrC,aAAa,CAAC,KAAK,CAAC,cAAc,GAAG,QAAQ,CAAC;QAC9C,aAAa,CAAC,KAAK,CAAC,UAAU,GAAG,QAAQ,CAAC;QAC1C,MAAM,cAAc,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACrD,cAAc,CAAC,KAAK,CAAC,UAAU,GAAG,QAAQ,CAAC;QAC3C,cAAc,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QACpC,aAAa,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;QAC1C,OAAO,aAAa,CAAC;IACzB,CAAC;IACD,UAAU,CAAC,aAA0B,EAAE,KAAa,EAAE,MAAc;QAChE,MAAM,cAAc,GAAG,aAAa,CAAC,iBAAiC,CAAC;QACvE,aAAa,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,KAAK,IAAI,CAAC;QACzC,aAAa,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC;QAE3C,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,GAAG,CAAC,cAAe,CAAC,WAAW,EAAE,cAAe,CAAC,YAAY,CAAC,CAAC;QAC9F,cAAc,CAAC,KAAK,CAAC,SAAS,GAAG,SAAS,KAAK,GAAG,UAAU,KAAK,MAAM,GAAG,WAAW,GAAG,CAAC;QACzF,cAAc,CAAC,KAAK,CAAC,UAAU,GAAG,SAAS,CAAC;IAChD,CAAC;CACJ,CAAC;AAEF,MAAM,eAAe,GAAoB;IACrC,WAAW,CAAC,OAAoB;QAC5B,OAAO,OAAO,CAAC;IACnB,CAAC;IACD,UAAU,CAAC,aAA0B,EAAE,KAAa,EAAE,MAAc;QAChE,IAAI,aAAa,EAAE;YACf,aAAa,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,KAAK,IAAI,CAAC;YACzC,aAAa,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC;SAC9C;IACL,CAAC;CACJ,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG;IACvB,OAAO,EAAE,kBAAkB;IAC3B,KAAK,EAAE,gBAAgB;IACvB,OAAO,EAAE,kBAAkB;IAC3B,IAAI,EAAE,eAAe;CACxB,CAAC","sourcesContent":["export type FitStrategyType = {\r\n wrapElement(element: HTMLElement): HTMLElement;\r\n updateSize(sizingElement: HTMLElement, width: number, height: number): void;\r\n};\r\n\r\nconst FitStrategyContain: FitStrategyType = {\r\n wrapElement(element: HTMLElement): HTMLElement {\r\n const sizingElement = document.createElement(\"div\");\r\n sizingElement.style.display = \"flex\";\r\n sizingElement.style.justifyContent = \"center\";\r\n sizingElement.style.alignItems = \"center\";\r\n const scalingElement = document.createElement(\"div\");\r\n scalingElement.style.visibility = \"hidden\";\r\n scalingElement.appendChild(element);\r\n sizingElement.appendChild(scalingElement);\r\n return sizingElement;\r\n },\r\n updateSize(sizingElement: HTMLElement, width: number, height: number) {\r\n const scalingElement = sizingElement.firstElementChild! as HTMLElement;\r\n sizingElement.style.width = `${width}px`;\r\n sizingElement.style.height = `${height}px`;\r\n\r\n const [childWidth, childHeight] = [scalingElement!.offsetWidth, scalingElement!.offsetHeight];\r\n const scale = Math.min(width / childWidth, height / childHeight);\r\n scalingElement.style.transform = `scale(${scale})`;\r\n scalingElement.style.visibility = \"visible\";\r\n },\r\n};\r\n\r\nconst FitStrategyCover: FitStrategyType = {\r\n wrapElement(element: HTMLElement): HTMLElement {\r\n const sizingElement = document.createElement(\"div\");\r\n sizingElement.style.display = \"flex\";\r\n sizingElement.style.justifyContent = \"center\";\r\n sizingElement.style.alignItems = \"center\";\r\n sizingElement.style.overflow = \"hidden\";\r\n const scalingElement = document.createElement(\"div\");\r\n scalingElement.style.visibility = \"hidden\";\r\n scalingElement.appendChild(element);\r\n sizingElement.appendChild(scalingElement);\r\n return sizingElement;\r\n },\r\n updateSize(sizingElement: HTMLElement, width: number, height: number) {\r\n const scalingElement = sizingElement.firstElementChild! as HTMLElement;\r\n sizingElement.style.width = `${width}px`;\r\n sizingElement.style.height = `${height}px`;\r\n\r\n const [childWidth, childHeight] = [scalingElement!.offsetWidth, scalingElement!.offsetHeight];\r\n const scale = Math.max(width / childWidth, height / childHeight);\r\n scalingElement.style.transform = `scale(${scale})`;\r\n scalingElement.style.visibility = \"visible\";\r\n },\r\n};\r\n\r\nconst FitStrategyStretch: FitStrategyType = {\r\n wrapElement(element: HTMLElement): HTMLElement {\r\n const sizingElement = document.createElement(\"div\");\r\n sizingElement.style.display = \"flex\";\r\n sizingElement.style.justifyContent = \"center\";\r\n sizingElement.style.alignItems = \"center\";\r\n const scalingElement = document.createElement(\"div\");\r\n scalingElement.style.visibility = \"hidden\";\r\n scalingElement.appendChild(element);\r\n sizingElement.appendChild(scalingElement);\r\n return sizingElement;\r\n },\r\n updateSize(sizingElement: HTMLElement, width: number, height: number) {\r\n const scalingElement = sizingElement.firstElementChild! as HTMLElement;\r\n sizingElement.style.width = `${width}px`;\r\n sizingElement.style.height = `${height}px`;\r\n\r\n const [childWidth, childHeight] = [scalingElement!.offsetWidth, scalingElement!.offsetHeight];\r\n scalingElement.style.transform = `scale(${width / childWidth}, ${height / childHeight})`;\r\n scalingElement.style.visibility = \"visible\";\r\n },\r\n};\r\n\r\nconst FitStrategyNone: FitStrategyType = {\r\n wrapElement(element: HTMLElement): HTMLElement {\r\n return element;\r\n },\r\n updateSize(sizingElement: HTMLElement, width: number, height: number) {\r\n if (sizingElement) {\r\n sizingElement.style.width = `${width}px`;\r\n sizingElement.style.height = `${height}px`;\r\n }\r\n },\r\n};\r\n\r\nexport const FitStrategy = {\r\n CONTAIN: FitStrategyContain,\r\n COVER: FitStrategyCover,\r\n STRETCH: FitStrategyStretch,\r\n NONE: FitStrategyNone,\r\n};\r\n"]}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { Mesh } from "@babylonjs/core/Meshes/mesh.js";
|
|
2
|
+
import type { Scene } from "@babylonjs/core/scene.js";
|
|
3
|
+
import type { FitStrategyType } from "./fitStrategy";
|
|
4
|
+
/**
|
|
5
|
+
* This class represents HTML content that we want to render as though it is part of the scene. The HTML content is actually
|
|
6
|
+
* rendered below the canvas, but a depth mask is created by this class that writes to the depth buffer but does not
|
|
7
|
+
* write to the color buffer, effectively punching a hole in the canvas. CSS transforms are used to scale, translate, and rotate
|
|
8
|
+
* the HTML content so that it matches the camera and mesh orientation. The class supports interactions in editable and non-editable mode.
|
|
9
|
+
* In non-editable mode (the default), events are passed to the HTML content when the pointer is over the mask (and not occluded by other meshes
|
|
10
|
+
* in the scene).
|
|
11
|
+
* #HVHYJC#5
|
|
12
|
+
* #B17TC7#112
|
|
13
|
+
*/
|
|
14
|
+
export declare class HtmlMesh extends Mesh {
|
|
15
|
+
/**
|
|
16
|
+
* Helps identifying a html mesh from a regular mesh
|
|
17
|
+
*/
|
|
18
|
+
get isHtmlMesh(): boolean;
|
|
19
|
+
private _enabled;
|
|
20
|
+
private _ready;
|
|
21
|
+
/**
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
_isCanvasOverlay: boolean;
|
|
25
|
+
private _requiresUpdate;
|
|
26
|
+
private _element?;
|
|
27
|
+
private _width?;
|
|
28
|
+
private _height?;
|
|
29
|
+
private _inverseScaleMatrix;
|
|
30
|
+
private _captureOnPointerEnter;
|
|
31
|
+
private _pointerEventCaptureBehavior;
|
|
32
|
+
private _sourceWidth;
|
|
33
|
+
private _sourceHeight;
|
|
34
|
+
/**
|
|
35
|
+
* Return the source width of the content in pixels
|
|
36
|
+
*/
|
|
37
|
+
get sourceWidth(): number | null;
|
|
38
|
+
/**
|
|
39
|
+
* Return the source height of the content in pixels
|
|
40
|
+
*/
|
|
41
|
+
get sourceHeight(): number | null;
|
|
42
|
+
private _worldMatrixUpdateObserver;
|
|
43
|
+
private _fitStrategy;
|
|
44
|
+
/**
|
|
45
|
+
* Contruct an instance of HtmlMesh
|
|
46
|
+
* @param scene
|
|
47
|
+
* @param id The id of the mesh. Will be used as the id of the HTML element as well.
|
|
48
|
+
* @param options object with optional parameters
|
|
49
|
+
*/
|
|
50
|
+
constructor(scene: Scene, id: string, { captureOnPointerEnter, isCanvasOverlay, fitStrategy }?: {
|
|
51
|
+
captureOnPointerEnter?: boolean | undefined;
|
|
52
|
+
isCanvasOverlay?: boolean | undefined;
|
|
53
|
+
fitStrategy?: FitStrategyType | undefined;
|
|
54
|
+
});
|
|
55
|
+
/**
|
|
56
|
+
* The width of the content in pixels
|
|
57
|
+
*/
|
|
58
|
+
get width(): number | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* The height of the content in pixels
|
|
61
|
+
*/
|
|
62
|
+
get height(): number | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* The HTML element that is being rendered as a mesh
|
|
65
|
+
*/
|
|
66
|
+
get element(): HTMLElement | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* True if the mesh has been moved, rotated, or scaled since the last time this
|
|
69
|
+
* property was read. This property is reset to false after reading.
|
|
70
|
+
*/
|
|
71
|
+
get requiresUpdate(): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Enable capture for the pointer when entering the mesh area
|
|
74
|
+
*/
|
|
75
|
+
set captureOnPointerEnter(captureOnPointerEnter: boolean);
|
|
76
|
+
/**
|
|
77
|
+
* Disposes of the mesh and the HTML element
|
|
78
|
+
*/
|
|
79
|
+
dispose(): void;
|
|
80
|
+
/**
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
83
|
+
_markAsUpdated(): void;
|
|
84
|
+
/**
|
|
85
|
+
* Sets the content of the element to the specified content adjusting the mesh scale to match and making it visible.
|
|
86
|
+
* If the the specified content is undefined, then it will make the mesh invisible. In either case it will clear the
|
|
87
|
+
* element content first.
|
|
88
|
+
* @param element The element to render as a mesh
|
|
89
|
+
* @param width The width of the mesh in Babylon units
|
|
90
|
+
* @param height The height of the mesh in Babylon units
|
|
91
|
+
*/
|
|
92
|
+
setContent(element: HTMLElement, width: number, height: number): void;
|
|
93
|
+
setEnabled(enabled: boolean): void;
|
|
94
|
+
/**
|
|
95
|
+
* Sets the content size in pixels
|
|
96
|
+
* @param width width of the source
|
|
97
|
+
* @param height height of the source
|
|
98
|
+
*/
|
|
99
|
+
setContentSizePx(width: number, height: number): void;
|
|
100
|
+
protected _setAsReady(ready: boolean): void;
|
|
101
|
+
protected _doSetEnabled(enabled: boolean): void;
|
|
102
|
+
protected _updateScaleIfNecessary(): void;
|
|
103
|
+
protected _createMask(): void;
|
|
104
|
+
protected _setElementZIndex(zIndex: number): void;
|
|
105
|
+
/**
|
|
106
|
+
* Callback used by the PointerEventsCaptureBehavior to capture pointer events
|
|
107
|
+
*/
|
|
108
|
+
capturePointerEvents(): void;
|
|
109
|
+
/**
|
|
110
|
+
* Callback used by the PointerEventsCaptureBehavior to release pointer events
|
|
111
|
+
*/
|
|
112
|
+
releasePointerEvents(): void;
|
|
113
|
+
protected _createElement(): HTMLDivElement | undefined;
|
|
114
|
+
}
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { Mesh } from "@babylonjs/core/Meshes/mesh.js";
|
|
2
|
+
import { CreatePlaneVertexData } from "@babylonjs/core/Meshes/Builders/planeBuilder.js";
|
|
3
|
+
import { StandardMaterial } from "@babylonjs/core/Materials/standardMaterial.js";
|
|
4
|
+
import { Matrix } from "@babylonjs/core/Maths/math.js";
|
|
5
|
+
import { PointerEventsCaptureBehavior } from "./pointerEventsCaptureBehavior.js";
|
|
6
|
+
import { Logger } from "@babylonjs/core/Misc/logger.js";
|
|
7
|
+
import { FitStrategy } from "./fitStrategy.js";
|
|
8
|
+
/**
|
|
9
|
+
* This class represents HTML content that we want to render as though it is part of the scene. The HTML content is actually
|
|
10
|
+
* rendered below the canvas, but a depth mask is created by this class that writes to the depth buffer but does not
|
|
11
|
+
* write to the color buffer, effectively punching a hole in the canvas. CSS transforms are used to scale, translate, and rotate
|
|
12
|
+
* the HTML content so that it matches the camera and mesh orientation. The class supports interactions in editable and non-editable mode.
|
|
13
|
+
* In non-editable mode (the default), events are passed to the HTML content when the pointer is over the mask (and not occluded by other meshes
|
|
14
|
+
* in the scene).
|
|
15
|
+
* #HVHYJC#5
|
|
16
|
+
* #B17TC7#112
|
|
17
|
+
*/
|
|
18
|
+
export class HtmlMesh extends Mesh {
|
|
19
|
+
/**
|
|
20
|
+
* Helps identifying a html mesh from a regular mesh
|
|
21
|
+
*/
|
|
22
|
+
get isHtmlMesh() {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Return the source width of the content in pixels
|
|
27
|
+
*/
|
|
28
|
+
get sourceWidth() {
|
|
29
|
+
return this._sourceWidth;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Return the source height of the content in pixels
|
|
33
|
+
*/
|
|
34
|
+
get sourceHeight() {
|
|
35
|
+
return this._sourceHeight;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Contruct an instance of HtmlMesh
|
|
39
|
+
* @param scene
|
|
40
|
+
* @param id The id of the mesh. Will be used as the id of the HTML element as well.
|
|
41
|
+
* @param options object with optional parameters
|
|
42
|
+
*/
|
|
43
|
+
constructor(scene, id, { captureOnPointerEnter = true, isCanvasOverlay = false, fitStrategy = FitStrategy.NONE } = {}) {
|
|
44
|
+
super(id, scene);
|
|
45
|
+
// Override the super class's _isEnabled property so we can control when the mesh
|
|
46
|
+
// is enabled. I.e., we don't want to render the mesh until there is content to show.
|
|
47
|
+
this._enabled = false;
|
|
48
|
+
// The mesh is ready when content has been set and the content size has been set
|
|
49
|
+
// The former is done by the user, the latter is done by the renderer.
|
|
50
|
+
this._ready = false;
|
|
51
|
+
/**
|
|
52
|
+
* @internal
|
|
53
|
+
*/
|
|
54
|
+
this._isCanvasOverlay = false;
|
|
55
|
+
this._requiresUpdate = true;
|
|
56
|
+
this._inverseScaleMatrix = null;
|
|
57
|
+
this._captureOnPointerEnter = true;
|
|
58
|
+
this._pointerEventCaptureBehavior = null;
|
|
59
|
+
this._sourceWidth = null;
|
|
60
|
+
this._sourceHeight = null;
|
|
61
|
+
this._fitStrategy = FitStrategy.NONE;
|
|
62
|
+
// Requires a browser to work. Bail if we aren't running in a browser
|
|
63
|
+
if (typeof document === "undefined") {
|
|
64
|
+
Logger.Warn(`Creating an instance of an HtmlMesh with id ${id} outside of a browser. The mesh will not be visible.`);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
this._fitStrategy = fitStrategy;
|
|
68
|
+
this._isCanvasOverlay = isCanvasOverlay;
|
|
69
|
+
this._createMask();
|
|
70
|
+
this._element = this._createElement();
|
|
71
|
+
// Set enabled by default, so this will show as soon as it's ready
|
|
72
|
+
this.setEnabled(true);
|
|
73
|
+
this._captureOnPointerEnter = captureOnPointerEnter;
|
|
74
|
+
// Create a behavior to capture pointer events
|
|
75
|
+
this._pointerEventCaptureBehavior = new PointerEventsCaptureBehavior(this.capturePointerEvents.bind(this), this.releasePointerEvents.bind(this), {
|
|
76
|
+
captureOnPointerEnter: this._captureOnPointerEnter,
|
|
77
|
+
});
|
|
78
|
+
this.addBehavior(this._pointerEventCaptureBehavior);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The width of the content in pixels
|
|
82
|
+
*/
|
|
83
|
+
get width() {
|
|
84
|
+
return this._width;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The height of the content in pixels
|
|
88
|
+
*/
|
|
89
|
+
get height() {
|
|
90
|
+
return this._height;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The HTML element that is being rendered as a mesh
|
|
94
|
+
*/
|
|
95
|
+
get element() {
|
|
96
|
+
return this._element;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* True if the mesh has been moved, rotated, or scaled since the last time this
|
|
100
|
+
* property was read. This property is reset to false after reading.
|
|
101
|
+
*/
|
|
102
|
+
get requiresUpdate() {
|
|
103
|
+
return this._requiresUpdate;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Enable capture for the pointer when entering the mesh area
|
|
107
|
+
*/
|
|
108
|
+
set captureOnPointerEnter(captureOnPointerEnter) {
|
|
109
|
+
this._captureOnPointerEnter = captureOnPointerEnter;
|
|
110
|
+
if (this._pointerEventCaptureBehavior) {
|
|
111
|
+
this._pointerEventCaptureBehavior.captureOnPointerEnter = captureOnPointerEnter;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Disposes of the mesh and the HTML element
|
|
116
|
+
*/
|
|
117
|
+
dispose() {
|
|
118
|
+
super.dispose();
|
|
119
|
+
this._element?.remove();
|
|
120
|
+
this._element = undefined;
|
|
121
|
+
if (this._pointerEventCaptureBehavior) {
|
|
122
|
+
this._pointerEventCaptureBehavior.dispose();
|
|
123
|
+
this._pointerEventCaptureBehavior = null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* @internal
|
|
128
|
+
*/
|
|
129
|
+
_markAsUpdated() {
|
|
130
|
+
this._requiresUpdate = false;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Sets the content of the element to the specified content adjusting the mesh scale to match and making it visible.
|
|
134
|
+
* If the the specified content is undefined, then it will make the mesh invisible. In either case it will clear the
|
|
135
|
+
* element content first.
|
|
136
|
+
* @param element The element to render as a mesh
|
|
137
|
+
* @param width The width of the mesh in Babylon units
|
|
138
|
+
* @param height The height of the mesh in Babylon units
|
|
139
|
+
*/
|
|
140
|
+
setContent(element, width, height) {
|
|
141
|
+
// If content is changed, we are no longer ready
|
|
142
|
+
this._setAsReady(false);
|
|
143
|
+
// Also invalidate the source width and height
|
|
144
|
+
this._sourceWidth = null;
|
|
145
|
+
this._sourceHeight = null;
|
|
146
|
+
if (!this._element) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
this._width = width;
|
|
150
|
+
this._height = height;
|
|
151
|
+
this._requiresUpdate = true;
|
|
152
|
+
this.scaling.setAll(1);
|
|
153
|
+
if (element) {
|
|
154
|
+
this._element.appendChild(this._fitStrategy.wrapElement(element));
|
|
155
|
+
this._updateScaleIfNecessary();
|
|
156
|
+
}
|
|
157
|
+
if (this.sourceWidth && this.sourceHeight) {
|
|
158
|
+
this._setAsReady(true);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Overides BABYLON.Mesh.setEnabled
|
|
162
|
+
setEnabled(enabled) {
|
|
163
|
+
// Capture requested enabled state
|
|
164
|
+
this._enabled = enabled;
|
|
165
|
+
// If disabling or enabling and we are ready
|
|
166
|
+
if (!enabled || this._ready) {
|
|
167
|
+
this._doSetEnabled(enabled);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Sets the content size in pixels
|
|
172
|
+
* @param width width of the source
|
|
173
|
+
* @param height height of the source
|
|
174
|
+
*/
|
|
175
|
+
setContentSizePx(width, height) {
|
|
176
|
+
this._sourceWidth = width;
|
|
177
|
+
this._sourceHeight = height;
|
|
178
|
+
if (!this._element || !this._element.firstElementChild) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
this._fitStrategy.updateSize(this._element.firstElementChild, width, height);
|
|
182
|
+
this._updateScaleIfNecessary();
|
|
183
|
+
if (this.width && this.height) {
|
|
184
|
+
this._setAsReady(true);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
_setAsReady(ready) {
|
|
188
|
+
this._ready = ready;
|
|
189
|
+
if (ready) {
|
|
190
|
+
this._doSetEnabled(this._enabled);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
this._doSetEnabled(false);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
_doSetEnabled(enabled) {
|
|
197
|
+
if (!this._element) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
//if enabled, then start listening for changes to the
|
|
201
|
+
// scaling, rotation, and position. otherwise stop listening
|
|
202
|
+
if (enabled && !this._worldMatrixUpdateObserver) {
|
|
203
|
+
this._worldMatrixUpdateObserver = this.onAfterWorldMatrixUpdateObservable.add(() => {
|
|
204
|
+
this._requiresUpdate = true;
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
else if (!enabled) {
|
|
208
|
+
this._worldMatrixUpdateObserver?.remove();
|
|
209
|
+
this._worldMatrixUpdateObserver = null;
|
|
210
|
+
}
|
|
211
|
+
// If enabled, then revert the content element display
|
|
212
|
+
// otherwise hide it
|
|
213
|
+
this._element.style.display = enabled ? "" : "none";
|
|
214
|
+
// Capture the content z index
|
|
215
|
+
this._setElementZIndex(this.position.z * -10000);
|
|
216
|
+
super.setEnabled(enabled);
|
|
217
|
+
}
|
|
218
|
+
_updateScaleIfNecessary() {
|
|
219
|
+
// If we have setContent before, the content scale is baked into the mesh. If we don't reset the vertices to
|
|
220
|
+
// the original size, then we will multiply the scale when we bake the scale below. By applying the inverse, we back out
|
|
221
|
+
// the scaling that has been done so we are starting from the same point.
|
|
222
|
+
// First reset the scale to 1
|
|
223
|
+
this.scaling.setAll(1);
|
|
224
|
+
// Then back out the original vertices changes to match the content scale
|
|
225
|
+
if (this._inverseScaleMatrix) {
|
|
226
|
+
this.bakeTransformIntoVertices(this._inverseScaleMatrix);
|
|
227
|
+
// Clear out the matrix so it doesn't get applied again unless we scale
|
|
228
|
+
this._inverseScaleMatrix = null;
|
|
229
|
+
}
|
|
230
|
+
// Set scale to match content. Note we can't just scale the mesh, because that will scale the content as well
|
|
231
|
+
// What we need to do is compute a scale matrix and then bake that into the mesh vertices. This will leave the
|
|
232
|
+
// mesh scale at 1, so our content will stay it's original width and height until we scale the mesh.
|
|
233
|
+
const scaleX = this._width || 1;
|
|
234
|
+
const scaleY = this._height || 1;
|
|
235
|
+
const scaleMatrix = Matrix.Scaling(scaleX, scaleY, 1);
|
|
236
|
+
this.bakeTransformIntoVertices(scaleMatrix);
|
|
237
|
+
// Get an inverse of the scale matrix that we can use to back out the scale changes we have made so
|
|
238
|
+
// we don't multiply the scale.
|
|
239
|
+
this._inverseScaleMatrix = new Matrix();
|
|
240
|
+
scaleMatrix.invertToRef(this._inverseScaleMatrix);
|
|
241
|
+
}
|
|
242
|
+
_createMask() {
|
|
243
|
+
const vertexData = CreatePlaneVertexData({ width: 1, height: 1 });
|
|
244
|
+
vertexData.applyToMesh(this);
|
|
245
|
+
const scene = this.getScene();
|
|
246
|
+
this.checkCollisions = true;
|
|
247
|
+
const depthMask = new StandardMaterial(`${this.id}-mat`, scene);
|
|
248
|
+
if (!this._isCanvasOverlay) {
|
|
249
|
+
depthMask.backFaceCulling = false;
|
|
250
|
+
depthMask.disableColorWrite = true;
|
|
251
|
+
depthMask.disableLighting = true;
|
|
252
|
+
}
|
|
253
|
+
this.material = depthMask;
|
|
254
|
+
// Optimization - Freeze material since it never needs to change
|
|
255
|
+
this.material.freeze();
|
|
256
|
+
}
|
|
257
|
+
_setElementZIndex(zIndex) {
|
|
258
|
+
if (this._element) {
|
|
259
|
+
this._element.style.zIndex = `${zIndex}`;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Callback used by the PointerEventsCaptureBehavior to capture pointer events
|
|
264
|
+
*/
|
|
265
|
+
capturePointerEvents() {
|
|
266
|
+
if (!this._element) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
// Enable dom content to capture pointer events
|
|
270
|
+
this._element.style.pointerEvents = "auto";
|
|
271
|
+
// Supress events outside of the dom content
|
|
272
|
+
document.getElementsByTagName("body")[0].style.pointerEvents = "none";
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Callback used by the PointerEventsCaptureBehavior to release pointer events
|
|
276
|
+
*/
|
|
277
|
+
releasePointerEvents() {
|
|
278
|
+
if (!this._element) {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
// Enable pointer events on canvas
|
|
282
|
+
document.getElementsByTagName("body")[0].style.pointerEvents = "auto";
|
|
283
|
+
// Disable pointer events on dom content
|
|
284
|
+
this._element.style.pointerEvents = "none";
|
|
285
|
+
}
|
|
286
|
+
_createElement() {
|
|
287
|
+
// Requires a browser to work. Bail if we aren't running in a browser
|
|
288
|
+
if (typeof document === "undefined") {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
const div = document.createElement("div");
|
|
292
|
+
div.id = this.id;
|
|
293
|
+
div.style.backgroundColor = this._isCanvasOverlay ? "transparent" : "#000";
|
|
294
|
+
div.style.zIndex = "1";
|
|
295
|
+
div.style.position = "absolute";
|
|
296
|
+
div.style.pointerEvents = "none";
|
|
297
|
+
div.style.backfaceVisibility = "hidden";
|
|
298
|
+
return div;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
//# sourceMappingURL=htmlMesh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"htmlMesh.js","sourceRoot":"","sources":["../../../../dev/addons/src/htmlMesh/htmlMesh.ts"],"names":[],"mappings":"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","sourcesContent":["import { Mesh } from \"core/Meshes/mesh\";\r\nimport { CreatePlaneVertexData } from \"core/Meshes/Builders/planeBuilder\";\r\nimport { StandardMaterial } from \"core/Materials/standardMaterial\";\r\nimport { Matrix } from \"core/Maths/math\";\r\nimport { PointerEventsCaptureBehavior } from \"./pointerEventsCaptureBehavior\";\r\nimport type { Scene } from \"core/scene\";\r\nimport { Logger } from \"core/Misc/logger\";\r\nimport type { FitStrategyType } from \"./fitStrategy\";\r\nimport { FitStrategy } from \"./fitStrategy\";\r\n\r\n/**\r\n * This class represents HTML content that we want to render as though it is part of the scene. The HTML content is actually\r\n * rendered below the canvas, but a depth mask is created by this class that writes to the depth buffer but does not\r\n * write to the color buffer, effectively punching a hole in the canvas. CSS transforms are used to scale, translate, and rotate\r\n * the HTML content so that it matches the camera and mesh orientation. The class supports interactions in editable and non-editable mode.\r\n * In non-editable mode (the default), events are passed to the HTML content when the pointer is over the mask (and not occluded by other meshes\r\n * in the scene).\r\n * #HVHYJC#5\r\n * #B17TC7#112\r\n */\r\nexport class HtmlMesh extends Mesh {\r\n /**\r\n * Helps identifying a html mesh from a regular mesh\r\n */\r\n public get isHtmlMesh() {\r\n return true;\r\n }\r\n\r\n // Override the super class's _isEnabled property so we can control when the mesh\r\n // is enabled. I.e., we don't want to render the mesh until there is content to show.\r\n private _enabled = false;\r\n\r\n // The mesh is ready when content has been set and the content size has been set\r\n // The former is done by the user, the latter is done by the renderer.\r\n private _ready = false;\r\n\r\n /**\r\n * @internal\r\n */\r\n public _isCanvasOverlay = false;\r\n\r\n private _requiresUpdate = true;\r\n\r\n private _element?: HTMLElement;\r\n private _width?: number;\r\n private _height?: number;\r\n\r\n private _inverseScaleMatrix: Matrix | null = null;\r\n\r\n private _captureOnPointerEnter: boolean = true;\r\n private _pointerEventCaptureBehavior: PointerEventsCaptureBehavior | null = null;\r\n\r\n private _sourceWidth: number | null = null;\r\n private _sourceHeight: number | null = null;\r\n\r\n /**\r\n * Return the source width of the content in pixels\r\n */\r\n public get sourceWidth() {\r\n return this._sourceWidth;\r\n }\r\n\r\n /**\r\n * Return the source height of the content in pixels\r\n */\r\n public get sourceHeight() {\r\n return this._sourceHeight;\r\n }\r\n\r\n private _worldMatrixUpdateObserver: any;\r\n\r\n private _fitStrategy: FitStrategyType = FitStrategy.NONE;\r\n\r\n /**\r\n * Contruct an instance of HtmlMesh\r\n * @param scene\r\n * @param id The id of the mesh. Will be used as the id of the HTML element as well.\r\n * @param options object with optional parameters\r\n */\r\n constructor(scene: Scene, id: string, { captureOnPointerEnter = true, isCanvasOverlay = false, fitStrategy = FitStrategy.NONE } = {}) {\r\n super(id, scene);\r\n\r\n // Requires a browser to work. Bail if we aren't running in a browser\r\n if (typeof document === \"undefined\") {\r\n Logger.Warn(`Creating an instance of an HtmlMesh with id ${id} outside of a browser. The mesh will not be visible.`);\r\n return;\r\n }\r\n\r\n this._fitStrategy = fitStrategy;\r\n this._isCanvasOverlay = isCanvasOverlay;\r\n this._createMask();\r\n this._element = this._createElement();\r\n\r\n // Set enabled by default, so this will show as soon as it's ready\r\n this.setEnabled(true);\r\n\r\n this._captureOnPointerEnter = captureOnPointerEnter;\r\n\r\n // Create a behavior to capture pointer events\r\n this._pointerEventCaptureBehavior = new PointerEventsCaptureBehavior(this.capturePointerEvents.bind(this), this.releasePointerEvents.bind(this), {\r\n captureOnPointerEnter: this._captureOnPointerEnter,\r\n });\r\n this.addBehavior(this._pointerEventCaptureBehavior);\r\n }\r\n\r\n /**\r\n * The width of the content in pixels\r\n */\r\n public get width() {\r\n return this._width;\r\n }\r\n\r\n /**\r\n * The height of the content in pixels\r\n */\r\n public get height() {\r\n return this._height;\r\n }\r\n\r\n /**\r\n * The HTML element that is being rendered as a mesh\r\n */\r\n public get element() {\r\n return this._element;\r\n }\r\n\r\n /**\r\n * True if the mesh has been moved, rotated, or scaled since the last time this\r\n * property was read. This property is reset to false after reading.\r\n */\r\n public get requiresUpdate() {\r\n return this._requiresUpdate;\r\n }\r\n\r\n /**\r\n * Enable capture for the pointer when entering the mesh area\r\n */\r\n public set captureOnPointerEnter(captureOnPointerEnter: boolean) {\r\n this._captureOnPointerEnter = captureOnPointerEnter;\r\n if (this._pointerEventCaptureBehavior) {\r\n this._pointerEventCaptureBehavior.captureOnPointerEnter = captureOnPointerEnter;\r\n }\r\n }\r\n\r\n /**\r\n * Disposes of the mesh and the HTML element\r\n */\r\n public override dispose() {\r\n super.dispose();\r\n this._element?.remove();\r\n this._element = undefined;\r\n if (this._pointerEventCaptureBehavior) {\r\n this._pointerEventCaptureBehavior.dispose();\r\n this._pointerEventCaptureBehavior = null;\r\n }\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n public _markAsUpdated() {\r\n this._requiresUpdate = false;\r\n }\r\n\r\n /**\r\n * Sets the content of the element to the specified content adjusting the mesh scale to match and making it visible.\r\n * If the the specified content is undefined, then it will make the mesh invisible. In either case it will clear the\r\n * element content first.\r\n * @param element The element to render as a mesh\r\n * @param width The width of the mesh in Babylon units\r\n * @param height The height of the mesh in Babylon units\r\n */\r\n setContent(element: HTMLElement, width: number, height: number) {\r\n // If content is changed, we are no longer ready\r\n this._setAsReady(false);\r\n\r\n // Also invalidate the source width and height\r\n this._sourceWidth = null;\r\n this._sourceHeight = null;\r\n\r\n if (!this._element) {\r\n return;\r\n }\r\n\r\n this._width = width;\r\n this._height = height;\r\n this._requiresUpdate = true;\r\n\r\n this.scaling.setAll(1);\r\n\r\n if (element) {\r\n this._element!.appendChild(this._fitStrategy.wrapElement(element));\r\n\r\n this._updateScaleIfNecessary();\r\n }\r\n\r\n if (this.sourceWidth && this.sourceHeight) {\r\n this._setAsReady(true);\r\n }\r\n }\r\n\r\n // Overides BABYLON.Mesh.setEnabled\r\n public override setEnabled(enabled: boolean) {\r\n // Capture requested enabled state\r\n this._enabled = enabled;\r\n\r\n // If disabling or enabling and we are ready\r\n if (!enabled || this._ready) {\r\n this._doSetEnabled(enabled);\r\n }\r\n }\r\n\r\n /**\r\n * Sets the content size in pixels\r\n * @param width width of the source\r\n * @param height height of the source\r\n */\r\n public setContentSizePx(width: number, height: number) {\r\n this._sourceWidth = width;\r\n this._sourceHeight = height;\r\n\r\n if (!this._element || !this._element.firstElementChild) {\r\n return;\r\n }\r\n\r\n this._fitStrategy.updateSize(this._element.firstElementChild! as HTMLElement, width, height);\r\n\r\n this._updateScaleIfNecessary();\r\n\r\n if (this.width && this.height) {\r\n this._setAsReady(true);\r\n }\r\n }\r\n\r\n protected _setAsReady(ready: boolean) {\r\n this._ready = ready;\r\n if (ready) {\r\n this._doSetEnabled(this._enabled);\r\n } else {\r\n this._doSetEnabled(false);\r\n }\r\n }\r\n\r\n protected _doSetEnabled(enabled: boolean) {\r\n if (!this._element) {\r\n return;\r\n }\r\n\r\n //if enabled, then start listening for changes to the\r\n // scaling, rotation, and position. otherwise stop listening\r\n if (enabled && !this._worldMatrixUpdateObserver) {\r\n this._worldMatrixUpdateObserver = this.onAfterWorldMatrixUpdateObservable.add(() => {\r\n this._requiresUpdate = true;\r\n });\r\n } else if (!enabled) {\r\n this._worldMatrixUpdateObserver?.remove();\r\n this._worldMatrixUpdateObserver = null;\r\n }\r\n\r\n // If enabled, then revert the content element display\r\n // otherwise hide it\r\n this._element!.style.display = enabled ? \"\" : \"none\";\r\n // Capture the content z index\r\n this._setElementZIndex(this.position.z * -10000);\r\n super.setEnabled(enabled);\r\n }\r\n\r\n protected _updateScaleIfNecessary() {\r\n // If we have setContent before, the content scale is baked into the mesh. If we don't reset the vertices to\r\n // the original size, then we will multiply the scale when we bake the scale below. By applying the inverse, we back out\r\n // the scaling that has been done so we are starting from the same point.\r\n // First reset the scale to 1\r\n this.scaling.setAll(1);\r\n // Then back out the original vertices changes to match the content scale\r\n if (this._inverseScaleMatrix) {\r\n this.bakeTransformIntoVertices(this._inverseScaleMatrix);\r\n // Clear out the matrix so it doesn't get applied again unless we scale\r\n this._inverseScaleMatrix = null;\r\n }\r\n\r\n // Set scale to match content. Note we can't just scale the mesh, because that will scale the content as well\r\n // What we need to do is compute a scale matrix and then bake that into the mesh vertices. This will leave the\r\n // mesh scale at 1, so our content will stay it's original width and height until we scale the mesh.\r\n const scaleX = this._width || 1;\r\n const scaleY = this._height || 1;\r\n const scaleMatrix = Matrix.Scaling(scaleX, scaleY, 1);\r\n this.bakeTransformIntoVertices(scaleMatrix);\r\n\r\n // Get an inverse of the scale matrix that we can use to back out the scale changes we have made so\r\n // we don't multiply the scale.\r\n this._inverseScaleMatrix = new Matrix();\r\n scaleMatrix.invertToRef(this._inverseScaleMatrix);\r\n }\r\n\r\n protected _createMask() {\r\n const vertexData = CreatePlaneVertexData({ width: 1, height: 1 });\r\n vertexData.applyToMesh(this);\r\n\r\n const scene = this.getScene();\r\n this.checkCollisions = true;\r\n\r\n const depthMask = new StandardMaterial(`${this.id}-mat`, scene);\r\n if (!this._isCanvasOverlay) {\r\n depthMask.backFaceCulling = false;\r\n depthMask.disableColorWrite = true;\r\n depthMask.disableLighting = true;\r\n }\r\n\r\n this.material = depthMask;\r\n\r\n // Optimization - Freeze material since it never needs to change\r\n this.material.freeze();\r\n }\r\n\r\n protected _setElementZIndex(zIndex: number) {\r\n if (this._element) {\r\n this._element!.style.zIndex = `${zIndex}`;\r\n }\r\n }\r\n\r\n /**\r\n * Callback used by the PointerEventsCaptureBehavior to capture pointer events\r\n */\r\n capturePointerEvents() {\r\n if (!this._element) {\r\n return;\r\n }\r\n\r\n // Enable dom content to capture pointer events\r\n this._element.style.pointerEvents = \"auto\";\r\n\r\n // Supress events outside of the dom content\r\n document.getElementsByTagName(\"body\")[0].style.pointerEvents = \"none\";\r\n }\r\n\r\n /**\r\n * Callback used by the PointerEventsCaptureBehavior to release pointer events\r\n */\r\n releasePointerEvents() {\r\n if (!this._element) {\r\n return;\r\n }\r\n\r\n // Enable pointer events on canvas\r\n document.getElementsByTagName(\"body\")[0].style.pointerEvents = \"auto\";\r\n\r\n // Disable pointer events on dom content\r\n this._element.style.pointerEvents = \"none\";\r\n }\r\n\r\n protected _createElement() {\r\n // Requires a browser to work. Bail if we aren't running in a browser\r\n if (typeof document === \"undefined\") {\r\n return;\r\n }\r\n const div = document.createElement(\"div\");\r\n div.id = this.id;\r\n div.style.backgroundColor = this._isCanvasOverlay ? \"transparent\" : \"#000\";\r\n div.style.zIndex = \"1\";\r\n div.style.position = \"absolute\";\r\n div.style.pointerEvents = \"none\";\r\n div.style.backfaceVisibility = \"hidden\";\r\n\r\n return div;\r\n }\r\n}\r\n"]}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { Scene } from "@babylonjs/core/scene.js";
|
|
2
|
+
import { Matrix } from "@babylonjs/core/Maths/math.js";
|
|
3
|
+
import type { HtmlMesh } from "./htmlMesh";
|
|
4
|
+
import { Camera } from "@babylonjs/core/Cameras/camera.js";
|
|
5
|
+
import type { SubMesh } from "@babylonjs/core/Meshes/subMesh.js";
|
|
6
|
+
/**
|
|
7
|
+
* A function that compares two submeshes and returns a number indicating which
|
|
8
|
+
* should be rendered first.
|
|
9
|
+
*/
|
|
10
|
+
type RenderOrderFunction = (subMeshA: SubMesh, subMeshB: SubMesh) => number;
|
|
11
|
+
/**
|
|
12
|
+
* An instance of this is required to render HtmlMeshes in the scene.
|
|
13
|
+
* if using HtmlMeshes, you must not set render order for group 0 using
|
|
14
|
+
* scene.setRenderingOrder. You must instead pass the compare functions
|
|
15
|
+
* to the HtmlMeshRenderer constructor. If you do not, then your render
|
|
16
|
+
* order will be overwritten if the HtmlMeshRenderer is created after and
|
|
17
|
+
* the HtmlMeshes will not render correctly (they will appear in front of
|
|
18
|
+
* meshes that are actually in front of them) if the HtmlMeshRenderer is
|
|
19
|
+
* created before.
|
|
20
|
+
*/
|
|
21
|
+
export declare class HtmlMeshRenderer {
|
|
22
|
+
private _containerId?;
|
|
23
|
+
private _inSceneElements?;
|
|
24
|
+
private _overlayElements?;
|
|
25
|
+
private _engine;
|
|
26
|
+
private _cache;
|
|
27
|
+
private _width;
|
|
28
|
+
private _height;
|
|
29
|
+
private _heightHalf;
|
|
30
|
+
private _cameraWorldMatrix?;
|
|
31
|
+
private _temp;
|
|
32
|
+
private _lastDevicePixelRatio;
|
|
33
|
+
private _cameraMatrixUpdated;
|
|
34
|
+
private _previousCanvasDocumentPosition;
|
|
35
|
+
private _renderObserver;
|
|
36
|
+
/**
|
|
37
|
+
* Contruct an instance of HtmlMeshRenderer
|
|
38
|
+
* @param scene
|
|
39
|
+
* @param options object containing the following optional properties:
|
|
40
|
+
* @returns
|
|
41
|
+
*/
|
|
42
|
+
constructor(scene: Scene, { parentContainerId, _containerId, enableOverlayRender, defaultOpaqueRenderOrder, defaultAlphaTestRenderOrder, defaultTransparentRenderOrder, }?: {
|
|
43
|
+
parentContainerId?: string | null;
|
|
44
|
+
_containerId?: string;
|
|
45
|
+
defaultOpaqueRenderOrder?: RenderOrderFunction;
|
|
46
|
+
defaultAlphaTestRenderOrder?: RenderOrderFunction;
|
|
47
|
+
defaultTransparentRenderOrder?: RenderOrderFunction;
|
|
48
|
+
enableOverlayRender?: boolean;
|
|
49
|
+
});
|
|
50
|
+
/**
|
|
51
|
+
* Dispose of the HtmlMeshRenderer
|
|
52
|
+
*/
|
|
53
|
+
dispose(): void;
|
|
54
|
+
protected _init(scene: Scene, parentContainerId: string | null, enableOverlayRender: boolean, defaultOpaqueRenderOrder: RenderOrderFunction, defaultAlphaTestRenderOrder: RenderOrderFunction, defaultTransparentRenderOrder: RenderOrderFunction): void;
|
|
55
|
+
private _createRenderLayerElements;
|
|
56
|
+
protected _getSize(): {
|
|
57
|
+
width: number;
|
|
58
|
+
height: number;
|
|
59
|
+
};
|
|
60
|
+
protected _setSize(width: number, height: number): void;
|
|
61
|
+
protected _getCameraCSSMatrix(matrix: Matrix): string;
|
|
62
|
+
protected _getHtmlContentCSSMatrix(matrix: Matrix, useRightHandedSystem: boolean): string;
|
|
63
|
+
protected _getTransformationMatrix(htmlMesh: HtmlMesh, useRightHandedSystem: boolean): Matrix;
|
|
64
|
+
protected _renderHtmlMesh(htmlMesh: HtmlMesh, useRightHandedSystem: boolean): void;
|
|
65
|
+
protected _render(scene: Scene, camera: Camera): void;
|
|
66
|
+
protected _updateBaseScaleFactor(htmlMesh: HtmlMesh): void;
|
|
67
|
+
protected _updateContainerPositionIfNeeded(): void;
|
|
68
|
+
protected _onCameraMatrixChanged: (camera: Camera) => void;
|
|
69
|
+
private _epsilon;
|
|
70
|
+
private _getAncestorMarginsAndPadding;
|
|
71
|
+
}
|
|
72
|
+
export {};
|