diff options
-rw-r--r-- | doc/classes/NavigationObstacle2D.xml | 13 | ||||
-rw-r--r-- | doc/classes/NavigationObstacle3D.xml | 13 | ||||
-rw-r--r-- | scene/2d/navigation_obstacle_2d.cpp | 52 | ||||
-rw-r--r-- | scene/2d/navigation_obstacle_2d.h | 7 | ||||
-rw-r--r-- | scene/3d/navigation_obstacle_3d.cpp | 52 | ||||
-rw-r--r-- | scene/3d/navigation_obstacle_3d.h | 7 |
6 files changed, 122 insertions, 22 deletions
diff --git a/doc/classes/NavigationObstacle2D.xml b/doc/classes/NavigationObstacle2D.xml index 4ecdc06645..6d05e220e3 100644 --- a/doc/classes/NavigationObstacle2D.xml +++ b/doc/classes/NavigationObstacle2D.xml @@ -10,12 +10,25 @@ <tutorials> </tutorials> <methods> + <method name="get_navigation_map" qualifiers="const"> + <return type="RID" /> + <description> + Returns the [RID] of the navigation map for this NavigationObstacle node. This function returns always the map set on the NavigationObstacle node and not the map of the abstract agent on the NavigationServer. If the agent map is changed directly with the NavigationServer API the NavigationObstacle node will not be aware of the map change. Use [method set_navigation_map] to change the navigation map for the NavigationObstacle and also update the agent on the NavigationServer. + </description> + </method> <method name="get_rid" qualifiers="const"> <return type="RID" /> <description> Returns the [RID] of this obstacle on the [NavigationServer2D]. </description> </method> + <method name="set_navigation_map"> + <return type="void" /> + <param index="0" name="navigation_map" type="RID" /> + <description> + Sets the [RID] of the navigation map this NavigationObstacle node should use and also updates the [code]agent[/code] on the NavigationServer. + </description> + </method> </methods> <members> <member name="estimate_radius" type="bool" setter="set_estimate_radius" getter="is_radius_estimated" default="true"> diff --git a/doc/classes/NavigationObstacle3D.xml b/doc/classes/NavigationObstacle3D.xml index ed8af3883c..f5a0bde089 100644 --- a/doc/classes/NavigationObstacle3D.xml +++ b/doc/classes/NavigationObstacle3D.xml @@ -10,12 +10,25 @@ <tutorials> </tutorials> <methods> + <method name="get_navigation_map" qualifiers="const"> + <return type="RID" /> + <description> + Returns the [RID] of the navigation map for this NavigationObstacle node. This function returns always the map set on the NavigationObstacle node and not the map of the abstract agent on the NavigationServer. If the agent map is changed directly with the NavigationServer API the NavigationObstacle node will not be aware of the map change. Use [method set_navigation_map] to change the navigation map for the NavigationObstacle and also update the agent on the NavigationServer. + </description> + </method> <method name="get_rid" qualifiers="const"> <return type="RID" /> <description> Returns the [RID] of this obstacle on the [NavigationServer3D]. </description> </method> + <method name="set_navigation_map"> + <return type="void" /> + <param index="0" name="navigation_map" type="RID" /> + <description> + Sets the [RID] of the navigation map this NavigationObstacle node should use and also updates the [code]agent[/code] on the NavigationServer. + </description> + </method> </methods> <members> <member name="estimate_radius" type="bool" setter="set_estimate_radius" getter="is_radius_estimated" default="true"> diff --git a/scene/2d/navigation_obstacle_2d.cpp b/scene/2d/navigation_obstacle_2d.cpp index a592d20cba..1850e00ecd 100644 --- a/scene/2d/navigation_obstacle_2d.cpp +++ b/scene/2d/navigation_obstacle_2d.cpp @@ -38,6 +38,9 @@ void NavigationObstacle2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_rid"), &NavigationObstacle2D::get_rid); + ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationObstacle2D::set_navigation_map); + ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationObstacle2D::get_navigation_map); + ClassDB::bind_method(D_METHOD("set_estimate_radius", "estimate_radius"), &NavigationObstacle2D::set_estimate_radius); ClassDB::bind_method(D_METHOD("is_radius_estimated"), &NavigationObstacle2D::is_radius_estimated); ClassDB::bind_method(D_METHOD("set_radius", "radius"), &NavigationObstacle2D::set_radius); @@ -57,28 +60,26 @@ void NavigationObstacle2D::_validate_property(PropertyInfo &p_property) const { void NavigationObstacle2D::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - parent_node2d = Object::cast_to<Node2D>(get_parent()); - reevaluate_agent_radius(); - if (parent_node2d != nullptr) { - // place agent on navigation map first or else the RVO agent callback creation fails silently later - NavigationServer2D::get_singleton()->agent_set_map(get_rid(), parent_node2d->get_world_2d()->get_navigation_map()); - } + case NOTIFICATION_POST_ENTER_TREE: { + set_agent_parent(get_parent()); set_physics_process_internal(true); } break; case NOTIFICATION_EXIT_TREE: { - parent_node2d = nullptr; + set_agent_parent(nullptr); set_physics_process_internal(false); } break; case NOTIFICATION_PARENTED: { - parent_node2d = Object::cast_to<Node2D>(get_parent()); - reevaluate_agent_radius(); + if (is_inside_tree() && (get_parent() != parent_node2d)) { + set_agent_parent(get_parent()); + set_physics_process_internal(true); + } } break; case NOTIFICATION_UNPARENTED: { - parent_node2d = nullptr; + set_agent_parent(nullptr); + set_physics_process_internal(false); } break; case NOTIFICATION_PAUSED: { @@ -182,6 +183,35 @@ real_t NavigationObstacle2D::estimate_agent_radius() const { return 1.0; // Never a 0 radius } +void NavigationObstacle2D::set_agent_parent(Node *p_agent_parent) { + if (Object::cast_to<Node2D>(p_agent_parent) != nullptr) { + parent_node2d = Object::cast_to<Node2D>(p_agent_parent); + if (map_override.is_valid()) { + NavigationServer2D::get_singleton()->agent_set_map(get_rid(), map_override); + } else { + NavigationServer2D::get_singleton()->agent_set_map(get_rid(), parent_node2d->get_world_2d()->get_navigation_map()); + } + reevaluate_agent_radius(); + } else { + parent_node2d = nullptr; + NavigationServer2D::get_singleton()->agent_set_map(get_rid(), RID()); + } +} + +void NavigationObstacle2D::set_navigation_map(RID p_navigation_map) { + map_override = p_navigation_map; + NavigationServer2D::get_singleton()->agent_set_map(agent, map_override); +} + +RID NavigationObstacle2D::get_navigation_map() const { + if (map_override.is_valid()) { + return map_override; + } else if (parent_node2d != nullptr) { + return parent_node2d->get_world_2d()->get_navigation_map(); + } + return RID(); +} + void NavigationObstacle2D::set_estimate_radius(bool p_estimate_radius) { estimate_radius = p_estimate_radius; notify_property_list_changed(); diff --git a/scene/2d/navigation_obstacle_2d.h b/scene/2d/navigation_obstacle_2d.h index 5795c6c94f..6eff95adec 100644 --- a/scene/2d/navigation_obstacle_2d.h +++ b/scene/2d/navigation_obstacle_2d.h @@ -38,8 +38,10 @@ class NavigationObstacle2D : public Node { GDCLASS(NavigationObstacle2D, Node); Node2D *parent_node2d = nullptr; + RID agent; RID map_before_pause; + RID map_override; bool estimate_radius = true; real_t radius = 1.0; @@ -57,6 +59,11 @@ public: return agent; } + void set_agent_parent(Node *p_agent_parent); + + void set_navigation_map(RID p_navigation_map); + RID get_navigation_map() const; + void set_estimate_radius(bool p_estimate_radius); bool is_radius_estimated() const { return estimate_radius; diff --git a/scene/3d/navigation_obstacle_3d.cpp b/scene/3d/navigation_obstacle_3d.cpp index 953e52e591..9b49238333 100644 --- a/scene/3d/navigation_obstacle_3d.cpp +++ b/scene/3d/navigation_obstacle_3d.cpp @@ -37,6 +37,9 @@ void NavigationObstacle3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_rid"), &NavigationObstacle3D::get_rid); + ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationObstacle3D::set_navigation_map); + ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationObstacle3D::get_navigation_map); + ClassDB::bind_method(D_METHOD("set_estimate_radius", "estimate_radius"), &NavigationObstacle3D::set_estimate_radius); ClassDB::bind_method(D_METHOD("is_radius_estimated"), &NavigationObstacle3D::is_radius_estimated); ClassDB::bind_method(D_METHOD("set_radius", "radius"), &NavigationObstacle3D::set_radius); @@ -56,28 +59,26 @@ void NavigationObstacle3D::_validate_property(PropertyInfo &p_property) const { void NavigationObstacle3D::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - parent_node3d = Object::cast_to<Node3D>(get_parent()); - reevaluate_agent_radius(); - if (parent_node3d != nullptr) { - // place agent on navigation map first or else the RVO agent callback creation fails silently later - NavigationServer3D::get_singleton()->agent_set_map(get_rid(), parent_node3d->get_world_3d()->get_navigation_map()); - } + case NOTIFICATION_POST_ENTER_TREE: { + set_agent_parent(get_parent()); set_physics_process_internal(true); } break; case NOTIFICATION_EXIT_TREE: { - parent_node3d = nullptr; + set_agent_parent(nullptr); set_physics_process_internal(false); } break; case NOTIFICATION_PARENTED: { - parent_node3d = Object::cast_to<Node3D>(get_parent()); - reevaluate_agent_radius(); + if (is_inside_tree() && (get_parent() != parent_node3d)) { + set_agent_parent(get_parent()); + set_physics_process_internal(true); + } } break; case NOTIFICATION_UNPARENTED: { - parent_node3d = nullptr; + set_agent_parent(nullptr); + set_physics_process_internal(false); } break; case NOTIFICATION_PAUSED: { @@ -189,6 +190,35 @@ real_t NavigationObstacle3D::estimate_agent_radius() const { return 1.0; // Never a 0 radius } +void NavigationObstacle3D::set_agent_parent(Node *p_agent_parent) { + if (Object::cast_to<Node3D>(p_agent_parent) != nullptr) { + parent_node3d = Object::cast_to<Node3D>(p_agent_parent); + if (map_override.is_valid()) { + NavigationServer3D::get_singleton()->agent_set_map(get_rid(), map_override); + } else { + NavigationServer3D::get_singleton()->agent_set_map(get_rid(), parent_node3d->get_world_3d()->get_navigation_map()); + } + reevaluate_agent_radius(); + } else { + parent_node3d = nullptr; + NavigationServer3D::get_singleton()->agent_set_map(get_rid(), RID()); + } +} + +void NavigationObstacle3D::set_navigation_map(RID p_navigation_map) { + map_override = p_navigation_map; + NavigationServer3D::get_singleton()->agent_set_map(agent, map_override); +} + +RID NavigationObstacle3D::get_navigation_map() const { + if (map_override.is_valid()) { + return map_override; + } else if (parent_node3d != nullptr) { + return parent_node3d->get_world_3d()->get_navigation_map(); + } + return RID(); +} + void NavigationObstacle3D::set_estimate_radius(bool p_estimate_radius) { estimate_radius = p_estimate_radius; notify_property_list_changed(); diff --git a/scene/3d/navigation_obstacle_3d.h b/scene/3d/navigation_obstacle_3d.h index 7f6af668b6..24caf50680 100644 --- a/scene/3d/navigation_obstacle_3d.h +++ b/scene/3d/navigation_obstacle_3d.h @@ -37,8 +37,10 @@ class NavigationObstacle3D : public Node { GDCLASS(NavigationObstacle3D, Node); Node3D *parent_node3d = nullptr; + RID agent; RID map_before_pause; + RID map_override; bool estimate_radius = true; real_t radius = 1.0; @@ -56,6 +58,11 @@ public: return agent; } + void set_agent_parent(Node *p_agent_parent); + + void set_navigation_map(RID p_navigation_map); + RID get_navigation_map() const; + void set_estimate_radius(bool p_estimate_radius); bool is_radius_estimated() const { return estimate_radius; |