mirror of
https://github.com/godotengine/godot.git
synced 2024-11-21 19:42:43 +00:00
Add navigation source geometry parser callbacks
Adds navigation source geometry parser callbacks so that externals can hook their own geometry into the navigation mesh baking process.
This commit is contained in:
parent
9bc49a66ba
commit
58593d1bb7
@ -956,6 +956,23 @@
|
|||||||
Path simplification can be helpful to mitigate various path following issues that can arise with certain agent types and script behaviors. E.g. "steering" agents or avoidance in "open fields".
|
Path simplification can be helpful to mitigate various path following issues that can arise with certain agent types and script behaviors. E.g. "steering" agents or avoidance in "open fields".
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="source_geometry_parser_create">
|
||||||
|
<return type="RID" />
|
||||||
|
<description>
|
||||||
|
Creates a new source geometry parser. If a [Callable] is set for the parser with [method source_geometry_parser_set_callback] the callback will be called for every single node that gets parsed whenever [method parse_source_geometry_data] is used.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
|
<method name="source_geometry_parser_set_callback">
|
||||||
|
<return type="void" />
|
||||||
|
<param index="0" name="parser" type="RID" />
|
||||||
|
<param index="1" name="callback" type="Callable" />
|
||||||
|
<description>
|
||||||
|
Sets the [param callback] [Callable] for the specific source geometry [param parser]. The [Callable] will receive a call with the following parameters:
|
||||||
|
- [code]navigation_mesh[/code] - The [NavigationPolygon] reference used to define the parse settings. Do NOT edit or add directly to the navigation mesh.
|
||||||
|
- [code]source_geometry_data[/code] - The [NavigationMeshSourceGeometryData2D] reference. Add custom source geometry for navigation mesh baking to this object.
|
||||||
|
- [code]node[/code] - The [Node] that is parsed.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
</methods>
|
</methods>
|
||||||
<signals>
|
<signals>
|
||||||
<signal name="map_changed">
|
<signal name="map_changed">
|
||||||
|
@ -1103,6 +1103,23 @@
|
|||||||
Path simplification can be helpful to mitigate various path following issues that can arise with certain agent types and script behaviors. E.g. "steering" agents or avoidance in "open fields".
|
Path simplification can be helpful to mitigate various path following issues that can arise with certain agent types and script behaviors. E.g. "steering" agents or avoidance in "open fields".
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="source_geometry_parser_create">
|
||||||
|
<return type="RID" />
|
||||||
|
<description>
|
||||||
|
Creates a new source geometry parser. If a [Callable] is set for the parser with [method source_geometry_parser_set_callback] the callback will be called for every single node that gets parsed whenever [method parse_source_geometry_data] is used.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
|
<method name="source_geometry_parser_set_callback">
|
||||||
|
<return type="void" />
|
||||||
|
<param index="0" name="parser" type="RID" />
|
||||||
|
<param index="1" name="callback" type="Callable" />
|
||||||
|
<description>
|
||||||
|
Sets the [param callback] [Callable] for the specific source geometry [param parser]. The [Callable] will receive a call with the following parameters:
|
||||||
|
- [code]navigation_mesh[/code] - The [NavigationMesh] reference used to define the parse settings. Do NOT edit or add directly to the navigation mesh.
|
||||||
|
- [code]source_geometry_data[/code] - The [NavigationMeshSourceGeometryData3D] reference. Add custom source geometry for navigation mesh baking to this object.
|
||||||
|
- [code]node[/code] - The [Node] that is parsed.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
</methods>
|
</methods>
|
||||||
<signals>
|
<signals>
|
||||||
<signal name="avoidance_debug_changed">
|
<signal name="avoidance_debug_changed">
|
||||||
|
@ -389,7 +389,16 @@ bool FORWARD_1_C(agent_is_map_changed, RID, p_agent, rid_to_rid);
|
|||||||
void FORWARD_2(agent_set_paused, RID, p_agent, bool, p_paused, rid_to_rid, bool_to_bool);
|
void FORWARD_2(agent_set_paused, RID, p_agent, bool, p_paused, rid_to_rid, bool_to_bool);
|
||||||
bool FORWARD_1_C(agent_get_paused, RID, p_agent, rid_to_rid);
|
bool FORWARD_1_C(agent_get_paused, RID, p_agent, rid_to_rid);
|
||||||
|
|
||||||
void FORWARD_1(free, RID, p_object, rid_to_rid);
|
void GodotNavigationServer2D::free(RID p_object) {
|
||||||
|
#ifdef CLIPPER2_ENABLED
|
||||||
|
if (navmesh_generator_2d && navmesh_generator_2d->owns(p_object)) {
|
||||||
|
navmesh_generator_2d->free(p_object);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif // CLIPPER2_ENABLED
|
||||||
|
NavigationServer3D::get_singleton()->free(p_object);
|
||||||
|
}
|
||||||
|
|
||||||
void FORWARD_2(agent_set_avoidance_callback, RID, p_agent, Callable, p_callback, rid_to_rid, callable_to_callable);
|
void FORWARD_2(agent_set_avoidance_callback, RID, p_agent, Callable, p_callback, rid_to_rid, callable_to_callable);
|
||||||
bool GodotNavigationServer2D::agent_has_avoidance_callback(RID p_agent) const {
|
bool GodotNavigationServer2D::agent_has_avoidance_callback(RID p_agent) const {
|
||||||
return NavigationServer3D::get_singleton()->agent_has_avoidance_callback(p_agent);
|
return NavigationServer3D::get_singleton()->agent_has_avoidance_callback(p_agent);
|
||||||
@ -453,3 +462,20 @@ void GodotNavigationServer2D::query_path(const Ref<NavigationPathQueryParameters
|
|||||||
p_query_result->set_path_rids(_query_result.path_rids);
|
p_query_result->set_path_rids(_query_result.path_rids);
|
||||||
p_query_result->set_path_owner_ids(_query_result.path_owner_ids);
|
p_query_result->set_path_owner_ids(_query_result.path_owner_ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RID GodotNavigationServer2D::source_geometry_parser_create() {
|
||||||
|
#ifdef CLIPPER2_ENABLED
|
||||||
|
if (navmesh_generator_2d) {
|
||||||
|
return navmesh_generator_2d->source_geometry_parser_create();
|
||||||
|
}
|
||||||
|
#endif // CLIPPER2_ENABLED
|
||||||
|
return RID();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GodotNavigationServer2D::source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) {
|
||||||
|
#ifdef CLIPPER2_ENABLED
|
||||||
|
if (navmesh_generator_2d) {
|
||||||
|
navmesh_generator_2d->source_geometry_parser_set_callback(p_parser, p_callback);
|
||||||
|
}
|
||||||
|
#endif // CLIPPER2_ENABLED
|
||||||
|
}
|
||||||
|
@ -253,6 +253,9 @@ public:
|
|||||||
virtual void bake_from_source_geometry_data_async(const Ref<NavigationPolygon> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData2D> &p_source_geometry_data, const Callable &p_callback = Callable()) override;
|
virtual void bake_from_source_geometry_data_async(const Ref<NavigationPolygon> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData2D> &p_source_geometry_data, const Callable &p_callback = Callable()) override;
|
||||||
virtual bool is_baking_navigation_polygon(Ref<NavigationPolygon> p_navigation_polygon) const override;
|
virtual bool is_baking_navigation_polygon(Ref<NavigationPolygon> p_navigation_polygon) const override;
|
||||||
|
|
||||||
|
virtual RID source_geometry_parser_create() override;
|
||||||
|
virtual void source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) override;
|
||||||
|
|
||||||
virtual Vector<Vector2> simplify_path(const Vector<Vector2> &p_path, real_t p_epsilon) override;
|
virtual Vector<Vector2> simplify_path(const Vector<Vector2> &p_path, real_t p_epsilon) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -53,11 +53,14 @@
|
|||||||
NavMeshGenerator2D *NavMeshGenerator2D::singleton = nullptr;
|
NavMeshGenerator2D *NavMeshGenerator2D::singleton = nullptr;
|
||||||
Mutex NavMeshGenerator2D::baking_navmesh_mutex;
|
Mutex NavMeshGenerator2D::baking_navmesh_mutex;
|
||||||
Mutex NavMeshGenerator2D::generator_task_mutex;
|
Mutex NavMeshGenerator2D::generator_task_mutex;
|
||||||
|
RWLock NavMeshGenerator2D::generator_rid_rwlock;
|
||||||
bool NavMeshGenerator2D::use_threads = true;
|
bool NavMeshGenerator2D::use_threads = true;
|
||||||
bool NavMeshGenerator2D::baking_use_multiple_threads = true;
|
bool NavMeshGenerator2D::baking_use_multiple_threads = true;
|
||||||
bool NavMeshGenerator2D::baking_use_high_priority_threads = true;
|
bool NavMeshGenerator2D::baking_use_high_priority_threads = true;
|
||||||
HashSet<Ref<NavigationPolygon>> NavMeshGenerator2D::baking_navmeshes;
|
HashSet<Ref<NavigationPolygon>> NavMeshGenerator2D::baking_navmeshes;
|
||||||
HashMap<WorkerThreadPool::TaskID, NavMeshGenerator2D::NavMeshGeneratorTask2D *> NavMeshGenerator2D::generator_tasks;
|
HashMap<WorkerThreadPool::TaskID, NavMeshGenerator2D::NavMeshGeneratorTask2D *> NavMeshGenerator2D::generator_tasks;
|
||||||
|
RID_Owner<NavMeshGenerator2D::NavMeshGeometryParser2D> NavMeshGenerator2D::generator_parser_owner;
|
||||||
|
LocalVector<NavMeshGenerator2D::NavMeshGeometryParser2D *> NavMeshGenerator2D::generator_parsers;
|
||||||
|
|
||||||
NavMeshGenerator2D *NavMeshGenerator2D::get_singleton() {
|
NavMeshGenerator2D *NavMeshGenerator2D::get_singleton() {
|
||||||
return singleton;
|
return singleton;
|
||||||
@ -126,6 +129,13 @@ void NavMeshGenerator2D::cleanup() {
|
|||||||
}
|
}
|
||||||
generator_tasks.clear();
|
generator_tasks.clear();
|
||||||
|
|
||||||
|
generator_rid_rwlock.write_lock();
|
||||||
|
for (NavMeshGeometryParser2D *parser : generator_parsers) {
|
||||||
|
generator_parser_owner.free(parser->self);
|
||||||
|
}
|
||||||
|
generator_parsers.clear();
|
||||||
|
generator_rid_rwlock.write_unlock();
|
||||||
|
|
||||||
generator_task_mutex.unlock();
|
generator_task_mutex.unlock();
|
||||||
baking_navmesh_mutex.unlock();
|
baking_navmesh_mutex.unlock();
|
||||||
}
|
}
|
||||||
@ -236,6 +246,15 @@ void NavMeshGenerator2D::generator_parse_geometry_node(Ref<NavigationPolygon> p_
|
|||||||
generator_parse_tilemap_node(p_navigation_mesh, p_source_geometry_data, p_node);
|
generator_parse_tilemap_node(p_navigation_mesh, p_source_geometry_data, p_node);
|
||||||
generator_parse_navigationobstacle_node(p_navigation_mesh, p_source_geometry_data, p_node);
|
generator_parse_navigationobstacle_node(p_navigation_mesh, p_source_geometry_data, p_node);
|
||||||
|
|
||||||
|
generator_rid_rwlock.read_lock();
|
||||||
|
for (const NavMeshGeometryParser2D *parser : generator_parsers) {
|
||||||
|
if (!parser->callback.is_valid()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
parser->callback.call(p_navigation_mesh, p_source_geometry_data, p_node);
|
||||||
|
}
|
||||||
|
generator_rid_rwlock.read_unlock();
|
||||||
|
|
||||||
if (p_recurse_children) {
|
if (p_recurse_children) {
|
||||||
for (int i = 0; i < p_node->get_child_count(); i++) {
|
for (int i = 0; i < p_node->get_child_count(); i++) {
|
||||||
generator_parse_geometry_node(p_navigation_mesh, p_source_geometry_data, p_node->get_child(i), p_recurse_children);
|
generator_parse_geometry_node(p_navigation_mesh, p_source_geometry_data, p_node->get_child(i), p_recurse_children);
|
||||||
@ -813,6 +832,47 @@ bool NavMeshGenerator2D::generator_emit_callback(const Callable &p_callback) {
|
|||||||
return ce.error == Callable::CallError::CALL_OK;
|
return ce.error == Callable::CallError::CALL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RID NavMeshGenerator2D::source_geometry_parser_create() {
|
||||||
|
RWLockWrite write_lock(generator_rid_rwlock);
|
||||||
|
|
||||||
|
RID rid = generator_parser_owner.make_rid();
|
||||||
|
|
||||||
|
NavMeshGeometryParser2D *parser = generator_parser_owner.get_or_null(rid);
|
||||||
|
parser->self = rid;
|
||||||
|
|
||||||
|
generator_parsers.push_back(parser);
|
||||||
|
|
||||||
|
return rid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavMeshGenerator2D::source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) {
|
||||||
|
RWLockWrite write_lock(generator_rid_rwlock);
|
||||||
|
|
||||||
|
NavMeshGeometryParser2D *parser = generator_parser_owner.get_or_null(p_parser);
|
||||||
|
ERR_FAIL_NULL(parser);
|
||||||
|
|
||||||
|
parser->callback = p_callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NavMeshGenerator2D::owns(RID p_object) {
|
||||||
|
RWLockRead read_lock(generator_rid_rwlock);
|
||||||
|
return generator_parser_owner.owns(p_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavMeshGenerator2D::free(RID p_object) {
|
||||||
|
RWLockWrite write_lock(generator_rid_rwlock);
|
||||||
|
|
||||||
|
if (generator_parser_owner.owns(p_object)) {
|
||||||
|
NavMeshGeometryParser2D *parser = generator_parser_owner.get_or_null(p_object);
|
||||||
|
|
||||||
|
generator_parsers.erase(parser);
|
||||||
|
|
||||||
|
generator_parser_owner.free(p_object);
|
||||||
|
} else {
|
||||||
|
ERR_PRINT("Attempted to free a NavMeshGenerator2D RID that did not exist (or was already freed).");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NavMeshGenerator2D::generator_bake_from_source_geometry_data(Ref<NavigationPolygon> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data) {
|
void NavMeshGenerator2D::generator_bake_from_source_geometry_data(Ref<NavigationPolygon> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data) {
|
||||||
if (p_navigation_mesh.is_null() || p_source_geometry_data.is_null()) {
|
if (p_navigation_mesh.is_null() || p_source_geometry_data.is_null()) {
|
||||||
return;
|
return;
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
#include "core/object/class_db.h"
|
#include "core/object/class_db.h"
|
||||||
#include "core/object/worker_thread_pool.h"
|
#include "core/object/worker_thread_pool.h"
|
||||||
|
#include "core/templates/rid_owner.h"
|
||||||
|
|
||||||
class Node;
|
class Node;
|
||||||
class NavigationPolygon;
|
class NavigationPolygon;
|
||||||
@ -46,6 +47,14 @@ class NavMeshGenerator2D : public Object {
|
|||||||
static Mutex baking_navmesh_mutex;
|
static Mutex baking_navmesh_mutex;
|
||||||
static Mutex generator_task_mutex;
|
static Mutex generator_task_mutex;
|
||||||
|
|
||||||
|
static RWLock generator_rid_rwlock;
|
||||||
|
struct NavMeshGeometryParser2D {
|
||||||
|
RID self;
|
||||||
|
Callable callback;
|
||||||
|
};
|
||||||
|
static RID_Owner<NavMeshGeometryParser2D> generator_parser_owner;
|
||||||
|
static LocalVector<NavMeshGeometryParser2D *> generator_parsers;
|
||||||
|
|
||||||
static bool use_threads;
|
static bool use_threads;
|
||||||
static bool baking_use_multiple_threads;
|
static bool baking_use_multiple_threads;
|
||||||
static bool baking_use_high_priority_threads;
|
static bool baking_use_high_priority_threads;
|
||||||
@ -97,6 +106,12 @@ public:
|
|||||||
static void bake_from_source_geometry_data_async(Ref<NavigationPolygon> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, const Callable &p_callback = Callable());
|
static void bake_from_source_geometry_data_async(Ref<NavigationPolygon> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, const Callable &p_callback = Callable());
|
||||||
static bool is_baking(Ref<NavigationPolygon> p_navigation_polygon);
|
static bool is_baking(Ref<NavigationPolygon> p_navigation_polygon);
|
||||||
|
|
||||||
|
static RID source_geometry_parser_create();
|
||||||
|
static void source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback);
|
||||||
|
|
||||||
|
static bool owns(RID p_object);
|
||||||
|
static void free(RID p_object);
|
||||||
|
|
||||||
NavMeshGenerator2D();
|
NavMeshGenerator2D();
|
||||||
~NavMeshGenerator2D();
|
~NavMeshGenerator2D();
|
||||||
};
|
};
|
||||||
|
@ -1202,6 +1202,11 @@ COMMAND_1(free, RID, p_object) {
|
|||||||
} else if (obstacle_owner.owns(p_object)) {
|
} else if (obstacle_owner.owns(p_object)) {
|
||||||
internal_free_obstacle(p_object);
|
internal_free_obstacle(p_object);
|
||||||
|
|
||||||
|
#ifndef _3D_DISABLED
|
||||||
|
} else if (navmesh_generator_3d && navmesh_generator_3d->owns(p_object)) {
|
||||||
|
navmesh_generator_3d->free(p_object);
|
||||||
|
#endif // _3D_DISABLED
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ERR_PRINT("Attempted to free a NavigationServer RID that did not exist (or was already freed).");
|
ERR_PRINT("Attempted to free a NavigationServer RID that did not exist (or was already freed).");
|
||||||
}
|
}
|
||||||
@ -1428,6 +1433,23 @@ PathQueryResult GodotNavigationServer3D::_query_path(const PathQueryParameters &
|
|||||||
return r_query_result;
|
return r_query_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RID GodotNavigationServer3D::source_geometry_parser_create() {
|
||||||
|
#ifndef _3D_DISABLED
|
||||||
|
if (navmesh_generator_3d) {
|
||||||
|
return navmesh_generator_3d->source_geometry_parser_create();
|
||||||
|
}
|
||||||
|
#endif // _3D_DISABLED
|
||||||
|
return RID();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GodotNavigationServer3D::source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) {
|
||||||
|
#ifndef _3D_DISABLED
|
||||||
|
if (navmesh_generator_3d) {
|
||||||
|
navmesh_generator_3d->source_geometry_parser_set_callback(p_parser, p_callback);
|
||||||
|
}
|
||||||
|
#endif // _3D_DISABLED
|
||||||
|
}
|
||||||
|
|
||||||
Vector<Vector3> GodotNavigationServer3D::simplify_path(const Vector<Vector3> &p_path, real_t p_epsilon) {
|
Vector<Vector3> GodotNavigationServer3D::simplify_path(const Vector<Vector3> &p_path, real_t p_epsilon) {
|
||||||
if (p_path.size() <= 2) {
|
if (p_path.size() <= 2) {
|
||||||
return p_path;
|
return p_path;
|
||||||
|
@ -264,6 +264,9 @@ public:
|
|||||||
virtual void bake_from_source_geometry_data_async(const Ref<NavigationMesh> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data, const Callable &p_callback = Callable()) override;
|
virtual void bake_from_source_geometry_data_async(const Ref<NavigationMesh> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data, const Callable &p_callback = Callable()) override;
|
||||||
virtual bool is_baking_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh) const override;
|
virtual bool is_baking_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh) const override;
|
||||||
|
|
||||||
|
virtual RID source_geometry_parser_create() override;
|
||||||
|
virtual void source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) override;
|
||||||
|
|
||||||
virtual Vector<Vector3> simplify_path(const Vector<Vector3> &p_path, real_t p_epsilon) override;
|
virtual Vector<Vector3> simplify_path(const Vector<Vector3> &p_path, real_t p_epsilon) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -66,11 +66,14 @@
|
|||||||
NavMeshGenerator3D *NavMeshGenerator3D::singleton = nullptr;
|
NavMeshGenerator3D *NavMeshGenerator3D::singleton = nullptr;
|
||||||
Mutex NavMeshGenerator3D::baking_navmesh_mutex;
|
Mutex NavMeshGenerator3D::baking_navmesh_mutex;
|
||||||
Mutex NavMeshGenerator3D::generator_task_mutex;
|
Mutex NavMeshGenerator3D::generator_task_mutex;
|
||||||
|
RWLock NavMeshGenerator3D::generator_rid_rwlock;
|
||||||
bool NavMeshGenerator3D::use_threads = true;
|
bool NavMeshGenerator3D::use_threads = true;
|
||||||
bool NavMeshGenerator3D::baking_use_multiple_threads = true;
|
bool NavMeshGenerator3D::baking_use_multiple_threads = true;
|
||||||
bool NavMeshGenerator3D::baking_use_high_priority_threads = true;
|
bool NavMeshGenerator3D::baking_use_high_priority_threads = true;
|
||||||
HashSet<Ref<NavigationMesh>> NavMeshGenerator3D::baking_navmeshes;
|
HashSet<Ref<NavigationMesh>> NavMeshGenerator3D::baking_navmeshes;
|
||||||
HashMap<WorkerThreadPool::TaskID, NavMeshGenerator3D::NavMeshGeneratorTask3D *> NavMeshGenerator3D::generator_tasks;
|
HashMap<WorkerThreadPool::TaskID, NavMeshGenerator3D::NavMeshGeneratorTask3D *> NavMeshGenerator3D::generator_tasks;
|
||||||
|
RID_Owner<NavMeshGenerator3D::NavMeshGeometryParser3D> NavMeshGenerator3D::generator_parser_owner;
|
||||||
|
LocalVector<NavMeshGenerator3D::NavMeshGeometryParser3D *> NavMeshGenerator3D::generator_parsers;
|
||||||
|
|
||||||
NavMeshGenerator3D *NavMeshGenerator3D::get_singleton() {
|
NavMeshGenerator3D *NavMeshGenerator3D::get_singleton() {
|
||||||
return singleton;
|
return singleton;
|
||||||
@ -139,6 +142,13 @@ void NavMeshGenerator3D::cleanup() {
|
|||||||
}
|
}
|
||||||
generator_tasks.clear();
|
generator_tasks.clear();
|
||||||
|
|
||||||
|
generator_rid_rwlock.write_lock();
|
||||||
|
for (NavMeshGeometryParser3D *parser : generator_parsers) {
|
||||||
|
generator_parser_owner.free(parser->self);
|
||||||
|
}
|
||||||
|
generator_parsers.clear();
|
||||||
|
generator_rid_rwlock.write_unlock();
|
||||||
|
|
||||||
generator_task_mutex.unlock();
|
generator_task_mutex.unlock();
|
||||||
baking_navmesh_mutex.unlock();
|
baking_navmesh_mutex.unlock();
|
||||||
}
|
}
|
||||||
@ -254,6 +264,15 @@ void NavMeshGenerator3D::generator_parse_geometry_node(const Ref<NavigationMesh>
|
|||||||
#endif
|
#endif
|
||||||
generator_parse_navigationobstacle_node(p_navigation_mesh, p_source_geometry_data, p_node);
|
generator_parse_navigationobstacle_node(p_navigation_mesh, p_source_geometry_data, p_node);
|
||||||
|
|
||||||
|
generator_rid_rwlock.read_lock();
|
||||||
|
for (const NavMeshGeometryParser3D *parser : generator_parsers) {
|
||||||
|
if (!parser->callback.is_valid()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
parser->callback.call(p_navigation_mesh, p_source_geometry_data, p_node);
|
||||||
|
}
|
||||||
|
generator_rid_rwlock.read_unlock();
|
||||||
|
|
||||||
if (p_recurse_children) {
|
if (p_recurse_children) {
|
||||||
for (int i = 0; i < p_node->get_child_count(); i++) {
|
for (int i = 0; i < p_node->get_child_count(); i++) {
|
||||||
generator_parse_geometry_node(p_navigation_mesh, p_source_geometry_data, p_node->get_child(i), p_recurse_children);
|
generator_parse_geometry_node(p_navigation_mesh, p_source_geometry_data, p_node->get_child(i), p_recurse_children);
|
||||||
@ -920,4 +939,45 @@ bool NavMeshGenerator3D::generator_emit_callback(const Callable &p_callback) {
|
|||||||
return ce.error == Callable::CallError::CALL_OK;
|
return ce.error == Callable::CallError::CALL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RID NavMeshGenerator3D::source_geometry_parser_create() {
|
||||||
|
RWLockWrite write_lock(generator_rid_rwlock);
|
||||||
|
|
||||||
|
RID rid = generator_parser_owner.make_rid();
|
||||||
|
|
||||||
|
NavMeshGeometryParser3D *parser = generator_parser_owner.get_or_null(rid);
|
||||||
|
parser->self = rid;
|
||||||
|
|
||||||
|
generator_parsers.push_back(parser);
|
||||||
|
|
||||||
|
return rid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavMeshGenerator3D::source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) {
|
||||||
|
RWLockWrite write_lock(generator_rid_rwlock);
|
||||||
|
|
||||||
|
NavMeshGeometryParser3D *parser = generator_parser_owner.get_or_null(p_parser);
|
||||||
|
ERR_FAIL_NULL(parser);
|
||||||
|
|
||||||
|
parser->callback = p_callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NavMeshGenerator3D::owns(RID p_object) {
|
||||||
|
RWLockRead read_lock(generator_rid_rwlock);
|
||||||
|
return generator_parser_owner.owns(p_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavMeshGenerator3D::free(RID p_object) {
|
||||||
|
RWLockWrite write_lock(generator_rid_rwlock);
|
||||||
|
|
||||||
|
if (generator_parser_owner.owns(p_object)) {
|
||||||
|
NavMeshGeometryParser3D *parser = generator_parser_owner.get_or_null(p_object);
|
||||||
|
|
||||||
|
generator_parsers.erase(parser);
|
||||||
|
|
||||||
|
generator_parser_owner.free(p_object);
|
||||||
|
} else {
|
||||||
|
ERR_PRINT("Attempted to free a NavMeshGenerator3D RID that did not exist (or was already freed).");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // _3D_DISABLED
|
#endif // _3D_DISABLED
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
#include "core/object/class_db.h"
|
#include "core/object/class_db.h"
|
||||||
#include "core/object/worker_thread_pool.h"
|
#include "core/object/worker_thread_pool.h"
|
||||||
|
#include "core/templates/rid_owner.h"
|
||||||
#include "modules/modules_enabled.gen.h" // For csg, gridmap.
|
#include "modules/modules_enabled.gen.h" // For csg, gridmap.
|
||||||
|
|
||||||
class Node;
|
class Node;
|
||||||
@ -47,6 +48,14 @@ class NavMeshGenerator3D : public Object {
|
|||||||
static Mutex baking_navmesh_mutex;
|
static Mutex baking_navmesh_mutex;
|
||||||
static Mutex generator_task_mutex;
|
static Mutex generator_task_mutex;
|
||||||
|
|
||||||
|
static RWLock generator_rid_rwlock;
|
||||||
|
struct NavMeshGeometryParser3D {
|
||||||
|
RID self;
|
||||||
|
Callable callback;
|
||||||
|
};
|
||||||
|
static RID_Owner<NavMeshGeometryParser3D> generator_parser_owner;
|
||||||
|
static LocalVector<NavMeshGeometryParser3D *> generator_parsers;
|
||||||
|
|
||||||
static bool use_threads;
|
static bool use_threads;
|
||||||
static bool baking_use_multiple_threads;
|
static bool baking_use_multiple_threads;
|
||||||
static bool baking_use_high_priority_threads;
|
static bool baking_use_high_priority_threads;
|
||||||
@ -102,6 +111,12 @@ public:
|
|||||||
static void bake_from_source_geometry_data_async(Ref<NavigationMesh> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, const Callable &p_callback = Callable());
|
static void bake_from_source_geometry_data_async(Ref<NavigationMesh> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, const Callable &p_callback = Callable());
|
||||||
static bool is_baking(Ref<NavigationMesh> p_navigation_mesh);
|
static bool is_baking(Ref<NavigationMesh> p_navigation_mesh);
|
||||||
|
|
||||||
|
static RID source_geometry_parser_create();
|
||||||
|
static void source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback);
|
||||||
|
|
||||||
|
static bool owns(RID p_object);
|
||||||
|
static void free(RID p_object);
|
||||||
|
|
||||||
NavMeshGenerator3D();
|
NavMeshGenerator3D();
|
||||||
~NavMeshGenerator3D();
|
~NavMeshGenerator3D();
|
||||||
};
|
};
|
||||||
|
@ -165,6 +165,9 @@ void NavigationServer2D::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("bake_from_source_geometry_data_async", "navigation_polygon", "source_geometry_data", "callback"), &NavigationServer2D::bake_from_source_geometry_data_async, DEFVAL(Callable()));
|
ClassDB::bind_method(D_METHOD("bake_from_source_geometry_data_async", "navigation_polygon", "source_geometry_data", "callback"), &NavigationServer2D::bake_from_source_geometry_data_async, DEFVAL(Callable()));
|
||||||
ClassDB::bind_method(D_METHOD("is_baking_navigation_polygon", "navigation_polygon"), &NavigationServer2D::is_baking_navigation_polygon);
|
ClassDB::bind_method(D_METHOD("is_baking_navigation_polygon", "navigation_polygon"), &NavigationServer2D::is_baking_navigation_polygon);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("source_geometry_parser_create"), &NavigationServer2D::source_geometry_parser_create);
|
||||||
|
ClassDB::bind_method(D_METHOD("source_geometry_parser_set_callback", "parser", "callback"), &NavigationServer2D::source_geometry_parser_set_callback);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("simplify_path", "path", "epsilon"), &NavigationServer2D::simplify_path);
|
ClassDB::bind_method(D_METHOD("simplify_path", "path", "epsilon"), &NavigationServer2D::simplify_path);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer2D::free);
|
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer2D::free);
|
||||||
|
@ -306,6 +306,9 @@ public:
|
|||||||
virtual void bake_from_source_geometry_data_async(const Ref<NavigationPolygon> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData2D> &p_source_geometry_data, const Callable &p_callback = Callable()) = 0;
|
virtual void bake_from_source_geometry_data_async(const Ref<NavigationPolygon> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData2D> &p_source_geometry_data, const Callable &p_callback = Callable()) = 0;
|
||||||
virtual bool is_baking_navigation_polygon(Ref<NavigationPolygon> p_navigation_polygon) const = 0;
|
virtual bool is_baking_navigation_polygon(Ref<NavigationPolygon> p_navigation_polygon) const = 0;
|
||||||
|
|
||||||
|
virtual RID source_geometry_parser_create() = 0;
|
||||||
|
virtual void source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) = 0;
|
||||||
|
|
||||||
virtual Vector<Vector2> simplify_path(const Vector<Vector2> &p_path, real_t p_epsilon) = 0;
|
virtual Vector<Vector2> simplify_path(const Vector<Vector2> &p_path, real_t p_epsilon) = 0;
|
||||||
|
|
||||||
NavigationServer2D();
|
NavigationServer2D();
|
||||||
|
@ -170,6 +170,9 @@ public:
|
|||||||
void bake_from_source_geometry_data_async(const Ref<NavigationPolygon> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData2D> &p_source_geometry_data, const Callable &p_callback = Callable()) override {}
|
void bake_from_source_geometry_data_async(const Ref<NavigationPolygon> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData2D> &p_source_geometry_data, const Callable &p_callback = Callable()) override {}
|
||||||
bool is_baking_navigation_polygon(Ref<NavigationPolygon> p_navigation_polygon) const override { return false; }
|
bool is_baking_navigation_polygon(Ref<NavigationPolygon> p_navigation_polygon) const override { return false; }
|
||||||
|
|
||||||
|
RID source_geometry_parser_create() override { return RID(); }
|
||||||
|
void source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) override {}
|
||||||
|
|
||||||
Vector<Vector2> simplify_path(const Vector<Vector2> &p_path, real_t p_epsilon) override { return Vector<Vector2>(); }
|
Vector<Vector2> simplify_path(const Vector<Vector2> &p_path, real_t p_epsilon) override { return Vector<Vector2>(); }
|
||||||
|
|
||||||
void set_debug_enabled(bool p_enabled) {}
|
void set_debug_enabled(bool p_enabled) {}
|
||||||
|
@ -188,6 +188,9 @@ void NavigationServer3D::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("is_baking_navigation_mesh", "navigation_mesh"), &NavigationServer3D::is_baking_navigation_mesh);
|
ClassDB::bind_method(D_METHOD("is_baking_navigation_mesh", "navigation_mesh"), &NavigationServer3D::is_baking_navigation_mesh);
|
||||||
#endif // _3D_DISABLED
|
#endif // _3D_DISABLED
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("source_geometry_parser_create"), &NavigationServer3D::source_geometry_parser_create);
|
||||||
|
ClassDB::bind_method(D_METHOD("source_geometry_parser_set_callback", "parser", "callback"), &NavigationServer3D::source_geometry_parser_set_callback);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("simplify_path", "path", "epsilon"), &NavigationServer3D::simplify_path);
|
ClassDB::bind_method(D_METHOD("simplify_path", "path", "epsilon"), &NavigationServer3D::simplify_path);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer3D::free);
|
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer3D::free);
|
||||||
|
@ -351,6 +351,9 @@ public:
|
|||||||
virtual bool is_baking_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh) const = 0;
|
virtual bool is_baking_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh) const = 0;
|
||||||
#endif // _3D_DISABLED
|
#endif // _3D_DISABLED
|
||||||
|
|
||||||
|
virtual RID source_geometry_parser_create() = 0;
|
||||||
|
virtual void source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) = 0;
|
||||||
|
|
||||||
virtual Vector<Vector3> simplify_path(const Vector<Vector3> &p_path, real_t p_epsilon) = 0;
|
virtual Vector<Vector3> simplify_path(const Vector<Vector3> &p_path, real_t p_epsilon) = 0;
|
||||||
|
|
||||||
NavigationServer3D();
|
NavigationServer3D();
|
||||||
|
@ -182,6 +182,9 @@ public:
|
|||||||
bool is_baking_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh) const override { return false; }
|
bool is_baking_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh) const override { return false; }
|
||||||
#endif // _3D_DISABLED
|
#endif // _3D_DISABLED
|
||||||
|
|
||||||
|
RID source_geometry_parser_create() override { return RID(); }
|
||||||
|
void source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) override {}
|
||||||
|
|
||||||
Vector<Vector3> simplify_path(const Vector<Vector3> &p_path, real_t p_epsilon) override { return Vector<Vector3>(); }
|
Vector<Vector3> simplify_path(const Vector<Vector3> &p_path, real_t p_epsilon) override { return Vector<Vector3>(); }
|
||||||
|
|
||||||
void free(RID p_object) override {}
|
void free(RID p_object) override {}
|
||||||
|
Loading…
Reference in New Issue
Block a user