@babylonjs/addons 8.5.0 → 8.6.0
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.js.map +1 -1
- package/htmlMesh/htmlMesh.d.ts +1 -1
- package/htmlMesh/htmlMesh.js +2 -2
- package/htmlMesh/htmlMesh.js.map +1 -1
- package/htmlMesh/htmlMeshRenderer.d.ts +2 -2
- package/htmlMesh/htmlMeshRenderer.js +22 -22
- package/htmlMesh/htmlMeshRenderer.js.map +1 -1
- package/htmlMesh/pointerEventsCapture.d.ts +1 -1
- package/htmlMesh/pointerEventsCapture.js +55 -51
- package/htmlMesh/pointerEventsCapture.js.map +1 -1
- package/htmlMesh/pointerEventsCaptureBehavior.js +32 -32
- package/htmlMesh/pointerEventsCaptureBehavior.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +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,
|
|
1
|
+
{"version":3,"file":"fitStrategy.js","sourceRoot":"","sources":["../../../../dev/addons/src/htmlMesh/fitStrategy.ts"],"names":[],"mappings":"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","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"]}
|
package/htmlMesh/htmlMesh.d.ts
CHANGED
|
@@ -101,7 +101,7 @@ export declare class HtmlMesh extends Mesh {
|
|
|
101
101
|
protected _doSetEnabled(enabled: boolean): void;
|
|
102
102
|
protected _updateScaleIfNecessary(): void;
|
|
103
103
|
protected _createMask(): void;
|
|
104
|
-
protected
|
|
104
|
+
protected _setElementzIndex(zIndex: number): void;
|
|
105
105
|
/**
|
|
106
106
|
* Callback used by the PointerEventsCaptureBehavior to capture pointer events
|
|
107
107
|
*/
|
package/htmlMesh/htmlMesh.js
CHANGED
|
@@ -212,7 +212,7 @@ export class HtmlMesh extends Mesh {
|
|
|
212
212
|
// otherwise hide it
|
|
213
213
|
this._element.style.display = enabled ? "" : "none";
|
|
214
214
|
// Capture the content z index
|
|
215
|
-
this.
|
|
215
|
+
this._setElementzIndex(this.position.z * -10000);
|
|
216
216
|
super.setEnabled(enabled);
|
|
217
217
|
}
|
|
218
218
|
_updateScaleIfNecessary() {
|
|
@@ -254,7 +254,7 @@ export class HtmlMesh extends Mesh {
|
|
|
254
254
|
// Optimization - Freeze material since it never needs to change
|
|
255
255
|
this.material.freeze();
|
|
256
256
|
}
|
|
257
|
-
|
|
257
|
+
_setElementzIndex(zIndex) {
|
|
258
258
|
if (this._element) {
|
|
259
259
|
this._element.style.zIndex = `${zIndex}`;
|
|
260
260
|
}
|
package/htmlMesh/htmlMesh.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"htmlMesh.js","sourceRoot":"","sources":["../../../../dev/addons/src/htmlMesh/htmlMesh.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,uCAAyB;AACxC,OAAO,EAAE,qBAAqB,EAAE,wDAA0C;AAC1E,OAAO,EAAE,gBAAgB,EAAE,sDAAwC;AACnE,OAAO,EAAE,MAAM,EAAE,sCAAwB;AACzC,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAE9E,OAAO,EAAE,MAAM,EAAE,uCAAyB;AAE1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C;;;;;;;;;GASG;AACH,MAAM,OAAO,QAAS,SAAQ,IAAI;IAC9B;;OAEG;IACH,IAAW,UAAU;QACjB,OAAO,IAAI,CAAC;IAChB,CAAC;IA6BD;;OAEG;IACH,IAAW,WAAW;QAClB,OAAO,IAAI,CAAC,YAAY,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,IAAW,YAAY;QACnB,OAAO,IAAI,CAAC,aAAa,CAAC;IAC9B,CAAC;IAMD;;;;;OAKG;IACH,YAAY,KAAY,EAAE,EAAU,EAAE,EAAE,qBAAqB,GAAG,IAAI,EAAE,eAAe,GAAG,KAAK,EAAE,WAAW,GAAG,WAAW,CAAC,IAAI,EAAE,GAAG,EAAE;QAChI,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QApDrB,iFAAiF;QACjF,sFAAsF;QAC9E,aAAQ,GAAG,KAAK,CAAC;QAEzB,gFAAgF;QAChF,sEAAsE;QAC9D,WAAM,GAAG,KAAK,CAAC;QAEvB;;WAEG;QACI,qBAAgB,GAAG,KAAK,CAAC;QAExB,oBAAe,GAAG,IAAI,CAAC;QAMvB,wBAAmB,GAAkB,IAAI,CAAC;QAE1C,2BAAsB,GAAY,IAAI,CAAC;QACvC,iCAA4B,GAAwC,IAAI,CAAC;QAEzE,iBAAY,GAAkB,IAAI,CAAC;QACnC,kBAAa,GAAkB,IAAI,CAAC;QAkBpC,iBAAY,GAAoB,WAAW,CAAC,IAAI,CAAC;QAWrD,sEAAsE;QACtE,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,+CAA+C,EAAE,uDAAuD,CAAC,CAAC;YACtH,OAAO;QACX,CAAC;QAED,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;QAChC,IAAI,CAAC,gBAAgB,GAAG,eAAe,CAAC;QACxC,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QAEtC,kEAAkE;QAClE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAEtB,IAAI,CAAC,sBAAsB,GAAG,qBAAqB,CAAC;QAEpD,8CAA8C;QAC9C,IAAI,CAAC,4BAA4B,GAAG,IAAI,4BAA4B,CAAC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAC7I,qBAAqB,EAAE,IAAI,CAAC,sBAAsB;SACrD,CAAC,CAAC;QACH,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IACxD,CAAC;IAED;;OAEG;IACH,IAAW,KAAK;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,IAAW,MAAM;QACb,OAAO,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,IAAW,OAAO;QACd,OAAO,IAAI,CAAC,QAAQ,CAAC;IACzB,CAAC;IAED;;;OAGG;IACH,IAAW,cAAc;QACrB,OAAO,IAAI,CAAC,eAAe,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,IAAW,qBAAqB,CAAC,qBAA8B;QAC3D,IAAI,CAAC,sBAAsB,GAAG,qBAAqB,CAAC;QACpD,IAAI,IAAI,CAAC,4BAA4B,EAAE,CAAC;YACpC,IAAI,CAAC,4BAA4B,CAAC,qBAAqB,GAAG,qBAAqB,CAAC;QACpF,CAAC;IACL,CAAC;IAED;;OAEG;IACa,OAAO;QACnB,KAAK,CAAC,OAAO,EAAE,CAAC;QAChB,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;QACxB,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC1B,IAAI,IAAI,CAAC,4BAA4B,EAAE,CAAC;YACpC,IAAI,CAAC,4BAA4B,CAAC,OAAO,EAAE,CAAC;YAC5C,IAAI,CAAC,4BAA4B,GAAG,IAAI,CAAC;QAC7C,CAAC;IACL,CAAC;IAED;;OAEG;IACI,cAAc;QACjB,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;IACjC,CAAC;IAED;;;;;;;OAOG;IACH,UAAU,CAAC,OAAoB,EAAE,KAAa,EAAE,MAAc;QAC1D,gDAAgD;QAChD,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAExB,8CAA8C;QAC9C,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAE1B,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjB,OAAO;QACX,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAE5B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAEvB,IAAI,OAAO,EAAE,CAAC;YACV,IAAI,CAAC,QAAS,CAAC,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;YAEnE,IAAI,CAAC,uBAAuB,EAAE,CAAC;QACnC,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACxC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;IACL,CAAC;IAED,mCAAmC;IACnB,UAAU,CAAC,OAAgB;QACvC,kCAAkC;QAClC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QAExB,4CAA4C;QAC5C,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC1B,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACI,gBAAgB,CAAC,KAAa,EAAE,MAAc;QACjD,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC1B,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC;QAE5B,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,EAAE,CAAC;YACrD,OAAO;QACX,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAE7F,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAE/B,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC5B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;IACL,CAAC;IAES,WAAW,CAAC,KAAc;QAChC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,KAAK,EAAE,CAAC;YACR,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtC,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;IACL,CAAC;IAES,aAAa,CAAC,OAAgB;QACpC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjB,OAAO;QACX,CAAC;QAED,qDAAqD;QACrD,6DAA6D;QAC7D,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,0BAA0B,EAAE,CAAC;YAC9C,IAAI,CAAC,0BAA0B,GAAG,IAAI,CAAC,kCAAkC,CAAC,GAAG,CAAC,GAAG,EAAE;gBAC/E,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;YAChC,CAAC,CAAC,CAAC;QACP,CAAC;aAAM,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,IAAI,CAAC,0BAA0B,EAAE,MAAM,EAAE,CAAC;YAC1C,IAAI,CAAC,0BAA0B,GAAG,IAAI,CAAC;QAC3C,CAAC;QAED,sDAAsD;QACtD,oBAAoB;QACpB,IAAI,CAAC,QAAS,CAAC,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QACrD,8BAA8B;QAC9B,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACjD,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAES,uBAAuB;QAC7B,6GAA6G;QAC7G,yHAAyH;QACzH,yEAAyE;QACzE,6BAA6B;QAC7B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvB,yEAAyE;QACzE,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC3B,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YACzD,uEAAuE;YACvE,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;QACpC,CAAC;QAED,8GAA8G;QAC9G,+GAA+G;QAC/G,oGAAoG;QACpG,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;QACjC,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;QACtD,IAAI,CAAC,yBAAyB,CAAC,WAAW,CAAC,CAAC;QAE5C,mGAAmG;QACnG,+BAA+B;QAC/B,IAAI,CAAC,mBAAmB,GAAG,IAAI,MAAM,EAAE,CAAC;QACxC,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IACtD,CAAC;IAES,WAAW;QACjB,MAAM,UAAU,GAAG,qBAAqB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;QAClE,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAE7B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC9B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAE5B,MAAM,SAAS,GAAG,IAAI,gBAAgB,CAAC,GAAG,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QAChE,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACzB,SAAS,CAAC,eAAe,GAAG,KAAK,CAAC;YAClC,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC;YACnC,SAAS,CAAC,eAAe,GAAG,IAAI,CAAC;QACrC,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAE1B,gEAAgE;QAChE,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;IAC3B,CAAC;IAES,iBAAiB,CAAC,MAAc;QACtC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,IAAI,CAAC,QAAS,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;QAC9C,CAAC;IACL,CAAC;IAED;;OAEG;IACH,oBAAoB;QAChB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjB,OAAO;QACX,CAAC;QAED,+CAA+C;QAC/C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC;QAE3C,4CAA4C;QAC5C,QAAQ,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC;IAC1E,CAAC;IAED;;OAEG;IACH,oBAAoB;QAChB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjB,OAAO;QACX,CAAC;QAED,kCAAkC;QAClC,QAAQ,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC;QAEtE,wCAAwC;QACxC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC;IAC/C,CAAC;IAES,cAAc;QACpB,sEAAsE;QACtE,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;YAClC,OAAO;QACX,CAAC;QACD,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC1C,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QACjB,GAAG,CAAC,KAAK,CAAC,eAAe,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC;QAC3E,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;QACvB,GAAG,CAAC,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAC;QAChC,GAAG,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC;QACjC,GAAG,CAAC,KAAK,CAAC,kBAAkB,GAAG,QAAQ,CAAC;QAExC,OAAO,GAAG,CAAC;IACf,CAAC;CACJ","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 * @see https://playground.babylonjs.com/#HVHYJC#5\r\n * @see https://playground.babylonjs.com/#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"]}
|
|
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 * @see https://playground.babylonjs.com/#HVHYJC#5\r\n * @see https://playground.babylonjs.com/#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"]}
|
|
@@ -58,8 +58,8 @@ export declare class HtmlMeshRenderer {
|
|
|
58
58
|
height: number;
|
|
59
59
|
};
|
|
60
60
|
protected _setSize(width: number, height: number): void;
|
|
61
|
-
protected
|
|
62
|
-
protected
|
|
61
|
+
protected _getCameraCssMatrix(matrix: Matrix): string;
|
|
62
|
+
protected _getHtmlContentCssMatrix(matrix: Matrix, useRightHandedSystem: boolean): string;
|
|
63
63
|
protected _getTransformationMatrix(htmlMesh: HtmlMesh, useRightHandedSystem: boolean): Matrix;
|
|
64
64
|
protected _renderHtmlMesh(htmlMesh: HtmlMesh, useRightHandedSystem: boolean): void;
|
|
65
65
|
protected _render(scene: Scene, camera: Camera): void;
|
|
@@ -2,25 +2,25 @@ import { Matrix, Quaternion, Vector3 } from "@babylonjs/core/Maths/math.js";
|
|
|
2
2
|
import { Camera } from "@babylonjs/core/Cameras/camera.js";
|
|
3
3
|
import { RenderingGroup } from "@babylonjs/core/Rendering/renderingGroup.js";
|
|
4
4
|
import { Logger } from "@babylonjs/core/Misc/logger.js";
|
|
5
|
-
const
|
|
6
|
-
const
|
|
5
|
+
const PositionUpdateFailMessage = "Failed to update html mesh renderer position due to failure to get canvas rect. HtmlMesh instances may not render correctly";
|
|
6
|
+
const BabylonUnitsToPixels = 100;
|
|
7
7
|
// Returns a function that ensures that HtmlMeshes are rendered before all other meshes.
|
|
8
8
|
// Note this will only be applied to group 0.
|
|
9
9
|
// If neither mesh is an HtmlMesh, then the default render order is used
|
|
10
10
|
// This prevents HtmlMeshes from appearing in front of other meshes when they are behind them
|
|
11
|
-
const
|
|
11
|
+
const RenderOrderFunc = (defaultRenderOrder) => {
|
|
12
12
|
return (subMeshA, subMeshB) => {
|
|
13
13
|
const meshA = subMeshA.getMesh();
|
|
14
14
|
const meshB = subMeshB.getMesh();
|
|
15
15
|
// Use property check instead of instanceof since it is less expensive and
|
|
16
16
|
// this will be called many times per frame
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
if (
|
|
20
|
-
return
|
|
17
|
+
const meshIsHtmlMeshA = meshA["isHtmlMesh"];
|
|
18
|
+
const meshIsHtmlMeshB = meshB["isHtmlMesh"];
|
|
19
|
+
if (meshIsHtmlMeshA) {
|
|
20
|
+
return meshIsHtmlMeshB ? (meshA.absolutePosition.z <= meshB.absolutePosition.z ? 1 : -1) : -1;
|
|
21
21
|
}
|
|
22
22
|
else {
|
|
23
|
-
return
|
|
23
|
+
return meshIsHtmlMeshB ? 1 : defaultRenderOrder(subMeshA, subMeshB);
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
26
|
};
|
|
@@ -159,9 +159,9 @@ export class HtmlMeshRenderer {
|
|
|
159
159
|
// Updating the render order isn't ideal, but it is the only way to acheive this
|
|
160
160
|
// The implication is that an app using the HtmlMeshRendered must set the scene render order
|
|
161
161
|
// via the HtmlMeshRendered constructor
|
|
162
|
-
const opaqueRenderOrder =
|
|
163
|
-
const alphaTestRenderOrder =
|
|
164
|
-
const transparentRenderOrder =
|
|
162
|
+
const opaqueRenderOrder = RenderOrderFunc(defaultOpaqueRenderOrder);
|
|
163
|
+
const alphaTestRenderOrder = RenderOrderFunc(defaultAlphaTestRenderOrder);
|
|
164
|
+
const transparentRenderOrder = RenderOrderFunc(defaultTransparentRenderOrder);
|
|
165
165
|
scene.setRenderingOrder(0, opaqueRenderOrder, alphaTestRenderOrder, transparentRenderOrder);
|
|
166
166
|
this._renderObserver = scene.onBeforeRenderObservable.add(() => {
|
|
167
167
|
this._render(scene, scene.activeCamera);
|
|
@@ -214,7 +214,7 @@ export class HtmlMeshRenderer {
|
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
// prettier-ignore
|
|
217
|
-
|
|
217
|
+
_getCameraCssMatrix(matrix) {
|
|
218
218
|
const elements = matrix.m;
|
|
219
219
|
return `matrix3d(${this._epsilon(elements[0])},${this._epsilon(-elements[1])},${this._epsilon(elements[2])},${this._epsilon(elements[3])},${this._epsilon(elements[4])},${this._epsilon(-elements[5])},${this._epsilon(elements[6])},${this._epsilon(elements[7])},${this._epsilon(elements[8])},${this._epsilon(-elements[9])},${this._epsilon(elements[10])},${this._epsilon(elements[11])},${this._epsilon(elements[12])},${this._epsilon(-elements[13])},${this._epsilon(elements[14])},${this._epsilon(elements[15])})`;
|
|
220
220
|
}
|
|
@@ -222,7 +222,7 @@ export class HtmlMeshRenderer {
|
|
|
222
222
|
// This also handles conversion from BJS left handed coords
|
|
223
223
|
// to CSS right handed coords
|
|
224
224
|
// prettier-ignore
|
|
225
|
-
|
|
225
|
+
_getHtmlContentCssMatrix(matrix, useRightHandedSystem) {
|
|
226
226
|
const elements = matrix.m;
|
|
227
227
|
// In a right handed coordinate system, the elements 11 to 14 have to change their direction
|
|
228
228
|
const direction = useRightHandedSystem ? -1 : 1;
|
|
@@ -245,8 +245,8 @@ export class HtmlMeshRenderer {
|
|
|
245
245
|
let widthScaleFactor = 1;
|
|
246
246
|
let heightScaleFactor = 1;
|
|
247
247
|
if (htmlMesh.sourceWidth && htmlMesh.sourceHeight) {
|
|
248
|
-
widthScaleFactor = htmlMesh.width / (htmlMesh.sourceWidth /
|
|
249
|
-
heightScaleFactor = htmlMesh.height / (htmlMesh.sourceHeight /
|
|
248
|
+
widthScaleFactor = htmlMesh.width / (htmlMesh.sourceWidth / BabylonUnitsToPixels);
|
|
249
|
+
heightScaleFactor = htmlMesh.height / (htmlMesh.sourceHeight / BabylonUnitsToPixels);
|
|
250
250
|
}
|
|
251
251
|
// Apply the scale to the object's world matrix. Note we aren't scaling
|
|
252
252
|
// the object, just getting a matrix as though it were scaled, so we can
|
|
@@ -264,11 +264,11 @@ export class HtmlMeshRenderer {
|
|
|
264
264
|
// Adjust translation values to be from camera vs world origin
|
|
265
265
|
// Note that we are also adjusting these values to be pixels vs Babylon units
|
|
266
266
|
const position = htmlMesh.getAbsolutePosition();
|
|
267
|
-
scaledAndTranslatedObjectMatrix.setRowFromFloats(3, (-this._cameraWorldMatrix.m[12] + position.x) *
|
|
267
|
+
scaledAndTranslatedObjectMatrix.setRowFromFloats(3, (-this._cameraWorldMatrix.m[12] + position.x) * BabylonUnitsToPixels * direction, (-this._cameraWorldMatrix.m[13] + position.y) * BabylonUnitsToPixels * direction, (this._cameraWorldMatrix.m[14] - position.z) * BabylonUnitsToPixels, this._cameraWorldMatrix.m[15] * 0.00001 * BabylonUnitsToPixels);
|
|
268
268
|
// Adjust other values to be pixels vs Babylon units
|
|
269
|
-
scaledAndTranslatedObjectMatrix.multiplyAtIndex(3,
|
|
270
|
-
scaledAndTranslatedObjectMatrix.multiplyAtIndex(7,
|
|
271
|
-
scaledAndTranslatedObjectMatrix.multiplyAtIndex(11,
|
|
269
|
+
scaledAndTranslatedObjectMatrix.multiplyAtIndex(3, BabylonUnitsToPixels);
|
|
270
|
+
scaledAndTranslatedObjectMatrix.multiplyAtIndex(7, BabylonUnitsToPixels);
|
|
271
|
+
scaledAndTranslatedObjectMatrix.multiplyAtIndex(11, BabylonUnitsToPixels);
|
|
272
272
|
return scaledAndTranslatedObjectMatrix;
|
|
273
273
|
}
|
|
274
274
|
_renderHtmlMesh(htmlMesh, useRightHandedSystem) {
|
|
@@ -293,7 +293,7 @@ export class HtmlMeshRenderer {
|
|
|
293
293
|
}
|
|
294
294
|
// Get the transformation matrix for the html mesh
|
|
295
295
|
const scaledAndTranslatedObjectMatrix = this._getTransformationMatrix(htmlMesh, useRightHandedSystem);
|
|
296
|
-
let style = `translate(-50%, -50%) ${this.
|
|
296
|
+
let style = `translate(-50%, -50%) ${this._getHtmlContentCssMatrix(scaledAndTranslatedObjectMatrix, useRightHandedSystem)}`;
|
|
297
297
|
// In a right handed system, screens are on the wrong side of the mesh, so we have to rotate by Math.PI which results in the matrix3d seen below
|
|
298
298
|
style += `${useRightHandedSystem ? "matrix3d(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)" : ""}`;
|
|
299
299
|
if (htmlMeshData.style !== style) {
|
|
@@ -373,7 +373,7 @@ export class HtmlMeshRenderer {
|
|
|
373
373
|
cameraMatrixWorldAsArray[8] = cameraRotationMatrix.m[8] * direction;
|
|
374
374
|
cameraMatrixWorldAsArray[9] = cameraRotationMatrix.m[9] * direction;
|
|
375
375
|
Matrix.FromArrayToRef(cameraMatrixWorldAsArray, 0, cameraMatrixWorld);
|
|
376
|
-
const cameraCSSMatrix = this.
|
|
376
|
+
const cameraCSSMatrix = this._getCameraCssMatrix(cameraMatrixWorld);
|
|
377
377
|
const style = cameraCSSMatrix;
|
|
378
378
|
if (this._cache.cameraData.style !== style) {
|
|
379
379
|
const source = [this._inSceneElements?.cameraElement, this._overlayElements?.cameraElement];
|
|
@@ -414,7 +414,7 @@ export class HtmlMeshRenderer {
|
|
|
414
414
|
const canvasRect = this._engine.getRenderingCanvasClientRect();
|
|
415
415
|
// canvas rect may be null if layout not complete
|
|
416
416
|
if (!canvasRect) {
|
|
417
|
-
Logger.Warn(
|
|
417
|
+
Logger.Warn(PositionUpdateFailMessage);
|
|
418
418
|
return;
|
|
419
419
|
}
|
|
420
420
|
const scrollTop = window.scrollY;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"htmlMeshRenderer.js","sourceRoot":"","sources":["../../../../dev/addons/src/htmlMesh/htmlMeshRenderer.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Scene } from \"core/scene\";\r\nimport { Matrix, Quaternion, Vector3 } from \"core/Maths/math\";\r\n\r\nimport type { HtmlMesh } from \"./htmlMesh\";\r\nimport { Camera } from \"core/Cameras/camera\";\r\nimport type { SubMesh } from \"core/Meshes/subMesh\";\r\nimport { RenderingGroup } from \"core/Rendering/renderingGroup\";\r\n\r\nimport type { Observer } from \"core/Misc/observable\";\r\nimport { Logger } from \"core/Misc/logger\";\r\nimport type { AbstractEngine } from \"core/Engines\";\r\n\r\nconst _positionUpdateFailMessage = \"Failed to update html mesh renderer position due to failure to get canvas rect. HtmlMesh instances may not render correctly\";\r\nconst babylonUnitsToPixels = 100;\r\n\r\n/**\r\n * A function that compares two submeshes and returns a number indicating which\r\n * should be rendered first.\r\n */\r\ntype RenderOrderFunction = (subMeshA: SubMesh, subMeshB: SubMesh) => number;\r\n\r\ntype RenderLayerElements = {\r\n container: HTMLElement;\r\n domElement: HTMLElement;\r\n cameraElement: HTMLElement;\r\n};\r\n\r\n// Returns a function that ensures that HtmlMeshes are rendered before all other meshes.\r\n// Note this will only be applied to group 0.\r\n// If neither mesh is an HtmlMesh, then the default render order is used\r\n// This prevents HtmlMeshes from appearing in front of other meshes when they are behind them\r\nconst renderOrderFunc = (defaultRenderOrder: RenderOrderFunction): RenderOrderFunction => {\r\n return (subMeshA: SubMesh, subMeshB: SubMesh) => {\r\n const meshA = subMeshA.getMesh();\r\n const meshB = subMeshB.getMesh();\r\n\r\n // Use property check instead of instanceof since it is less expensive and\r\n // this will be called many times per frame\r\n const meshAIsHtmlMesh = (meshA as any)[\"isHtmlMesh\"];\r\n const meshBIsHtmlMesh = (meshB as any)[\"isHtmlMesh\"];\r\n if (meshAIsHtmlMesh) {\r\n return meshBIsHtmlMesh ? (meshA.absolutePosition.z <= meshB.absolutePosition.z ? 1 : -1) : -1;\r\n } else {\r\n return meshBIsHtmlMesh ? 1 : defaultRenderOrder(subMeshA, subMeshB);\r\n }\r\n };\r\n};\r\n\r\n/**\r\n * An instance of this is required to render HtmlMeshes in the scene.\r\n * if using HtmlMeshes, you must not set render order for group 0 using\r\n * scene.setRenderingOrder. You must instead pass the compare functions\r\n * to the HtmlMeshRenderer constructor. If you do not, then your render\r\n * order will be overwritten if the HtmlMeshRenderer is created after and\r\n * the HtmlMeshes will not render correctly (they will appear in front of\r\n * meshes that are actually in front of them) if the HtmlMeshRenderer is\r\n * created before.\r\n */\r\nexport class HtmlMeshRenderer {\r\n private _containerId?: string;\r\n private _inSceneElements?: RenderLayerElements | null;\r\n private _overlayElements?: RenderLayerElements | null;\r\n private _engine: AbstractEngine;\r\n\r\n private _cache = {\r\n cameraData: { fov: 0, position: new Vector3(), style: \"\" },\r\n htmlMeshData: new WeakMap<object, { style: string }>(),\r\n };\r\n private _width = 0;\r\n private _height = 0;\r\n private _heightHalf = 0;\r\n\r\n private _cameraWorldMatrix?: Matrix;\r\n\r\n // Create some refs to avoid creating new objects every frame\r\n private _temp = {\r\n scaleTransform: new Vector3(),\r\n rotationTransform: new Quaternion(),\r\n positionTransform: new Vector3(),\r\n objectMatrix: Matrix.Identity(),\r\n cameraWorldMatrix: Matrix.Identity(),\r\n cameraRotationMatrix: Matrix.Identity(),\r\n cameraWorldMatrixAsArray: new Array(16),\r\n };\r\n\r\n // Keep track of DPR so we can resize if DPR changes\r\n // Otherwise the DOM content will scale, but the mesh won't\r\n private _lastDevicePixelRatio = window.devicePixelRatio;\r\n\r\n // Keep track of camera matrix changes so we only update the\r\n // DOM element styles when necessary\r\n private _cameraMatrixUpdated = true;\r\n\r\n // Keep track of position changes so we only update the DOM element\r\n // styles when necessary\r\n private _previousCanvasDocumentPosition = {\r\n top: 0,\r\n left: 0,\r\n };\r\n\r\n private _renderObserver: Observer<Scene> | null = null;\r\n\r\n /**\r\n * Contruct an instance of HtmlMeshRenderer\r\n * @param scene\r\n * @param options object containing the following optional properties:\r\n * @returns\r\n */\r\n constructor(\r\n scene: Scene,\r\n {\r\n parentContainerId = null,\r\n _containerId = \"css-container\",\r\n enableOverlayRender = true,\r\n defaultOpaqueRenderOrder = RenderingGroup.PainterSortCompare,\r\n defaultAlphaTestRenderOrder = RenderingGroup.PainterSortCompare,\r\n defaultTransparentRenderOrder = RenderingGroup.defaultTransparentSortCompare,\r\n }: {\r\n parentContainerId?: string | null;\r\n _containerId?: string;\r\n defaultOpaqueRenderOrder?: RenderOrderFunction;\r\n defaultAlphaTestRenderOrder?: RenderOrderFunction;\r\n defaultTransparentRenderOrder?: RenderOrderFunction;\r\n enableOverlayRender?: boolean;\r\n } = {}\r\n ) {\r\n // Requires a browser to work. Only init if we are in a browser\r\n if (typeof document === \"undefined\") {\r\n return;\r\n }\r\n this._containerId = _containerId;\r\n this._init(scene, parentContainerId, enableOverlayRender, defaultOpaqueRenderOrder, defaultAlphaTestRenderOrder, defaultTransparentRenderOrder);\r\n }\r\n\r\n /**\r\n * Dispose of the HtmlMeshRenderer\r\n */\r\n public dispose() {\r\n if (this._renderObserver) {\r\n this._renderObserver.remove();\r\n this._renderObserver = null;\r\n }\r\n\r\n this._overlayElements?.container.remove();\r\n this._overlayElements = null;\r\n\r\n this._inSceneElements?.container.remove();\r\n this._inSceneElements = null;\r\n }\r\n\r\n protected _init(\r\n scene: Scene,\r\n parentContainerId: string | null,\r\n enableOverlayRender: boolean,\r\n defaultOpaqueRenderOrder: RenderOrderFunction,\r\n defaultAlphaTestRenderOrder: RenderOrderFunction,\r\n defaultTransparentRenderOrder: RenderOrderFunction\r\n ): void {\r\n // Requires a browser to work. Only init if we are in a browser\r\n if (typeof document === \"undefined\") {\r\n return;\r\n }\r\n\r\n // Create the DOM containers\r\n let parentContainer = parentContainerId ? document.getElementById(parentContainerId) : document.body;\r\n\r\n if (!parentContainer) {\r\n parentContainer = document.body;\r\n }\r\n\r\n // if the container already exists, then remove it\r\n const inSceneContainerId = `${this._containerId}_in_scene`;\r\n this._inSceneElements = this._createRenderLayerElements(inSceneContainerId);\r\n\r\n parentContainer.insertBefore(this._inSceneElements.container, parentContainer.firstChild);\r\n\r\n if (enableOverlayRender) {\r\n const overlayContainerId = `${this._containerId}_overlay`;\r\n this._overlayElements = this._createRenderLayerElements(overlayContainerId);\r\n const zIndex = +(scene.getEngine().getRenderingCanvas()!.style.zIndex ?? \"0\") + 1;\r\n this._overlayElements.container.style.zIndex = `${zIndex}`;\r\n this._overlayElements.container.style.pointerEvents = \"none\";\r\n parentContainer.insertBefore(this._overlayElements.container, parentContainer.firstChild);\r\n }\r\n this._engine = scene.getEngine();\r\n const clientRect = this._engine.getRenderingCanvasClientRect();\r\n if (!clientRect) {\r\n throw new Error(\"Failed to get client rect for rendering canvas\");\r\n }\r\n\r\n // Set the size and resize behavior\r\n this._setSize(clientRect.width, clientRect.height);\r\n\r\n this._engine.onResizeObservable.add(() => {\r\n const clientRect = this._engine.getRenderingCanvasClientRect();\r\n if (clientRect) {\r\n this._setSize(clientRect.width, clientRect.height);\r\n }\r\n });\r\n\r\n let projectionObs: Observer<Camera>;\r\n let matrixObs: Observer<Camera>;\r\n\r\n const observeCamera = () => {\r\n const camera = scene.activeCamera;\r\n if (camera) {\r\n projectionObs = camera.onProjectionMatrixChangedObservable.add(() => {\r\n this._onCameraMatrixChanged(camera);\r\n });\r\n matrixObs = camera.onViewMatrixChangedObservable.add(() => {\r\n this._onCameraMatrixChanged(camera);\r\n });\r\n }\r\n };\r\n\r\n observeCamera();\r\n\r\n scene.onActiveCameraChanged.add(() => {\r\n if (projectionObs) {\r\n scene.activeCamera?.onProjectionMatrixChangedObservable.remove(projectionObs);\r\n }\r\n if (matrixObs) {\r\n scene.activeCamera?.onViewMatrixChangedObservable.remove(matrixObs);\r\n }\r\n observeCamera();\r\n });\r\n\r\n // We need to make sure that HtmlMeshes are rendered before all other meshes\r\n // so that they don't appear in front of meshes that are actually in front of them\r\n // Updating the render order isn't ideal, but it is the only way to acheive this\r\n // The implication is that an app using the HtmlMeshRendered must set the scene render order\r\n // via the HtmlMeshRendered constructor\r\n const opaqueRenderOrder = renderOrderFunc(defaultOpaqueRenderOrder);\r\n const alphaTestRenderOrder = renderOrderFunc(defaultAlphaTestRenderOrder);\r\n const transparentRenderOrder = renderOrderFunc(defaultTransparentRenderOrder);\r\n scene.setRenderingOrder(0, opaqueRenderOrder, alphaTestRenderOrder, transparentRenderOrder);\r\n\r\n this._renderObserver = scene.onBeforeRenderObservable.add(() => {\r\n this._render(scene, scene.activeCamera as Camera);\r\n });\r\n }\r\n\r\n private _createRenderLayerElements(containerId: string): RenderLayerElements {\r\n const existingContainer = document.getElementById(containerId);\r\n if (existingContainer) {\r\n existingContainer.remove();\r\n }\r\n const container = document.createElement(\"div\");\r\n container.id = containerId;\r\n container.style.position = \"absolute\";\r\n container.style.width = \"100%\";\r\n container.style.height = \"100%\";\r\n container.style.zIndex = \"-1\";\r\n\r\n const domElement = document.createElement(\"div\");\r\n domElement.style.overflow = \"hidden\";\r\n\r\n const cameraElement = document.createElement(\"div\");\r\n\r\n cameraElement.style.webkitTransformStyle = \"preserve-3d\";\r\n cameraElement.style.transformStyle = \"preserve-3d\";\r\n\r\n cameraElement.style.pointerEvents = \"none\";\r\n\r\n domElement.appendChild(cameraElement);\r\n container.appendChild(domElement);\r\n return {\r\n container,\r\n domElement,\r\n cameraElement,\r\n };\r\n }\r\n\r\n protected _getSize(): { width: number; height: number } {\r\n return {\r\n width: this._width,\r\n height: this._height,\r\n };\r\n }\r\n\r\n protected _setSize(width: number, height: number): void {\r\n this._width = width;\r\n this._height = height;\r\n this._heightHalf = this._height / 2;\r\n\r\n if (!this._inSceneElements || !this._overlayElements) {\r\n return;\r\n }\r\n\r\n const domElements = [this._inSceneElements!.domElement, this._overlayElements!.domElement, this._inSceneElements!.cameraElement, this._overlayElements!.cameraElement];\r\n for (const dom of domElements) {\r\n if (dom) {\r\n dom.style.width = `${width}px`;\r\n dom.style.height = `${height}px`;\r\n }\r\n }\r\n }\r\n\r\n // prettier-ignore\r\n protected _getCameraCSSMatrix(matrix: Matrix): string {\r\n const elements = matrix.m;\r\n return `matrix3d(${\r\n this._epsilon( elements[0] )\r\n },${\r\n this._epsilon( - elements[1] )\r\n },${\r\n this._epsilon( elements[2] )\r\n },${\r\n this._epsilon( elements[3] )\r\n },${\r\n this._epsilon( elements[4] )\r\n },${\r\n this._epsilon( - elements[5] )\r\n },${\r\n this._epsilon( elements[6] )\r\n },${\r\n this._epsilon( elements[7] )\r\n },${\r\n this._epsilon( elements[8] )\r\n },${\r\n this._epsilon( - elements[9] )\r\n },${\r\n this._epsilon( elements[10] )\r\n },${\r\n this._epsilon( elements[11] )\r\n },${\r\n this._epsilon( elements[12] )\r\n },${\r\n this._epsilon( - elements[13] )\r\n },${\r\n this._epsilon( elements[14] )\r\n },${\r\n this._epsilon( elements[15] )\r\n })`;\r\n }\r\n\r\n // Convert a Babylon world matrix to a CSS matrix\r\n // This also handles conversion from BJS left handed coords\r\n // to CSS right handed coords\r\n // prettier-ignore\r\n protected _getHtmlContentCSSMatrix(matrix: Matrix, useRightHandedSystem: boolean): string {\r\n const elements = matrix.m;\r\n // In a right handed coordinate system, the elements 11 to 14 have to change their direction\r\n const direction = useRightHandedSystem ? -1 : 1;\r\n const matrix3d = `matrix3d(${\r\n this._epsilon( elements[0] )\r\n },${\r\n this._epsilon( elements[1] )\r\n },${\r\n this._epsilon( elements[2] * -direction )\r\n },${\r\n this._epsilon( elements[3] )\r\n },${\r\n this._epsilon( - elements[4] )\r\n },${\r\n this._epsilon( - elements[5] )\r\n },${\r\n this._epsilon( elements[6] * direction )\r\n },${\r\n this._epsilon( - elements[7] )\r\n },${\r\n this._epsilon( elements[8] * -direction )\r\n },${\r\n this._epsilon( elements[9] * -direction )\r\n },${\r\n this._epsilon( elements[10] )\r\n },${\r\n this._epsilon( elements[11] * direction )\r\n },${\r\n this._epsilon( elements[12] * direction )\r\n },${\r\n this._epsilon( elements[13] * direction )\r\n },${\r\n this._epsilon( elements[14] * direction )\r\n },${\r\n this._epsilon( elements[15] )\r\n })`;\r\n return matrix3d;\r\n }\r\n\r\n protected _getTransformationMatrix(htmlMesh: HtmlMesh, useRightHandedSystem: boolean): Matrix {\r\n // Get the camera world matrix\r\n // Make sure the camera world matrix is up to date\r\n if (!this._cameraWorldMatrix) {\r\n this._cameraWorldMatrix = htmlMesh.getScene().activeCamera?.getWorldMatrix();\r\n }\r\n if (!this._cameraWorldMatrix) {\r\n return Matrix.Identity();\r\n }\r\n\r\n const objectWorldMatrix = htmlMesh.getWorldMatrix();\r\n\r\n // Scale the object matrix by the base scale factor for the mesh\r\n // which is the ratio of the mesh width/height to the renderer\r\n // width/height divided by the babylon units to pixels ratio\r\n let widthScaleFactor = 1;\r\n let heightScaleFactor = 1;\r\n if (htmlMesh.sourceWidth && htmlMesh.sourceHeight) {\r\n widthScaleFactor = htmlMesh.width! / (htmlMesh.sourceWidth / babylonUnitsToPixels);\r\n heightScaleFactor = htmlMesh.height! / (htmlMesh.sourceHeight / babylonUnitsToPixels);\r\n }\r\n\r\n // Apply the scale to the object's world matrix. Note we aren't scaling\r\n // the object, just getting a matrix as though it were scaled, so we can\r\n // scale the content\r\n const scaleTransform = this._temp.scaleTransform;\r\n const rotationTransform = this._temp.rotationTransform;\r\n const positionTransform = this._temp.positionTransform;\r\n const scaledAndTranslatedObjectMatrix = this._temp.objectMatrix;\r\n\r\n objectWorldMatrix.decompose(scaleTransform, rotationTransform, positionTransform);\r\n scaleTransform.x *= widthScaleFactor;\r\n scaleTransform.y *= heightScaleFactor;\r\n\r\n Matrix.ComposeToRef(scaleTransform, rotationTransform, positionTransform, scaledAndTranslatedObjectMatrix);\r\n\r\n // Adjust direction of 12 and 13 of the transformation matrix based on the handedness of the system\r\n const direction = useRightHandedSystem ? -1 : 1;\r\n // Adjust translation values to be from camera vs world origin\r\n // Note that we are also adjusting these values to be pixels vs Babylon units\r\n const position = htmlMesh.getAbsolutePosition();\r\n scaledAndTranslatedObjectMatrix.setRowFromFloats(\r\n 3,\r\n (-this._cameraWorldMatrix.m[12] + position.x) * babylonUnitsToPixels * direction,\r\n (-this._cameraWorldMatrix.m[13] + position.y) * babylonUnitsToPixels * direction,\r\n (this._cameraWorldMatrix.m[14] - position.z) * babylonUnitsToPixels,\r\n this._cameraWorldMatrix.m[15] * 0.00001 * babylonUnitsToPixels\r\n );\r\n\r\n // Adjust other values to be pixels vs Babylon units\r\n scaledAndTranslatedObjectMatrix.multiplyAtIndex(3, babylonUnitsToPixels);\r\n scaledAndTranslatedObjectMatrix.multiplyAtIndex(7, babylonUnitsToPixels);\r\n scaledAndTranslatedObjectMatrix.multiplyAtIndex(11, babylonUnitsToPixels);\r\n\r\n return scaledAndTranslatedObjectMatrix;\r\n }\r\n\r\n protected _renderHtmlMesh(htmlMesh: HtmlMesh, useRightHandedSystem: boolean) {\r\n if (!htmlMesh.element || !htmlMesh.element.firstElementChild) {\r\n // nothing to render, so bail\r\n return;\r\n }\r\n\r\n // We need to ensure html mesh data is initialized before\r\n // computing the base scale factor\r\n let htmlMeshData = this._cache.htmlMeshData.get(htmlMesh);\r\n if (!htmlMeshData) {\r\n htmlMeshData = { style: \"\" };\r\n this._cache.htmlMeshData.set(htmlMesh, htmlMeshData);\r\n }\r\n\r\n const cameraElement = htmlMesh._isCanvasOverlay ? this._overlayElements?.cameraElement : this._inSceneElements?.cameraElement;\r\n\r\n if (htmlMesh.element.parentNode !== cameraElement) {\r\n cameraElement!.appendChild(htmlMesh.element);\r\n }\r\n\r\n // If the htmlMesh content has changed, update the base scale factor\r\n if (htmlMesh.requiresUpdate) {\r\n this._updateBaseScaleFactor(htmlMesh);\r\n }\r\n\r\n // Get the transformation matrix for the html mesh\r\n const scaledAndTranslatedObjectMatrix = this._getTransformationMatrix(htmlMesh, useRightHandedSystem);\r\n\r\n let style = `translate(-50%, -50%) ${this._getHtmlContentCSSMatrix(scaledAndTranslatedObjectMatrix, useRightHandedSystem)}`;\r\n // In a right handed system, screens are on the wrong side of the mesh, so we have to rotate by Math.PI which results in the matrix3d seen below\r\n style += `${useRightHandedSystem ? \"matrix3d(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)\" : \"\"}`;\r\n\r\n if (htmlMeshData.style !== style) {\r\n htmlMesh.element.style.webkitTransform = style;\r\n htmlMesh.element.style.transform = style;\r\n }\r\n\r\n htmlMesh._markAsUpdated();\r\n }\r\n\r\n protected _render(scene: Scene, camera: Camera) {\r\n let needsUpdate = false;\r\n\r\n const useRightHandedSystem = scene.useRightHandedSystem;\r\n\r\n // Update the container position and size if necessary\r\n this._updateContainerPositionIfNeeded();\r\n\r\n // Check for a camera change\r\n if (this._cameraMatrixUpdated) {\r\n this._cameraMatrixUpdated = false;\r\n needsUpdate = true;\r\n }\r\n\r\n // If the camera position has changed, then we also need to update\r\n if (\r\n camera.position.x !== this._cache.cameraData.position.x ||\r\n camera.position.y !== this._cache.cameraData.position.y ||\r\n camera.position.z !== this._cache.cameraData.position.z\r\n ) {\r\n this._cache.cameraData.position.copyFrom(camera.position);\r\n needsUpdate = true;\r\n }\r\n\r\n // Check for a dpr change\r\n if (window.devicePixelRatio !== this._lastDevicePixelRatio) {\r\n this._lastDevicePixelRatio = window.devicePixelRatio;\r\n Logger.Log(\"In render - dpr changed: \", this._lastDevicePixelRatio);\r\n needsUpdate = true;\r\n }\r\n\r\n // Check if any meshes need to be updated\r\n const meshesNeedingUpdate = scene.meshes.filter((mesh) => (mesh as any)[\"isHtmlMesh\"] && (needsUpdate || (mesh as HtmlMesh).requiresUpdate));\r\n needsUpdate = needsUpdate || meshesNeedingUpdate.length > 0;\r\n\r\n if (!needsUpdate) {\r\n return;\r\n }\r\n\r\n // Get a projection matrix for the camera\r\n const projectionMatrix = camera.getProjectionMatrix();\r\n const fov = projectionMatrix.m[5] * this._heightHalf;\r\n\r\n if (this._cache.cameraData.fov !== fov) {\r\n const source = [this._overlayElements?.domElement, this._inSceneElements?.domElement];\r\n if (camera.mode == Camera.PERSPECTIVE_CAMERA) {\r\n for (const el of source) {\r\n if (el) {\r\n el.style.webkitPerspective = fov + \"px\";\r\n el.style.perspective = fov + \"px\";\r\n }\r\n }\r\n } else {\r\n for (const el of source) {\r\n if (el) {\r\n el.style.webkitPerspective = \"\";\r\n el.style.perspective = \"\";\r\n }\r\n }\r\n }\r\n this._cache.cameraData.fov = fov;\r\n }\r\n\r\n // Get the CSS matrix for the camera (which will include any camera rotation)\r\n if (camera.parent === null) {\r\n camera.computeWorldMatrix();\r\n }\r\n\r\n const cameraMatrixWorld = this._temp.cameraWorldMatrix;\r\n cameraMatrixWorld.copyFrom(camera.getWorldMatrix());\r\n const cameraRotationMatrix = this._temp.cameraRotationMatrix;\r\n cameraMatrixWorld.getRotationMatrix().transposeToRef(cameraRotationMatrix);\r\n\r\n const cameraMatrixWorldAsArray = this._temp.cameraWorldMatrixAsArray;\r\n cameraMatrixWorld.copyToArray(cameraMatrixWorldAsArray);\r\n\r\n // For a few values, we have to adjust the direction based on the handedness of the system\r\n const direction = useRightHandedSystem ? 1 : -1;\r\n\r\n cameraMatrixWorldAsArray[1] = cameraRotationMatrix.m[1];\r\n cameraMatrixWorldAsArray[2] = cameraRotationMatrix.m[2] * direction;\r\n cameraMatrixWorldAsArray[4] = cameraRotationMatrix.m[4] * direction;\r\n cameraMatrixWorldAsArray[6] = cameraRotationMatrix.m[6] * direction;\r\n cameraMatrixWorldAsArray[8] = cameraRotationMatrix.m[8] * direction;\r\n cameraMatrixWorldAsArray[9] = cameraRotationMatrix.m[9] * direction;\r\n\r\n Matrix.FromArrayToRef(cameraMatrixWorldAsArray, 0, cameraMatrixWorld);\r\n\r\n const cameraCSSMatrix = this._getCameraCSSMatrix(cameraMatrixWorld);\r\n const style = cameraCSSMatrix;\r\n\r\n if (this._cache.cameraData.style !== style) {\r\n const source = [this._inSceneElements?.cameraElement, this._overlayElements?.cameraElement];\r\n for (const el of source) {\r\n if (el) {\r\n el.style.webkitTransform = style;\r\n el.style.transform = style;\r\n }\r\n }\r\n this._cache.cameraData.style = style;\r\n }\r\n\r\n // _Render objects if necessary\r\n for (const mesh of meshesNeedingUpdate) {\r\n this._renderHtmlMesh(mesh as HtmlMesh, useRightHandedSystem);\r\n }\r\n }\r\n\r\n protected _updateBaseScaleFactor(htmlMesh: HtmlMesh) {\r\n // Get screen width and height\r\n let screenWidth = this._width;\r\n let screenHeight = this._height;\r\n\r\n // Calculate aspect ratios\r\n const htmlMeshAspectRatio = (htmlMesh.width || 1) / (htmlMesh.height || 1);\r\n const screenAspectRatio = screenWidth / screenHeight;\r\n\r\n // Adjust screen dimensions based on aspect ratios\r\n if (htmlMeshAspectRatio > screenAspectRatio) {\r\n // If the HTML mesh is wider relative to its height than the screen, adjust the screen width\r\n screenWidth = screenHeight * htmlMeshAspectRatio;\r\n } else {\r\n // If the HTML mesh is taller relative to its width than the screen, adjust the screen height\r\n screenHeight = screenWidth / htmlMeshAspectRatio;\r\n }\r\n\r\n // Set content to fill screen so we get max resolution when it is shrunk to fit the mesh\r\n htmlMesh.setContentSizePx(screenWidth, screenHeight);\r\n }\r\n\r\n protected _updateContainerPositionIfNeeded() {\r\n // Determine if the canvas has moved on the screen\r\n const canvasRect = this._engine.getRenderingCanvasClientRect();\r\n\r\n // canvas rect may be null if layout not complete\r\n if (!canvasRect) {\r\n Logger.Warn(_positionUpdateFailMessage);\r\n return;\r\n }\r\n const scrollTop = window.scrollY;\r\n const scrollLeft = window.scrollX;\r\n const canvasDocumentTop = canvasRect.top + scrollTop;\r\n const canvasDocumentLeft = canvasRect.left + scrollLeft;\r\n\r\n if (this._previousCanvasDocumentPosition.top !== canvasDocumentTop || this._previousCanvasDocumentPosition.left !== canvasDocumentLeft) {\r\n this._previousCanvasDocumentPosition.top = canvasDocumentTop;\r\n this._previousCanvasDocumentPosition.left = canvasDocumentLeft;\r\n\r\n const source = [this._inSceneElements?.container, this._overlayElements?.container];\r\n for (const container of source) {\r\n if (!container) {\r\n return;\r\n }\r\n // set the top and left of the css container to match the canvas\r\n const containerParent = container.offsetParent as HTMLElement;\r\n const parentRect = containerParent.getBoundingClientRect();\r\n const parentDocumentTop = parentRect.top + scrollTop;\r\n const parentDocumentLeft = parentRect.left + scrollLeft;\r\n\r\n const ancestorMarginsAndPadding = this._getAncestorMarginsAndPadding(containerParent);\r\n\r\n // Add the body margin\r\n const bodyStyle = window.getComputedStyle(document.body);\r\n const bodyMarginTop = parseInt(bodyStyle.marginTop, 10);\r\n const bodyMarginLeft = parseInt(bodyStyle.marginLeft, 10);\r\n\r\n container.style.top = `${canvasDocumentTop - parentDocumentTop - ancestorMarginsAndPadding.marginTop + ancestorMarginsAndPadding.paddingTop + bodyMarginTop}px`;\r\n container.style.left = `${\r\n canvasDocumentLeft - parentDocumentLeft - ancestorMarginsAndPadding.marginLeft + ancestorMarginsAndPadding.paddingLeft + bodyMarginLeft\r\n }px`;\r\n }\r\n }\r\n }\r\n\r\n protected _onCameraMatrixChanged = (camera: Camera) => {\r\n this._cameraWorldMatrix = camera.getWorldMatrix();\r\n this._cameraMatrixUpdated = true;\r\n };\r\n\r\n private _epsilon(value: number) {\r\n return Math.abs(value) < 1e-10 ? 0 : value;\r\n }\r\n\r\n // Get total margins and padding for an element, excluding the body and document margins\r\n private _getAncestorMarginsAndPadding(element: HTMLElement) {\r\n let marginTop = 0;\r\n let marginLeft = 0;\r\n let paddingTop = 0;\r\n let paddingLeft = 0;\r\n\r\n while (element && element !== document.body && element !== document.documentElement) {\r\n const style = window.getComputedStyle(element);\r\n marginTop += parseInt(style.marginTop, 10);\r\n marginLeft += parseInt(style.marginLeft, 10);\r\n paddingTop += parseInt(style.paddingTop, 10);\r\n paddingLeft += parseInt(style.paddingLeft, 10);\r\n element = element.offsetParent as HTMLElement;\r\n }\r\n\r\n return { marginTop, marginLeft, paddingTop, paddingLeft };\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"htmlMeshRenderer.js","sourceRoot":"","sources":["../../../../dev/addons/src/htmlMesh/htmlMeshRenderer.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Scene } from \"core/scene\";\r\nimport { Matrix, Quaternion, Vector3 } from \"core/Maths/math\";\r\n\r\nimport type { HtmlMesh } from \"./htmlMesh\";\r\nimport { Camera } from \"core/Cameras/camera\";\r\nimport type { SubMesh } from \"core/Meshes/subMesh\";\r\nimport { RenderingGroup } from \"core/Rendering/renderingGroup\";\r\n\r\nimport type { Observer } from \"core/Misc/observable\";\r\nimport { Logger } from \"core/Misc/logger\";\r\nimport type { AbstractEngine } from \"core/Engines\";\r\n\r\nconst PositionUpdateFailMessage = \"Failed to update html mesh renderer position due to failure to get canvas rect. HtmlMesh instances may not render correctly\";\r\nconst BabylonUnitsToPixels = 100;\r\n\r\n/**\r\n * A function that compares two submeshes and returns a number indicating which\r\n * should be rendered first.\r\n */\r\ntype RenderOrderFunction = (subMeshA: SubMesh, subMeshB: SubMesh) => number;\r\n\r\ntype RenderLayerElements = {\r\n container: HTMLElement;\r\n domElement: HTMLElement;\r\n cameraElement: HTMLElement;\r\n};\r\n\r\n// Returns a function that ensures that HtmlMeshes are rendered before all other meshes.\r\n// Note this will only be applied to group 0.\r\n// If neither mesh is an HtmlMesh, then the default render order is used\r\n// This prevents HtmlMeshes from appearing in front of other meshes when they are behind them\r\nconst RenderOrderFunc = (defaultRenderOrder: RenderOrderFunction): RenderOrderFunction => {\r\n return (subMeshA: SubMesh, subMeshB: SubMesh) => {\r\n const meshA = subMeshA.getMesh();\r\n const meshB = subMeshB.getMesh();\r\n\r\n // Use property check instead of instanceof since it is less expensive and\r\n // this will be called many times per frame\r\n const meshIsHtmlMeshA = (meshA as any)[\"isHtmlMesh\"];\r\n const meshIsHtmlMeshB = (meshB as any)[\"isHtmlMesh\"];\r\n if (meshIsHtmlMeshA) {\r\n return meshIsHtmlMeshB ? (meshA.absolutePosition.z <= meshB.absolutePosition.z ? 1 : -1) : -1;\r\n } else {\r\n return meshIsHtmlMeshB ? 1 : defaultRenderOrder(subMeshA, subMeshB);\r\n }\r\n };\r\n};\r\n\r\n/**\r\n * An instance of this is required to render HtmlMeshes in the scene.\r\n * if using HtmlMeshes, you must not set render order for group 0 using\r\n * scene.setRenderingOrder. You must instead pass the compare functions\r\n * to the HtmlMeshRenderer constructor. If you do not, then your render\r\n * order will be overwritten if the HtmlMeshRenderer is created after and\r\n * the HtmlMeshes will not render correctly (they will appear in front of\r\n * meshes that are actually in front of them) if the HtmlMeshRenderer is\r\n * created before.\r\n */\r\nexport class HtmlMeshRenderer {\r\n private _containerId?: string;\r\n private _inSceneElements?: RenderLayerElements | null;\r\n private _overlayElements?: RenderLayerElements | null;\r\n private _engine: AbstractEngine;\r\n\r\n private _cache = {\r\n cameraData: { fov: 0, position: new Vector3(), style: \"\" },\r\n htmlMeshData: new WeakMap<object, { style: string }>(),\r\n };\r\n private _width = 0;\r\n private _height = 0;\r\n private _heightHalf = 0;\r\n\r\n private _cameraWorldMatrix?: Matrix;\r\n\r\n // Create some refs to avoid creating new objects every frame\r\n private _temp = {\r\n scaleTransform: new Vector3(),\r\n rotationTransform: new Quaternion(),\r\n positionTransform: new Vector3(),\r\n objectMatrix: Matrix.Identity(),\r\n cameraWorldMatrix: Matrix.Identity(),\r\n cameraRotationMatrix: Matrix.Identity(),\r\n cameraWorldMatrixAsArray: new Array(16),\r\n };\r\n\r\n // Keep track of DPR so we can resize if DPR changes\r\n // Otherwise the DOM content will scale, but the mesh won't\r\n private _lastDevicePixelRatio = window.devicePixelRatio;\r\n\r\n // Keep track of camera matrix changes so we only update the\r\n // DOM element styles when necessary\r\n private _cameraMatrixUpdated = true;\r\n\r\n // Keep track of position changes so we only update the DOM element\r\n // styles when necessary\r\n private _previousCanvasDocumentPosition = {\r\n top: 0,\r\n left: 0,\r\n };\r\n\r\n private _renderObserver: Observer<Scene> | null = null;\r\n\r\n /**\r\n * Contruct an instance of HtmlMeshRenderer\r\n * @param scene\r\n * @param options object containing the following optional properties:\r\n * @returns\r\n */\r\n constructor(\r\n scene: Scene,\r\n {\r\n parentContainerId = null,\r\n _containerId = \"css-container\",\r\n enableOverlayRender = true,\r\n defaultOpaqueRenderOrder = RenderingGroup.PainterSortCompare,\r\n defaultAlphaTestRenderOrder = RenderingGroup.PainterSortCompare,\r\n defaultTransparentRenderOrder = RenderingGroup.defaultTransparentSortCompare,\r\n }: {\r\n parentContainerId?: string | null;\r\n _containerId?: string;\r\n defaultOpaqueRenderOrder?: RenderOrderFunction;\r\n defaultAlphaTestRenderOrder?: RenderOrderFunction;\r\n defaultTransparentRenderOrder?: RenderOrderFunction;\r\n enableOverlayRender?: boolean;\r\n } = {}\r\n ) {\r\n // Requires a browser to work. Only init if we are in a browser\r\n if (typeof document === \"undefined\") {\r\n return;\r\n }\r\n this._containerId = _containerId;\r\n this._init(scene, parentContainerId, enableOverlayRender, defaultOpaqueRenderOrder, defaultAlphaTestRenderOrder, defaultTransparentRenderOrder);\r\n }\r\n\r\n /**\r\n * Dispose of the HtmlMeshRenderer\r\n */\r\n public dispose() {\r\n if (this._renderObserver) {\r\n this._renderObserver.remove();\r\n this._renderObserver = null;\r\n }\r\n\r\n this._overlayElements?.container.remove();\r\n this._overlayElements = null;\r\n\r\n this._inSceneElements?.container.remove();\r\n this._inSceneElements = null;\r\n }\r\n\r\n protected _init(\r\n scene: Scene,\r\n parentContainerId: string | null,\r\n enableOverlayRender: boolean,\r\n defaultOpaqueRenderOrder: RenderOrderFunction,\r\n defaultAlphaTestRenderOrder: RenderOrderFunction,\r\n defaultTransparentRenderOrder: RenderOrderFunction\r\n ): void {\r\n // Requires a browser to work. Only init if we are in a browser\r\n if (typeof document === \"undefined\") {\r\n return;\r\n }\r\n\r\n // Create the DOM containers\r\n let parentContainer = parentContainerId ? document.getElementById(parentContainerId) : document.body;\r\n\r\n if (!parentContainer) {\r\n parentContainer = document.body;\r\n }\r\n\r\n // if the container already exists, then remove it\r\n const inSceneContainerId = `${this._containerId}_in_scene`;\r\n this._inSceneElements = this._createRenderLayerElements(inSceneContainerId);\r\n\r\n parentContainer.insertBefore(this._inSceneElements.container, parentContainer.firstChild);\r\n\r\n if (enableOverlayRender) {\r\n const overlayContainerId = `${this._containerId}_overlay`;\r\n this._overlayElements = this._createRenderLayerElements(overlayContainerId);\r\n const zIndex = +(scene.getEngine().getRenderingCanvas()!.style.zIndex ?? \"0\") + 1;\r\n this._overlayElements.container.style.zIndex = `${zIndex}`;\r\n this._overlayElements.container.style.pointerEvents = \"none\";\r\n parentContainer.insertBefore(this._overlayElements.container, parentContainer.firstChild);\r\n }\r\n this._engine = scene.getEngine();\r\n const clientRect = this._engine.getRenderingCanvasClientRect();\r\n if (!clientRect) {\r\n throw new Error(\"Failed to get client rect for rendering canvas\");\r\n }\r\n\r\n // Set the size and resize behavior\r\n this._setSize(clientRect.width, clientRect.height);\r\n\r\n this._engine.onResizeObservable.add(() => {\r\n const clientRect = this._engine.getRenderingCanvasClientRect();\r\n if (clientRect) {\r\n this._setSize(clientRect.width, clientRect.height);\r\n }\r\n });\r\n\r\n let projectionObs: Observer<Camera>;\r\n let matrixObs: Observer<Camera>;\r\n\r\n const observeCamera = () => {\r\n const camera = scene.activeCamera;\r\n if (camera) {\r\n projectionObs = camera.onProjectionMatrixChangedObservable.add(() => {\r\n this._onCameraMatrixChanged(camera);\r\n });\r\n matrixObs = camera.onViewMatrixChangedObservable.add(() => {\r\n this._onCameraMatrixChanged(camera);\r\n });\r\n }\r\n };\r\n\r\n observeCamera();\r\n\r\n scene.onActiveCameraChanged.add(() => {\r\n if (projectionObs) {\r\n scene.activeCamera?.onProjectionMatrixChangedObservable.remove(projectionObs);\r\n }\r\n if (matrixObs) {\r\n scene.activeCamera?.onViewMatrixChangedObservable.remove(matrixObs);\r\n }\r\n observeCamera();\r\n });\r\n\r\n // We need to make sure that HtmlMeshes are rendered before all other meshes\r\n // so that they don't appear in front of meshes that are actually in front of them\r\n // Updating the render order isn't ideal, but it is the only way to acheive this\r\n // The implication is that an app using the HtmlMeshRendered must set the scene render order\r\n // via the HtmlMeshRendered constructor\r\n const opaqueRenderOrder = RenderOrderFunc(defaultOpaqueRenderOrder);\r\n const alphaTestRenderOrder = RenderOrderFunc(defaultAlphaTestRenderOrder);\r\n const transparentRenderOrder = RenderOrderFunc(defaultTransparentRenderOrder);\r\n scene.setRenderingOrder(0, opaqueRenderOrder, alphaTestRenderOrder, transparentRenderOrder);\r\n\r\n this._renderObserver = scene.onBeforeRenderObservable.add(() => {\r\n this._render(scene, scene.activeCamera as Camera);\r\n });\r\n }\r\n\r\n private _createRenderLayerElements(containerId: string): RenderLayerElements {\r\n const existingContainer = document.getElementById(containerId);\r\n if (existingContainer) {\r\n existingContainer.remove();\r\n }\r\n const container = document.createElement(\"div\");\r\n container.id = containerId;\r\n container.style.position = \"absolute\";\r\n container.style.width = \"100%\";\r\n container.style.height = \"100%\";\r\n container.style.zIndex = \"-1\";\r\n\r\n const domElement = document.createElement(\"div\");\r\n domElement.style.overflow = \"hidden\";\r\n\r\n const cameraElement = document.createElement(\"div\");\r\n\r\n cameraElement.style.webkitTransformStyle = \"preserve-3d\";\r\n cameraElement.style.transformStyle = \"preserve-3d\";\r\n\r\n cameraElement.style.pointerEvents = \"none\";\r\n\r\n domElement.appendChild(cameraElement);\r\n container.appendChild(domElement);\r\n return {\r\n container,\r\n domElement,\r\n cameraElement,\r\n };\r\n }\r\n\r\n protected _getSize(): { width: number; height: number } {\r\n return {\r\n width: this._width,\r\n height: this._height,\r\n };\r\n }\r\n\r\n protected _setSize(width: number, height: number): void {\r\n this._width = width;\r\n this._height = height;\r\n this._heightHalf = this._height / 2;\r\n\r\n if (!this._inSceneElements || !this._overlayElements) {\r\n return;\r\n }\r\n\r\n const domElements = [this._inSceneElements.domElement, this._overlayElements.domElement, this._inSceneElements.cameraElement, this._overlayElements.cameraElement];\r\n for (const dom of domElements) {\r\n if (dom) {\r\n dom.style.width = `${width}px`;\r\n dom.style.height = `${height}px`;\r\n }\r\n }\r\n }\r\n\r\n // prettier-ignore\r\n protected _getCameraCssMatrix(matrix: Matrix): string {\r\n const elements = matrix.m;\r\n return `matrix3d(${\r\n this._epsilon( elements[0] )\r\n },${\r\n this._epsilon( - elements[1] )\r\n },${\r\n this._epsilon( elements[2] )\r\n },${\r\n this._epsilon( elements[3] )\r\n },${\r\n this._epsilon( elements[4] )\r\n },${\r\n this._epsilon( - elements[5] )\r\n },${\r\n this._epsilon( elements[6] )\r\n },${\r\n this._epsilon( elements[7] )\r\n },${\r\n this._epsilon( elements[8] )\r\n },${\r\n this._epsilon( - elements[9] )\r\n },${\r\n this._epsilon( elements[10] )\r\n },${\r\n this._epsilon( elements[11] )\r\n },${\r\n this._epsilon( elements[12] )\r\n },${\r\n this._epsilon( - elements[13] )\r\n },${\r\n this._epsilon( elements[14] )\r\n },${\r\n this._epsilon( elements[15] )\r\n })`;\r\n }\r\n\r\n // Convert a Babylon world matrix to a CSS matrix\r\n // This also handles conversion from BJS left handed coords\r\n // to CSS right handed coords\r\n // prettier-ignore\r\n protected _getHtmlContentCssMatrix(matrix: Matrix, useRightHandedSystem: boolean): string {\r\n const elements = matrix.m;\r\n // In a right handed coordinate system, the elements 11 to 14 have to change their direction\r\n const direction = useRightHandedSystem ? -1 : 1;\r\n const matrix3d = `matrix3d(${\r\n this._epsilon( elements[0] )\r\n },${\r\n this._epsilon( elements[1] )\r\n },${\r\n this._epsilon( elements[2] * -direction )\r\n },${\r\n this._epsilon( elements[3] )\r\n },${\r\n this._epsilon( - elements[4] )\r\n },${\r\n this._epsilon( - elements[5] )\r\n },${\r\n this._epsilon( elements[6] * direction )\r\n },${\r\n this._epsilon( - elements[7] )\r\n },${\r\n this._epsilon( elements[8] * -direction )\r\n },${\r\n this._epsilon( elements[9] * -direction )\r\n },${\r\n this._epsilon( elements[10] )\r\n },${\r\n this._epsilon( elements[11] * direction )\r\n },${\r\n this._epsilon( elements[12] * direction )\r\n },${\r\n this._epsilon( elements[13] * direction )\r\n },${\r\n this._epsilon( elements[14] * direction )\r\n },${\r\n this._epsilon( elements[15] )\r\n })`;\r\n return matrix3d;\r\n }\r\n\r\n protected _getTransformationMatrix(htmlMesh: HtmlMesh, useRightHandedSystem: boolean): Matrix {\r\n // Get the camera world matrix\r\n // Make sure the camera world matrix is up to date\r\n if (!this._cameraWorldMatrix) {\r\n this._cameraWorldMatrix = htmlMesh.getScene().activeCamera?.getWorldMatrix();\r\n }\r\n if (!this._cameraWorldMatrix) {\r\n return Matrix.Identity();\r\n }\r\n\r\n const objectWorldMatrix = htmlMesh.getWorldMatrix();\r\n\r\n // Scale the object matrix by the base scale factor for the mesh\r\n // which is the ratio of the mesh width/height to the renderer\r\n // width/height divided by the babylon units to pixels ratio\r\n let widthScaleFactor = 1;\r\n let heightScaleFactor = 1;\r\n if (htmlMesh.sourceWidth && htmlMesh.sourceHeight) {\r\n widthScaleFactor = htmlMesh.width! / (htmlMesh.sourceWidth / BabylonUnitsToPixels);\r\n heightScaleFactor = htmlMesh.height! / (htmlMesh.sourceHeight / BabylonUnitsToPixels);\r\n }\r\n\r\n // Apply the scale to the object's world matrix. Note we aren't scaling\r\n // the object, just getting a matrix as though it were scaled, so we can\r\n // scale the content\r\n const scaleTransform = this._temp.scaleTransform;\r\n const rotationTransform = this._temp.rotationTransform;\r\n const positionTransform = this._temp.positionTransform;\r\n const scaledAndTranslatedObjectMatrix = this._temp.objectMatrix;\r\n\r\n objectWorldMatrix.decompose(scaleTransform, rotationTransform, positionTransform);\r\n scaleTransform.x *= widthScaleFactor;\r\n scaleTransform.y *= heightScaleFactor;\r\n\r\n Matrix.ComposeToRef(scaleTransform, rotationTransform, positionTransform, scaledAndTranslatedObjectMatrix);\r\n\r\n // Adjust direction of 12 and 13 of the transformation matrix based on the handedness of the system\r\n const direction = useRightHandedSystem ? -1 : 1;\r\n // Adjust translation values to be from camera vs world origin\r\n // Note that we are also adjusting these values to be pixels vs Babylon units\r\n const position = htmlMesh.getAbsolutePosition();\r\n scaledAndTranslatedObjectMatrix.setRowFromFloats(\r\n 3,\r\n (-this._cameraWorldMatrix.m[12] + position.x) * BabylonUnitsToPixels * direction,\r\n (-this._cameraWorldMatrix.m[13] + position.y) * BabylonUnitsToPixels * direction,\r\n (this._cameraWorldMatrix.m[14] - position.z) * BabylonUnitsToPixels,\r\n this._cameraWorldMatrix.m[15] * 0.00001 * BabylonUnitsToPixels\r\n );\r\n\r\n // Adjust other values to be pixels vs Babylon units\r\n scaledAndTranslatedObjectMatrix.multiplyAtIndex(3, BabylonUnitsToPixels);\r\n scaledAndTranslatedObjectMatrix.multiplyAtIndex(7, BabylonUnitsToPixels);\r\n scaledAndTranslatedObjectMatrix.multiplyAtIndex(11, BabylonUnitsToPixels);\r\n\r\n return scaledAndTranslatedObjectMatrix;\r\n }\r\n\r\n protected _renderHtmlMesh(htmlMesh: HtmlMesh, useRightHandedSystem: boolean) {\r\n if (!htmlMesh.element || !htmlMesh.element.firstElementChild) {\r\n // nothing to render, so bail\r\n return;\r\n }\r\n\r\n // We need to ensure html mesh data is initialized before\r\n // computing the base scale factor\r\n let htmlMeshData = this._cache.htmlMeshData.get(htmlMesh);\r\n if (!htmlMeshData) {\r\n htmlMeshData = { style: \"\" };\r\n this._cache.htmlMeshData.set(htmlMesh, htmlMeshData);\r\n }\r\n\r\n const cameraElement = htmlMesh._isCanvasOverlay ? this._overlayElements?.cameraElement : this._inSceneElements?.cameraElement;\r\n\r\n if (htmlMesh.element.parentNode !== cameraElement) {\r\n cameraElement!.appendChild(htmlMesh.element);\r\n }\r\n\r\n // If the htmlMesh content has changed, update the base scale factor\r\n if (htmlMesh.requiresUpdate) {\r\n this._updateBaseScaleFactor(htmlMesh);\r\n }\r\n\r\n // Get the transformation matrix for the html mesh\r\n const scaledAndTranslatedObjectMatrix = this._getTransformationMatrix(htmlMesh, useRightHandedSystem);\r\n\r\n let style = `translate(-50%, -50%) ${this._getHtmlContentCssMatrix(scaledAndTranslatedObjectMatrix, useRightHandedSystem)}`;\r\n // In a right handed system, screens are on the wrong side of the mesh, so we have to rotate by Math.PI which results in the matrix3d seen below\r\n style += `${useRightHandedSystem ? \"matrix3d(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)\" : \"\"}`;\r\n\r\n if (htmlMeshData.style !== style) {\r\n htmlMesh.element.style.webkitTransform = style;\r\n htmlMesh.element.style.transform = style;\r\n }\r\n\r\n htmlMesh._markAsUpdated();\r\n }\r\n\r\n protected _render(scene: Scene, camera: Camera) {\r\n let needsUpdate = false;\r\n\r\n const useRightHandedSystem = scene.useRightHandedSystem;\r\n\r\n // Update the container position and size if necessary\r\n this._updateContainerPositionIfNeeded();\r\n\r\n // Check for a camera change\r\n if (this._cameraMatrixUpdated) {\r\n this._cameraMatrixUpdated = false;\r\n needsUpdate = true;\r\n }\r\n\r\n // If the camera position has changed, then we also need to update\r\n if (\r\n camera.position.x !== this._cache.cameraData.position.x ||\r\n camera.position.y !== this._cache.cameraData.position.y ||\r\n camera.position.z !== this._cache.cameraData.position.z\r\n ) {\r\n this._cache.cameraData.position.copyFrom(camera.position);\r\n needsUpdate = true;\r\n }\r\n\r\n // Check for a dpr change\r\n if (window.devicePixelRatio !== this._lastDevicePixelRatio) {\r\n this._lastDevicePixelRatio = window.devicePixelRatio;\r\n Logger.Log(\"In render - dpr changed: \", this._lastDevicePixelRatio);\r\n needsUpdate = true;\r\n }\r\n\r\n // Check if any meshes need to be updated\r\n const meshesNeedingUpdate = scene.meshes.filter((mesh) => (mesh as any)[\"isHtmlMesh\"] && (needsUpdate || (mesh as HtmlMesh).requiresUpdate));\r\n needsUpdate = needsUpdate || meshesNeedingUpdate.length > 0;\r\n\r\n if (!needsUpdate) {\r\n return;\r\n }\r\n\r\n // Get a projection matrix for the camera\r\n const projectionMatrix = camera.getProjectionMatrix();\r\n const fov = projectionMatrix.m[5] * this._heightHalf;\r\n\r\n if (this._cache.cameraData.fov !== fov) {\r\n const source = [this._overlayElements?.domElement, this._inSceneElements?.domElement];\r\n if (camera.mode == Camera.PERSPECTIVE_CAMERA) {\r\n for (const el of source) {\r\n if (el) {\r\n el.style.webkitPerspective = fov + \"px\";\r\n el.style.perspective = fov + \"px\";\r\n }\r\n }\r\n } else {\r\n for (const el of source) {\r\n if (el) {\r\n el.style.webkitPerspective = \"\";\r\n el.style.perspective = \"\";\r\n }\r\n }\r\n }\r\n this._cache.cameraData.fov = fov;\r\n }\r\n\r\n // Get the CSS matrix for the camera (which will include any camera rotation)\r\n if (camera.parent === null) {\r\n camera.computeWorldMatrix();\r\n }\r\n\r\n const cameraMatrixWorld = this._temp.cameraWorldMatrix;\r\n cameraMatrixWorld.copyFrom(camera.getWorldMatrix());\r\n const cameraRotationMatrix = this._temp.cameraRotationMatrix;\r\n cameraMatrixWorld.getRotationMatrix().transposeToRef(cameraRotationMatrix);\r\n\r\n const cameraMatrixWorldAsArray = this._temp.cameraWorldMatrixAsArray;\r\n cameraMatrixWorld.copyToArray(cameraMatrixWorldAsArray);\r\n\r\n // For a few values, we have to adjust the direction based on the handedness of the system\r\n const direction = useRightHandedSystem ? 1 : -1;\r\n\r\n cameraMatrixWorldAsArray[1] = cameraRotationMatrix.m[1];\r\n cameraMatrixWorldAsArray[2] = cameraRotationMatrix.m[2] * direction;\r\n cameraMatrixWorldAsArray[4] = cameraRotationMatrix.m[4] * direction;\r\n cameraMatrixWorldAsArray[6] = cameraRotationMatrix.m[6] * direction;\r\n cameraMatrixWorldAsArray[8] = cameraRotationMatrix.m[8] * direction;\r\n cameraMatrixWorldAsArray[9] = cameraRotationMatrix.m[9] * direction;\r\n\r\n Matrix.FromArrayToRef(cameraMatrixWorldAsArray, 0, cameraMatrixWorld);\r\n\r\n const cameraCSSMatrix = this._getCameraCssMatrix(cameraMatrixWorld);\r\n const style = cameraCSSMatrix;\r\n\r\n if (this._cache.cameraData.style !== style) {\r\n const source = [this._inSceneElements?.cameraElement, this._overlayElements?.cameraElement];\r\n for (const el of source) {\r\n if (el) {\r\n el.style.webkitTransform = style;\r\n el.style.transform = style;\r\n }\r\n }\r\n this._cache.cameraData.style = style;\r\n }\r\n\r\n // _Render objects if necessary\r\n for (const mesh of meshesNeedingUpdate) {\r\n this._renderHtmlMesh(mesh as HtmlMesh, useRightHandedSystem);\r\n }\r\n }\r\n\r\n protected _updateBaseScaleFactor(htmlMesh: HtmlMesh) {\r\n // Get screen width and height\r\n let screenWidth = this._width;\r\n let screenHeight = this._height;\r\n\r\n // Calculate aspect ratios\r\n const htmlMeshAspectRatio = (htmlMesh.width || 1) / (htmlMesh.height || 1);\r\n const screenAspectRatio = screenWidth / screenHeight;\r\n\r\n // Adjust screen dimensions based on aspect ratios\r\n if (htmlMeshAspectRatio > screenAspectRatio) {\r\n // If the HTML mesh is wider relative to its height than the screen, adjust the screen width\r\n screenWidth = screenHeight * htmlMeshAspectRatio;\r\n } else {\r\n // If the HTML mesh is taller relative to its width than the screen, adjust the screen height\r\n screenHeight = screenWidth / htmlMeshAspectRatio;\r\n }\r\n\r\n // Set content to fill screen so we get max resolution when it is shrunk to fit the mesh\r\n htmlMesh.setContentSizePx(screenWidth, screenHeight);\r\n }\r\n\r\n protected _updateContainerPositionIfNeeded() {\r\n // Determine if the canvas has moved on the screen\r\n const canvasRect = this._engine.getRenderingCanvasClientRect();\r\n\r\n // canvas rect may be null if layout not complete\r\n if (!canvasRect) {\r\n Logger.Warn(PositionUpdateFailMessage);\r\n return;\r\n }\r\n const scrollTop = window.scrollY;\r\n const scrollLeft = window.scrollX;\r\n const canvasDocumentTop = canvasRect.top + scrollTop;\r\n const canvasDocumentLeft = canvasRect.left + scrollLeft;\r\n\r\n if (this._previousCanvasDocumentPosition.top !== canvasDocumentTop || this._previousCanvasDocumentPosition.left !== canvasDocumentLeft) {\r\n this._previousCanvasDocumentPosition.top = canvasDocumentTop;\r\n this._previousCanvasDocumentPosition.left = canvasDocumentLeft;\r\n\r\n const source = [this._inSceneElements?.container, this._overlayElements?.container];\r\n for (const container of source) {\r\n if (!container) {\r\n return;\r\n }\r\n // set the top and left of the css container to match the canvas\r\n const containerParent = container.offsetParent as HTMLElement;\r\n const parentRect = containerParent.getBoundingClientRect();\r\n const parentDocumentTop = parentRect.top + scrollTop;\r\n const parentDocumentLeft = parentRect.left + scrollLeft;\r\n\r\n const ancestorMarginsAndPadding = this._getAncestorMarginsAndPadding(containerParent);\r\n\r\n // Add the body margin\r\n const bodyStyle = window.getComputedStyle(document.body);\r\n const bodyMarginTop = parseInt(bodyStyle.marginTop, 10);\r\n const bodyMarginLeft = parseInt(bodyStyle.marginLeft, 10);\r\n\r\n container.style.top = `${canvasDocumentTop - parentDocumentTop - ancestorMarginsAndPadding.marginTop + ancestorMarginsAndPadding.paddingTop + bodyMarginTop}px`;\r\n container.style.left = `${\r\n canvasDocumentLeft - parentDocumentLeft - ancestorMarginsAndPadding.marginLeft + ancestorMarginsAndPadding.paddingLeft + bodyMarginLeft\r\n }px`;\r\n }\r\n }\r\n }\r\n\r\n protected _onCameraMatrixChanged = (camera: Camera) => {\r\n this._cameraWorldMatrix = camera.getWorldMatrix();\r\n this._cameraMatrixUpdated = true;\r\n };\r\n\r\n private _epsilon(value: number) {\r\n return Math.abs(value) < 1e-10 ? 0 : value;\r\n }\r\n\r\n // Get total margins and padding for an element, excluding the body and document margins\r\n private _getAncestorMarginsAndPadding(element: HTMLElement) {\r\n let marginTop = 0;\r\n let marginLeft = 0;\r\n let paddingTop = 0;\r\n let paddingLeft = 0;\r\n\r\n while (element && element !== document.body && element !== document.documentElement) {\r\n const style = window.getComputedStyle(element);\r\n marginTop += parseInt(style.marginTop, 10);\r\n marginLeft += parseInt(style.marginLeft, 10);\r\n paddingTop += parseInt(style.paddingTop, 10);\r\n paddingLeft += parseInt(style.paddingLeft, 10);\r\n element = element.offsetParent as HTMLElement;\r\n }\r\n\r\n return { marginTop, marginLeft, paddingTop, paddingLeft };\r\n }\r\n}\r\n"]}
|
|
@@ -26,7 +26,7 @@ export declare const requestCapture: (requestId: string, captureCallback: Captur
|
|
|
26
26
|
*/
|
|
27
27
|
export declare const requestRelease: (requestId: string | null) => void;
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
29
|
+
* Release pointer events from the current owner
|
|
30
30
|
*/
|
|
31
31
|
export declare const releaseCurrent: () => void;
|
|
32
32
|
declare global {
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { Tools } from "@babylonjs/core/Misc/tools.js";
|
|
2
|
-
let
|
|
2
|
+
let CaptureRequestQueue = [];
|
|
3
3
|
// Key is request id, value is object with capture and release callbacks
|
|
4
|
-
const
|
|
4
|
+
const PendingRequestCallbacks = new Map();
|
|
5
5
|
// Keep track of release requests with no matching capture request
|
|
6
6
|
// in case the release request arrived before the capture to avoid
|
|
7
7
|
// the capture request never getting released.
|
|
8
|
-
let
|
|
9
|
-
let
|
|
8
|
+
let UnmatchedReleaseRequests = [];
|
|
9
|
+
let CurrentOwner = null; // Called on first capture or release request
|
|
10
10
|
/**
|
|
11
11
|
* Get the id of the object currently capturing pointer events
|
|
12
12
|
* @returns The id of the object currently capturing pointer events
|
|
13
13
|
* or null if no object is capturing pointer events
|
|
14
14
|
*/
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
15
16
|
export const getCapturingId = () => {
|
|
16
|
-
return
|
|
17
|
+
return CurrentOwner;
|
|
17
18
|
};
|
|
18
19
|
/**
|
|
19
20
|
* Request that the object with the given id capture pointer events. If there is no current
|
|
@@ -24,20 +25,21 @@ export const getCapturingId = () => {
|
|
|
24
25
|
* @param captureCallback The callback to call when the request is granted and the object is capturing
|
|
25
26
|
* @param releaseCallback The callback to call when the object is no longer capturing pointer events
|
|
26
27
|
*/
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
27
29
|
export const requestCapture = (requestId, captureCallback, releaseCallback) => {
|
|
28
|
-
|
|
30
|
+
DebugLog(`In pointerEventsCapture.requestCapture - Pointer events capture requested for ${requestId}`);
|
|
29
31
|
// If there is a release for this request, then ignore the request
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
+
if (RemoveUnmatchedRequest(requestId)) {
|
|
33
|
+
DebugLog(`In pointerEventsCapture.requestCapture - Capture request matched previous release request ${requestId}. Cancelling capture request`);
|
|
32
34
|
return;
|
|
33
35
|
}
|
|
34
|
-
else if (requestId !==
|
|
36
|
+
else if (requestId !== CurrentOwner) {
|
|
35
37
|
// if the request is not already in the queue, add it to the queue
|
|
36
|
-
|
|
38
|
+
EnqueueCaptureRequest(requestId, captureCallback, releaseCallback);
|
|
37
39
|
}
|
|
38
|
-
if (!
|
|
40
|
+
if (!CurrentOwner) {
|
|
39
41
|
// If there is no current owner, go ahead and grant the request
|
|
40
|
-
|
|
42
|
+
TransferPointerEventsOwnership();
|
|
41
43
|
}
|
|
42
44
|
// If the request id is the current owner, do nothing
|
|
43
45
|
};
|
|
@@ -50,57 +52,59 @@ export const requestCapture = (requestId, captureCallback, releaseCallback) => {
|
|
|
50
52
|
* the release request arrived before the capture request.
|
|
51
53
|
* @param requestId The id which should match the id of the capture request
|
|
52
54
|
*/
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
53
56
|
export const requestRelease = (requestId) => {
|
|
54
|
-
|
|
57
|
+
DebugLog(`In pointerEventsCapture.requestRelease - Pointer events release requested for ${requestId}`);
|
|
55
58
|
// if the requestId is the current capture holder release it
|
|
56
|
-
if (!requestId || requestId ===
|
|
57
|
-
|
|
59
|
+
if (!requestId || requestId === CurrentOwner) {
|
|
60
|
+
TransferPointerEventsOwnership();
|
|
58
61
|
}
|
|
59
|
-
else if (
|
|
62
|
+
else if (CancelRequest(requestId)) {
|
|
60
63
|
// if the request is in the queue, but not the current capture holder, remove it and it's callbacks
|
|
61
|
-
|
|
64
|
+
PendingRequestCallbacks.delete(requestId);
|
|
62
65
|
}
|
|
63
66
|
else {
|
|
64
|
-
|
|
67
|
+
DebugLog(`In pointerEventsCapture.requestRelease - Received release request ${requestId} but no matching capture request was received`);
|
|
65
68
|
// request was not current and not in queue, likely because we received a release
|
|
66
69
|
// request before the capture. Add it to the unmatched list to guard against this possibility
|
|
67
|
-
if (!
|
|
68
|
-
|
|
70
|
+
if (!UnmatchedReleaseRequests.includes(requestId)) {
|
|
71
|
+
UnmatchedReleaseRequests.push(requestId);
|
|
69
72
|
}
|
|
70
73
|
}
|
|
71
74
|
};
|
|
72
75
|
/**
|
|
73
|
-
*
|
|
76
|
+
* Release pointer events from the current owner
|
|
74
77
|
*/
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
75
79
|
export const releaseCurrent = () => {
|
|
76
|
-
requestRelease(
|
|
80
|
+
requestRelease(CurrentOwner);
|
|
77
81
|
};
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
if (!
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
const EnqueueCaptureRequest = (requestId, capture, release) => {
|
|
83
|
+
DebugLog(`In pointerEventsCapture.enqueueCaptureRequest - Enqueueing capture request for ${requestId}`);
|
|
84
|
+
if (!CaptureRequestQueue.includes(requestId)) {
|
|
85
|
+
CaptureRequestQueue.push(requestId);
|
|
86
|
+
PendingRequestCallbacks.set(requestId, { capture, release });
|
|
83
87
|
}
|
|
84
88
|
};
|
|
85
89
|
// Removes the request from the queue if it exists. Returns true
|
|
86
90
|
// if the request was found and removed, otherwise false
|
|
87
|
-
const
|
|
91
|
+
const CancelRequest = (requestId) => {
|
|
88
92
|
let removed = false;
|
|
89
|
-
|
|
93
|
+
CaptureRequestQueue = CaptureRequestQueue.filter((id) => {
|
|
90
94
|
if (id !== requestId) {
|
|
91
95
|
return true;
|
|
92
96
|
}
|
|
93
97
|
else {
|
|
94
98
|
removed = true;
|
|
95
|
-
|
|
99
|
+
DebugLog(`In pointerEventsCapture.cancelRequest - Canceling pointer events capture request ${requestId}`);
|
|
96
100
|
return false;
|
|
97
101
|
}
|
|
98
102
|
});
|
|
99
103
|
return removed;
|
|
100
104
|
};
|
|
101
|
-
const
|
|
105
|
+
const RemoveUnmatchedRequest = (requestId) => {
|
|
102
106
|
let removed = false;
|
|
103
|
-
|
|
107
|
+
UnmatchedReleaseRequests = UnmatchedReleaseRequests.filter((id) => {
|
|
104
108
|
if (id !== requestId) {
|
|
105
109
|
return true;
|
|
106
110
|
}
|
|
@@ -111,41 +115,41 @@ const removeUnmatchedRequest = (requestId) => {
|
|
|
111
115
|
});
|
|
112
116
|
return removed;
|
|
113
117
|
};
|
|
114
|
-
const
|
|
115
|
-
const newOwnerId =
|
|
116
|
-
|
|
118
|
+
const TransferPointerEventsOwnership = () => {
|
|
119
|
+
const newOwnerId = NextCaptureRequest();
|
|
120
|
+
DebugLog(`In pointerEventsCapture.transferPointerEventsOwnership - Transferrring pointer events from ${CurrentOwner} to ${newOwnerId}`);
|
|
117
121
|
// Release the current owner
|
|
118
|
-
|
|
122
|
+
DoRelease();
|
|
119
123
|
if (newOwnerId) {
|
|
120
|
-
|
|
124
|
+
DoCapture(newOwnerId);
|
|
121
125
|
}
|
|
122
126
|
};
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
if (
|
|
127
|
+
const DoRelease = () => {
|
|
128
|
+
DebugLog(`In pointerEventsCapture.doRelease - Releasing pointer events from ${CurrentOwner}`);
|
|
129
|
+
if (CurrentOwner) {
|
|
126
130
|
// call the release callback
|
|
127
|
-
|
|
131
|
+
PendingRequestCallbacks.get(CurrentOwner)?.release();
|
|
128
132
|
// And remove the callbacks
|
|
129
|
-
|
|
130
|
-
|
|
133
|
+
PendingRequestCallbacks.delete(CurrentOwner);
|
|
134
|
+
CurrentOwner = null;
|
|
131
135
|
}
|
|
132
136
|
};
|
|
133
|
-
const
|
|
137
|
+
const DoCapture = (newOwnerId) => {
|
|
134
138
|
if (newOwnerId) {
|
|
135
139
|
// call the capture callback
|
|
136
|
-
|
|
140
|
+
PendingRequestCallbacks.get(newOwnerId)?.capture();
|
|
137
141
|
}
|
|
138
|
-
|
|
139
|
-
|
|
142
|
+
CurrentOwner = newOwnerId;
|
|
143
|
+
DebugLog(`In pointerEventsCapture.doCapture - Pointer events now captured by ${newOwnerId}`);
|
|
140
144
|
};
|
|
141
|
-
const
|
|
142
|
-
return
|
|
145
|
+
const NextCaptureRequest = () => {
|
|
146
|
+
return CaptureRequestQueue.length > 0 ? CaptureRequestQueue.shift() : null;
|
|
143
147
|
};
|
|
144
|
-
const
|
|
148
|
+
const DebugLog = (message) => {
|
|
145
149
|
// If we are runnning in a test runner (in node, so window is not defined)
|
|
146
150
|
// or if the debug flag is set, then log the message
|
|
147
151
|
if (typeof window === "undefined" || window["pointer-events-capture-debug"]) {
|
|
148
|
-
Tools.Log(`${performance.now()} - game.scene.pointerEvents - ${message}\ncurrentOwner: ${
|
|
152
|
+
Tools.Log(`${performance.now()} - game.scene.pointerEvents - ${message}\ncurrentOwner: ${CurrentOwner}\nqueue: ${CaptureRequestQueue}\nunmatched: ${UnmatchedReleaseRequests}`);
|
|
149
153
|
}
|
|
150
154
|
};
|
|
151
155
|
// #endregion Debugging support
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pointerEventsCapture.js","sourceRoot":"","sources":["../../../../dev/addons/src/htmlMesh/pointerEventsCapture.ts"],"names":[],"mappings":"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","sourcesContent":["import { Tools } from \"core/Misc/tools\";\r\n\r\n// A capture management system to ensure that the correct object has the pointer\r\n// events by eliminating race conditions that can cause the pointer events to be\r\n// released by a different object after they are captured leaving no object\r\n// as the owner. It does this by queueing requests and only allowing\r\n// capture when the current capture owner releases pointer events.\r\n\r\ntype CaptureReleaseCallback = () => void;\r\n\r\ntype CaptureReleaseCallbacks = {\r\n capture: CaptureReleaseCallback;\r\n release: CaptureReleaseCallback;\r\n};\r\n\r\nlet captureRequestQueue: string[] = [];\r\n\r\n// Key is request id, value is object with capture and release callbacks\r\nconst pendingRequestCallbacks: Map<string, CaptureReleaseCallbacks> = new Map();\r\n\r\n// Keep track of release requests with no matching capture request\r\n// in case the release request arrived before the capture to avoid\r\n// the capture request never getting released.\r\nlet unmatchedReleaseRequests: string[] = [];\r\n\r\nlet currentOwner: string | null = null; // Called on first capture or release request\r\n\r\n/**\r\n * Get the id of the object currently capturing pointer events\r\n * @returns The id of the object currently capturing pointer events\r\n * or null if no object is capturing pointer events\r\n */\r\nexport const getCapturingId = () => {\r\n return currentOwner;\r\n};\r\n\r\n/**\r\n * Request that the object with the given id capture pointer events. If there is no current\r\n * owner, then the request is granted immediately. If there is a current owner, then the request\r\n * is queued until the current owner releases pointer events.\r\n * @param requestId An id to identify the request. This id will be used to match the capture\r\n * request with the release request.\r\n * @param captureCallback The callback to call when the request is granted and the object is capturing\r\n * @param releaseCallback The callback to call when the object is no longer capturing pointer events\r\n */\r\nexport const requestCapture = (requestId: string, captureCallback: CaptureReleaseCallback, releaseCallback: CaptureReleaseCallback) => {\r\n debugLog(`In pointerEventsCapture.requestCapture - Pointer events capture requested for ${requestId}`);\r\n\r\n // If there is a release for this request, then ignore the request\r\n if (removeUnmatchedRequest(requestId)) {\r\n debugLog(`In pointerEventsCapture.requestCapture - Capture request matched previous release request ${requestId}. Cancelling capture request`);\r\n return;\r\n } else if (requestId !== currentOwner) {\r\n // if the request is not already in the queue, add it to the queue\r\n enqueueCaptureRequest(requestId, captureCallback, releaseCallback);\r\n }\r\n\r\n if (!currentOwner) {\r\n // If there is no current owner, go ahead and grant the request\r\n transferPointerEventsOwnership();\r\n }\r\n // If the request id is the current owner, do nothing\r\n};\r\n\r\n/**\r\n * Release pointer events from the object with the given id. If the object is the current owner\r\n * then pointer events are released immediately. If the object is not the current owner, then the\r\n * associated capture request is removed from the queue. If there is no matching capture request\r\n * in the queue, then the release request is added to a list of unmatched release requests and will\r\n * negate the next capture request with the same id. This is to guard against the possibility that\r\n * the release request arrived before the capture request.\r\n * @param requestId The id which should match the id of the capture request\r\n */\r\nexport const requestRelease = (requestId: string | null) => {\r\n debugLog(`In pointerEventsCapture.requestRelease - Pointer events release requested for ${requestId}`);\r\n\r\n // if the requestId is the current capture holder release it\r\n if (!requestId || requestId === currentOwner) {\r\n transferPointerEventsOwnership();\r\n } else if (cancelRequest(requestId)) {\r\n // if the request is in the queue, but not the current capture holder, remove it and it's callbacks\r\n pendingRequestCallbacks.delete(requestId);\r\n } else {\r\n debugLog(`In pointerEventsCapture.requestRelease - Received release request ${requestId} but no matching capture request was received`);\r\n // request was not current and not in queue, likely because we received a release\r\n // request before the capture. Add it to the unmatched list to guard against this possibility\r\n if (!unmatchedReleaseRequests.includes(requestId)) {\r\n unmatchedReleaseRequests.push(requestId);\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Relase pointer events from the current owner\r\n */\r\nexport const releaseCurrent = () => {\r\n requestRelease(currentOwner);\r\n};\r\n\r\nconst enqueueCaptureRequest = (requestId: string, capture: CaptureReleaseCallback, release: CaptureReleaseCallback) => {\r\n debugLog(`In pointerEventsCapture.enqueueCaptureRequest - Enqueueing capture request for ${requestId}`);\r\n if (!captureRequestQueue.includes(requestId)) {\r\n captureRequestQueue.push(requestId);\r\n pendingRequestCallbacks.set(requestId, { capture, release });\r\n }\r\n};\r\n\r\n// Removes the request from the queue if it exists. Returns true\r\n// if the request was found and removed, otherwise false\r\nconst cancelRequest = (requestId: string | null) => {\r\n let removed = false;\r\n captureRequestQueue = captureRequestQueue.filter((id) => {\r\n if (id !== requestId) {\r\n return true;\r\n } else {\r\n removed = true;\r\n debugLog(`In pointerEventsCapture.cancelRequest - Canceling pointer events capture request ${requestId}`);\r\n return false;\r\n }\r\n });\r\n return removed;\r\n};\r\n\r\nconst removeUnmatchedRequest = (requestId: string) => {\r\n let removed = false;\r\n unmatchedReleaseRequests = unmatchedReleaseRequests.filter((id) => {\r\n if (id !== requestId) {\r\n return true;\r\n } else {\r\n removed = true;\r\n return false;\r\n }\r\n });\r\n return removed;\r\n};\r\n\r\nconst transferPointerEventsOwnership = () => {\r\n const newOwnerId = nextCaptureRequest();\r\n debugLog(`In pointerEventsCapture.transferPointerEventsOwnership - Transferrring pointer events from ${currentOwner} to ${newOwnerId}`);\r\n // Release the current owner\r\n doRelease();\r\n if (newOwnerId) {\r\n doCapture(newOwnerId);\r\n }\r\n};\r\n\r\nconst doRelease = () => {\r\n debugLog(`In pointerEventsCapture.doRelease - Releasing pointer events from ${currentOwner}`);\r\n if (currentOwner) {\r\n // call the release callback\r\n pendingRequestCallbacks.get(currentOwner)?.release();\r\n // And remove the callbacks\r\n pendingRequestCallbacks.delete(currentOwner);\r\n currentOwner = null;\r\n }\r\n};\r\n\r\nconst doCapture = (newOwnerId: string) => {\r\n if (newOwnerId) {\r\n // call the capture callback\r\n pendingRequestCallbacks.get(newOwnerId)?.capture();\r\n }\r\n currentOwner = newOwnerId;\r\n debugLog(`In pointerEventsCapture.doCapture - Pointer events now captured by ${newOwnerId}`);\r\n};\r\n\r\nconst nextCaptureRequest = () => {\r\n return captureRequestQueue.length > 0 ? captureRequestQueue.shift() : null;\r\n};\r\n\r\n// #region Debugging support\r\ndeclare global {\r\n interface Window {\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n \"pointer-events-capture-debug\": boolean | null;\r\n }\r\n}\r\n\r\nconst debugLog = (message: string) => {\r\n // If we are runnning in a test runner (in node, so window is not defined)\r\n // or if the debug flag is set, then log the message\r\n if (typeof window === \"undefined\" || window[\"pointer-events-capture-debug\"]) {\r\n Tools.Log(\r\n `${performance.now()} - game.scene.pointerEvents - ${message}\\ncurrentOwner: ${currentOwner}\\nqueue: ${captureRequestQueue}\\nunmatched: ${unmatchedReleaseRequests}`\r\n );\r\n }\r\n};\r\n// #endregion Debugging support\r\n"]}
|
|
1
|
+
{"version":3,"file":"pointerEventsCapture.js","sourceRoot":"","sources":["../../../../dev/addons/src/htmlMesh/pointerEventsCapture.ts"],"names":[],"mappings":"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","sourcesContent":["import { Tools } from \"core/Misc/tools\";\r\n\r\n// A capture management system to ensure that the correct object has the pointer\r\n// events by eliminating race conditions that can cause the pointer events to be\r\n// released by a different object after they are captured leaving no object\r\n// as the owner. It does this by queueing requests and only allowing\r\n// capture when the current capture owner releases pointer events.\r\n\r\ntype CaptureReleaseCallback = () => void;\r\n\r\ntype CaptureReleaseCallbacks = {\r\n capture: CaptureReleaseCallback;\r\n release: CaptureReleaseCallback;\r\n};\r\n\r\nlet CaptureRequestQueue: string[] = [];\r\n\r\n// Key is request id, value is object with capture and release callbacks\r\nconst PendingRequestCallbacks: Map<string, CaptureReleaseCallbacks> = new Map();\r\n\r\n// Keep track of release requests with no matching capture request\r\n// in case the release request arrived before the capture to avoid\r\n// the capture request never getting released.\r\nlet UnmatchedReleaseRequests: string[] = [];\r\n\r\nlet CurrentOwner: string | null = null; // Called on first capture or release request\r\n\r\n/**\r\n * Get the id of the object currently capturing pointer events\r\n * @returns The id of the object currently capturing pointer events\r\n * or null if no object is capturing pointer events\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport const getCapturingId = () => {\r\n return CurrentOwner;\r\n};\r\n\r\n/**\r\n * Request that the object with the given id capture pointer events. If there is no current\r\n * owner, then the request is granted immediately. If there is a current owner, then the request\r\n * is queued until the current owner releases pointer events.\r\n * @param requestId An id to identify the request. This id will be used to match the capture\r\n * request with the release request.\r\n * @param captureCallback The callback to call when the request is granted and the object is capturing\r\n * @param releaseCallback The callback to call when the object is no longer capturing pointer events\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport const requestCapture = (requestId: string, captureCallback: CaptureReleaseCallback, releaseCallback: CaptureReleaseCallback) => {\r\n DebugLog(`In pointerEventsCapture.requestCapture - Pointer events capture requested for ${requestId}`);\r\n\r\n // If there is a release for this request, then ignore the request\r\n if (RemoveUnmatchedRequest(requestId)) {\r\n DebugLog(`In pointerEventsCapture.requestCapture - Capture request matched previous release request ${requestId}. Cancelling capture request`);\r\n return;\r\n } else if (requestId !== CurrentOwner) {\r\n // if the request is not already in the queue, add it to the queue\r\n EnqueueCaptureRequest(requestId, captureCallback, releaseCallback);\r\n }\r\n\r\n if (!CurrentOwner) {\r\n // If there is no current owner, go ahead and grant the request\r\n TransferPointerEventsOwnership();\r\n }\r\n // If the request id is the current owner, do nothing\r\n};\r\n\r\n/**\r\n * Release pointer events from the object with the given id. If the object is the current owner\r\n * then pointer events are released immediately. If the object is not the current owner, then the\r\n * associated capture request is removed from the queue. If there is no matching capture request\r\n * in the queue, then the release request is added to a list of unmatched release requests and will\r\n * negate the next capture request with the same id. This is to guard against the possibility that\r\n * the release request arrived before the capture request.\r\n * @param requestId The id which should match the id of the capture request\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport const requestRelease = (requestId: string | null) => {\r\n DebugLog(`In pointerEventsCapture.requestRelease - Pointer events release requested for ${requestId}`);\r\n\r\n // if the requestId is the current capture holder release it\r\n if (!requestId || requestId === CurrentOwner) {\r\n TransferPointerEventsOwnership();\r\n } else if (CancelRequest(requestId)) {\r\n // if the request is in the queue, but not the current capture holder, remove it and it's callbacks\r\n PendingRequestCallbacks.delete(requestId);\r\n } else {\r\n DebugLog(`In pointerEventsCapture.requestRelease - Received release request ${requestId} but no matching capture request was received`);\r\n // request was not current and not in queue, likely because we received a release\r\n // request before the capture. Add it to the unmatched list to guard against this possibility\r\n if (!UnmatchedReleaseRequests.includes(requestId)) {\r\n UnmatchedReleaseRequests.push(requestId);\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Release pointer events from the current owner\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport const releaseCurrent = () => {\r\n requestRelease(CurrentOwner);\r\n};\r\n\r\nconst EnqueueCaptureRequest = (requestId: string, capture: CaptureReleaseCallback, release: CaptureReleaseCallback) => {\r\n DebugLog(`In pointerEventsCapture.enqueueCaptureRequest - Enqueueing capture request for ${requestId}`);\r\n if (!CaptureRequestQueue.includes(requestId)) {\r\n CaptureRequestQueue.push(requestId);\r\n PendingRequestCallbacks.set(requestId, { capture, release });\r\n }\r\n};\r\n\r\n// Removes the request from the queue if it exists. Returns true\r\n// if the request was found and removed, otherwise false\r\nconst CancelRequest = (requestId: string | null) => {\r\n let removed = false;\r\n CaptureRequestQueue = CaptureRequestQueue.filter((id) => {\r\n if (id !== requestId) {\r\n return true;\r\n } else {\r\n removed = true;\r\n DebugLog(`In pointerEventsCapture.cancelRequest - Canceling pointer events capture request ${requestId}`);\r\n return false;\r\n }\r\n });\r\n return removed;\r\n};\r\n\r\nconst RemoveUnmatchedRequest = (requestId: string) => {\r\n let removed = false;\r\n UnmatchedReleaseRequests = UnmatchedReleaseRequests.filter((id) => {\r\n if (id !== requestId) {\r\n return true;\r\n } else {\r\n removed = true;\r\n return false;\r\n }\r\n });\r\n return removed;\r\n};\r\n\r\nconst TransferPointerEventsOwnership = () => {\r\n const newOwnerId = NextCaptureRequest();\r\n DebugLog(`In pointerEventsCapture.transferPointerEventsOwnership - Transferrring pointer events from ${CurrentOwner} to ${newOwnerId}`);\r\n // Release the current owner\r\n DoRelease();\r\n if (newOwnerId) {\r\n DoCapture(newOwnerId);\r\n }\r\n};\r\n\r\nconst DoRelease = () => {\r\n DebugLog(`In pointerEventsCapture.doRelease - Releasing pointer events from ${CurrentOwner}`);\r\n if (CurrentOwner) {\r\n // call the release callback\r\n PendingRequestCallbacks.get(CurrentOwner)?.release();\r\n // And remove the callbacks\r\n PendingRequestCallbacks.delete(CurrentOwner);\r\n CurrentOwner = null;\r\n }\r\n};\r\n\r\nconst DoCapture = (newOwnerId: string) => {\r\n if (newOwnerId) {\r\n // call the capture callback\r\n PendingRequestCallbacks.get(newOwnerId)?.capture();\r\n }\r\n CurrentOwner = newOwnerId;\r\n DebugLog(`In pointerEventsCapture.doCapture - Pointer events now captured by ${newOwnerId}`);\r\n};\r\n\r\nconst NextCaptureRequest = () => {\r\n return CaptureRequestQueue.length > 0 ? CaptureRequestQueue.shift() : null;\r\n};\r\n\r\n// #region Debugging support\r\ndeclare global {\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n interface Window {\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n \"pointer-events-capture-debug\": boolean | null;\r\n }\r\n}\r\n\r\nconst DebugLog = (message: string) => {\r\n // If we are runnning in a test runner (in node, so window is not defined)\r\n // or if the debug flag is set, then log the message\r\n if (typeof window === \"undefined\" || window[\"pointer-events-capture-debug\"]) {\r\n Tools.Log(\r\n `${performance.now()} - game.scene.pointerEvents - ${message}\\ncurrentOwner: ${CurrentOwner}\\nqueue: ${CaptureRequestQueue}\\nunmatched: ${UnmatchedReleaseRequests}`\r\n );\r\n }\r\n};\r\n// #endregion Debugging support\r\n"]}
|
|
@@ -1,55 +1,55 @@
|
|
|
1
1
|
import { Logger } from "@babylonjs/core/Misc/logger.js";
|
|
2
2
|
import { requestCapture, requestRelease, releaseCurrent, getCapturingId } from "./pointerEventsCapture.js";
|
|
3
3
|
// Module level variable for holding the current scene
|
|
4
|
-
let
|
|
4
|
+
let LocalScene = null;
|
|
5
5
|
// Module level variable to hold the count of behavior instances that are currently capturing pointer events
|
|
6
6
|
// on entry. This is used to determine if we need to start or stop observing pointer movement.
|
|
7
|
-
let
|
|
7
|
+
let CaptureOnEnterCount = 0;
|
|
8
8
|
// Map used to store instance of the PointerEventsCaptureBehavior for a mesh
|
|
9
9
|
// We do this because this gets checked on pointer move and we don't want to
|
|
10
10
|
// use getBehaviorByName() because that is a linear search
|
|
11
|
-
const
|
|
12
|
-
const
|
|
11
|
+
const MeshToBehaviorMap = new WeakMap();
|
|
12
|
+
const StartCaptureOnEnter = (scene) => {
|
|
13
13
|
// If we are not in a browser, do nothing
|
|
14
14
|
if (typeof document === "undefined") {
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
|
-
if (
|
|
18
|
-
document.addEventListener("pointermove",
|
|
19
|
-
document.addEventListener("touchstart",
|
|
20
|
-
|
|
17
|
+
if (CaptureOnEnterCount === 0) {
|
|
18
|
+
document.addEventListener("pointermove", OnPointerMove);
|
|
19
|
+
document.addEventListener("touchstart", OnPointerMove);
|
|
20
|
+
LocalScene = LocalScene ?? scene;
|
|
21
21
|
Logger.Log("PointerEventsCaptureBehavior: Starting observation of pointer move events.");
|
|
22
|
-
|
|
22
|
+
LocalScene.onDisposeObservable.add(DoStopCaptureOnEnter);
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
CaptureOnEnterCount++;
|
|
25
25
|
};
|
|
26
|
-
const
|
|
27
|
-
document.removeEventListener("pointermove",
|
|
28
|
-
document.removeEventListener("touchstart",
|
|
29
|
-
|
|
26
|
+
const DoStopCaptureOnEnter = () => {
|
|
27
|
+
document.removeEventListener("pointermove", OnPointerMove);
|
|
28
|
+
document.removeEventListener("touchstart", OnPointerMove);
|
|
29
|
+
LocalScene = null;
|
|
30
30
|
Logger.Log("PointerEventsCaptureBehavior: Stopping observation of pointer move events.");
|
|
31
|
-
|
|
31
|
+
CaptureOnEnterCount = 0;
|
|
32
32
|
};
|
|
33
|
-
const
|
|
33
|
+
const StopCaptureOnEnter = () => {
|
|
34
34
|
// If we are not in a browser, do nothing
|
|
35
35
|
if (typeof document === "undefined") {
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
38
38
|
// If we are not observing pointer movement, do nothing
|
|
39
|
-
if (!
|
|
39
|
+
if (!LocalScene) {
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
|
-
|
|
43
|
-
if (
|
|
44
|
-
|
|
42
|
+
CaptureOnEnterCount--;
|
|
43
|
+
if (CaptureOnEnterCount <= 0) {
|
|
44
|
+
DoStopCaptureOnEnter();
|
|
45
45
|
}
|
|
46
46
|
};
|
|
47
47
|
// Module level function used to determine if an entered mesh should capture pointer events
|
|
48
|
-
const
|
|
49
|
-
if (!
|
|
48
|
+
const OnPointerMove = (evt) => {
|
|
49
|
+
if (!LocalScene) {
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
52
|
-
const canvasRect =
|
|
52
|
+
const canvasRect = LocalScene.getEngine().getRenderingCanvasClientRect();
|
|
53
53
|
if (!canvasRect) {
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
@@ -60,10 +60,10 @@ const onPointerMove = (evt) => {
|
|
|
60
60
|
const pointerScreenX = clientX - canvasRect.left;
|
|
61
61
|
const pointerScreenY = clientY - canvasRect.top;
|
|
62
62
|
let pointerCaptureBehavior;
|
|
63
|
-
const pickResult =
|
|
63
|
+
const pickResult = LocalScene.pick(pointerScreenX, pointerScreenY, (mesh) => {
|
|
64
64
|
// If the mesh has an instance of PointerEventsCaptureBehavior attached to it,
|
|
65
65
|
// and capture on pointer enter is true, then we want to pick it
|
|
66
|
-
const pointerCaptureBehavior =
|
|
66
|
+
const pointerCaptureBehavior = MeshToBehaviorMap.get(mesh);
|
|
67
67
|
return mesh.isEnabled() && typeof pointerCaptureBehavior !== "undefined" && pointerCaptureBehavior._captureOnPointerEnter;
|
|
68
68
|
});
|
|
69
69
|
let pickedMesh;
|
|
@@ -87,7 +87,7 @@ const onPointerMove = (evt) => {
|
|
|
87
87
|
// the pointer events. Note that the current capturing mesh has already been
|
|
88
88
|
// released above
|
|
89
89
|
if (pickedMesh) {
|
|
90
|
-
pointerCaptureBehavior =
|
|
90
|
+
pointerCaptureBehavior = MeshToBehaviorMap.get(pickedMesh);
|
|
91
91
|
pointerCaptureBehavior.capturePointerEvents();
|
|
92
92
|
}
|
|
93
93
|
};
|
|
@@ -128,10 +128,10 @@ export class PointerEventsCaptureBehavior {
|
|
|
128
128
|
this._captureOnPointerEnter = captureOnPointerEnter;
|
|
129
129
|
if (this._attachedMesh) {
|
|
130
130
|
if (this._captureOnPointerEnter) {
|
|
131
|
-
|
|
131
|
+
StartCaptureOnEnter(this._attachedMesh.getScene());
|
|
132
132
|
}
|
|
133
133
|
else {
|
|
134
|
-
|
|
134
|
+
StopCaptureOnEnter();
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
}
|
|
@@ -148,9 +148,9 @@ export class PointerEventsCaptureBehavior {
|
|
|
148
148
|
// reference to the behavior in the onPointerMove function without relying on
|
|
149
149
|
// getBehaviorByName(), which does a linear search of the behaviors array.
|
|
150
150
|
this.attachedMesh = mesh;
|
|
151
|
-
|
|
151
|
+
MeshToBehaviorMap.set(mesh, this);
|
|
152
152
|
if (this._captureOnPointerEnter) {
|
|
153
|
-
|
|
153
|
+
StartCaptureOnEnter(mesh.getScene());
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
/**
|
|
@@ -161,9 +161,9 @@ export class PointerEventsCaptureBehavior {
|
|
|
161
161
|
return;
|
|
162
162
|
}
|
|
163
163
|
// Remove the reference to this behavior from the mesh
|
|
164
|
-
|
|
164
|
+
MeshToBehaviorMap.delete(this.attachedMesh);
|
|
165
165
|
if (this._captureOnPointerEnter) {
|
|
166
|
-
|
|
166
|
+
StopCaptureOnEnter();
|
|
167
167
|
}
|
|
168
168
|
this.attachedMesh = null;
|
|
169
169
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pointerEventsCaptureBehavior.js","sourceRoot":"","sources":["../../../../dev/addons/src/htmlMesh/pointerEventsCaptureBehavior.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AbstractMesh } from \"core/Meshes/abstractMesh\";\r\nimport type { Behavior } from \"core/Behaviors/behavior\";\r\nimport type { Scene } from \"core/scene\";\r\nimport { Logger } from \"core/Misc/logger\";\r\nimport { requestCapture, requestRelease, releaseCurrent, getCapturingId } from \"./pointerEventsCapture\";\r\n\r\n// Module level variable for holding the current scene\r\nlet _scene: Scene | null = null;\r\n\r\n// Module level variable to hold the count of behavior instances that are currently capturing pointer events\r\n// on entry. This is used to determine if we need to start or stop observing pointer movement.\r\nlet captureOnEnterCount = 0;\r\n\r\n// Map used to store instance of the PointerEventsCaptureBehavior for a mesh\r\n// We do this because this gets checked on pointer move and we don't want to\r\n// use getBehaviorByName() because that is a linear search\r\nconst meshToBehaviorMap = new WeakMap<AbstractMesh, PointerEventsCaptureBehavior>();\r\n\r\nconst startCaptureOnEnter = (scene: Scene) => {\r\n // If we are not in a browser, do nothing\r\n if (typeof document === \"undefined\") {\r\n return;\r\n }\r\n if (captureOnEnterCount === 0) {\r\n document.addEventListener(\"pointermove\", onPointerMove);\r\n document.addEventListener(\"touchstart\", onPointerMove);\r\n _scene = _scene ?? scene;\r\n Logger.Log(\"PointerEventsCaptureBehavior: Starting observation of pointer move events.\");\r\n _scene.onDisposeObservable.add(doStopCaptureOnEnter);\r\n }\r\n captureOnEnterCount++;\r\n};\r\n\r\nconst doStopCaptureOnEnter = () => {\r\n document.removeEventListener(\"pointermove\", onPointerMove);\r\n document.removeEventListener(\"touchstart\", onPointerMove);\r\n _scene = null;\r\n Logger.Log(\"PointerEventsCaptureBehavior: Stopping observation of pointer move events.\");\r\n captureOnEnterCount = 0;\r\n};\r\n\r\nconst stopCaptureOnEnter = () => {\r\n // If we are not in a browser, do nothing\r\n if (typeof document === \"undefined\") {\r\n return;\r\n }\r\n\r\n // If we are not observing pointer movement, do nothing\r\n if (!_scene) {\r\n return;\r\n }\r\n\r\n captureOnEnterCount--;\r\n if (captureOnEnterCount <= 0) {\r\n doStopCaptureOnEnter();\r\n }\r\n};\r\n\r\n// Module level function used to determine if an entered mesh should capture pointer events\r\nconst onPointerMove = (evt: PointerEvent | TouchEvent) => {\r\n if (!_scene) {\r\n return;\r\n }\r\n\r\n const canvasRect = _scene.getEngine().getRenderingCanvasClientRect();\r\n if (!canvasRect) {\r\n return;\r\n }\r\n\r\n // Get the object that contains the client X and Y from either the pointer event or from the\r\n // TouchEvent touch\r\n const { clientX, clientY } = \"touches\" in evt ? evt.touches[0] : evt;\r\n\r\n // get the picked mesh, if any\r\n const pointerScreenX = clientX - canvasRect.left;\r\n const pointerScreenY = clientY - canvasRect.top;\r\n\r\n let pointerCaptureBehavior: PointerEventsCaptureBehavior | undefined;\r\n const pickResult = _scene.pick(pointerScreenX, pointerScreenY, (mesh) => {\r\n // If the mesh has an instance of PointerEventsCaptureBehavior attached to it,\r\n // and capture on pointer enter is true, then we want to pick it\r\n const pointerCaptureBehavior = meshToBehaviorMap.get(mesh);\r\n return mesh.isEnabled() && typeof pointerCaptureBehavior !== \"undefined\" && pointerCaptureBehavior._captureOnPointerEnter;\r\n });\r\n\r\n let pickedMesh: AbstractMesh | null;\r\n if (pickResult.hit) {\r\n pickedMesh = pickResult.pickedMesh;\r\n } else {\r\n pickedMesh = null;\r\n }\r\n\r\n const capturingIdAsInt = parseInt(getCapturingId() || \"\");\r\n\r\n // if the picked mesh is the current capturing mesh, do nothing\r\n if (pickedMesh && pickedMesh.uniqueId === capturingIdAsInt) {\r\n return;\r\n }\r\n\r\n // If there is a capturing mesh and it is not the current picked mesh, or no\r\n // mesh is picked, release the capturing mesh\r\n if (capturingIdAsInt && (!pickedMesh || pickedMesh.uniqueId !== capturingIdAsInt)) {\r\n releaseCurrent();\r\n }\r\n\r\n // If there is a picked mesh and it is not the current capturing mesh, capture\r\n // the pointer events. Note that the current capturing mesh has already been\r\n // released above\r\n if (pickedMesh) {\r\n pointerCaptureBehavior = meshToBehaviorMap.get(pickedMesh);\r\n pointerCaptureBehavior!.capturePointerEvents();\r\n }\r\n};\r\n\r\n/**\r\n * Behavior for any content that can capture pointer events, i.e. bypass the Babylon pointer event handling\r\n * and receive pointer events directly. It will register the capture triggers and negotiate the capture and\r\n * release of pointer events. Curerntly this applies only to HtmlMesh\r\n */\r\nexport class PointerEventsCaptureBehavior implements Behavior<AbstractMesh> {\r\n /** gets or sets behavior's name */\r\n public name = \"PointerEventsCaptureBehavior\";\r\n\r\n private _attachedMesh: AbstractMesh | null;\r\n /** @internal */\r\n public _captureOnPointerEnter: boolean;\r\n\r\n /**\r\n * Gets or sets the mesh that the behavior is attached to\r\n */\r\n public get attachedMesh() {\r\n return this._attachedMesh;\r\n }\r\n\r\n public set attachedMesh(value: AbstractMesh | null) {\r\n this._attachedMesh = value;\r\n }\r\n\r\n constructor(\r\n private _captureCallback: () => void,\r\n private _releaseCallback: () => void,\r\n { captureOnPointerEnter = true } = {}\r\n ) {\r\n this._attachedMesh = null;\r\n this._captureOnPointerEnter = captureOnPointerEnter;\r\n\r\n // Warn if we are not in a browser\r\n if (typeof document === \"undefined\") {\r\n Logger.Warn(`Creating an instance of PointerEventsCaptureBehavior outside of a browser. The behavior will not work.`);\r\n }\r\n }\r\n\r\n /**\r\n * Set if the behavior should capture pointer events when the pointer enters the mesh\r\n */\r\n public set captureOnPointerEnter(captureOnPointerEnter: boolean) {\r\n if (this._captureOnPointerEnter === captureOnPointerEnter) {\r\n return;\r\n }\r\n this._captureOnPointerEnter = captureOnPointerEnter;\r\n if (this._attachedMesh) {\r\n if (this._captureOnPointerEnter) {\r\n startCaptureOnEnter(this._attachedMesh.getScene()!);\r\n } else {\r\n stopCaptureOnEnter();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Function called when the behavior needs to be initialized (before attaching it to a target)\r\n */\r\n public init() {}\r\n\r\n /**\r\n * Called when the behavior is attached to a target\r\n * @param mesh defines the target where the behavior is attached to\r\n */\r\n public attach(mesh: AbstractMesh) {\r\n // Add a reference to this behavior on the mesh. We do this so we can get a\r\n // reference to the behavior in the onPointerMove function without relying on\r\n // getBehaviorByName(), which does a linear search of the behaviors array.\r\n this.attachedMesh = mesh;\r\n meshToBehaviorMap.set(mesh, this);\r\n if (this._captureOnPointerEnter) {\r\n startCaptureOnEnter(mesh.getScene()!);\r\n }\r\n }\r\n\r\n /**\r\n * Called when the behavior is detached from its target\r\n */\r\n public detach() {\r\n if (!this.attachedMesh) {\r\n return;\r\n }\r\n // Remove the reference to this behavior from the mesh\r\n meshToBehaviorMap.delete(this.attachedMesh);\r\n if (this._captureOnPointerEnter) {\r\n stopCaptureOnEnter();\r\n }\r\n this.attachedMesh = null;\r\n }\r\n\r\n /**\r\n * Dispose the behavior\r\n */\r\n public dispose() {\r\n this.detach();\r\n }\r\n\r\n // Release pointer events\r\n public releasePointerEvents() {\r\n if (!this.attachedMesh) {\r\n return;\r\n }\r\n requestRelease(this.attachedMesh.uniqueId.toString());\r\n }\r\n\r\n // Capture pointer events\r\n public capturePointerEvents() {\r\n if (!this.attachedMesh) {\r\n return;\r\n }\r\n requestCapture(this.attachedMesh.uniqueId.toString(), this._captureCallback, this._releaseCallback);\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"pointerEventsCaptureBehavior.js","sourceRoot":"","sources":["../../../../dev/addons/src/htmlMesh/pointerEventsCaptureBehavior.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AbstractMesh } from \"core/Meshes/abstractMesh\";\r\nimport type { Behavior } from \"core/Behaviors/behavior\";\r\nimport type { Scene } from \"core/scene\";\r\nimport { Logger } from \"core/Misc/logger\";\r\nimport { requestCapture, requestRelease, releaseCurrent, getCapturingId } from \"./pointerEventsCapture\";\r\n\r\n// Module level variable for holding the current scene\r\nlet LocalScene: Scene | null = null;\r\n\r\n// Module level variable to hold the count of behavior instances that are currently capturing pointer events\r\n// on entry. This is used to determine if we need to start or stop observing pointer movement.\r\nlet CaptureOnEnterCount = 0;\r\n\r\n// Map used to store instance of the PointerEventsCaptureBehavior for a mesh\r\n// We do this because this gets checked on pointer move and we don't want to\r\n// use getBehaviorByName() because that is a linear search\r\nconst MeshToBehaviorMap = new WeakMap<AbstractMesh, PointerEventsCaptureBehavior>();\r\n\r\nconst StartCaptureOnEnter = (scene: Scene) => {\r\n // If we are not in a browser, do nothing\r\n if (typeof document === \"undefined\") {\r\n return;\r\n }\r\n if (CaptureOnEnterCount === 0) {\r\n document.addEventListener(\"pointermove\", OnPointerMove);\r\n document.addEventListener(\"touchstart\", OnPointerMove);\r\n LocalScene = LocalScene ?? scene;\r\n Logger.Log(\"PointerEventsCaptureBehavior: Starting observation of pointer move events.\");\r\n LocalScene.onDisposeObservable.add(DoStopCaptureOnEnter);\r\n }\r\n CaptureOnEnterCount++;\r\n};\r\n\r\nconst DoStopCaptureOnEnter = () => {\r\n document.removeEventListener(\"pointermove\", OnPointerMove);\r\n document.removeEventListener(\"touchstart\", OnPointerMove);\r\n LocalScene = null;\r\n Logger.Log(\"PointerEventsCaptureBehavior: Stopping observation of pointer move events.\");\r\n CaptureOnEnterCount = 0;\r\n};\r\n\r\nconst StopCaptureOnEnter = () => {\r\n // If we are not in a browser, do nothing\r\n if (typeof document === \"undefined\") {\r\n return;\r\n }\r\n\r\n // If we are not observing pointer movement, do nothing\r\n if (!LocalScene) {\r\n return;\r\n }\r\n\r\n CaptureOnEnterCount--;\r\n if (CaptureOnEnterCount <= 0) {\r\n DoStopCaptureOnEnter();\r\n }\r\n};\r\n\r\n// Module level function used to determine if an entered mesh should capture pointer events\r\nconst OnPointerMove = (evt: PointerEvent | TouchEvent) => {\r\n if (!LocalScene) {\r\n return;\r\n }\r\n\r\n const canvasRect = LocalScene.getEngine().getRenderingCanvasClientRect();\r\n if (!canvasRect) {\r\n return;\r\n }\r\n\r\n // Get the object that contains the client X and Y from either the pointer event or from the\r\n // TouchEvent touch\r\n const { clientX, clientY } = \"touches\" in evt ? evt.touches[0] : evt;\r\n\r\n // get the picked mesh, if any\r\n const pointerScreenX = clientX - canvasRect.left;\r\n const pointerScreenY = clientY - canvasRect.top;\r\n\r\n let pointerCaptureBehavior: PointerEventsCaptureBehavior | undefined;\r\n const pickResult = LocalScene.pick(pointerScreenX, pointerScreenY, (mesh) => {\r\n // If the mesh has an instance of PointerEventsCaptureBehavior attached to it,\r\n // and capture on pointer enter is true, then we want to pick it\r\n const pointerCaptureBehavior = MeshToBehaviorMap.get(mesh);\r\n return mesh.isEnabled() && typeof pointerCaptureBehavior !== \"undefined\" && pointerCaptureBehavior._captureOnPointerEnter;\r\n });\r\n\r\n let pickedMesh: AbstractMesh | null;\r\n if (pickResult.hit) {\r\n pickedMesh = pickResult.pickedMesh;\r\n } else {\r\n pickedMesh = null;\r\n }\r\n\r\n const capturingIdAsInt = parseInt(getCapturingId() || \"\");\r\n\r\n // if the picked mesh is the current capturing mesh, do nothing\r\n if (pickedMesh && pickedMesh.uniqueId === capturingIdAsInt) {\r\n return;\r\n }\r\n\r\n // If there is a capturing mesh and it is not the current picked mesh, or no\r\n // mesh is picked, release the capturing mesh\r\n if (capturingIdAsInt && (!pickedMesh || pickedMesh.uniqueId !== capturingIdAsInt)) {\r\n releaseCurrent();\r\n }\r\n\r\n // If there is a picked mesh and it is not the current capturing mesh, capture\r\n // the pointer events. Note that the current capturing mesh has already been\r\n // released above\r\n if (pickedMesh) {\r\n pointerCaptureBehavior = MeshToBehaviorMap.get(pickedMesh);\r\n pointerCaptureBehavior!.capturePointerEvents();\r\n }\r\n};\r\n\r\n/**\r\n * Behavior for any content that can capture pointer events, i.e. bypass the Babylon pointer event handling\r\n * and receive pointer events directly. It will register the capture triggers and negotiate the capture and\r\n * release of pointer events. Curerntly this applies only to HtmlMesh\r\n */\r\nexport class PointerEventsCaptureBehavior implements Behavior<AbstractMesh> {\r\n /** gets or sets behavior's name */\r\n public name = \"PointerEventsCaptureBehavior\";\r\n\r\n private _attachedMesh: AbstractMesh | null;\r\n /** @internal */\r\n public _captureOnPointerEnter: boolean;\r\n\r\n /**\r\n * Gets or sets the mesh that the behavior is attached to\r\n */\r\n public get attachedMesh() {\r\n return this._attachedMesh;\r\n }\r\n\r\n public set attachedMesh(value: AbstractMesh | null) {\r\n this._attachedMesh = value;\r\n }\r\n\r\n constructor(\r\n private _captureCallback: () => void,\r\n private _releaseCallback: () => void,\r\n { captureOnPointerEnter = true } = {}\r\n ) {\r\n this._attachedMesh = null;\r\n this._captureOnPointerEnter = captureOnPointerEnter;\r\n\r\n // Warn if we are not in a browser\r\n if (typeof document === \"undefined\") {\r\n Logger.Warn(`Creating an instance of PointerEventsCaptureBehavior outside of a browser. The behavior will not work.`);\r\n }\r\n }\r\n\r\n /**\r\n * Set if the behavior should capture pointer events when the pointer enters the mesh\r\n */\r\n public set captureOnPointerEnter(captureOnPointerEnter: boolean) {\r\n if (this._captureOnPointerEnter === captureOnPointerEnter) {\r\n return;\r\n }\r\n this._captureOnPointerEnter = captureOnPointerEnter;\r\n if (this._attachedMesh) {\r\n if (this._captureOnPointerEnter) {\r\n StartCaptureOnEnter(this._attachedMesh.getScene());\r\n } else {\r\n StopCaptureOnEnter();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Function called when the behavior needs to be initialized (before attaching it to a target)\r\n */\r\n public init() {}\r\n\r\n /**\r\n * Called when the behavior is attached to a target\r\n * @param mesh defines the target where the behavior is attached to\r\n */\r\n public attach(mesh: AbstractMesh) {\r\n // Add a reference to this behavior on the mesh. We do this so we can get a\r\n // reference to the behavior in the onPointerMove function without relying on\r\n // getBehaviorByName(), which does a linear search of the behaviors array.\r\n this.attachedMesh = mesh;\r\n MeshToBehaviorMap.set(mesh, this);\r\n if (this._captureOnPointerEnter) {\r\n StartCaptureOnEnter(mesh.getScene());\r\n }\r\n }\r\n\r\n /**\r\n * Called when the behavior is detached from its target\r\n */\r\n public detach() {\r\n if (!this.attachedMesh) {\r\n return;\r\n }\r\n // Remove the reference to this behavior from the mesh\r\n MeshToBehaviorMap.delete(this.attachedMesh);\r\n if (this._captureOnPointerEnter) {\r\n StopCaptureOnEnter();\r\n }\r\n this.attachedMesh = null;\r\n }\r\n\r\n /**\r\n * Dispose the behavior\r\n */\r\n public dispose() {\r\n this.detach();\r\n }\r\n\r\n // Release pointer events\r\n public releasePointerEvents() {\r\n if (!this.attachedMesh) {\r\n return;\r\n }\r\n requestRelease(this.attachedMesh.uniqueId.toString());\r\n }\r\n\r\n // Capture pointer events\r\n public capturePointerEvents() {\r\n if (!this.attachedMesh) {\r\n return;\r\n }\r\n requestCapture(this.attachedMesh.uniqueId.toString(), this._captureCallback, this._releaseCallback);\r\n }\r\n}\r\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@babylonjs/addons",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.6.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"module": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"postcompile": "build-tools -c add-js-to-es6"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@babylonjs/core": "^8.
|
|
21
|
+
"@babylonjs/core": "^8.6.0",
|
|
22
22
|
"@dev/addons": "^1.0.0",
|
|
23
23
|
"@dev/build-tools": "^1.0.0"
|
|
24
24
|
},
|