|
@@ -14642,6 +14642,12 @@ var BABYLON;
|
|
|
BABYLON.RenderingGroup = RenderingGroup;
|
|
|
})(BABYLON || (BABYLON = {}));
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
var BABYLON;
|
|
|
(function (BABYLON) {
|
|
|
var PointerEventTypes = (function () {
|
|
@@ -14690,32 +14696,40 @@ var BABYLON;
|
|
|
return PointerEventTypes;
|
|
|
})();
|
|
|
BABYLON.PointerEventTypes = PointerEventTypes;
|
|
|
+ var PointerInfoBase = (function () {
|
|
|
+ function PointerInfoBase(type, event) {
|
|
|
+ this.type = type;
|
|
|
+ this.event = event;
|
|
|
+ }
|
|
|
+ return PointerInfoBase;
|
|
|
+ })();
|
|
|
+ BABYLON.PointerInfoBase = PointerInfoBase;
|
|
|
/**
|
|
|
* This class is used to store pointer related info for the onPrePointerObservable event.
|
|
|
* Set the skipOnPointerObservable property to true if you want the engine to stop any process after this event is triggered, even not calling onPointerObservable
|
|
|
*/
|
|
|
- var PointerInfoPre = (function () {
|
|
|
+ var PointerInfoPre = (function (_super) {
|
|
|
+ __extends(PointerInfoPre, _super);
|
|
|
function PointerInfoPre(type, event, localX, localY) {
|
|
|
- this.type = type;
|
|
|
- this.event = event;
|
|
|
+ _super.call(this, type, event);
|
|
|
this.skipOnPointerObservable = false;
|
|
|
this.localPosition = new BABYLON.Vector2(localX, localY);
|
|
|
}
|
|
|
return PointerInfoPre;
|
|
|
- })();
|
|
|
+ })(PointerInfoBase);
|
|
|
BABYLON.PointerInfoPre = PointerInfoPre;
|
|
|
/**
|
|
|
* This type contains all the data related to a pointer event in Babylon.js.
|
|
|
* The event member is an instance of PointerEvent for all types except PointerWheel and is of type MouseWheelEvent when type equals PointerWheel. The different event types can be found in the PointerEventTypes class.
|
|
|
*/
|
|
|
- var PointerInfo = (function () {
|
|
|
+ var PointerInfo = (function (_super) {
|
|
|
+ __extends(PointerInfo, _super);
|
|
|
function PointerInfo(type, event, pickInfo) {
|
|
|
- this.type = type;
|
|
|
- this.event = event;
|
|
|
+ _super.call(this, type, event);
|
|
|
this.pickInfo = pickInfo;
|
|
|
}
|
|
|
return PointerInfo;
|
|
|
- })();
|
|
|
+ })(PointerInfoBase);
|
|
|
BABYLON.PointerInfo = PointerInfo;
|
|
|
/**
|
|
|
* Represents a scene to be rendered by the engine.
|
|
@@ -37718,7 +37732,7 @@ var BABYLON;
|
|
|
};
|
|
|
Prim2DBase.prototype.addChild = function (child) {
|
|
|
child._hierarchyDepthOffset = this._hierarchyDepthOffset + ((this._children.length + 1) * this._siblingDepthOffset);
|
|
|
- console.log("Node: " + child.id + " has depth: " + child._hierarchyDepthOffset);
|
|
|
+ // console.log(`Node: ${child.id} has depth: ${child._hierarchyDepthOffset}`);
|
|
|
child._siblingDepthOffset = this._siblingDepthOffset / this.owner.hierarchyLevelMaxSiblingCount;
|
|
|
this._children.push(child);
|
|
|
};
|
|
@@ -39266,6 +39280,34 @@ var BABYLON;
|
|
|
this._renderableData._cacheTexture.hasAlpha = true;
|
|
|
this._unbindCacheTarget();
|
|
|
};
|
|
|
+ Object.defineProperty(Group2D.prototype, "cachedRect", {
|
|
|
+ /**
|
|
|
+ * Allow you to access the information regarding the cached rectangle of the Group2D into the MapTexture.
|
|
|
+ * If the `noWorldSpaceNode` options was used at the creation of a WorldSpaceCanvas, the rendering of the canvas must be made by the caller, so typically you want to bind the cacheTexture property to some material/mesh and you must use the cachedRect.UVs property to get the UV coordinates to use for your quad that will display the Canvas.
|
|
|
+ */
|
|
|
+ get: function () {
|
|
|
+ if (!this._renderableData) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return this._renderableData._cacheNode;
|
|
|
+ },
|
|
|
+ enumerable: true,
|
|
|
+ configurable: true
|
|
|
+ });
|
|
|
+ Object.defineProperty(Group2D.prototype, "cacheTexture", {
|
|
|
+ /**
|
|
|
+ * Access the texture that maintains a cached version of the Group2D.
|
|
|
+ * This is useful only if you're not using a WorldSpaceNode for your WorldSpace Canvas and therefore need to perform the rendering yourself.
|
|
|
+ */
|
|
|
+ get: function () {
|
|
|
+ if (!this._renderableData) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return this._renderableData._cacheTexture;
|
|
|
+ },
|
|
|
+ enumerable: true,
|
|
|
+ configurable: true
|
|
|
+ });
|
|
|
/**
|
|
|
* Call this method to remove this Group and its children from the Canvas
|
|
|
*/
|
|
@@ -42408,7 +42450,28 @@ var BABYLON;
|
|
|
var Canvas2D = (function (_super) {
|
|
|
__extends(Canvas2D, _super);
|
|
|
function Canvas2D() {
|
|
|
+ var _this = this;
|
|
|
_super.apply(this, arguments);
|
|
|
+ /**
|
|
|
+ * If you set your own WorldSpaceNode to display the Canvas2D you have to provide your own implementation of this method which computes the local position in the Canvas based on the given 3D World one.
|
|
|
+ * Beware that you have to take under consideration the origin and the renderScaleFactor in your calculations! Good luck!
|
|
|
+ */
|
|
|
+ this.worldSpaceToNodeLocal = function (worldPos) {
|
|
|
+ var node = _this._worldSpaceNode;
|
|
|
+ if (!node) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var mtx = node.getWorldMatrix().clone();
|
|
|
+ mtx.invert();
|
|
|
+ var v = BABYLON.Vector3.TransformCoordinates(worldPos, mtx);
|
|
|
+ var rsf = _this._renderScaleFactor;
|
|
|
+ var res = new BABYLON.Vector2(v.x * rsf, v.y * rsf);
|
|
|
+ var size = _this.actualSize;
|
|
|
+ var o = _this.origin;
|
|
|
+ res.x += size.width * o.x;
|
|
|
+ res.y += size.width * o.y;
|
|
|
+ return res;
|
|
|
+ };
|
|
|
this._notifDebugMode = false;
|
|
|
this._mapCounter = 0;
|
|
|
}
|
|
@@ -42423,7 +42486,7 @@ var BABYLON;
|
|
|
* - pos: the position of the canvas, relative from the bottom/left of the scene's viewport. Alternatively you can set the x and y properties directly. Default value is [0, 0]
|
|
|
* - size: the Size of the canvas. Alternatively the width and height properties can be set. If null two behaviors depend on the cachingStrategy: if it's CACHESTRATEGY_CACHECANVAS then it will always auto-fit the rendering device, in all the other modes it will fit the content of the Canvas
|
|
|
* - cachingStrategy: either CACHESTRATEGY_TOPLEVELGROUPS, CACHESTRATEGY_ALLGROUPS, CACHESTRATEGY_CANVAS, CACHESTRATEGY_DONTCACHE. Please refer to their respective documentation for more information. Default is Canvas2D.CACHESTRATEGY_DONTCACHE
|
|
|
- * - enableInteraction: if true the pointer events will be listened and rerouted to the appropriate primitives of the Canvas2D through the Prim2DBase.onPointerEventObservable observable property.
|
|
|
+ * - enableInteraction: if true the pointer events will be listened and rerouted to the appropriate primitives of the Canvas2D through the Prim2DBase.onPointerEventObservable observable property. Default is true.
|
|
|
* - isVisible: true if the canvas must be visible, false for hidden. Default is true.
|
|
|
* - marginTop/Left/Right/Bottom: define the margin for the corresponding edge, if all of them are null, margin is not used in layout computing. Default Value is null for each.
|
|
|
* - hAlighment: define horizontal alignment of the Canvas, alignment is optional, default value null: no alignment.
|
|
@@ -42432,13 +42495,13 @@ var BABYLON;
|
|
|
Canvas2D.CreateScreenSpace = function (scene, options) {
|
|
|
var c = new Canvas2D();
|
|
|
if (!options) {
|
|
|
- c.setupCanvas(scene, null, null, true, Canvas2D.CACHESTRATEGY_DONTCACHE, true, BABYLON.Vector2.Zero(), true, null, null, null, null, null, null);
|
|
|
+ c.setupCanvas(scene, null, null, 1, true, Canvas2D.CACHESTRATEGY_DONTCACHE, true, BABYLON.Vector2.Zero(), true, null, null, null, null, null, null);
|
|
|
c.position = BABYLON.Vector2.Zero();
|
|
|
}
|
|
|
else {
|
|
|
var pos = options.position || new BABYLON.Vector2(options.x || 0, options.y || 0);
|
|
|
var size = (!options.size && !options.width && !options.height) ? null : (options.size || (new BABYLON.Size(options.width || 0, options.height || 0)));
|
|
|
- c.setupCanvas(scene, options.id || null, size, true, options.cachingStrategy || Canvas2D.CACHESTRATEGY_DONTCACHE, options.enableInteraction || true, options.origin || BABYLON.Vector2.Zero(), options.isVisible || true, options.marginTop, options.marginLeft, options.marginRight, options.marginBottom, options.hAlignment || BABYLON.Prim2DBase.HAlignLeft, options.vAlignment || BABYLON.Prim2DBase.VAlignTop);
|
|
|
+ c.setupCanvas(scene, options.id || null, size, 1, true, options.cachingStrategy || Canvas2D.CACHESTRATEGY_DONTCACHE, options.enableInteraction || true, options.origin || BABYLON.Vector2.Zero(), options.isVisible || true, options.marginTop, options.marginLeft, options.marginRight, options.marginBottom, options.hAlignment || BABYLON.Prim2DBase.HAlignLeft, options.vAlignment || BABYLON.Prim2DBase.VAlignTop);
|
|
|
c.position = pos;
|
|
|
}
|
|
|
return c;
|
|
@@ -42457,7 +42520,9 @@ var BABYLON;
|
|
|
* TIPS: if you want a renderScaleFactor independent reference of frame, create a child Group2D in the Canvas with position 0,0 and size set to null, then set its scale property to the same amount than the renderScaleFactor, put all your primitive inside using coordinates regarding the size property you pick for the Canvas and you'll be fine.
|
|
|
* - sideOrientation: Unexpected behavior occur if the value is different from Mesh.DEFAULTSIDE right now, so please use this one, which is the default.
|
|
|
* - cachingStrategy Must be CACHESTRATEGY_CANVAS for now, which is the default.
|
|
|
+ * - enableInteraction: if true the pointer events will be listened and rerouted to the appropriate primitives of the Canvas2D through the Prim2DBase.onPointerEventObservable observable property. Default is false (the opposite of ScreenSpace).
|
|
|
* - isVisible: true if the canvas must be visible, false for hidden. Default is true.
|
|
|
+ * - customWorldSpaceNode: if specified the Canvas will be rendered in this given Node. But it's the responsibility of the caller to set the "worldSpaceToNodeLocal" property to compute the hit of the mouse ray into the node (in world coordinate system) as well as rendering the cached bitmap in the node itself. The properties cachedRect and cachedTexture of Group2D will give you what you need to do that.
|
|
|
*/
|
|
|
Canvas2D.CreateWorldSpace = function (scene, size, options) {
|
|
|
var cs = options && options.cachingStrategy || Canvas2D.CACHESTRATEGY_CANVAS;
|
|
@@ -42467,32 +42532,49 @@ var BABYLON;
|
|
|
//if (cachingStrategy === Canvas2D.CACHESTRATEGY_DONTCACHE) {
|
|
|
// throw new Error("CACHESTRATEGY_DONTCACHE cache Strategy can't be used for WorldSpace Canvas");
|
|
|
//}
|
|
|
- var id = options && options.id || null;
|
|
|
- var rsf = options && options.renderScaleFactor || 1;
|
|
|
+ var enableInteraction = options ? options.enableInteraction : true;
|
|
|
+ var createWorldSpaceNode = !options || (options.customWorldSpaceNode == null);
|
|
|
+ var isVisible = options ? options.isVisible || true : true;
|
|
|
+ var id = options ? options.id || null : null;
|
|
|
+ var rsf = options ? options.renderScaleFactor || 1 : 1;
|
|
|
var c = new Canvas2D();
|
|
|
- c.setupCanvas(scene, id, new BABYLON.Size(size.width * rsf, size.height * rsf), false, cs, options && options.enableInteraction || true, BABYLON.Vector2.Zero(), options && options.isVisible || true, null, null, null, null, null, null);
|
|
|
- var plane = new BABYLON.WorldSpaceCanvas2D(id, scene, c);
|
|
|
- var vertexData = BABYLON.VertexData.CreatePlane({ width: size.width / 2, height: size.height / 2, sideOrientation: options && options.sideOrientation || BABYLON.Mesh.DEFAULTSIDE });
|
|
|
- var mtl = new BABYLON.StandardMaterial(id + "_Material", scene);
|
|
|
- c.applyCachedTexture(vertexData, mtl);
|
|
|
- vertexData.applyToMesh(plane, false);
|
|
|
- mtl.specularColor = new BABYLON.Color3(0, 0, 0);
|
|
|
- mtl.disableLighting = true;
|
|
|
- mtl.useAlphaFromDiffuseTexture = true;
|
|
|
- plane.position = options && options.position || BABYLON.Vector3.Zero();
|
|
|
- plane.rotationQuaternion = options && options.rotation || BABYLON.Quaternion.Identity();
|
|
|
- plane.material = mtl;
|
|
|
- c._worldSpaceNode = plane;
|
|
|
+ c.setupCanvas(scene, id, new BABYLON.Size(size.width, size.height), rsf, false, cs, enableInteraction, new BABYLON.Vector2(0.5, 0.5), isVisible, null, null, null, null, null, null);
|
|
|
+ if (createWorldSpaceNode) {
|
|
|
+ var plane = new BABYLON.WorldSpaceCanvas2D(id, scene, c);
|
|
|
+ var vertexData = BABYLON.VertexData.CreatePlane({
|
|
|
+ width: size.width,
|
|
|
+ height: size.height,
|
|
|
+ sideOrientation: options && options.sideOrientation || BABYLON.Mesh.DEFAULTSIDE
|
|
|
+ });
|
|
|
+ var mtl = new BABYLON.StandardMaterial(id + "_Material", scene);
|
|
|
+ c.applyCachedTexture(vertexData, mtl);
|
|
|
+ vertexData.applyToMesh(plane, false);
|
|
|
+ mtl.specularColor = new BABYLON.Color3(0, 0, 0);
|
|
|
+ mtl.disableLighting = true;
|
|
|
+ mtl.useAlphaFromDiffuseTexture = true;
|
|
|
+ plane.position = options && options.position || BABYLON.Vector3.Zero();
|
|
|
+ plane.rotationQuaternion = options && options.rotation || BABYLON.Quaternion.Identity();
|
|
|
+ plane.material = mtl;
|
|
|
+ c._worldSpaceNode = plane;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ c._worldSpaceNode = options.customWorldSpaceNode;
|
|
|
+ }
|
|
|
return c;
|
|
|
};
|
|
|
- Canvas2D.prototype.setupCanvas = function (scene, name, size, isScreenSpace, cachingstrategy, enableInteraction, origin, isVisible, marginTop, marginLeft, marginRight, marginBottom, hAlign, vAlign) {
|
|
|
+ Canvas2D.prototype.setupCanvas = function (scene, name, size, renderScaleFactor, isScreenSpace, cachingstrategy, enableInteraction, origin, isVisible, marginTop, marginLeft, marginRight, marginBottom, hAlign, vAlign) {
|
|
|
var _this = this;
|
|
|
var engine = scene.getEngine();
|
|
|
this._fitRenderingDevice = !size;
|
|
|
if (!size) {
|
|
|
size = new BABYLON.Size(engine.getRenderWidth(), engine.getRenderHeight());
|
|
|
}
|
|
|
+ else {
|
|
|
+ size.height *= renderScaleFactor;
|
|
|
+ size.width *= renderScaleFactor;
|
|
|
+ }
|
|
|
this.__engineData = engine.getOrAddExternalDataWithFactory("__BJSCANVAS2D__", function (k) { return new Canvas2DEngineBoundData(); });
|
|
|
+ this._renderScaleFactor = renderScaleFactor;
|
|
|
this._cachingStrategy = cachingstrategy;
|
|
|
this._primPointerInfo = new BABYLON.PrimitivePointerInfo();
|
|
|
this._capturedPointers = new BABYLON.StringDictionary();
|
|
@@ -42545,17 +42627,42 @@ var BABYLON;
|
|
|
}
|
|
|
// Set the new state
|
|
|
this._interactionEnabled = enable;
|
|
|
- // Disable interaction
|
|
|
- if (!enable) {
|
|
|
- if (this._scenePrePointerObserver) {
|
|
|
- this.scene.onPrePointerObservable.remove(this._scenePrePointerObserver);
|
|
|
- this._scenePrePointerObserver = null;
|
|
|
+ // ScreenSpace mode
|
|
|
+ if (this._isScreeSpace) {
|
|
|
+ // Disable interaction
|
|
|
+ if (!enable) {
|
|
|
+ if (this._scenePrePointerObserver) {
|
|
|
+ this.scene.onPrePointerObservable.remove(this._scenePrePointerObserver);
|
|
|
+ this._scenePrePointerObserver = null;
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // Enable Interaction
|
|
|
+ // Register the observable
|
|
|
+ this._scenePrePointerObserver = this.scene.onPrePointerObservable.add(function (e, s) {
|
|
|
+ var hs = 1 / _this.engine.getHardwareScalingLevel();
|
|
|
+ var localPos = e.localPosition.multiplyByFloats(hs, hs);
|
|
|
+ _this._handlePointerEventForInteraction(e, localPos, s);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ var scene = this.scene;
|
|
|
+ if (enable) {
|
|
|
+ scene.constantlyUpdateMeshUnderPointer = true;
|
|
|
+ this._scenePointerObserver = scene.onPointerObservable.add(function (e, s) {
|
|
|
+ if (e.pickInfo.hit && e.pickInfo.pickedMesh === _this._worldSpaceNode && _this.worldSpaceToNodeLocal) {
|
|
|
+ var localPos = _this.worldSpaceToNodeLocal(e.pickInfo.pickedPoint);
|
|
|
+ _this._handlePointerEventForInteraction(e, localPos, s);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (this._scenePointerObserver) {
|
|
|
+ this.scene.onPointerObservable.remove(this._scenePointerObserver);
|
|
|
+ this._scenePointerObserver = null;
|
|
|
+ }
|
|
|
}
|
|
|
- return;
|
|
|
}
|
|
|
- // Enable Interaction
|
|
|
- // Register the observable
|
|
|
- this.scene.onPrePointerObservable.add(function (e, s) { return _this._handlePointerEventForInteraction(e, s); });
|
|
|
};
|
|
|
/**
|
|
|
* Internal method, you should use the Prim2DBase version instead
|
|
@@ -42608,13 +42715,13 @@ var BABYLON;
|
|
|
}
|
|
|
return this._capturedPointers.get(pointerId.toString());
|
|
|
};
|
|
|
- Canvas2D.prototype._handlePointerEventForInteraction = function (eventData, eventState) {
|
|
|
+ Canvas2D.prototype._handlePointerEventForInteraction = function (eventData, localPosition, eventState) {
|
|
|
// Dispose check
|
|
|
if (this.isDisposed) {
|
|
|
return;
|
|
|
}
|
|
|
// Update the this._primPointerInfo structure we'll send to observers using the PointerEvent data
|
|
|
- this._updatePointerInfo(eventData);
|
|
|
+ this._updatePointerInfo(eventData, localPosition);
|
|
|
var capturedPrim = this.getCapturedPrimitive(this._primPointerInfo.pointerId);
|
|
|
// Make sure the intersection list is up to date, we maintain this list either in response of a mouse event (here) or before rendering the canvas.
|
|
|
// Why before rendering the canvas? because some primitives may move and get away/under the mouse cursor (which is not moving). So we need to update at both location in order to always have an accurate list, which is needed for the hover state change.
|
|
@@ -42643,20 +42750,26 @@ var BABYLON;
|
|
|
this._bubbleNotifyPrimPointerObserver(targetPrim, BABYLON.PrimitivePointerInfo.PointerUp, eventData.event);
|
|
|
}
|
|
|
};
|
|
|
- Canvas2D.prototype._updatePointerInfo = function (eventData) {
|
|
|
+ Canvas2D.prototype._updatePointerInfo = function (eventData, localPosition) {
|
|
|
var pii = this._primPointerInfo;
|
|
|
if (!pii.canvasPointerPos) {
|
|
|
pii.canvasPointerPos = BABYLON.Vector2.Zero();
|
|
|
}
|
|
|
var camera = this._scene.activeCamera;
|
|
|
var engine = this._scene.getEngine();
|
|
|
- var cameraViewport = camera.viewport;
|
|
|
- var viewport = cameraViewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
|
|
|
- // Moving coordinates to local viewport world
|
|
|
- var x = eventData.localPosition.x / engine.getHardwareScalingLevel() - viewport.x;
|
|
|
- var y = eventData.localPosition.y / engine.getHardwareScalingLevel() - viewport.y;
|
|
|
- pii.canvasPointerPos.x = x - this.position.x;
|
|
|
- pii.canvasPointerPos.y = engine.getRenderHeight() - y - this.position.y;
|
|
|
+ if (this._isScreeSpace) {
|
|
|
+ var cameraViewport = camera.viewport;
|
|
|
+ var viewport = cameraViewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
|
|
|
+ // Moving coordinates to local viewport world
|
|
|
+ var x = localPosition.x - viewport.x;
|
|
|
+ var y = localPosition.y - viewport.y;
|
|
|
+ pii.canvasPointerPos.x = x - this.position.x;
|
|
|
+ pii.canvasPointerPos.y = engine.getRenderHeight() - y - this.position.y;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ pii.canvasPointerPos.x = localPosition.x;
|
|
|
+ pii.canvasPointerPos.y = localPosition.y;
|
|
|
+ }
|
|
|
pii.mouseWheelDelta = 0;
|
|
|
if (eventData.type === BABYLON.PointerEventTypes.POINTERWHEEL) {
|
|
|
var event = eventData.event;
|
|
@@ -42954,7 +43067,7 @@ var BABYLON;
|
|
|
});
|
|
|
Object.defineProperty(Canvas2D.prototype, "worldSpaceCanvasNode", {
|
|
|
/**
|
|
|
- * Only valid for World Space Canvas, returns the scene node that display the canvas
|
|
|
+ * Only valid for World Space Canvas, returns the scene node that displays the canvas
|
|
|
*/
|
|
|
get: function () {
|
|
|
return this._worldSpaceNode;
|
|
@@ -45557,7 +45670,20 @@ var BABYLON;
|
|
|
|
|
|
// All the credit goes to this project and the guy who's behind it https://github.com/mapbox/earcut
|
|
|
// Huge respect for a such great lib.
|
|
|
-// We just make it TypeScript compiling compliant and typed the public function.
|
|
|
+// Earcut license:
|
|
|
+// Copyright (c) 2016, Mapbox
|
|
|
+//
|
|
|
+// Permission to use, copy, modify, and/or distribute this software for any purpose
|
|
|
+// with or without fee is hereby granted, provided that the above copyright notice
|
|
|
+// and this permission notice appear in all copies.
|
|
|
+//
|
|
|
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
|
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
|
+// FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
|
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
|
+// OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
|
+// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
|
|
+// THIS SOFTWARE.
|
|
|
var Earcut;
|
|
|
(function (Earcut) {
|
|
|
/**
|