feat: updated engine
This commit is contained in:
parent
cbe99774ff
commit
f4cf6b3999
6607 changed files with 910135 additions and 430025 deletions
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="GridMap" inherits="Node3D" keywords="tilemap" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
|
||||
<class name="GridMap" inherits="Node3D" api_type="core" keywords="tilemap" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
|
||||
<brief_description>
|
||||
Node for 3D tile-based maps.
|
||||
</brief_description>
|
||||
|
|
@ -97,6 +97,20 @@
|
|||
This function returns always the map set on the GridMap node and not the map on the NavigationServer. If the map is changed directly with the NavigationServer API the GridMap node will not be aware of the map change.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_octant_coords_from_cell_coords" qualifiers="const">
|
||||
<return type="Vector3i" />
|
||||
<param index="0" name="cell_coords" type="Vector3i" />
|
||||
<description>
|
||||
Returns the [Vector3i] octant coordinates of the octant that the cell at [param cell_coords] belongs to.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_octants_in_bounds" qualifiers="const">
|
||||
<return type="Vector3i[]" />
|
||||
<param index="0" name="bounds" type="AABB" />
|
||||
<description>
|
||||
Returns an array of [Vector3i] octant coordinates that are inside the given [param bounds], including octants that have no cells in use.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_orthogonal_index_from_basis" qualifiers="const">
|
||||
<return type="int" />
|
||||
<param index="0" name="basis" type="Basis" />
|
||||
|
|
@ -117,6 +131,41 @@
|
|||
Returns an array of all cells with the given item index specified in [param item].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_used_cells_in_octant" qualifiers="const">
|
||||
<return type="Vector3i[]" />
|
||||
<param index="0" name="octant_coords" type="Vector3i" />
|
||||
<description>
|
||||
Returns an array of [Vector3i]s with the cell coordinates of non-empty cells inside the octant at [param octant_coords].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_used_cells_in_octant_by_item" qualifiers="const">
|
||||
<return type="Vector3i[]" />
|
||||
<param index="0" name="octant_coords" type="Vector3i" />
|
||||
<param index="1" name="item" type="int" />
|
||||
<description>
|
||||
Returns an array of [Vector3i]s with the cell coordinates of cells inside the octant at [param octant_coords] that use the specified cell [param item].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_used_octants" qualifiers="const">
|
||||
<return type="Vector3i[]" />
|
||||
<description>
|
||||
Returns an array of [Vector3i]s with the octant coordinates of the non-empty octants in the grid map.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_used_octants_by_item" qualifiers="const">
|
||||
<return type="Vector3i[]" />
|
||||
<param index="0" name="item" type="int" />
|
||||
<description>
|
||||
Returns an array of [Vector3i]s with the octant coordinates of the octants that use the specified [param item] in the grid map.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_used_octants_in_bounds" qualifiers="const">
|
||||
<return type="Vector3i[]" />
|
||||
<param index="0" name="bounds" type="AABB" />
|
||||
<description>
|
||||
Returns an array of [Vector3i]s with the octant coordinates of non-empty octants that are inside the local [param bounds].
|
||||
</description>
|
||||
</method>
|
||||
<method name="local_to_map" qualifiers="const">
|
||||
<return type="Vector3i" />
|
||||
<param index="0" name="local_position" type="Vector3" />
|
||||
|
|
@ -216,6 +265,15 @@
|
|||
<member name="collision_priority" type="float" setter="set_collision_priority" getter="get_collision_priority" default="1.0">
|
||||
The priority used to solve colliding when occurring penetration. The higher the priority is, the lower the penetration into the object will be. This can for example be used to prevent the player from breaking through the boundaries of a level.
|
||||
</member>
|
||||
<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>
|
||||
|
|
@ -240,5 +298,14 @@
|
|||
<constant name="INVALID_CELL_ITEM" value="-1">
|
||||
Invalid cell item that can be used in [method set_cell_item] to clear cells (or represent an empty cell in [method get_cell_item]).
|
||||
</constant>
|
||||
<constant name="DEBUG_VISIBILITY_MODE_DEFAULT" value="0" enum="DebugVisibilityMode">
|
||||
Hide the collisions debug shapes in the editor, and use the debug settings to determine their visibility in game (i.e. [member SceneTree.debug_collisions_hint] or [member SceneTree.debug_navigation_hint]).
|
||||
</constant>
|
||||
<constant name="DEBUG_VISIBILITY_MODE_FORCE_SHOW" value="1" enum="DebugVisibilityMode">
|
||||
Always show the collisions debug shapes.
|
||||
</constant>
|
||||
<constant name="DEBUG_VISIBILITY_MODE_FORCE_HIDE" value="2" enum="DebugVisibilityMode">
|
||||
Always hide the collisions debug shapes.
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="GridMapEditorPlugin" inherits="EditorPlugin" keywords="tilemap" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
|
||||
<class name="GridMapEditorPlugin" inherits="EditorPlugin" api_type="editor" keywords="tilemap" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
|
||||
<brief_description>
|
||||
Editor for [GridMap] nodes.
|
||||
</brief_description>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -32,21 +32,27 @@
|
|||
|
||||
#include "../grid_map.h"
|
||||
|
||||
#include "editor/docks/editor_dock.h"
|
||||
#include "editor/plugins/editor_plugin.h"
|
||||
#include "scene/gui/box_container.h"
|
||||
#include "scene/gui/item_list.h"
|
||||
#include "scene/gui/slider.h"
|
||||
#include "scene/gui/spin_box.h"
|
||||
|
||||
class BaseButton;
|
||||
class Button;
|
||||
class ButtonGroup;
|
||||
class ConfirmationDialog;
|
||||
class EditorZoomWidget;
|
||||
class FilterLineEdit;
|
||||
class HSlider;
|
||||
class ItemList;
|
||||
class MenuButton;
|
||||
class Node3DEditorPlugin;
|
||||
class ButtonGroup;
|
||||
class EditorZoomWidget;
|
||||
class BaseButton;
|
||||
class Node3DEditorViewport;
|
||||
class SpinBox;
|
||||
class Tree;
|
||||
class TreeItem;
|
||||
|
||||
class GridMapEditor : public VBoxContainer {
|
||||
GDCLASS(GridMapEditor, VBoxContainer);
|
||||
class GridMapEditor : public EditorDock {
|
||||
GDCLASS(GridMapEditor, EditorDock);
|
||||
|
||||
static constexpr int32_t GRID_CURSOR_SIZE = 50;
|
||||
|
||||
|
|
@ -90,11 +96,12 @@ class GridMapEditor : public VBoxContainer {
|
|||
Button *rotate_x_button = nullptr;
|
||||
Button *rotate_y_button = nullptr;
|
||||
Button *rotate_z_button = nullptr;
|
||||
Button *clear_rotation_button = nullptr;
|
||||
|
||||
EditorZoomWidget *zoom_widget = nullptr;
|
||||
Button *mode_thumbnail = nullptr;
|
||||
Button *mode_list = nullptr;
|
||||
LineEdit *search_box = nullptr;
|
||||
FilterLineEdit *search_box = nullptr;
|
||||
HSlider *size_slider = nullptr;
|
||||
ConfirmationDialog *settings_dialog = nullptr;
|
||||
VBoxContainer *settings_vbc = nullptr;
|
||||
|
|
@ -116,10 +123,15 @@ class GridMapEditor : public VBoxContainer {
|
|||
|
||||
Transform3D grid_xform;
|
||||
Transform3D edit_grid_xform;
|
||||
Vector3::Axis edit_axis;
|
||||
Vector3::Axis edit_axis_select = Vector3::AXIS_Y;
|
||||
int edit_floor[3];
|
||||
int edit_main_vp = 0;
|
||||
Vector3 grid_ofs;
|
||||
|
||||
bool allow_viewport_override = true;
|
||||
Viewport *last_viewport = nullptr;
|
||||
Vector3::Axis viewport_axis = edit_axis_select;
|
||||
|
||||
RID grid[3];
|
||||
RID grid_instance[3];
|
||||
RID cursor_mesh;
|
||||
|
|
@ -189,6 +201,7 @@ class GridMapEditor : public VBoxContainer {
|
|||
MENU_OPTION_X_AXIS,
|
||||
MENU_OPTION_Y_AXIS,
|
||||
MENU_OPTION_Z_AXIS,
|
||||
MENU_OPTION_VIEWPORT_OVERRIDE,
|
||||
MENU_OPTION_CURSOR_ROTATE_Y,
|
||||
MENU_OPTION_CURSOR_ROTATE_X,
|
||||
MENU_OPTION_CURSOR_ROTATE_Z,
|
||||
|
|
@ -205,21 +218,21 @@ class GridMapEditor : public VBoxContainer {
|
|||
|
||||
};
|
||||
|
||||
Node3DEditorPlugin *spatial_editor = nullptr;
|
||||
|
||||
struct AreaDisplay {
|
||||
RID mesh;
|
||||
RID instance;
|
||||
};
|
||||
|
||||
Tree *categories = nullptr;
|
||||
MarginContainer *item_palette_mc = nullptr;
|
||||
ItemList *mesh_library_palette = nullptr;
|
||||
Label *info_message = nullptr;
|
||||
|
||||
void update_grid(); // Change which and where the grid is displayed
|
||||
void update_grid(); // Change which and where the grid is displayed.
|
||||
void _draw_grids(const Vector3 &cell_size);
|
||||
void _configure();
|
||||
void _menu_option(int);
|
||||
void update_palette();
|
||||
void _update_resource_preview(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, int p_idx);
|
||||
void _update_mesh_library();
|
||||
void _set_display_mode(int p_mode);
|
||||
void _item_selected_cbk(int idx);
|
||||
|
|
@ -229,7 +242,6 @@ class GridMapEditor : public VBoxContainer {
|
|||
void _update_theme();
|
||||
|
||||
void _text_changed(const String &p_text);
|
||||
void _sbox_input(const Ref<InputEvent> &p_event);
|
||||
void _mesh_library_palette_input(const Ref<InputEvent> &p_ie);
|
||||
|
||||
void _icon_size_changed(float p_value);
|
||||
|
|
@ -247,22 +259,43 @@ class GridMapEditor : public VBoxContainer {
|
|||
bool _has_selection() const;
|
||||
Array _get_selected_cells() const;
|
||||
|
||||
void _update_edit_axis();
|
||||
Vector3::Axis _get_facing_axis(const Basis &p_grid_basis, const Vector3 &p_direction) const;
|
||||
Vector3::Axis _get_edit_axis() const { return allow_viewport_override ? viewport_axis : edit_axis_select; }
|
||||
|
||||
void _view_state_changed(Node3DEditorViewport *p_viewport);
|
||||
|
||||
String _get_cursor_coordinates() const;
|
||||
|
||||
void _floor_changed(float p_value);
|
||||
void _floor_mouse_exited();
|
||||
|
||||
void _delete_selection();
|
||||
void _delete_selection_with_undo();
|
||||
void _fill_selection();
|
||||
void _clear_selection_with_undo();
|
||||
void _setup_paste_mode();
|
||||
|
||||
bool do_input_action(Camera3D *p_camera, const Point2 &p_point, bool p_click);
|
||||
|
||||
friend class GridMapEditorPlugin;
|
||||
|
||||
struct ItemCategoryMapping {
|
||||
AHashMap<StringName, HashSet<StringName>> category_to_category_children;
|
||||
AHashMap<StringName, HashSet<int>> category_to_items;
|
||||
};
|
||||
|
||||
void _on_categories_item_activated();
|
||||
|
||||
void _rebuild_categories();
|
||||
void _add_child_categories_recursive(Tree *p_categories, TreeItem *p_ti_parent, const StringName &p_category, const ItemCategoryMapping &p_mapping);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
virtual void update_layout(EditorDock::DockLayout p_layout, int p_slot) override;
|
||||
|
||||
public:
|
||||
EditorPlugin::AfterGUIInput forward_spatial_input_event(Camera3D *p_camera, const Ref<InputEvent> &p_event);
|
||||
|
||||
|
|
@ -275,16 +308,17 @@ class GridMapEditorPlugin : public EditorPlugin {
|
|||
GDCLASS(GridMapEditorPlugin, EditorPlugin);
|
||||
|
||||
GridMapEditor *grid_map_editor = nullptr;
|
||||
Button *panel_button = nullptr;
|
||||
|
||||
void _overlay_update_requested();
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void forward_3d_draw_over_viewport(Control *p_overlay) override;
|
||||
virtual EditorPlugin::AfterGUIInput forward_3d_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) override { return grid_map_editor->forward_spatial_input_event(p_camera, p_event); }
|
||||
virtual String get_plugin_name() const override { return "GridMap"; }
|
||||
bool has_main_screen() const override { return false; }
|
||||
virtual void edit(Object *p_object) override;
|
||||
virtual bool handles(Object *p_object) const override;
|
||||
virtual void make_visible(bool p_visible) override;
|
||||
|
|
|
|||
|
|
@ -30,8 +30,12 @@
|
|||
|
||||
#include "grid_map.h"
|
||||
|
||||
#include "core/config/engine.h"
|
||||
#include "core/io/marshalls.h"
|
||||
#include "core/object/callable_mp.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/templates/a_hash_map.h"
|
||||
#include "scene/main/scene_tree.h"
|
||||
#include "scene/resources/3d/mesh_library.h"
|
||||
#include "scene/resources/3d/primitive_meshes.h"
|
||||
#include "scene/resources/surface_tool.h"
|
||||
|
|
@ -39,7 +43,6 @@
|
|||
|
||||
#ifndef PHYSICS_3D_DISABLED
|
||||
#include "core/math/convex_hull.h"
|
||||
#include "scene/resources/3d/box_shape_3d.h"
|
||||
#include "scene/resources/3d/capsule_shape_3d.h"
|
||||
#include "scene/resources/3d/concave_polygon_shape_3d.h"
|
||||
#include "scene/resources/3d/convex_polygon_shape_3d.h"
|
||||
|
|
@ -216,6 +219,18 @@ real_t GridMap::get_collision_priority() const {
|
|||
return collision_priority;
|
||||
}
|
||||
|
||||
void GridMap::set_collision_visibility_mode(DebugVisibilityMode p_visibility_mode) {
|
||||
if (collision_visibility_mode == p_visibility_mode) {
|
||||
return;
|
||||
}
|
||||
collision_visibility_mode = p_visibility_mode;
|
||||
_recreate_octant_data();
|
||||
}
|
||||
|
||||
GridMap::DebugVisibilityMode GridMap::get_collision_visibility_mode() const {
|
||||
return collision_visibility_mode;
|
||||
}
|
||||
|
||||
void GridMap::set_physics_material(Ref<PhysicsMaterial> p_material) {
|
||||
physics_material = p_material;
|
||||
_update_physics_bodies_characteristics();
|
||||
|
|
@ -236,7 +251,7 @@ Array GridMap::get_collision_shapes() const {
|
|||
for (const KeyValue<OctantKey, Octant *> &E : octant_map) {
|
||||
Octant *g = E.value;
|
||||
RID body = g->static_body;
|
||||
Transform3D body_xform = PhysicsServer3D::get_singleton()->body_get_state(body, PhysicsServer3D::BODY_STATE_TRANSFORM);
|
||||
Transform3D body_xform = PhysicsServer3D::get_singleton()->body_get_state(body, PS3DE::BODY_STATE_TRANSFORM);
|
||||
int nshapes = PhysicsServer3D::get_singleton()->body_get_shape_count(body);
|
||||
for (int i = 0; i < nshapes; i++) {
|
||||
RID shape = PhysicsServer3D::get_singleton()->body_get_shape(body, i);
|
||||
|
|
@ -248,6 +263,24 @@ Array GridMap::get_collision_shapes() const {
|
|||
|
||||
return shapes;
|
||||
}
|
||||
|
||||
RID GridMap::get_physics_body_from_octant_coord(const Vector3i &p_octant_coords) const {
|
||||
OctantKey octantkey;
|
||||
octantkey.x = p_octant_coords.x;
|
||||
octantkey.y = p_octant_coords.y;
|
||||
octantkey.z = p_octant_coords.z;
|
||||
|
||||
const HashMap<OctantKey, Octant *, OctantKey>::ConstIterator octant_kv = octant_map.find(octantkey);
|
||||
|
||||
if (!octant_kv) {
|
||||
return RID();
|
||||
}
|
||||
|
||||
Octant *g = octant_kv->value;
|
||||
RID body_rid = g->static_body;
|
||||
|
||||
return body_rid;
|
||||
}
|
||||
#endif // PHYSICS_3D_DISABLED
|
||||
|
||||
void GridMap::set_bake_navigation(bool p_bake_navigation) {
|
||||
|
|
@ -347,6 +380,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
|
||||
|
|
@ -388,22 +549,33 @@ void GridMap::set_cell_item(const Vector3i &p_position, int p_item, int p_rot) {
|
|||
g->dirty = true;
|
||||
#ifndef PHYSICS_3D_DISABLED
|
||||
g->static_body = PhysicsServer3D::get_singleton()->body_create();
|
||||
PhysicsServer3D::get_singleton()->body_set_mode(g->static_body, PhysicsServer3D::BODY_MODE_STATIC);
|
||||
PhysicsServer3D::get_singleton()->body_set_mode(g->static_body, PS3DE::BODY_MODE_STATIC);
|
||||
PhysicsServer3D::get_singleton()->body_attach_object_instance_id(g->static_body, get_instance_id());
|
||||
PhysicsServer3D::get_singleton()->body_set_collision_layer(g->static_body, collision_layer);
|
||||
PhysicsServer3D::get_singleton()->body_set_collision_mask(g->static_body, collision_mask);
|
||||
PhysicsServer3D::get_singleton()->body_set_collision_priority(g->static_body, collision_priority);
|
||||
if (physics_material.is_valid()) {
|
||||
PhysicsServer3D::get_singleton()->body_set_param(g->static_body, PhysicsServer3D::BODY_PARAM_FRICTION, physics_material->computed_friction());
|
||||
PhysicsServer3D::get_singleton()->body_set_param(g->static_body, PhysicsServer3D::BODY_PARAM_BOUNCE, physics_material->computed_bounce());
|
||||
PhysicsServer3D::get_singleton()->body_set_param(g->static_body, PS3DE::BODY_PARAM_FRICTION, physics_material->computed_friction());
|
||||
PhysicsServer3D::get_singleton()->body_set_param(g->static_body, PS3DE::BODY_PARAM_BOUNCE, physics_material->computed_bounce());
|
||||
}
|
||||
#endif // PHYSICS_3D_DISABLED
|
||||
SceneTree *st = SceneTree::get_singleton();
|
||||
|
||||
if (st && st->is_debugging_collisions_hint()) {
|
||||
g->collision_debug = RenderingServer::get_singleton()->mesh_create();
|
||||
g->collision_debug_instance = RenderingServer::get_singleton()->instance_create();
|
||||
RenderingServer::get_singleton()->instance_set_base(g->collision_debug_instance, g->collision_debug);
|
||||
bool debug_collisions = false;
|
||||
switch (collision_visibility_mode) {
|
||||
case DEBUG_VISIBILITY_MODE_DEFAULT: {
|
||||
SceneTree *st = SceneTree::get_singleton();
|
||||
debug_collisions = st && !Engine::get_singleton()->is_editor_hint() && st->is_debugging_collisions_hint();
|
||||
} break;
|
||||
case DEBUG_VISIBILITY_MODE_FORCE_HIDE: {
|
||||
debug_collisions = false;
|
||||
} break;
|
||||
case DEBUG_VISIBILITY_MODE_FORCE_SHOW: {
|
||||
debug_collisions = true;
|
||||
} break;
|
||||
}
|
||||
if (debug_collisions) {
|
||||
g->collision_debug = RS::get_singleton()->mesh_create();
|
||||
g->collision_debug_instance = RS::get_singleton()->instance_create();
|
||||
RS::get_singleton()->instance_set_base(g->collision_debug_instance, g->collision_debug);
|
||||
}
|
||||
|
||||
octant_map[octantkey] = g;
|
||||
|
|
@ -571,7 +743,7 @@ void GridMap::_octant_transform(const OctantKey &p_key) {
|
|||
ERR_FAIL_COND(!octant_map.has(p_key));
|
||||
Octant &g = *octant_map[p_key];
|
||||
#ifndef PHYSICS_3D_DISABLED
|
||||
PhysicsServer3D::get_singleton()->body_set_state(g.static_body, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform());
|
||||
PhysicsServer3D::get_singleton()->body_set_state(g.static_body, PS3DE::BODY_STATE_TRANSFORM, get_global_transform());
|
||||
|
||||
if (g.collision_debug_instance.is_valid()) {
|
||||
RS::get_singleton()->instance_set_transform(g.collision_debug_instance, get_global_transform());
|
||||
|
|
@ -769,7 +941,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
|
|||
Octant::MultimeshInstance mmi;
|
||||
|
||||
RID mm = RS::get_singleton()->multimesh_create();
|
||||
RS::get_singleton()->multimesh_allocate_data(mm, E.value.size(), RS::MULTIMESH_TRANSFORM_3D);
|
||||
RS::get_singleton()->multimesh_allocate_data(mm, E.value.size(), RSE::MULTIMESH_TRANSFORM_3D);
|
||||
RS::get_singleton()->multimesh_set_mesh(mm, mesh_library->get_item_mesh(E.key)->get_rid());
|
||||
|
||||
int idx = 0;
|
||||
|
|
@ -796,7 +968,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
|
|||
RS::get_singleton()->instance_set_transform(instance, get_global_transform());
|
||||
}
|
||||
|
||||
RS::ShadowCastingSetting cast_shadows = (RS::ShadowCastingSetting)mesh_library->get_item_mesh_cast_shadow(E.key);
|
||||
RSE::ShadowCastingSetting cast_shadows = (RSE::ShadowCastingSetting)mesh_library->get_item_mesh_cast_shadow(E.key);
|
||||
RS::get_singleton()->instance_geometry_set_cast_shadows_setting(instance, cast_shadows);
|
||||
|
||||
mmi.multimesh = mm;
|
||||
|
|
@ -817,11 +989,11 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
|
|||
}
|
||||
|
||||
Array arr;
|
||||
arr.resize(RS::ARRAY_MAX);
|
||||
arr[RS::ARRAY_VERTEX] = col_debug;
|
||||
arr[RS::ARRAY_COLOR] = colors;
|
||||
arr.resize(RSE::ARRAY_MAX);
|
||||
arr[RSE::ARRAY_VERTEX] = col_debug;
|
||||
arr[RSE::ARRAY_COLOR] = colors;
|
||||
|
||||
RS::get_singleton()->mesh_add_surface_from_arrays(g.collision_debug, RS::PRIMITIVE_LINES, arr);
|
||||
RS::get_singleton()->mesh_add_surface_from_arrays(g.collision_debug, RSE::PRIMITIVE_LINES, arr);
|
||||
if (st) {
|
||||
RS::get_singleton()->mesh_surface_set_material(g.collision_debug, 0, st->get_debug_collision_material()->get_rid());
|
||||
}
|
||||
|
|
@ -850,8 +1022,8 @@ void GridMap::_update_physics_bodies_characteristics() {
|
|||
bounce = physics_material->computed_bounce();
|
||||
}
|
||||
for (const KeyValue<OctantKey, Octant *> &E : octant_map) {
|
||||
PhysicsServer3D::get_singleton()->body_set_param(E.value->static_body, PhysicsServer3D::BODY_PARAM_FRICTION, friction);
|
||||
PhysicsServer3D::get_singleton()->body_set_param(E.value->static_body, PhysicsServer3D::BODY_PARAM_BOUNCE, bounce);
|
||||
PhysicsServer3D::get_singleton()->body_set_param(E.value->static_body, PS3DE::BODY_PARAM_FRICTION, friction);
|
||||
PhysicsServer3D::get_singleton()->body_set_param(E.value->static_body, PS3DE::BODY_PARAM_BOUNCE, bounce);
|
||||
}
|
||||
}
|
||||
#endif // PHYSICS_3D_DISABLED
|
||||
|
|
@ -863,7 +1035,7 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) {
|
|||
const RID scenario = get_world_3d()->get_scenario();
|
||||
|
||||
#ifndef PHYSICS_3D_DISABLED
|
||||
PhysicsServer3D::get_singleton()->body_set_state(g.static_body, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform());
|
||||
PhysicsServer3D::get_singleton()->body_set_state(g.static_body, PS3DE::BODY_STATE_TRANSFORM, get_global_transform());
|
||||
PhysicsServer3D::get_singleton()->body_set_space(g.static_body, get_world_3d()->get_space());
|
||||
|
||||
if (g.collision_debug_instance.is_valid()) {
|
||||
|
|
@ -930,7 +1102,7 @@ void GridMap::_octant_exit_world(const OctantKey &p_key) {
|
|||
Octant &g = *octant_map[p_key];
|
||||
|
||||
#ifndef PHYSICS_3D_DISABLED
|
||||
PhysicsServer3D::get_singleton()->body_set_state(g.static_body, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform());
|
||||
PhysicsServer3D::get_singleton()->body_set_state(g.static_body, PS3DE::BODY_STATE_TRANSFORM, get_global_transform());
|
||||
PhysicsServer3D::get_singleton()->body_set_space(g.static_body, RID());
|
||||
|
||||
if (g.collision_debug_instance.is_valid()) {
|
||||
|
|
@ -965,6 +1137,8 @@ void GridMap::_octant_exit_world(const OctantKey &p_key) {
|
|||
g.navigation_debug_edge_connections_mesh.unref();
|
||||
}
|
||||
}
|
||||
|
||||
_debug_clear_octants();
|
||||
#endif // DEBUG_ENABLED
|
||||
}
|
||||
|
||||
|
|
@ -1014,9 +1188,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);
|
||||
|
|
@ -1041,20 +1217,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);
|
||||
}
|
||||
|
|
@ -1064,6 +1252,17 @@ 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: {
|
||||
|
|
@ -1071,9 +1270,6 @@ void GridMap::_notification(int p_what) {
|
|||
_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());
|
||||
}
|
||||
|
|
@ -1101,6 +1297,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() {
|
||||
|
|
@ -1114,12 +1319,17 @@ void GridMap::_queue_octants_dirty() {
|
|||
|
||||
void GridMap::_recreate_octant_data() {
|
||||
recreating_octants = true;
|
||||
HashMap<IndexKey, Cell, IndexKey> cell_copy = cell_map;
|
||||
|
||||
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() {
|
||||
|
|
@ -1134,6 +1344,10 @@ void GridMap::_clear_internal() {
|
|||
|
||||
octant_map.clear();
|
||||
cell_map.clear();
|
||||
#ifdef DEBUG_ENABLED
|
||||
_debug_clear_octants();
|
||||
_debug_update();
|
||||
#endif
|
||||
}
|
||||
|
||||
void GridMap::clear() {
|
||||
|
|
@ -1168,6 +1382,10 @@ void GridMap::_update_octants_callback() {
|
|||
|
||||
_update_visibility();
|
||||
awaiting_update = false;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
_debug_update_octants();
|
||||
#endif
|
||||
}
|
||||
|
||||
void GridMap::_bind_methods() {
|
||||
|
|
@ -1187,6 +1405,9 @@ void GridMap::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_collision_priority", "priority"), &GridMap::set_collision_priority);
|
||||
ClassDB::bind_method(D_METHOD("get_collision_priority"), &GridMap::get_collision_priority);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_collision_visibility_mode", "visibility_mode"), &GridMap::set_collision_visibility_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_collision_visibility_mode"), &GridMap::get_collision_visibility_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_physics_material", "material"), &GridMap::set_physics_material);
|
||||
ClassDB::bind_method(D_METHOD("get_physics_material"), &GridMap::get_physics_material);
|
||||
#endif // PHYSICS_3D_DISABLED
|
||||
|
|
@ -1237,6 +1458,17 @@ void GridMap::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_used_cells"), &GridMap::get_used_cells);
|
||||
ClassDB::bind_method(D_METHOD("get_used_cells_by_item", "item"), &GridMap::get_used_cells_by_item);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_used_octants"), &GridMap::get_used_octants);
|
||||
ClassDB::bind_method(D_METHOD("get_used_octants_by_item", "item"), &GridMap::get_used_octants_by_item);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_used_cells_in_octant", "octant_coords"), &GridMap::get_used_cells_in_octant);
|
||||
ClassDB::bind_method(D_METHOD("get_used_cells_in_octant_by_item", "octant_coords", "item"), &GridMap::get_used_cells_in_octant_by_item);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_octants_in_bounds", "bounds"), &GridMap::get_octants_in_bounds);
|
||||
ClassDB::bind_method(D_METHOD("get_used_octants_in_bounds", "bounds"), &GridMap::get_used_octants_in_bounds);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_octant_coords_from_cell_coords", "cell_coords"), &GridMap::get_octant_coords_from_cell_coords);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_meshes"), &GridMap::get_meshes);
|
||||
ClassDB::bind_method(D_METHOD("get_bake_meshes"), &GridMap::get_bake_meshes);
|
||||
ClassDB::bind_method(D_METHOD("get_bake_mesh_instance", "idx"), &GridMap::get_bake_mesh_instance);
|
||||
|
|
@ -1244,9 +1476,15 @@ 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));
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh_library", PROPERTY_HINT_RESOURCE_TYPE, "MeshLibrary"), "set_mesh_library", "get_mesh_library");
|
||||
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"), "set_physics_material", "get_physics_material");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material", PROPERTY_HINT_RESOURCE_TYPE, PhysicsMaterial::get_class_static()), "set_physics_material", "get_physics_material");
|
||||
#endif // PHYSICS_3D_DISABLED
|
||||
ADD_GROUP("Cell", "cell_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "cell_size", PROPERTY_HINT_NONE, "suffix:m"), "set_cell_size", "get_cell_size");
|
||||
|
|
@ -1260,14 +1498,22 @@ void GridMap::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_priority"), "set_collision_priority", "get_collision_priority");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_visibility_mode", PROPERTY_HINT_ENUM, "Default,Force Show,Force Hide"), "set_collision_visibility_mode", "get_collision_visibility_mode");
|
||||
#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);
|
||||
|
||||
ADD_SIGNAL(MethodInfo("cell_size_changed", PropertyInfo(Variant::VECTOR3, "cell_size")));
|
||||
ADD_SIGNAL(MethodInfo(CoreStringName(changed)));
|
||||
|
||||
BIND_ENUM_CONSTANT(DEBUG_VISIBILITY_MODE_DEFAULT);
|
||||
BIND_ENUM_CONSTANT(DEBUG_VISIBILITY_MODE_FORCE_SHOW);
|
||||
BIND_ENUM_CONSTANT(DEBUG_VISIBILITY_MODE_FORCE_HIDE);
|
||||
}
|
||||
|
||||
void GridMap::set_cell_scale(float p_scale) {
|
||||
|
|
@ -1303,6 +1549,193 @@ TypedArray<Vector3i> GridMap::get_used_cells_by_item(int p_item) const {
|
|||
return a;
|
||||
}
|
||||
|
||||
TypedArray<Vector3i> GridMap::get_used_octants() const {
|
||||
TypedArray<Vector3i> octant_coords;
|
||||
octant_coords.resize(octant_map.size());
|
||||
int i = 0;
|
||||
for (const KeyValue<OctantKey, Octant *> &octant_kv : octant_map) {
|
||||
const OctantKey &octant_key = octant_kv.key;
|
||||
Vector3i octant_coord(octant_key.x, octant_key.y, octant_key.z);
|
||||
octant_coords[i++] = octant_coord;
|
||||
}
|
||||
|
||||
return octant_coords;
|
||||
}
|
||||
|
||||
TypedArray<Vector3i> GridMap::get_used_octants_by_item(int p_item) const {
|
||||
TypedArray<Vector3i> octant_coords;
|
||||
for (const KeyValue<OctantKey, Octant *> &octant_kv : octant_map) {
|
||||
const OctantKey &octant_key = octant_kv.key;
|
||||
const Octant &octant = *octant_kv.value;
|
||||
for (const IndexKey &cell_key : octant.cells) {
|
||||
const Cell &cell = cell_map[cell_key];
|
||||
if ((int)cell.item == p_item) {
|
||||
Vector3i octant_coord(octant_key.x, octant_key.y, octant_key.z);
|
||||
octant_coords.push_back(octant_coord);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return octant_coords;
|
||||
}
|
||||
|
||||
TypedArray<Vector3i> GridMap::get_used_cells_in_octant(const Vector3i &p_octant_coords) const {
|
||||
TypedArray<Vector3i> cell_coords;
|
||||
|
||||
const OctantKey octantkey = get_octant_key_from_cell_coords(p_octant_coords);
|
||||
if (!octant_map.has(octantkey)) {
|
||||
return cell_coords;
|
||||
}
|
||||
|
||||
const Octant &octant = *octant_map[octantkey];
|
||||
|
||||
for (const IndexKey &cell_key : octant.cells) {
|
||||
Vector3i cell_coord(cell_key.x, cell_key.y, cell_key.z);
|
||||
cell_coords.push_back(cell_coord);
|
||||
}
|
||||
|
||||
return cell_coords;
|
||||
}
|
||||
|
||||
TypedArray<Vector3i> GridMap::get_used_cells_in_octant_by_item(const Vector3i &p_octant_coords, int p_item) const {
|
||||
TypedArray<Vector3i> cell_coords;
|
||||
|
||||
const OctantKey octantkey = get_octant_key_from_cell_coords(p_octant_coords);
|
||||
if (!octant_map.has(octantkey)) {
|
||||
return cell_coords;
|
||||
}
|
||||
|
||||
const Octant &octant = *octant_map[octantkey];
|
||||
|
||||
for (const IndexKey &cell_key : octant.cells) {
|
||||
const Cell &cell = cell_map[cell_key];
|
||||
if ((int)cell.item == p_item) {
|
||||
Vector3i cell_coord(cell_key.x, cell_key.y, cell_key.z);
|
||||
cell_coords.push_back(cell_coord);
|
||||
}
|
||||
}
|
||||
|
||||
return cell_coords;
|
||||
}
|
||||
|
||||
Vector3i GridMap::get_octant_coords_from_cell_coords(const Vector3i &p_cell_coords) const {
|
||||
return Vector3i(
|
||||
p_cell_coords.x > 0 ? p_cell_coords.x / octant_size : (p_cell_coords.x - (octant_size - 1)) / octant_size,
|
||||
p_cell_coords.y > 0 ? p_cell_coords.y / octant_size : (p_cell_coords.y - (octant_size - 1)) / octant_size,
|
||||
p_cell_coords.z > 0 ? p_cell_coords.z / octant_size : (p_cell_coords.z - (octant_size - 1)) / octant_size);
|
||||
}
|
||||
|
||||
LocalVector<GridMap::IndexKey> GridMap::get_index_keys_in_bounds(const AABB &p_bounds, bool p_used_only) const {
|
||||
LocalVector<IndexKey> index_keys;
|
||||
if (!p_bounds.has_volume()) {
|
||||
return index_keys;
|
||||
}
|
||||
|
||||
Vector3i cell_coords_start = (p_bounds.position / cell_size).floor();
|
||||
// -CMP_EPSILON because we don't want the octants that are just starting at the edge of the bounds.
|
||||
Vector3i cell_coords_end = ((p_bounds.get_end() - Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON)) / cell_size).floor();
|
||||
|
||||
for (int z = cell_coords_start.z; z < cell_coords_end.z + 1; z++) {
|
||||
for (int y = cell_coords_start.y; y < cell_coords_end.y + 1; y++) {
|
||||
for (int x = cell_coords_start.x; x < cell_coords_end.x + 1; x++) {
|
||||
IndexKey index_key;
|
||||
index_key.x = x;
|
||||
index_key.y = y;
|
||||
index_key.z = z;
|
||||
|
||||
if (p_used_only) {
|
||||
const HashMap<IndexKey, Cell, IndexKey>::ConstIterator index_key_kv = cell_map.find(index_key);
|
||||
|
||||
if (index_key_kv) {
|
||||
index_keys.push_back(index_key);
|
||||
}
|
||||
} else {
|
||||
index_keys.push_back(index_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return index_keys;
|
||||
}
|
||||
|
||||
LocalVector<GridMap::OctantKey> GridMap::get_octant_keys_in_bounds(const AABB &p_bounds, bool p_used_only) const {
|
||||
LocalVector<OctantKey> octant_keys;
|
||||
if (!p_bounds.has_volume()) {
|
||||
return octant_keys;
|
||||
}
|
||||
|
||||
Vector3i cell_coords_start = (p_bounds.position / cell_size).floor();
|
||||
// -CMP_EPSILON because we don't want the octants that are just starting at the edge of the bounds.
|
||||
Vector3i cell_coords_end = ((p_bounds.get_end() - Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON)) / cell_size).floor();
|
||||
|
||||
OctantKey octant_coords_start = get_octant_key_from_cell_coords(cell_coords_start);
|
||||
OctantKey octant_coords_end = get_octant_key_from_cell_coords(cell_coords_end);
|
||||
|
||||
for (int z = octant_coords_start.z; z < octant_coords_end.z + 1; z++) {
|
||||
for (int y = octant_coords_start.y; y < octant_coords_end.y + 1; y++) {
|
||||
for (int x = octant_coords_start.x; x < octant_coords_end.x + 1; x++) {
|
||||
OctantKey octant_key;
|
||||
octant_key.x = x;
|
||||
octant_key.y = y;
|
||||
octant_key.z = z;
|
||||
|
||||
if (p_used_only) {
|
||||
const HashMap<OctantKey, Octant *, OctantKey>::ConstIterator octant_kv = octant_map.find(octant_key);
|
||||
|
||||
if (octant_kv) {
|
||||
Vector3i octant_coord(x, y, z);
|
||||
octant_keys.push_back(octant_key);
|
||||
}
|
||||
} else {
|
||||
octant_keys.push_back(octant_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return octant_keys;
|
||||
}
|
||||
|
||||
TypedArray<Vector3i> GridMap::get_octants_in_bounds(const AABB &p_bounds) const {
|
||||
TypedArray<Vector3i> octant_coords;
|
||||
if (!p_bounds.has_volume()) {
|
||||
return octant_coords;
|
||||
}
|
||||
|
||||
bool used_only = false;
|
||||
|
||||
const LocalVector<OctantKey> &octant_keys = get_octant_keys_in_bounds(p_bounds, used_only);
|
||||
|
||||
octant_coords.resize(octant_keys.size());
|
||||
|
||||
for (uint32_t i = 0; i < octant_keys.size(); i++) {
|
||||
octant_coords[i] = Vector3i(octant_keys[i].x, octant_keys[i].y, octant_keys[i].z);
|
||||
}
|
||||
|
||||
return octant_coords;
|
||||
}
|
||||
|
||||
TypedArray<Vector3i> GridMap::get_used_octants_in_bounds(const AABB &p_bounds) const {
|
||||
TypedArray<Vector3i> octant_coords;
|
||||
if (!p_bounds.has_volume()) {
|
||||
return octant_coords;
|
||||
}
|
||||
|
||||
bool used_only = true;
|
||||
|
||||
const LocalVector<OctantKey> &octant_keys = get_octant_keys_in_bounds(p_bounds, used_only);
|
||||
|
||||
octant_coords.resize(octant_keys.size());
|
||||
|
||||
for (uint32_t i = 0; i < octant_keys.size(); i++) {
|
||||
octant_coords[i] = Vector3i(octant_keys[i].x, octant_keys[i].y, octant_keys[i].z);
|
||||
}
|
||||
|
||||
return octant_coords;
|
||||
}
|
||||
|
||||
Array GridMap::get_meshes() const {
|
||||
if (mesh_library.is_null()) {
|
||||
return Array();
|
||||
|
|
@ -1457,6 +1890,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)
|
||||
|
|
@ -1499,46 +1947,73 @@ void GridMap::navmesh_parse_source_geometry(const Ref<NavigationMesh> &p_navigat
|
|||
}
|
||||
#ifndef PHYSICS_3D_DISABLED
|
||||
else if ((parsed_geometry_type == NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS || parsed_geometry_type == NavigationMesh::PARSED_GEOMETRY_BOTH) && (gridmap->get_collision_layer() & parsed_collision_mask)) {
|
||||
Array shapes = gridmap->get_collision_shapes();
|
||||
Array shapes;
|
||||
|
||||
// If we have a baking AABB set we can skip wasting time on parsing the entire GridMap.
|
||||
AABB baking_aabb = p_navigation_mesh->get_filter_baking_aabb();
|
||||
if (baking_aabb.has_volume()) {
|
||||
Vector3 baking_aabb_offset = p_navigation_mesh->get_filter_baking_aabb_offset();
|
||||
baking_aabb.position = baking_aabb.position + baking_aabb_offset;
|
||||
|
||||
const TypedArray<Vector3i> octant_coords = gridmap->get_used_octants_in_bounds(baking_aabb);
|
||||
for (const Vector3i octant_coord : octant_coords) {
|
||||
RID body = gridmap->get_physics_body_from_octant_coord(octant_coord);
|
||||
if (body.is_null()) {
|
||||
continue;
|
||||
}
|
||||
const Transform3D body_xform = PhysicsServer3D::get_singleton()->body_get_state(body, PS3DE::BODY_STATE_TRANSFORM);
|
||||
int nshapes = PhysicsServer3D::get_singleton()->body_get_shape_count(body);
|
||||
for (int i = 0; i < nshapes; i++) {
|
||||
RID shape = PhysicsServer3D::get_singleton()->body_get_shape(body, i);
|
||||
Transform3D shape_xform = PhysicsServer3D::get_singleton()->body_get_shape_transform(body, i);
|
||||
Transform3D xform = body_xform * shape_xform;
|
||||
shapes.push_back(xform);
|
||||
shapes.push_back(shape);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
shapes = gridmap->get_collision_shapes();
|
||||
}
|
||||
|
||||
for (int i = 0; i < shapes.size(); i += 2) {
|
||||
RID shape = shapes[i + 1];
|
||||
PhysicsServer3D::ShapeType type = PhysicsServer3D::get_singleton()->shape_get_type(shape);
|
||||
PS3DE::ShapeType type = PhysicsServer3D::get_singleton()->shape_get_type(shape);
|
||||
Variant data = PhysicsServer3D::get_singleton()->shape_get_data(shape);
|
||||
|
||||
switch (type) {
|
||||
case PhysicsServer3D::SHAPE_SPHERE: {
|
||||
case PS3DE::SHAPE_SPHERE: {
|
||||
real_t radius = data;
|
||||
Array arr;
|
||||
arr.resize(RS::ARRAY_MAX);
|
||||
arr.resize(RSE::ARRAY_MAX);
|
||||
SphereMesh::create_mesh_array(arr, radius, radius * 2.0);
|
||||
p_source_geometry_data->add_mesh_array(arr, shapes[i]);
|
||||
} break;
|
||||
case PhysicsServer3D::SHAPE_BOX: {
|
||||
case PS3DE::SHAPE_BOX: {
|
||||
Vector3 extents = data;
|
||||
Array arr;
|
||||
arr.resize(RS::ARRAY_MAX);
|
||||
arr.resize(RSE::ARRAY_MAX);
|
||||
BoxMesh::create_mesh_array(arr, extents * 2.0);
|
||||
p_source_geometry_data->add_mesh_array(arr, shapes[i]);
|
||||
} break;
|
||||
case PhysicsServer3D::SHAPE_CAPSULE: {
|
||||
case PS3DE::SHAPE_CAPSULE: {
|
||||
Dictionary dict = data;
|
||||
real_t radius = dict["radius"];
|
||||
real_t height = dict["height"];
|
||||
Array arr;
|
||||
arr.resize(RS::ARRAY_MAX);
|
||||
arr.resize(RSE::ARRAY_MAX);
|
||||
CapsuleMesh::create_mesh_array(arr, radius, height);
|
||||
p_source_geometry_data->add_mesh_array(arr, shapes[i]);
|
||||
} break;
|
||||
case PhysicsServer3D::SHAPE_CYLINDER: {
|
||||
case PS3DE::SHAPE_CYLINDER: {
|
||||
Dictionary dict = data;
|
||||
real_t radius = dict["radius"];
|
||||
real_t height = dict["height"];
|
||||
Array arr;
|
||||
arr.resize(RS::ARRAY_MAX);
|
||||
arr.resize(RSE::ARRAY_MAX);
|
||||
CylinderMesh::create_mesh_array(arr, radius, radius, height);
|
||||
p_source_geometry_data->add_mesh_array(arr, shapes[i]);
|
||||
} break;
|
||||
case PhysicsServer3D::SHAPE_CONVEX_POLYGON: {
|
||||
case PS3DE::SHAPE_CONVEX_POLYGON: {
|
||||
PackedVector3Array vertices = data;
|
||||
Geometry3D::MeshData md;
|
||||
|
||||
|
|
@ -1558,12 +2033,12 @@ void GridMap::navmesh_parse_source_geometry(const Ref<NavigationMesh> &p_navigat
|
|||
p_source_geometry_data->add_faces(faces, shapes[i]);
|
||||
}
|
||||
} break;
|
||||
case PhysicsServer3D::SHAPE_CONCAVE_POLYGON: {
|
||||
case PS3DE::SHAPE_CONCAVE_POLYGON: {
|
||||
Dictionary dict = data;
|
||||
PackedVector3Array faces = Variant(dict["faces"]);
|
||||
p_source_geometry_data->add_faces(faces, shapes[i]);
|
||||
} break;
|
||||
case PhysicsServer3D::SHAPE_HEIGHTMAP: {
|
||||
case PS3DE::SHAPE_HEIGHTMAP: {
|
||||
Dictionary dict = data;
|
||||
///< dict( int:"width", int:"depth",float:"cell_size", float_array:"heights"
|
||||
int heightmap_depth = dict["depth"];
|
||||
|
|
@ -1625,10 +2100,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)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
#include "scene/3d/node_3d.h"
|
||||
#include "scene/resources/3d/mesh_library.h"
|
||||
#include "scene/resources/multimesh.h"
|
||||
|
||||
class NavigationMesh;
|
||||
class NavigationMeshSourceGeometryData3D;
|
||||
|
|
@ -43,6 +42,12 @@ class PhysicsMaterial;
|
|||
class GridMap : public Node3D {
|
||||
GDCLASS(GridMap, Node3D);
|
||||
|
||||
enum DebugVisibilityMode {
|
||||
DEBUG_VISIBILITY_MODE_DEFAULT,
|
||||
DEBUG_VISIBILITY_MODE_FORCE_SHOW,
|
||||
DEBUG_VISIBILITY_MODE_FORCE_HIDE,
|
||||
};
|
||||
|
||||
enum {
|
||||
MAP_DIRTY_TRANSFORMS = 1,
|
||||
MAP_DIRTY_INSTANCES = 2,
|
||||
|
|
@ -158,6 +163,7 @@ class GridMap : public Node3D {
|
|||
uint32_t collision_layer = 1;
|
||||
uint32_t collision_mask = 1;
|
||||
real_t collision_priority = 1.0;
|
||||
DebugVisibilityMode collision_visibility_mode = DEBUG_VISIBILITY_MODE_DEFAULT;
|
||||
Ref<PhysicsMaterial> physics_material;
|
||||
#endif // PHYSICS_3D_DISABLED
|
||||
bool bake_navigation = false;
|
||||
|
|
@ -183,10 +189,10 @@ class GridMap : public Node3D {
|
|||
void _recreate_octant_data();
|
||||
|
||||
struct BakeLight {
|
||||
RS::LightType type = RS::LightType::LIGHT_DIRECTIONAL;
|
||||
RSE::LightType type = RSE::LightType::LIGHT_DIRECTIONAL;
|
||||
Vector3 pos;
|
||||
Vector3 dir;
|
||||
float param[RS::LIGHT_PARAM_MAX] = {};
|
||||
float param[RSE::LIGHT_PARAM_MAX] = {};
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ Vector3 _octant_get_offset(const OctantKey &p_key) const {
|
||||
|
|
@ -227,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;
|
||||
|
|
@ -257,6 +284,9 @@ public:
|
|||
void set_collision_priority(real_t p_priority);
|
||||
real_t get_collision_priority() const;
|
||||
|
||||
void set_collision_visibility_mode(DebugVisibilityMode p_visibility_mode);
|
||||
DebugVisibilityMode get_collision_visibility_mode() const;
|
||||
|
||||
void set_physics_material(Ref<PhysicsMaterial> p_material);
|
||||
Ref<PhysicsMaterial> get_physics_material() const;
|
||||
|
||||
|
|
@ -303,6 +333,25 @@ public:
|
|||
TypedArray<Vector3i> get_used_cells() const;
|
||||
TypedArray<Vector3i> get_used_cells_by_item(int p_item) const;
|
||||
|
||||
TypedArray<Vector3i> get_used_octants() const;
|
||||
TypedArray<Vector3i> get_used_octants_by_item(int p_item) const;
|
||||
|
||||
TypedArray<Vector3i> get_used_cells_in_octant(const Vector3i &p_octant_coords) const;
|
||||
TypedArray<Vector3i> get_used_cells_in_octant_by_item(const Vector3i &p_octant_coords, int p_item) const;
|
||||
|
||||
// Fastpath functions for native modules that do not use Variant/TypedArray.
|
||||
LocalVector<IndexKey> get_index_keys_in_bounds(const AABB &p_bounds, bool p_used_only = true) const;
|
||||
LocalVector<OctantKey> get_octant_keys_in_bounds(const AABB &p_bounds, bool p_used_only = true) const;
|
||||
|
||||
TypedArray<Vector3i> get_octants_in_bounds(const AABB &p_bounds) const;
|
||||
TypedArray<Vector3i> get_used_octants_in_bounds(const AABB &p_bounds) const;
|
||||
|
||||
Vector3i get_octant_coords_from_cell_coords(const Vector3i &p_cell_coords) const;
|
||||
|
||||
#ifndef PHYSICS_3D_DISABLED
|
||||
RID get_physics_body_from_octant_coord(const Vector3i &p_octant_coords) const;
|
||||
#endif
|
||||
|
||||
Array get_meshes() const;
|
||||
|
||||
void clear_baked_meshes();
|
||||
|
|
@ -313,6 +362,12 @@ public:
|
|||
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;
|
||||
|
|
@ -328,3 +383,5 @@ public:
|
|||
GridMap();
|
||||
~GridMap();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(GridMap::DebugVisibilityMode);
|
||||
|
|
|
|||
1
engine/modules/gridmap/icons/GridMapDock.svg
Normal file
1
engine/modules/gridmap/icons/GridMapDock.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e0e0e0" d="m8 1-6 3v8l6 3 6-3v-2l-2-1-4 2-2-1v-4l2-1v-2l2-1zm4 2-2 1v2l2 1 2-1v-2z"/></svg>
|
||||
|
After Width: | Height: | Size: 168 B |
|
|
@ -49,7 +49,7 @@ void initialize_gridmap_module(ModuleInitializationLevel p_level) {
|
|||
}
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
|
||||
GDREGISTER_CLASS(GridMapEditorPlugin);
|
||||
GDREGISTER_VIRTUAL_CLASS(GridMapEditorPlugin);
|
||||
EditorPlugins::add_by_type<GridMapEditorPlugin>();
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
122
engine/modules/gridmap/tests/test_grid_map.h
Normal file
122
engine/modules/gridmap/tests/test_grid_map.h
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/**************************************************************************/
|
||||
/* test_grid_map.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../grid_map.h"
|
||||
|
||||
#include "scene/main/scene_tree.h"
|
||||
#include "scene/main/window.h"
|
||||
#include "scene/resources/3d/primitive_meshes.h"
|
||||
#include "tests/test_macros.h"
|
||||
|
||||
namespace TestGridMap {
|
||||
|
||||
TEST_CASE("[SceneTree][GridMap][MeshLibrary] Octant querying") {
|
||||
Ref<MeshLibrary> mesh_library;
|
||||
mesh_library.instantiate();
|
||||
|
||||
int item1 = 0;
|
||||
int item2 = 1;
|
||||
|
||||
{
|
||||
Vector<int> item_list = mesh_library->get_item_list();
|
||||
CHECK(item_list.size() == 0);
|
||||
}
|
||||
|
||||
mesh_library->create_item(item1);
|
||||
mesh_library->create_item(item2);
|
||||
|
||||
int last_unused_item_id = mesh_library->get_last_unused_item_id();
|
||||
CHECK(last_unused_item_id == 2);
|
||||
|
||||
mesh_library->set_item_name(item1, "Item1");
|
||||
mesh_library->set_item_name(item2, "Item2");
|
||||
|
||||
Ref<BoxMesh> box_mesh;
|
||||
box_mesh.instantiate();
|
||||
box_mesh->set_size(Vector3(1.0, 1.0, 1.0));
|
||||
|
||||
mesh_library->set_item_mesh(item1, box_mesh);
|
||||
mesh_library->set_item_mesh(item2, box_mesh);
|
||||
|
||||
{
|
||||
Vector<int> item_list = mesh_library->get_item_list();
|
||||
CHECK(item_list.size() == 2);
|
||||
CHECK(item_list[0] == item1);
|
||||
CHECK(item_list[1] == item2);
|
||||
}
|
||||
|
||||
GridMap *grid_map = memnew(GridMap);
|
||||
grid_map->set_mesh_library(mesh_library);
|
||||
|
||||
SceneTree::get_singleton()->get_root()->add_child(grid_map);
|
||||
|
||||
grid_map->set_octant_size(8);
|
||||
grid_map->set_cell_size(Vector3(1.0, 1.0, 1.0));
|
||||
|
||||
grid_map->set_cell_item(Vector3i(0, 0, 0), -1);
|
||||
|
||||
CHECK(grid_map->get_used_cells().size() == 0);
|
||||
CHECK(grid_map->get_used_octants().size() == 0);
|
||||
|
||||
grid_map->set_cell_item(Vector3i(0, 0, 0), item1);
|
||||
grid_map->set_cell_item(Vector3i(7, 7, 7), item2);
|
||||
|
||||
CHECK(grid_map->get_used_cells().size() == 2);
|
||||
CHECK(grid_map->get_used_octants().size() == 1);
|
||||
CHECK(grid_map->get_used_octants()[0] == Vector3i(0, 0, 0));
|
||||
|
||||
grid_map->set_cell_item(Vector3i(8, 8, 8), item2);
|
||||
|
||||
CHECK(grid_map->get_used_cells().size() == 3);
|
||||
CHECK(grid_map->get_used_octants().size() == 2);
|
||||
CHECK(grid_map->get_used_octants()[0] == Vector3i(0, 0, 0));
|
||||
CHECK(grid_map->get_used_octants()[1] == Vector3i(1, 1, 1));
|
||||
|
||||
AABB bounds;
|
||||
bounds.position = Vector3(0.0, 0.0, 0.0);
|
||||
bounds.size = Vector3(8.0, 8.0, 8.0);
|
||||
|
||||
CHECK(grid_map->get_octants_in_bounds(bounds).size() == 1);
|
||||
CHECK(grid_map->get_used_octants_in_bounds(bounds).size() == 1);
|
||||
CHECK(grid_map->get_octants_in_bounds(bounds)[0] == Vector3i(0, 0, 0));
|
||||
|
||||
// Edge margin is -CMP_EPSILON.
|
||||
bounds.size = Vector3(8.001, 8.001, 8.001);
|
||||
CHECK(grid_map->get_octants_in_bounds(bounds).size() == 8);
|
||||
CHECK(grid_map->get_used_octants_in_bounds(bounds).size() == 2);
|
||||
|
||||
SceneTree::get_singleton()->get_root()->remove_child(grid_map);
|
||||
|
||||
memdelete(grid_map);
|
||||
}
|
||||
|
||||
} // namespace TestGridMap
|
||||
Loading…
Add table
Add a link
Reference in a new issue