phaser-navmesh
Version:
A plugin for Phaser (v3) for fast pathfinding using navigation meshes
2 lines • 21.6 kB
JavaScript
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("phaser")):"function"==typeof define&&define.amd?define(["phaser"],e):"object"==typeof exports?exports.PhaserNavMeshPlugin=e(require("phaser")):t.PhaserNavMeshPlugin=e(t.Phaser)}(self,(function(t){return(()=>{var e={774:(t,e)=>{var i,s,n,o;o=function(){function t(t){for(var e=t,i=[];e.parent;)i.unshift(e),e=e.parent;return i}var e={search:function(i,s,o,r){i.cleanDirty();var h=(r=r||{}).heuristic||e.heuristics.manhattan,a=r.closest||!1,l=new n((function(t){return t.f})),c=s;for(s.h=h(s,o),i.markDirty(s),l.push(s);l.size()>0;){var u=l.pop();if(u===o)return t(u);u.closed=!0;for(var d=i.neighbors(u),p=0,g=d.length;p<g;++p){var f=d[p];if(!f.closed&&!f.isWall()){var y=u.g+f.getCost(u),b=f.visited;(!b||y<f.g)&&(f.visited=!0,f.parent=u,f.h=f.h||h(f,o),f.g=y,f.f=f.g+f.h,i.markDirty(f),a&&(f.h<c.h||f.h===c.h&&f.g<c.g)&&(c=f),b?l.rescoreElement(f):l.push(f))}}}return a?t(c):[]},heuristics:{manhattan:function(t,e){return Math.abs(e.x-t.x)+Math.abs(e.y-t.y)},diagonal:function(t,e){var i=Math.sqrt(2),s=Math.abs(e.x-t.x),n=Math.abs(e.y-t.y);return 1*(s+n)+(i-2)*Math.min(s,n)}},cleanNode:function(t){t.f=0,t.g=0,t.h=0,t.visited=!1,t.closed=!1,t.parent=null}};function i(t,e){e=e||{},this.nodes=[],this.diagonal=!!e.diagonal,this.grid=[];for(var i=0;i<t.length;i++){this.grid[i]=[];for(var n=0,o=t[i];n<o.length;n++){var r=new s(i,n,o[n]);this.grid[i][n]=r,this.nodes.push(r)}}this.init()}function s(t,e,i){this.x=t,this.y=e,this.weight=i}function n(t){this.content=[],this.scoreFunction=t}return i.prototype.init=function(){this.dirtyNodes=[];for(var t=0;t<this.nodes.length;t++)e.cleanNode(this.nodes[t])},i.prototype.cleanDirty=function(){for(var t=0;t<this.dirtyNodes.length;t++)e.cleanNode(this.dirtyNodes[t]);this.dirtyNodes=[]},i.prototype.markDirty=function(t){this.dirtyNodes.push(t)},i.prototype.neighbors=function(t){var e=[],i=t.x,s=t.y,n=this.grid;return n[i-1]&&n[i-1][s]&&e.push(n[i-1][s]),n[i+1]&&n[i+1][s]&&e.push(n[i+1][s]),n[i]&&n[i][s-1]&&e.push(n[i][s-1]),n[i]&&n[i][s+1]&&e.push(n[i][s+1]),this.diagonal&&(n[i-1]&&n[i-1][s-1]&&e.push(n[i-1][s-1]),n[i+1]&&n[i+1][s-1]&&e.push(n[i+1][s-1]),n[i-1]&&n[i-1][s+1]&&e.push(n[i-1][s+1]),n[i+1]&&n[i+1][s+1]&&e.push(n[i+1][s+1])),e},i.prototype.toString=function(){for(var t=[],e=this.grid,i=0;i<e.length;i++){for(var s=[],n=e[i],o=0;o<n.length;o++)s.push(n[o].weight);t.push(s.join(" "))}return t.join("\n")},s.prototype.toString=function(){return"["+this.x+" "+this.y+"]"},s.prototype.getCost=function(t){return t&&t.x!=this.x&&t.y!=this.y?1.41421*this.weight:this.weight},s.prototype.isWall=function(){return 0===this.weight},n.prototype={push:function(t){this.content.push(t),this.sinkDown(this.content.length-1)},pop:function(){var t=this.content[0],e=this.content.pop();return this.content.length>0&&(this.content[0]=e,this.bubbleUp(0)),t},remove:function(t){var e=this.content.indexOf(t),i=this.content.pop();e!==this.content.length-1&&(this.content[e]=i,this.scoreFunction(i)<this.scoreFunction(t)?this.sinkDown(e):this.bubbleUp(e))},size:function(){return this.content.length},rescoreElement:function(t){this.sinkDown(this.content.indexOf(t))},sinkDown:function(t){for(var e=this.content[t];t>0;){var i=(t+1>>1)-1,s=this.content[i];if(!(this.scoreFunction(e)<this.scoreFunction(s)))break;this.content[i]=e,this.content[t]=s,t=i}},bubbleUp:function(t){for(var e=this.content.length,i=this.content[t],s=this.scoreFunction(i);;){var n,o=t+1<<1,r=o-1,h=null;if(r<e){var a=this.content[r];(n=this.scoreFunction(a))<s&&(h=r)}if(o<e){var l=this.content[o];this.scoreFunction(l)<(null===h?s:n)&&(h=o)}if(null===h)break;this.content[t]=this.content[h],this.content[h]=i,t=h}}},{astar:e,Graph:i}},"object"==typeof t.exports?t.exports=o():(s=[],void 0===(n="function"==typeof(i=o)?i.apply(void 0,s):i)||(t.exports=n))},445:e=>{"use strict";e.exports=t}},i={};function s(t){var n=i[t];if(void 0!==n)return n.exports;var o=i[t]={exports:{}};return e[t](o,o.exports,s),o.exports}s.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return s.d(e,{a:e}),e},s.d=(t,e)=>{for(var i in e)s.o(e,i)&&!s.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},s.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),s.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var n={};return(()=>{"use strict";s.r(n),s.d(n,{PhaserNavMesh:()=>b,PhaserNavMeshPlugin:()=>M,default:()=>k});var t=s(445),e=s.n(t),i=s(774),o=s.n(i);class r{x;y;constructor(t=0,e=0){this.x=t,this.y=e}equals(t){return this.x===t.x&&this.y===t.y}angle(t){return Math.atan2(t.y-this.y,t.x-this.x)}distance(t){const e=t.x-this.x,i=t.y-this.y;return Math.sqrt(e*e+i*i)}add(t){this.x+=t.x,this.y+=t.y}subtract(t){this.x-=t.x,this.y-=t.y}clone(){return new r(this.x,this.y)}}class h{id;polygon;edges;neighbors;portals;centroid;boundingRadius;weight=1;x=0;y=0;constructor(t,e){this.id=t,this.polygon=e,this.edges=e.edges,this.neighbors=[],this.portals=[],this.centroid=this.calculateCentroid(),this.boundingRadius=this.calculateRadius()}getPoints(){return this.polygon.points}contains(t){return this.polygon.contains(t.x,t.y)||this.isPointOnEdge(t)}calculateCentroid(){const t=new r(0,0),e=this.polygon.points.length;return this.polygon.points.forEach((e=>t.add(e))),t.x/=e,t.y/=e,t}calculateRadius(){let t=0;for(const e of this.polygon.points){const i=this.centroid.distance(e);i>t&&(t=i)}return t}isPointOnEdge({x:t,y:e}){for(const i of this.edges)if(i.pointOnSegment(t,e))return!0;return!1}destroy(){this.neighbors=[],this.portals=[]}toString(){return`NavPoly(id: ${this.id} at: ${this.centroid})`}isWall(){return 0===this.weight}centroidDistance(t){return this.centroid.distance(t.centroid)}getCost(t){return this.centroidDistance(t)}}function a(t,e){const i=e.start,s=e.end,n=function(t,e){const i=e.x-t.x,s=e.y-t.y;return i*i+s*s}(i,s);let o=((t.x-i.x)*(s.x-i.x)+(t.y-i.y)*(s.y-i.y))/n;var h;return(h=o)<0&&(h=0),h>1&&(h=1),o=h,new r(i.x+o*(s.x-i.x),i.y+o*(s.y-i.y))}function l(t,e,i){const s=e.x-t.x,n=e.y-t.y;return(i.x-t.x)*n-s*(i.y-t.y)}function c(t,e,i=1e-4){return Math.abs(t-e)<=i}function u(t,e){let i=t-e;const s=i+Math.PI,n=2*Math.PI;return i=s-Math.floor(s/n)*n,i-=Math.PI,i}function d(t,e,i=1e-4){const s=l(t.start,t.end,e.start),n=l(t.start,t.end,e.end);return!(!c(s,0,i)||!c(n,0,i))}function p(t){return Boolean(t)}class g{path;portals;constructor(){this.portals=[],this.path=[]}push(t,e){void 0===e&&(e=t),this.portals.push({left:t,right:e})}stringPull(){const t=this.portals,e=[];let i=0,s=0,n=0,o=t[0].left,r=t[0].left,h=t[0].right;e.push(o);for(var a=1;a<t.length;a++){const c=t[a].left,u=t[a].right;if(l(o,h,u)<=0){if(!(o.equals(h)||l(o,r,u)>0)){e.push(r),o=r,i=s,r=o,h=o,s=i,n=i,a=i;continue}h=u,n=a}if(l(o,r,c)>=0){if(!(o.equals(r)||l(o,h,c)<0)){e.push(h),o=h,i=n,r=o,h=o,s=i,n=i,a=i;continue}r=c,s=a}}return 0!==e.length&&e[e.length-1].equals(t[t.length-1].left)||e.push(t[t.length-1].left),this.path=e,e}}class f{start;end;left;right;top;bottom;constructor(t,e,i,s){this.start=new r(t,e),this.end=new r(i,s),this.left=Math.min(t,i),this.right=Math.max(t,i),this.top=Math.min(e,s),this.bottom=Math.max(e,s)}pointOnSegment(t,e){return t>=this.left&&t<=this.right&&e>=this.top&&e<=this.bottom&&this.pointOnLine(t,e)}pointOnLine(t,e){return(t-this.left)*(this.bottom-this.top)==(this.right-this.left)*(e-this.top)}}class y{edges;points;isClosed;constructor(t,e=!0){this.isClosed=e,this.points=t,this.edges=[];for(let e=1;e<t.length;e++){const i=t[e-1],s=t[e];this.edges.push(new f(i.x,i.y,s.x,s.y))}if(this.isClosed){const e=t[0],i=t[t.length-1];this.edges.push(new f(e.x,e.y,i.x,i.y))}}contains(t,e){let i=!1;for(let s=-1,n=this.points.length-1;++s<this.points.length;n=s){const o=this.points[s].x,r=this.points[s].y,h=this.points[n].x,a=this.points[n].y;(r<=e&&e<a||a<=e&&e<r)&&t<(h-o)*(e-r)/(a-r)+o&&(i=!i)}return i}}class b{key;plugin;scene;debugGraphics;navMesh;constructor(t,e,i,s,n=0){this.key=i,this.plugin=t,this.scene=e,this.debugGraphics=null,this.navMesh=new class{meshShrinkAmount;navPolygons;graph;constructor(t,e=0){this.meshShrinkAmount=e;const i=t.map((t=>{const e=t.map((t=>new r(t.x,t.y)));return new y(e)}));this.navPolygons=i.map(((t,e)=>new h(e,t))),this.calculateNeighbors(),this.graph=new class{nodes;grid=[];constructor(t){this.nodes=t,this.init()}neighbors(t){return t.neighbors}navHeuristic(t,e){return t.centroidDistance(e)}destroy(){this.cleanDirty(),this.nodes=[]}init=o().Graph.prototype.init.bind(this);cleanDirty=o().Graph.prototype.cleanDirty.bind(this);markDirty=o().Graph.prototype.markDirty.bind(this);toString=o().Graph.prototype.toString.bind(this)}(this.navPolygons)}getPolygons(){return this.navPolygons}destroy(){this.graph.destroy();for(const t of this.navPolygons)t.destroy();this.navPolygons=[]}isPointInMesh(t){return this.navPolygons.some((e=>e.contains(t)))}findClosestMeshPoint(t,e=Number.POSITIVE_INFINITY){let i=e,s=null,n=null;for(const e of this.navPolygons){if(e.contains(t)){i=0,s=e,n=t;break}const o=e.boundingRadius;if(e.centroid.distance(t)-o<i){const o=this.projectPointToPolygon(t,e);o.distance<i&&(i=o.distance,s=e,n=o.point)}}return{distance:i,polygon:s,point:n}}findPath(t,e){let i,s,n=null,h=null,a=Number.MAX_VALUE,l=Number.MAX_VALUE;const c=new r(t.x,t.y),u=new r(e.x,e.y);for(const t of this.navPolygons)s=t.boundingRadius,i=t.centroid.distance(c),i<=a&&i<=s&&t.contains(c)&&(n=t,a=i),i=t.centroid.distance(u),i<=l&&i<=s&&t.contains(u)&&(h=t,l=i);if(!h&&this.meshShrinkAmount>0)for(const t of this.navPolygons)if(s=t.boundingRadius+this.meshShrinkAmount,i=t.centroid.distance(u),i<=s){const{distance:e}=this.projectPointToPolygon(u,t);e<=this.meshShrinkAmount&&e<l&&(h=t,l=e)}if(!h)return null;if(!n&&this.meshShrinkAmount>0)for(const t of this.navPolygons)if(s=t.boundingRadius+this.meshShrinkAmount,i=t.centroid.distance(c),i<=s){const{distance:e}=this.projectPointToPolygon(c,t);e<=this.meshShrinkAmount&&e<a&&(n=t,a=e)}if(!n)return null;if(n===h)return[c,u];const d=o().astar.search(this.graph,n,h,{heuristic:this.graph.navHeuristic});if(0===d.length)return null;d.unshift(n);const p=new g;p.push(c);for(let t=0;t<d.length-1;t++){const e=d[t],i=d[t+1];let s=null;for(let t=0;t<e.neighbors.length;t++)e.neighbors[t].id===i.id&&(s=e.portals[t]);if(!s)throw new Error("Path was supposed to be found, but portal is missing!");p.push(s.start,s.end)}p.push(u),p.stringPull();let f=null;const y=[];for(const t of p.path){const e=t.clone();f&&e.equals(f)||y.push(e),f=e}return y}calculateNeighbors(){for(let t=0;t<this.navPolygons.length;t++){const e=this.navPolygons[t];for(let i=t+1;i<this.navPolygons.length;i++){const t=this.navPolygons[i];if(!(e.centroid.distance(t.centroid)>e.boundingRadius+t.boundingRadius))for(const i of e.edges)for(const s of t.edges){if(!d(i,s))continue;const n=this.getSegmentOverlap(i,s);if(!n)continue;e.neighbors.push(t),t.neighbors.push(e);const[o,r]=n;let h=e.centroid.angle(i.start),a=e.centroid.angle(n[0]),l=e.centroid.angle(n[1]),c=u(h,a),p=u(h,l);c<p?e.portals.push(new f(o.x,o.y,r.x,r.y)):e.portals.push(new f(r.x,r.y,o.x,o.y)),h=t.centroid.angle(s.start),a=t.centroid.angle(n[0]),l=t.centroid.angle(n[1]),c=u(h,a),p=u(h,l),c<p?t.portals.push(new f(o.x,o.y,r.x,r.y)):t.portals.push(new f(r.x,r.y,o.x,o.y))}}}}getSegmentOverlap(t,e){const i=[{line:t,point:t.start},{line:t,point:t.end},{line:e,point:e.start},{line:e,point:e.end}];i.sort((function(t,e){return t.point.x<e.point.x?-1:t.point.x>e.point.x?1:t.point.y<e.point.y?-1:t.point.y>e.point.y?1:0}));const s=i[0].line===i[1].line,n=i[1].point.equals(i[2].point);return s||n?null:[i[1].point,i[2].point]}projectPointToPolygon(t,e){let i=null,s=Number.MAX_VALUE;for(const n of e.edges){const e=a(t,n),o=t.distance(e);(null===i||o<s)&&(s=o,i=e)}return{point:i,distance:s}}}(s,n)}isPointInMesh(t){return this.navMesh.isPointInMesh(t)}findPath(t,i,s=e().Geom.Point){const n=this.navMesh.findPath(t,i);return n?n.map((({x:t,y:e})=>new s(t,e))):n}enableDebug(t){return t||this.debugGraphics?t&&(this.debugGraphics&&this.debugGraphics.destroy(),this.debugGraphics=t):this.debugGraphics=this.scene.add.graphics(),this.debugGraphics.visible=!0,this.debugGraphics}disableDebug(){this.debugGraphics&&(this.debugGraphics.visible=!1)}isDebugEnabled(){return this.debugGraphics&&this.debugGraphics.visible}debugDrawClear(){this.debugGraphics&&this.debugGraphics.clear()}debugDrawMesh({drawCentroid:t=!0,drawBounds:e=!1,drawNeighbors:i=!0,drawPortals:s=!0,palette:n=[41136,6965820,13382463,15427649,15583569]}={}){if(!this.debugGraphics)return;const o=this.debugGraphics;this.navMesh.getPolygons().forEach((r=>{const h=n[r.id%n.length];o.fillStyle(h),o.fillPoints(r.getPoints(),!0),t&&(o.fillStyle(0),o.fillCircle(r.centroid.x,r.centroid.y,4)),e&&(o.lineStyle(1,16777215),o.strokeCircle(r.centroid.x,r.centroid.y,r.boundingRadius)),i&&(o.lineStyle(2,0),r.neighbors.forEach((t=>{o.lineBetween(r.centroid.x,r.centroid.y,t.centroid.x,t.centroid.y)}))),s&&(o.lineStyle(10,0),r.portals.forEach((t=>o.lineBetween(t.start.x,t.start.y,t.end.x,t.end.y))))}))}debugDrawPath(t,e=65280,i=10,s=1){if(this.debugGraphics&&t&&t.length){this.debugGraphics.lineStyle(i,e,s),this.debugGraphics.strokePoints(t),this.debugGraphics.fillStyle(e,s);const n=1.2*i;if(this.debugGraphics.fillCircle(t[0].x,t[0].y,n),t.length>1){const e=t[t.length-1];this.debugGraphics.fillCircle(e.x,e.y,n)}}}destroy(){this.navMesh&&this.navMesh.destroy(),this.debugGraphics&&this.debugGraphics.destroy(),this.plugin.removeMesh(this.key)}}class x{width;height;tileWidth;tileHeight;map;isWalkableTest;constructor(t,e,i,s){this.map=t,this.isWalkableTest=e,this.height=t.length,this.width=t[0].length,this.tileWidth=i,this.tileHeight=s}forEach(t){this.map.forEach(((e,i)=>{e.forEach(((e,s)=>{t(s,i,this.map[i][s])}))}))}isInGrid(t,e){return t>=0&&t<this.width&&e>=0&&e<this.height}isWalkable(t,e){return this.isInGrid(t,e)&&this.isWalkableTest(this.map[e][t],t,e)}isBlocked(t,e){return this.isInGrid(t,e)&&!this.isWalkableTest(this.map[e][t],t,e)}isBlockedAtWorld(t,e){return this.isBlocked(this.getGridX(t),this.getGridY(e))}getGridX(t){return Math.floor(t/this.tileWidth)}getGridY(t){return Math.floor(t/this.tileHeight)}getGridXY(t,e){return{x:this.getGridX(t),y:this.getGridY(e)}}getWorldX(t){return t*this.tileWidth}getWorldY(t){return t*this.tileHeight}getWorldXY(t,e){return{x:this.getWorldX(t),y:this.getWorldY(e)}}}class m{data=[];add(t){this.data.push(t)}shift(){return this.data.shift()}isEmpty(){return 0===this.data.length}containsPoint(t){return void 0!==this.data.find((e=>e.x===t.x&&e.y===t.y))}containsAllPoints(t){return t.every((t=>this.containsPoint(t)))}getIndexOfPoint(t){return this.data.findIndex((e=>e.x==t.x&&e.y==t.y))}removePoint(t){const e=this.getIndexOfPoint(t);-1!==e&&this.data.splice(e,1)}removePoints(t){t.forEach((t=>this.removePoint(t)))}}class v{x;y;width;height;constructor(t,e,i,s){this.x=t,this.y=e,this.width=i,this.height=s}setPosition(t,e){this.x=t,this.y=e}setSize(t,e){this.width=t,this.height=e}set(t,e,i,s){this.setPosition(t,e),this.setSize(i,s)}get left(){return this.x}set left(t){this.x=t}get top(){return this.y}set top(t){this.y=t}get right(){return this.x+this.width}set right(t){this.width=t-this.x}get bottom(){return this.y+this.height}set bottom(t){this.height=t-this.top}get center(){return{x:(this.x+this.right)/2,y:(this.y+this.bottom)/2}}doesOverlap(t){return!(this.right<t.x||this.x>t.right||this.y>t.bottom||this.bottom<t.y)}attemptMergeIn(t){const e=this.x===t.x&&this.width===t.width,i=this.y===t.y&&this.height===t.height;return e&&this.top===t.bottom?(this.height+=t.height,this.y=t.y,!0):e&&this.bottom===t.top?(this.bottom=t.bottom,!0):i&&this.left===t.right?(this.width+=t.width,this.x=t.x,!0):!(!i||this.right!==t.left||(this.right=t.right,0))}toPoints(){const{left:t,right:e,top:i,bottom:s}=this;return[{x:t,y:i},{x:e,y:i},{x:e,y:s},{x:t,y:s}]}}function w(t,e=1,i=1,s=p,n=0){const o=new x(t,s,e,i);if(n>=e||n>=i)throw new Error(`navmesh: Unsupported shrink amount ${n}. Must be less than tile width and height.`);let r=function(t){const e=new m,{tileWidth:i,tileHeight:s}=t,n=[];let o;t.forEach(((i,s)=>{t.isWalkable(i,s)&&e.add({x:i,y:s})}));const r=(t,i)=>{const s=((t,e)=>{const{top:i,left:s,right:n,bottom:o}=t;let r=[];if("top"===e)for(let t=s;t<=n-1;t++)r.push({x:t,y:i});else if("bottom"===e)for(let t=s;t<=n-1;t++)r.push({x:t,y:o});else if("left"===e)for(let t=i;t<=o-1;t++)r.push({x:s,y:t});else{if("right"!==e)throw new Error(`Invalid dir "${e}" for extend`);for(let t=i;t<=o-1;t++)r.push({x:n,y:t})}return r})(t,i),n=e.containsAllPoints(s);return n&&(((t,e)=>{if("top"===e)t.y-=1;else if("bottom"===e)t.bottom+=1;else if("left"===e)t.x-=1;else{if("right"!==e)throw new Error(`Invalid dir "${e}" for extend`);t.right+=1}})(t,i),e.removePoints(s)),n};for(;!e.isEmpty();){const t=e.shift();if(void 0===t)break;o=new v(t.x,t.y,1,1);let h=!0;for(;h;){const t=r(o,"top"),e=r(o,"right"),i=r(o,"left"),s=r(o,"bottom");h=t||s||i||e}o.setPosition(o.x*i,o.y*s),o.setSize(o.width*i,o.height*s),n.push(o)}return n}(o);return n>0&&(r=function(t,e,i){const{tileHeight:s,tileWidth:n}=e,o=[],r=[];t.forEach(((t,h)=>{const a=s,l=n,c=e.getGridX(t.x),u=e.getGridY(t.y),d=e.getGridY(t.bottom),p=e.getGridX(t.right),g=P(t,e,i,n,s);if(t.left>=t.right||t.top>=t.bottom)return;r.push(t);const f=[],y=[],b=(t,e,i,s)=>{const n=new v(t,e,i,s);i>s?y.push(n):f.push(n)};if(g.left){const s=t.left-i;let n=u,o=n-1;for(let t=u;t<d;t++)e.isBlocked(c-1,t)?(n<=o&&b(s,n*a,i,(o-n+1)*a),n=t+1):o=t;n<=o&&b(s,n*a,i,(o-n+1)*a)}if(g.right){const s=t.right;let n=u,o=n-1;for(let t=u;t<d;t++)e.isBlocked(p,t)?(n<=o&&b(s,n*a,i,(o-n+1)*a),n=t+1):o=t;n<=o&&b(s,n*a,i,(o-n+1)*a)}if(g.top){const s=t.top-i;let n=c,o=n-1;for(let t=c;t<p;t++)e.isBlocked(t,u-1)?(n<=o&&b(n*l,s,(o-n+1)*a,i),n=t+1):o=t;n<=o&&b(n*l,s,(o-n+1)*a,i)}if(g.bottom){const s=t.bottom;let n=c,o=n-1;for(let t=c;t<p;t++)e.isBlocked(t,d)?(n<=o&&b(n*l,s,(o-n+1)*a,i),n=t+1):o=t;n<=o&&b(n*l,s,(o-n+1)*a,i)}y.forEach((t=>{f.forEach((e=>{t.doesOverlap(e)&&(t.y>e.y?e.height-=i:e.top+=i)}))})),[...y,...f].forEach((t=>{P(t,e,i,n,s),t.left>=t.right||t.top>=t.bottom||o.push(t)}))}));for(let e=0;e<o.length;e++){let i=!1;for(const s of t)if(i=s.attemptMergeIn(o[e]),i)break;if(!i){for(let t=e+1;t<o.length&&(i=o[t].attemptMergeIn(o[e]),!i);t++);i||r.push(o[e])}}return r}(r,o,n)),r.map((t=>t.toPoints()))}function P(t,e,i,s,n){const o=i,r=s/2,h=n/2,{left:a,top:l,right:c,bottom:u}=t,d={left:!1,right:!1,top:!1,bottom:!1,topLeft:e.isBlockedAtWorld(a-o,l-o),topRight:e.isBlockedAtWorld(c+o,l-o),bottomLeft:e.isBlockedAtWorld(a-o,u+o),bottomRight:e.isBlockedAtWorld(c+o,u+o)};for(let t=l+h;t<u;t+=h)if(e.isBlockedAtWorld(a-o,t)){d.left=!0;break}for(let t=l+h;t<u;t+=h)if(e.isBlockedAtWorld(c+o,t)){d.right=!0;break}for(let t=a+r;t<c;t+=r)if(e.isBlockedAtWorld(t,l-i)){d.top=!0;break}for(let t=a+r;t<c;t+=r)if(e.isBlockedAtWorld(t,u+i)){d.bottom=!0;break}const p={left:d.left,right:d.right,top:d.top,bottom:d.bottom};return!d.topLeft||d.left||d.top||(t.width>t.height?p.left=!0:p.top=!0),!d.topRight||d.right||d.top||(t.width>t.height?p.right=!0:p.top=!0),!d.bottomLeft||d.bottom||d.left||(t.width>t.height?p.left=!0:p.bottom=!0),!d.bottomRight||d.bottom||d.right||(t.width>t.height?p.right=!0:p.bottom=!0),p.left&&(t.x+=i,t.width-=i),p.top&&(t.y+=i,t.height-=i),p.right&&(t.width-=i),p.bottom&&(t.height-=i),p}class M extends e().Plugins.ScenePlugin{phaserNavMeshes={};constructor(t,e,i){super(t,e,i)}boot(){this.systems.events.once("destroy",this.destroy,this)}init(){}start(){}destroy(){this.systems.events.off("boot",this.boot,this),this.removeAllMeshes()}removeAllMeshes(){const t=Object.values(this.phaserNavMeshes);this.phaserNavMeshes={},t.forEach((t=>t.destroy()))}removeMesh(t){this.phaserNavMeshes[t]&&delete this.phaserNavMeshes[t]}buildMeshFromTilemap(t,e,i,s,n=0){const o=i?i.map((t=>t.layer)):e.layers;s||(s=t=>!t.collides);let r=0,h=0,a=1,l=1;if(i){const t=i[0];r=t.tileToWorldX(0),h=t.tileToWorldY(0),a=t.scaleX,l=t.scaleY;for(const t of i)r===t.tileToWorldX(0)&&h===t.tileToWorldY(0)&&a===t.scaleX&&l===t.scaleY||console.warn(`PhaserNavMeshPlugin: buildMeshFromTilemap reads position & scale from the 1st TilemapLayer. Layer index ${t.layerIndex} has a different position & scale from the 1st TilemapLayer.`),0!==t.rotation&&console.warn(`PhaserNavMeshPlugin: buildMeshFromTilemap doesn't support TilemapLayer with rotation. Layer index ${t.layerIndex} is rotated.`)}o.forEach((t=>{0===t.x&&0===t.y||console.warn("PhaserNavMeshPlugin: buildMeshFromTilemap doesn't support layers with x/y positions from Tiled.")}));const c=[];for(let t=0;t<e.height;t+=1){const i=[];for(let n=0;n<e.width;n+=1){let e=!0;for(const i of o){const o=i.data[t][n];if(o&&!s(o)){e=!1;break}}i.push(e)}c.push(i)}let u=w(c,e.tileWidth,e.tileHeight,(t=>t),n);1!==a&&1!==l&&0!==r&&0!==h&&(u=u.map((t=>t.map((t=>({x:t.x*a+r,y:t.y*l+h}))))));const d=new b(this,this.scene,t,u,0);return this.phaserNavMeshes[t]=d,d}buildMeshFromTiled(t,e,i=0){if(this.phaserNavMeshes[t])return console.warn(`NavMeshPlugin: a navmesh already exists with the given key: ${t}`),this.phaserNavMeshes[t];e&&0!==e.objects.length||console.warn(`NavMeshPlugin: The given tilemap object layer is empty or undefined: ${e}`);const s=(e.objects??[]).map((t=>{const e=t.height??0,i=t.width??0,s=t.x??0,n=t.y??0,o=n+e,r=s+i;return[{x:s,y:n},{x:s,y:o},{x:r,y:o},{x:r,y:n}]})),n=new b(this,this.scene,t,s,i);return this.phaserNavMeshes[t]=n,n}}const k=M})(),n})()}));
//# sourceMappingURL=phaser-navmesh-plugin.js.map