Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions modules/gridmap/doc_classes/GridMap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,12 @@
<member name="collision_visibility_mode" type="int" setter="set_collision_visibility_mode" getter="get_collision_visibility_mode" enum="GridMap.DebugVisibilityMode" default="0">
Show or hide the [GridMap]'s collision shapes. If set to [constant DEBUG_VISIBILITY_MODE_DEFAULT], this depends on the show collision debug settings.
</member>
<member name="debug_octant_color" type="Color" setter="set_debug_octant_color" getter="get_debug_octant_color" default="Color(1, 1, 1, 1)">
The [Color] used for rendering octant debug visuals when [member debug_show_octants] is enabled.
</member>
<member name="debug_show_octants" type="bool" setter="set_debug_show_octants" getter="get_debug_show_octants" default="false">
If [code]true[/code], shows debug visuals for octants.
</member>
<member name="mesh_library" type="MeshLibrary" setter="set_mesh_library" getter="get_mesh_library">
The assigned [MeshLibrary].
</member>
Expand Down
222 changes: 213 additions & 9 deletions modules/gridmap/grid_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,134 @@ bool GridMap::get_center_z() const {
return center_z;
}

void GridMap::set_debug_octant_color(const Color &p_color) {
#ifdef DEBUG_ENABLED
if (debug_octant_color == p_color) {
return;
}

debug_octant_color = p_color;

if (debug_octant_line_material.is_valid()) {
debug_octant_line_material->set_albedo(debug_octant_color);
}
#endif
}

Color GridMap::get_debug_octant_color() const {
return debug_octant_color;
}

#ifdef DEBUG_ENABLED
void GridMap::_debug_update() {
if (debug_dirty || !is_inside_tree()) {
return;
}
debug_dirty = true;

callable_mp(this, &GridMap::_debug_update_octants).call_deferred();
}

void GridMap::_debug_update_octants() {
debug_dirty = false;

if (!debug_show_octants) {
_debug_clear_octants();
return;
}

if (debug_octant_line_material.is_null()) {
debug_octant_line_material.instantiate();
debug_octant_line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
debug_octant_line_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
debug_octant_line_material->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true);
debug_octant_line_material->set_albedo(debug_octant_color);
}

Array debug_mesh_arrays = _build_octant_line_mesh_arrays();

if (debug_octant_line_mesh_rid.is_null()) {
debug_octant_line_mesh_rid = RS::get_singleton()->mesh_create();
}
RS::get_singleton()->mesh_clear(debug_octant_line_mesh_rid);
RS::get_singleton()->mesh_add_surface_from_arrays(debug_octant_line_mesh_rid, RSE::PRIMITIVE_LINES, debug_mesh_arrays);
RS::get_singleton()->mesh_surface_set_material(debug_octant_line_mesh_rid, 0, debug_octant_line_material->get_rid());

RID debug_scenario = get_world_3d()->get_scenario();
const Transform3D &gridmap_xform = get_global_transform();

for (const KeyValue<OctantKey, Octant *> &ele : octant_map) {
OctantKey octant_key = ele.key;
HashMap<OctantKey, OctantDebug *, OctantKey>::Iterator E = debug_octant_map.find(octant_key);
if (!E) {
OctantDebug *octant_debug = memnew(OctantDebug);

RID debug_octant_line_instance_rid = RS::get_singleton()->instance_create();

RS::get_singleton()->instance_set_base(debug_octant_line_instance_rid, debug_octant_line_mesh_rid);
RS::get_singleton()->instance_set_scenario(debug_octant_line_instance_rid, debug_scenario);

octant_debug->debug_line_instance_rid = debug_octant_line_instance_rid;

E = debug_octant_map.insert(octant_key, octant_debug);
}

OctantDebug &octant_debug = *E->value;
const Transform3D octant_transform = gridmap_xform * (Transform3D(Basis(), Vector3(octant_key.x, octant_key.y, octant_key.z) * octant_size * cell_size));

RS::get_singleton()->instance_set_scenario(octant_debug.debug_line_instance_rid, debug_scenario);
RS::get_singleton()->instance_set_transform(octant_debug.debug_line_instance_rid, octant_transform);
RS::get_singleton()->instance_set_visible(octant_debug.debug_line_instance_rid, is_visible_in_tree());
}
}

void GridMap::_debug_clear_octants() {
for (const KeyValue<OctantKey, Octant *> &ele : octant_map) {
OctantKey octant_key = ele.key;
HashMap<OctantKey, OctantDebug *, OctantKey>::Iterator E = debug_octant_map.find(octant_key);
if (E) {
OctantDebug &octant_debug = *E->value;

if (octant_debug.debug_line_mesh_rid.is_valid()) {
RS::get_singleton()->free_rid(octant_debug.debug_line_mesh_rid);
octant_debug.debug_line_mesh_rid = RID();
}
if (octant_debug.debug_line_instance_rid.is_valid()) {
RS::get_singleton()->free_rid(octant_debug.debug_line_instance_rid);
octant_debug.debug_line_instance_rid = RID();
}

memdelete(&octant_debug);
}
}

debug_octant_map.clear();
}

Array GridMap::_build_octant_line_mesh_arrays() const {
AABB aabb;
aabb.size = octant_size * cell_size;

Vector<Vector3> vertex_array;
vertex_array.resize(24);
Vector3 *vertex_array_ptrw = vertex_array.ptrw();
int vertex_index = 0;

for (int i = 0; i < 12; i++) {
Vector3 a, b;
aabb.get_edge(i, a, b);
vertex_array_ptrw[vertex_index++] = a;
vertex_array_ptrw[vertex_index++] = b;
}

Array mesh_arrays;
mesh_arrays.resize(Mesh::ARRAY_MAX);
mesh_arrays[Mesh::ARRAY_VERTEX] = vertex_array;

return mesh_arrays;
}
#endif // DEBUG_ENABLED

void GridMap::set_cell_item(const Vector3i &p_position, int p_item, int p_rot) {
if (baked_meshes.size() && !recreating_octants) {
//if you set a cell item, baked meshes go good bye
Expand Down Expand Up @@ -991,6 +1119,8 @@ void GridMap::_octant_exit_world(const OctantKey &p_key) {
g.navigation_debug_edge_connections_mesh.unref();
}
}

_debug_clear_octants();
#endif // DEBUG_ENABLED
}

Expand Down Expand Up @@ -1040,9 +1170,11 @@ void GridMap::_octant_clean_up(const OctantKey &p_key) {
g.navigation_debug_edge_connections_mesh.unref();
}
}

_debug_clear_octants();
#endif // DEBUG_ENABLED

//erase multimeshes
// Erase multimeshes.

for (int i = 0; i < g.multimesh_instances.size(); i++) {
RS::get_singleton()->free_rid(g.multimesh_instances[i].instance);
Expand All @@ -1067,20 +1199,32 @@ void GridMap::_notification(int p_what) {
} break;

case NOTIFICATION_ENTER_TREE: {
#if defined(DEBUG_ENABLED) && !defined(NAVIGATION_3D_DISABLED)
#ifdef DEBUG_ENABLED
_debug_update();

#ifndef NAVIGATION_3D_DISABLED
if (bake_navigation && NavigationServer3D::get_singleton()->get_debug_navigation_enabled()) {
_update_navigation_debug_edge_connections();
}
#endif // defined(DEBUG_ENABLED) && !defined(NAVIGATION_3D_DISABLED)
#endif // NAVIGATION_3D_DISABLED

#endif // DEBUG_ENABLED

_update_visibility();
} break;

#ifdef DEBUG_ENABLED
case NOTIFICATION_EXIT_TREE: {
_debug_clear_octants();
} break;
#endif

case NOTIFICATION_TRANSFORM_CHANGED: {
Transform3D new_xform = get_global_transform();
if (new_xform == last_transform) {
break;
}
//update run

for (const KeyValue<OctantKey, Octant *> &E : octant_map) {
_octant_transform(E.key);
}
Expand All @@ -1090,16 +1234,24 @@ void GridMap::_notification(int p_what) {
for (int i = 0; i < baked_meshes.size(); i++) {
RS::get_singleton()->instance_set_transform(baked_meshes[i].instance, get_global_transform());
}

#ifdef DEBUG_ENABLED
for (const KeyValue<OctantKey, OctantDebug *> &E : debug_octant_map) {
OctantKey octant_key = E.key;
OctantDebug &octant_debug = *E.value;
if (octant_debug.debug_line_instance_rid.is_valid()) {
const Transform3D octant_transform = new_xform * (Transform3D(Basis(), Vector3(octant_key.x, octant_key.y, octant_key.z) * octant_size * cell_size));
RS::get_singleton()->instance_set_transform(octant_debug.debug_line_instance_rid, octant_transform);
}
}
#endif
} break;

case NOTIFICATION_EXIT_WORLD: {
for (const KeyValue<OctantKey, Octant *> &E : octant_map) {
_octant_exit_world(E.key);
}

//_queue_octants_dirty(MAP_DIRTY_INSTANCES|MAP_DIRTY_TRANSFORMS);
//_update_octants_callback();
//_update_area_instances();
for (int i = 0; i < baked_meshes.size(); i++) {
RS::get_singleton()->instance_set_scenario(baked_meshes[i].instance, RID());
}
Expand Down Expand Up @@ -1127,6 +1279,15 @@ void GridMap::_update_visibility() {
for (int i = 0; i < baked_meshes.size(); i++) {
RS::get_singleton()->instance_set_visible(baked_meshes[i].instance, is_visible_in_tree());
}

#ifdef DEBUG_ENABLED
for (const KeyValue<OctantKey, OctantDebug *> &E : debug_octant_map) {
OctantDebug &octant_debug = *E.value;
if (octant_debug.debug_line_instance_rid.is_valid()) {
RS::get_singleton()->instance_set_visible(octant_debug.debug_line_instance_rid, is_visible_in_tree());
}
}
#endif
}

void GridMap::_queue_octants_dirty() {
Expand All @@ -1140,12 +1301,17 @@ void GridMap::_queue_octants_dirty() {

void GridMap::_recreate_octant_data() {
recreating_octants = true;

HashMap<IndexKey, Cell, IndexKey> cell_copy(cell_map);
_clear_internal();
for (const KeyValue<IndexKey, Cell> &E : cell_copy) {
set_cell_item(Vector3i(E.key), E.value.item, E.value.rot);
}

recreating_octants = false;
#ifdef DEBUG_ENABLED
_debug_update();
#endif
}

void GridMap::_clear_internal() {
Expand All @@ -1160,6 +1326,10 @@ void GridMap::_clear_internal() {

octant_map.clear();
cell_map.clear();
#ifdef DEBUG_ENABLED
_debug_clear_octants();
_debug_update();
#endif
}

void GridMap::clear() {
Expand Down Expand Up @@ -1194,6 +1364,10 @@ void GridMap::_update_octants_callback() {

_update_visibility();
awaiting_update = false;

#ifdef DEBUG_ENABLED
_debug_update_octants();
#endif
}

void GridMap::_bind_methods() {
Expand Down Expand Up @@ -1284,6 +1458,12 @@ void GridMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_baked_meshes"), &GridMap::clear_baked_meshes);
ClassDB::bind_method(D_METHOD("make_baked_meshes", "gen_lightmap_uv", "lightmap_uv_texel_size"), &GridMap::make_baked_meshes, DEFVAL(false), DEFVAL(0.1));

ClassDB::bind_method(D_METHOD("set_debug_show_octants", "enable"), &GridMap::set_debug_show_octants);
ClassDB::bind_method(D_METHOD("get_debug_show_octants"), &GridMap::get_debug_show_octants);

ClassDB::bind_method(D_METHOD("set_debug_octant_color", "color"), &GridMap::set_debug_octant_color);
ClassDB::bind_method(D_METHOD("get_debug_octant_color"), &GridMap::get_debug_octant_color);

ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh_library", PROPERTY_HINT_RESOURCE_TYPE, MeshLibrary::get_class_static()), "set_mesh_library", "get_mesh_library");
#ifndef PHYSICS_3D_DISABLED
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material", PROPERTY_HINT_RESOURCE_TYPE, PhysicsMaterial::get_class_static()), "set_physics_material", "get_physics_material");
Expand All @@ -1304,6 +1484,9 @@ void GridMap::_bind_methods() {
#endif // PHYSICS_3D_DISABLED
ADD_GROUP("Navigation", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bake_navigation"), "set_bake_navigation", "is_baking_navigation");
ADD_GROUP("Debug", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_show_octants"), "set_debug_show_octants", "get_debug_show_octants");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "debug_octant_color"), "set_debug_octant_color", "get_debug_octant_color");

BIND_CONSTANT(INVALID_CELL_ITEM);

Expand Down Expand Up @@ -1689,6 +1872,21 @@ RID GridMap::get_bake_mesh_instance(int p_idx) {
return baked_meshes[p_idx].instance;
}

void GridMap::set_debug_show_octants(bool p_enable) {
#ifdef DEBUG_ENABLED
if (debug_show_octants == p_enable) {
return;
}

debug_show_octants = p_enable;
_debug_update();
#endif
}

bool GridMap::get_debug_show_octants() const {
return debug_show_octants;
}

GridMap::GridMap() {
set_notify_transform(true);
#if defined(DEBUG_ENABLED) && !defined(NAVIGATION_3D_DISABLED)
Expand Down Expand Up @@ -1857,10 +2055,16 @@ void GridMap::_navigation_map_changed(RID p_map) {

GridMap::~GridMap() {
clear();
#if defined(DEBUG_ENABLED) && !defined(NAVIGATION_3D_DISABLED)

#ifdef DEBUG_ENABLED
_debug_clear_octants();

#ifndef NAVIGATION_3D_DISABLED
NavigationServer3D::get_singleton()->disconnect("map_changed", callable_mp(this, &GridMap::_navigation_map_changed));
NavigationServer3D::get_singleton()->disconnect("navigation_debug_changed", callable_mp(this, &GridMap::_update_navigation_debug_edge_connections));
#endif // defined(DEBUG_ENABLED) && !defined(NAVIGATION_3D_DISABLED)
#endif // NAVIGATION_3D_DISABLED

#endif // DEBUG_ENABLED
}

#if defined(DEBUG_ENABLED) && !defined(NAVIGATION_3D_DISABLED)
Expand Down
27 changes: 27 additions & 0 deletions modules/gridmap/grid_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,27 @@ class GridMap : public Node3D {

Vector<BakedMesh> baked_meshes;

bool debug_show_octants = false;
Color debug_octant_color = Color(1.0, 1.0, 1.0, 1.0);
#ifdef DEBUG_ENABLED
bool debug_dirty = false;
Ref<StandardMaterial3D> debug_octant_line_material;

void _debug_update();
void _debug_update_octants();
void _debug_clear_octants();

RID debug_octant_line_mesh_rid;

struct OctantDebug {
RID debug_line_mesh_rid;
RID debug_line_instance_rid;
};
HashMap<OctantKey, OctantDebug *, OctantKey> debug_octant_map;

Array _build_octant_line_mesh_arrays() const;
#endif // DEBUG_ENABLED

protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
Expand Down Expand Up @@ -337,6 +358,12 @@ class GridMap : public Node3D {
Array get_bake_meshes();
RID get_bake_mesh_instance(int p_idx);

void set_debug_show_octants(bool p_enable);
bool get_debug_show_octants() const;

void set_debug_octant_color(const Color &p_color);
Color get_debug_octant_color() const;

#ifndef NAVIGATION_3D_DISABLED
private:
static Callable _navmesh_source_geometry_parsing_callback;
Expand Down