mirror of
https://github.com/godotengine/godot
synced 2024-10-03 01:33:43 +00:00
Merge pull request #90876 from smix8/source_geometry_callback
Add navigation mesh source geometry parsers and callbacks
This commit is contained in:
commit
fba6803486
|
@ -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 a new issue