Call gridless pathfinder from rust code
This commit is contained in:
+42
-18
@@ -4,34 +4,45 @@ import {debugGraphics} from "./main.js";
|
||||
import {settingsKey} from "./settings.js";
|
||||
import {getSnapPointForTokenObj, iterPairs} from "./util.js";
|
||||
|
||||
import * as GridlessPathfinding from "../wasm/gridless_pathfinding.js"
|
||||
|
||||
let cachedNodes = undefined;
|
||||
let use5105 = false;
|
||||
let gridlessPathfinder = undefined;
|
||||
|
||||
export function isPathfindingEnabled() {
|
||||
if (canvas.grid.type === CONST.GRID_TYPES.GRIDLESS)
|
||||
return false;
|
||||
if (!game.settings.get(settingsKey, "allowPathfinding"))
|
||||
return false;
|
||||
return game.settings.get(settingsKey, "autoPathfinding") != togglePathfinding;
|
||||
}
|
||||
|
||||
export function findPath(from, to, token, previousWaypoints) {
|
||||
const lastNode = calculatePath(from, to, token, previousWaypoints);
|
||||
if (!lastNode)
|
||||
return null;
|
||||
paintPathfindingDebug(lastNode, token);
|
||||
const path = [];
|
||||
let currentNode = lastNode;
|
||||
while (currentNode) {
|
||||
// TODO Check if the distance doesn't change
|
||||
if (path.length >= 2 && !stepCollidesWithWall(currentNode.node, path[path.length - 2], token))
|
||||
// Replace last waypoint if the current waypoint leads to a valid path
|
||||
path[path.length - 1] = {x: currentNode.node.x, y: currentNode.node.y};
|
||||
else
|
||||
path.push({x: currentNode.node.x, y: currentNode.node.y});
|
||||
currentNode = currentNode.previous;
|
||||
if (canvas.grid.type === CONST.GRID_TYPES.GRIDLESS) {
|
||||
if (!gridlessPathfinder)
|
||||
gridlessPathfinder = GridlessPathfinding.initialize(canvas.walls.placeables);
|
||||
paintGridlessPathfindingDebug(gridlessPathfinder);
|
||||
const path = GridlessPathfinding.findPath(gridlessPathfinder, from, to);
|
||||
console.warn(path);
|
||||
return path;
|
||||
}
|
||||
else {
|
||||
const lastNode = calculatePath(from, to, token, previousWaypoints);
|
||||
if (!lastNode)
|
||||
return null;
|
||||
paintGriddedPathfindingDebug(lastNode, token);
|
||||
const path = [];
|
||||
let currentNode = lastNode;
|
||||
while (currentNode) {
|
||||
// TODO Check if the distance doesn't change
|
||||
if (path.length >= 2 && !stepCollidesWithWall(currentNode.node, path[path.length - 2], token))
|
||||
// Replace last waypoint if the current waypoint leads to a valid path
|
||||
path[path.length - 1] = {x: currentNode.node.x, y: currentNode.node.y};
|
||||
else
|
||||
path.push({x: currentNode.node.x, y: currentNode.node.y});
|
||||
currentNode = currentNode.previous;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
export function wipePathfindingCache() {
|
||||
@@ -135,7 +146,7 @@ function stepCollidesWithWall(from, to, token) {
|
||||
return canvas.walls.checkCollision(new Ray(stepStart, stepEnd));
|
||||
}
|
||||
|
||||
function paintPathfindingDebug(lastNode, token) {
|
||||
function paintGriddedPathfindingDebug(lastNode, token) {
|
||||
if (!CONFIG.debug.dragRuler)
|
||||
return;
|
||||
|
||||
@@ -151,3 +162,16 @@ function paintPathfindingDebug(lastNode, token) {
|
||||
currentNode = currentNode.previous;
|
||||
}
|
||||
}
|
||||
|
||||
function paintGridlessPathfindingDebug(pathfinder) {
|
||||
if (!CONFIG.debug.dragRuler)
|
||||
return;
|
||||
|
||||
debugGraphics.removeChildren();
|
||||
let graphic = new PIXI.Graphics();
|
||||
graphic.lineStyle(2, 0x440000);
|
||||
for (const point of GridlessPathfinding.debugGetPathfindingPoints(pathfinder)) {
|
||||
graphic.drawCircle(point.x, point.y, 5);
|
||||
}
|
||||
debugGraphics.addChild(graphic);
|
||||
}
|
||||
|
||||
+35
-4
@@ -20,7 +20,7 @@ extern "C" {
|
||||
}
|
||||
|
||||
#[wasm_bindgen(
|
||||
inline_js = "export function collidesWithWall(p1, p2) { return canvas.walls.checkCollision(new Ray(p1, p2)); }"
|
||||
inline_js = "export function collidesWithWall(p1, p2) { return canvas.walls.checkCollision(new Ray(p1, p2));}"
|
||||
)]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_name=collidesWithWall)]
|
||||
@@ -39,6 +39,26 @@ extern "C" {
|
||||
fn c(this: &JsWallData) -> Vec<f64>;
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
pub type JsPoint;
|
||||
|
||||
#[wasm_bindgen(method, getter)]
|
||||
fn x(this: &JsPoint) -> f64;
|
||||
|
||||
#[wasm_bindgen(method, getter)]
|
||||
fn y(this: &JsPoint) -> f64;
|
||||
}
|
||||
|
||||
impl From<JsPoint> for Point {
|
||||
fn from(point: JsPoint) -> Self {
|
||||
Point {
|
||||
x: point.x(),
|
||||
y: point.y(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Wall {
|
||||
pub p1: Point,
|
||||
@@ -61,7 +81,7 @@ impl Wall {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[wasm_bindgen(js_name=buildCache)]
|
||||
#[wasm_bindgen]
|
||||
pub fn initialize(js_walls: Vec<JsValue>) -> Pathfinder {
|
||||
let mut walls = Vec::with_capacity(js_walls.len());
|
||||
for wall in js_walls {
|
||||
@@ -79,14 +99,25 @@ pub fn free(pathfinder: Pathfinder) {
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[wasm_bindgen(js_name=findPath)]
|
||||
pub fn find_path(pathfinder: &mut Pathfinder, from: Point, to: Point) -> Option<Array> {
|
||||
if let Some(first_node) = pathfinder.find_path(from, to) {
|
||||
pub fn find_path(pathfinder: &mut Pathfinder, from: JsPoint, to: JsPoint) -> Option<Array> {
|
||||
if let Some(first_node) = pathfinder.find_path(from.into(), to.into()) {
|
||||
Some(first_node.iter_path().map(JsValue::from).collect())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[wasm_bindgen(js_name=debugGetPathfindingPoints)]
|
||||
pub fn debug_get_pathfinding_points(pathfinder: &Pathfinder) -> Array {
|
||||
pathfinder
|
||||
.nodes
|
||||
.iter()
|
||||
.map(|node| node.borrow().point)
|
||||
.map(JsValue::from)
|
||||
.collect()
|
||||
}
|
||||
|
||||
trait IteratePath {
|
||||
fn iter_path(&self) -> PathIterator;
|
||||
}
|
||||
|
||||
@@ -83,6 +83,10 @@ impl NodeStorage {
|
||||
|
||||
node.borrow_mut().edges = Some(edges);
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> std::slice::Iter<'_, NodePtr> {
|
||||
self.0.iter()
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
|
||||
Reference in New Issue
Block a user