Add support for the wall height module in the gridless pathfinder
This commit is contained in:
+3
-3
@@ -25,12 +25,12 @@ export function isPathfindingEnabled() {
|
|||||||
|
|
||||||
export function findPath(from, to, token, previousWaypoints) {
|
export function findPath(from, to, token, previousWaypoints) {
|
||||||
checkCacheValid(token);
|
checkCacheValid(token);
|
||||||
|
|
||||||
if (canvas.grid.type === CONST.GRID_TYPES.GRIDLESS) {
|
if (canvas.grid.type === CONST.GRID_TYPES.GRIDLESS) {
|
||||||
let tokenSize = Math.max(token.data.width, token.data.height) * canvas.dimensions.size;
|
let tokenSize = Math.max(token.data.width, token.data.height) * canvas.dimensions.size;
|
||||||
let pathfinder = gridlessPathfinders.get(tokenSize);
|
let pathfinder = gridlessPathfinders.get(tokenSize);
|
||||||
if (!pathfinder) {
|
if (!pathfinder) {
|
||||||
pathfinder = GridlessPathfinding.initialize(canvas.walls.placeables, tokenSize);
|
pathfinder = GridlessPathfinding.initialize(canvas.walls.placeables, tokenSize, token.data.elevation, Boolean(game.modules.get("levels")?.active));
|
||||||
gridlessPathfinders.set(tokenSize, pathfinder);
|
gridlessPathfinders.set(tokenSize, pathfinder);
|
||||||
}
|
}
|
||||||
paintGridlessPathfindingDebug(pathfinder);
|
paintGridlessPathfindingDebug(pathfinder);
|
||||||
@@ -176,7 +176,7 @@ export function wipePathfindingCache() {
|
|||||||
* Check if the current cache is still suitable for the path we're about to find. If not, clear the cache
|
* Check if the current cache is still suitable for the path we're about to find. If not, clear the cache
|
||||||
*/
|
*/
|
||||||
function checkCacheValid(token) {
|
function checkCacheValid(token) {
|
||||||
// If levels is enabled, the cache is invalid if it was made for a
|
// If levels is enabled, the cache is invalid if it was made for a
|
||||||
if (game.modules.get("levels")?.active) {
|
if (game.modules.get("levels")?.active) {
|
||||||
const tokenElevation = token.data.elevation;
|
const tokenElevation = token.data.elevation;
|
||||||
if (tokenElevation !== cacheElevation) {
|
if (tokenElevation !== cacheElevation) {
|
||||||
|
|||||||
+60
-4
@@ -23,6 +23,8 @@ extern "C" {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
pub type JsWall;
|
pub type JsWall;
|
||||||
pub type JsWallData;
|
pub type JsWallData;
|
||||||
|
pub type JsWallFlags;
|
||||||
|
pub type JsWallHeight;
|
||||||
|
|
||||||
#[wasm_bindgen(method, getter)]
|
#[wasm_bindgen(method, getter)]
|
||||||
fn data(this: &JsWall) -> JsWallData;
|
fn data(this: &JsWall) -> JsWallData;
|
||||||
@@ -38,6 +40,18 @@ extern "C" {
|
|||||||
|
|
||||||
#[wasm_bindgen(method, getter, js_name = "move")]
|
#[wasm_bindgen(method, getter, js_name = "move")]
|
||||||
fn move_type(this: &JsWallData) -> WallSenseType;
|
fn move_type(this: &JsWallData) -> WallSenseType;
|
||||||
|
|
||||||
|
#[wasm_bindgen(method, getter)]
|
||||||
|
fn flags(this: &JsWallData) -> JsWallFlags;
|
||||||
|
|
||||||
|
#[wasm_bindgen(method, getter, js_name = "wallHeight")]
|
||||||
|
fn wall_height(this: &JsWallFlags) -> Option<JsWallHeight>;
|
||||||
|
|
||||||
|
#[wasm_bindgen(method, getter, js_name = "wallHeightTop")]
|
||||||
|
fn top(this: &JsWallHeight) -> Option<f64>;
|
||||||
|
|
||||||
|
#[wasm_bindgen(method, getter, js_name = "wallHeightBottom")]
|
||||||
|
fn bottom(this: &JsWallHeight) -> Option<f64>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
@@ -120,6 +134,38 @@ impl TryFrom<usize> for WallSenseType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct WallHeight {
|
||||||
|
pub top: f64,
|
||||||
|
pub bottom: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for WallHeight {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
top: f64::INFINITY,
|
||||||
|
bottom: f64::NEG_INFINITY,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Option<JsWallHeight>> for WallHeight {
|
||||||
|
fn from(height: Option<JsWallHeight>) -> Self {
|
||||||
|
let height = height
|
||||||
|
.map(|height| (height.top(), height.bottom()))
|
||||||
|
.unwrap_or((None, None));
|
||||||
|
let top = height.0.unwrap_or(WallHeight::default().top);
|
||||||
|
let bottom = height.1.unwrap_or(WallHeight::default().bottom);
|
||||||
|
Self { top, bottom }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WallHeight {
|
||||||
|
pub fn contains(&self, height: f64) -> bool {
|
||||||
|
self.top >= height && self.bottom <= height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Wall {
|
pub struct Wall {
|
||||||
pub p1: Point,
|
pub p1: Point,
|
||||||
@@ -127,6 +173,7 @@ pub struct Wall {
|
|||||||
pub door_type: DoorType,
|
pub door_type: DoorType,
|
||||||
pub door_state: DoorState,
|
pub door_state: DoorState,
|
||||||
pub move_type: WallSenseType,
|
pub move_type: WallSenseType,
|
||||||
|
pub height: WallHeight,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Wall {
|
impl Wall {
|
||||||
@@ -136,6 +183,7 @@ impl Wall {
|
|||||||
door_type: DoorType,
|
door_type: DoorType,
|
||||||
door_state: DoorState,
|
door_state: DoorState,
|
||||||
move_type: WallSenseType,
|
move_type: WallSenseType,
|
||||||
|
height: WallHeight,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
p1,
|
p1,
|
||||||
@@ -143,6 +191,7 @@ impl Wall {
|
|||||||
door_type,
|
door_type,
|
||||||
door_state,
|
door_state,
|
||||||
move_type,
|
move_type,
|
||||||
|
height,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,29 +205,36 @@ impl Wall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Wall {
|
impl Wall {
|
||||||
fn from_js(wall: &JsWall) -> Self {
|
fn from_js(wall: &JsWall, enable_height: bool) -> Self {
|
||||||
let data = wall.data();
|
let data = wall.data();
|
||||||
let mut c = data.c();
|
let mut c = data.c();
|
||||||
c.iter_mut().for_each(|val| *val = val.round());
|
c.iter_mut().for_each(|val| *val = val.round());
|
||||||
|
let height = if enable_height {
|
||||||
|
data.flags().wall_height().into()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
WallHeight::default()
|
||||||
|
};
|
||||||
Self::new(
|
Self::new(
|
||||||
Point::new(c[0], c[1]),
|
Point::new(c[0], c[1]),
|
||||||
Point::new(c[2], c[3]),
|
Point::new(c[2], c[3]),
|
||||||
data.door_type(),
|
data.door_type(),
|
||||||
data.door_state(),
|
data.door_state(),
|
||||||
data.move_type(),
|
data.move_type(),
|
||||||
|
height,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn initialize(js_walls: Vec<JsValue>, token_size: f64) -> Pathfinder {
|
pub fn initialize(js_walls: Vec<JsValue>, token_size: f64, token_elevation: f64, enable_height: bool) -> Pathfinder {
|
||||||
let mut walls = Vec::with_capacity(js_walls.len());
|
let mut walls = Vec::with_capacity(js_walls.len());
|
||||||
for wall in js_walls {
|
for wall in js_walls {
|
||||||
let wall = JsWall::from(wall);
|
let wall = JsWall::from(wall);
|
||||||
walls.push(Wall::from_js(&wall));
|
walls.push(Wall::from_js(&wall, enable_height));
|
||||||
}
|
}
|
||||||
Pathfinder::initialize(walls, token_size)
|
Pathfinder::initialize(walls, token_size, token_elevation)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ pub struct Pathfinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Pathfinder {
|
impl Pathfinder {
|
||||||
pub fn initialize<I>(walls: I, token_size: f64) -> Self
|
pub fn initialize<I>(walls: I, token_size: f64, token_elevation: f64) -> Self
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = Wall>,
|
I: IntoIterator<Item = Wall>,
|
||||||
{
|
{
|
||||||
@@ -162,6 +162,9 @@ impl Pathfinder {
|
|||||||
if wall.is_door() && wall.is_open() {
|
if wall.is_door() && wall.is_open() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if !wall.height.contains(token_elevation) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let x_diff = wall.p2.x - wall.p1.x;
|
let x_diff = wall.p2.x - wall.p1.x;
|
||||||
let y_diff = wall.p2.y - wall.p1.y;
|
let y_diff = wall.p2.y - wall.p1.y;
|
||||||
let p1_angle = y_diff.atan2(x_diff).rem_euclid(2.0 * PI);
|
let p1_angle = y_diff.atan2(x_diff).rem_euclid(2.0 * PI);
|
||||||
|
|||||||
Reference in New Issue
Block a user